diff --git a/.snyk b/.snyk new file mode 100644 index 0000000000..34320c65be --- /dev/null +++ b/.snyk @@ -0,0 +1,15 @@ +# Snyk policy — accepted risks, false positives, and paths excluded from Snyk Code. +version: v1.25.1 +ignore: + SNYK-JS-EXPRESSFILEUPLOAD-2635697: + - "*": + reason: No patched express-fileupload release; upload hardened in backend/app.js (limits, safeFileNames). + created: 2026-06-03T00:00:00.000Z + expires: 2027-06-03T00:00:00.000Z + SNYK-JS-EXPRESSFILEUPLOAD-2635946: + - "*": + reason: No patched express-fileupload release; upload hardened in backend/app.js (limits, safeFileNames). + created: 2026-06-03T00:00:00.000Z + expires: 2027-06-03T00:00:00.000Z +exclude: {} +patch: {} diff --git a/README.md b/README.md index 5cd9be1c96..55a922f3eb 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,9 @@ so that the barrier to entry here is low. - Access Lists and basic HTTP Authentication for your hosts - Advanced Nginx configuration available for super users - User management, permissions, and audit log +- **Credential vault** on the `/data` volume (encrypted DNS API tokens, optional external stores via OIDC) +- **Automation API** (API keys, async certificate jobs, signed webhooks) — see [docs](docs/src/advanced/automation-api.md) +- **Settings** UI for DNS credentials, external credential stores, API keys, and webhooks (see [SECURITY.md](SECURITY.md) for reporting vulnerabilities) ::: warning `armv7` is no longer supported in version 2.14+. This is due to Nodejs dropping support for armhf. Please @@ -74,6 +77,8 @@ services: This is the bare minimum configuration required. See the [documentation](https://nginxproxymanager.com/setup/) for more. +**Important:** Mount `./data:/data` so the credential vault, encryption keys, and automation settings persist across container restarts. Optional: set `NPM_SECRETS_ENCRYPTION_KEY` (32+ bytes, base64) to control encryption instead of the auto-generated key under `/data/keys/`. + 3. Bring up your stack by running ```bash diff --git a/SECURITY.md b/SECURITY.md index 66e4bb1f61..8062016298 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,8 +2,7 @@ ## Supported Versions -Only the latest stable release receives security updates. -Older versions are not actively maintained. +Only the latest stable release receives security updates. Older versions are not actively maintained. | Version | Supported | | ------- | --------- | @@ -19,12 +18,57 @@ See all releases: https://github.com/NginxProxyManager/nginx-proxy-manager/relea **Do NOT open a public GitHub Issue to report a security vulnerability.** Use GitHub's private vulnerability reporting: + https://github.com/NginxProxyManager/nginx-proxy-manager/security/advisories/new Please include: + - Affected version (Docker image tag or release) - Description of the vulnerability - Steps to reproduce - Potential impact Once a fix is available, a public GitHub Security Advisory will be published. + +## Dependency and code scanning + +Maintainers may use [Snyk](https://snyk.io/) for SCA and SAST. Policy exceptions and documented false positives live in [`.snyk`](.snyk). + +Local checks (from repo root): + +```bash +cd frontend && npm ci && npm audit +cd ../backend && npm ci && npm audit +cd ../test && npm ci && npm audit +cd ../docs && npm ci && npm audit +``` + +## Known accepted risks + +| Item | Mitigation | +|------|------------| +| `express-fileupload@1.5.2` (no patched release) | Upload middleware limited in [`backend/app.js`](backend/app.js): `limits.fileSize`, `abortOnLimit`, `safeFileNames`, `preserveExtension`. Documented in `.snyk`. | +| Bundled docs iframe (`/documentation`) | Only allowlisted `?section=` keys map to VitePress paths under `/docs/`; iframe uses `sandbox`. | + +Revisit `.snyk` entries when dependencies ship fixes or when mitigations change. + +## Deployment and secrets hygiene + +- Mount **`/data`** persistently so encryption keys and the credential vault survive restarts. +- Prefer **`NPM_SECRETS_ENCRYPTION_KEY`** (32-byte value, base64) in production instead of the auto-generated key under `/data/keys/`. +- Do not commit SSH keys, vault tokens, or API keys in the repository. +- Restrict admin port **81** to trusted networks; use strong passwords, 2FA, and scoped **API keys** for automation. +- Automation tokens (`npmak_…`) are shown once at creation; treat them like passwords. + +## Secure development + +- Package management uses **npm** and `package-lock.json`. +- JSON API routes return structured JSON via `res.json()` to avoid accidental HTML reflection. +- Production error responses do not include stack traces unless debug mode is enabled. +- OpenAPI operation descriptions are maintained in [`backend/schema/scripts/operation-descriptions.json`](backend/schema/scripts/operation-descriptions.json); regenerate the docs OpenAPI bundle after schema changes ([`docs/README.md`](docs/README.md)). + +## Related documentation + +- [Automation API](docs/src/advanced/automation-api.md) — API keys, webhooks, credential vault +- [Advanced configuration](docs/src/advanced-config/index.md) — `/data` volume and encryption +- In-app help: **Settings** → DNS credentials, external stores, API keys, webhooks (`/settings?tab=…`; `/credentials` redirects to DNS credentials) diff --git a/backend/app.js b/backend/app.js index b1f047661c..a2d1258bf4 100644 --- a/backend/app.js +++ b/backend/app.js @@ -12,7 +12,14 @@ import mainRoutes from "./routes/main.js"; * App */ const app = express(); -app.use(fileUpload()); +app.use( + fileUpload({ + limits: { fileSize: 50 * 1024 * 1024 }, + abortOnLimit: true, + safeFileNames: true, + preserveExtension: true, + }), +); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); @@ -71,7 +78,7 @@ app.use((err, req, res, _) => { payload.error.message_i18n = err.message_i18n; } - if (isDebugMode() || (req.baseUrl + req.path).includes("nginx/certificates")) { + if (isDebugMode()) { payload.debug = { stack: typeof err.stack !== "undefined" && err.stack ? err.stack.split("\n") : null, previous: err.previous, @@ -86,7 +93,7 @@ app.use((err, req, res, _) => { } } - res.status(err.status || 500).send(payload); + res.status(err.status || 500).json(payload); }); export default app; diff --git a/backend/internal/api-key.js b/backend/internal/api-key.js new file mode 100644 index 0000000000..ba6b2954fb --- /dev/null +++ b/backend/internal/api-key.js @@ -0,0 +1,120 @@ +import crypto from "node:crypto"; +import bcrypt from "bcrypt"; +import apiKeyModel from "../models/api_key.js"; +import now from "../models/now_helper.js"; +import errs from "../lib/error.js"; +import utils from "../lib/utils.js"; +import internalAuditLog from "./audit-log.js"; + +const omissions = () => ["is_deleted", "key_hash", "key_prefix"]; + +const hashApiKey = (rawKey) => bcrypt.hash(rawKey, 13); +const verifyApiKey = (rawKey, hash) => bcrypt.compare(rawKey, hash); + +const internalApiKey = { + create: async (access, data) => { + await access.can("api_keys:create", data); + + const prefix = crypto.randomBytes(4).toString("hex"); + const secret = crypto.randomBytes(24).toString("base64url"); + const rawKey = `npmak_${prefix}_${secret}`; + const keyHash = await hashApiKey(rawKey); + + const row = await apiKeyModel.query().insertAndFetch({ + name: data.name, + key_prefix: prefix, + key_hash: keyHash, + owner_user_id: access.token.getUserId(1), + permissions: data.permissions || {}, + expires_on: data.expires_on || null, + }); + + const result = utils.omitRow(omissions())(row); + result.key = rawKey; + + await internalAuditLog.add(access, { + action: "created", + object_type: "api-key", + object_id: row.id, + meta: { name: row.name }, + }); + + return result; + }, + + getAll: async (access) => { + await access.can("api_keys:list"); + return apiKeyModel + .query() + .where("is_deleted", 0) + .orderBy("name", "ASC") + .then(utils.omitRows(omissions())); + }, + + delete: async (access, data) => { + await access.can("api_keys:delete", data.id); + const row = await apiKeyModel + .query() + .where("id", data.id) + .andWhere("is_deleted", 0) + .first(); + + if (!row) { + throw new errs.ItemNotFoundError(data.id); + } + + await apiKeyModel.query().patchAndFetchById(row.id, { is_revoked: 1, is_deleted: 1 }); + + await internalAuditLog.add(access, { + action: "deleted", + object_type: "api-key", + object_id: row.id, + meta: { name: row.name }, + }); + + return true; + }, + + /** + * @param {string} rawKey + */ + authenticate: async (rawKey) => { + if (!rawKey?.startsWith("npmak_")) { + throw new errs.AuthError("Invalid API key"); + } + + const parts = rawKey.split("_"); + if (parts.length < 3) { + throw new errs.AuthError("Invalid API key"); + } + + const prefix = parts[1]; + const row = await apiKeyModel + .query() + .where("key_prefix", prefix) + .andWhere("is_deleted", 0) + .andWhere("is_revoked", 0) + .first(); + + if (!row) { + throw new errs.AuthError("Invalid API key"); + } + + if (row.expires_on && new Date(row.expires_on) < new Date()) { + throw new errs.AuthError("API key expired"); + } + + const valid = await verifyApiKey(rawKey, row.key_hash); + if (!valid) { + throw new errs.AuthError("Invalid API key"); + } + + await apiKeyModel.query().patchAndFetchById(row.id, { + last_used_at: now(), + }); + + return row; + }, +}; + +export default internalApiKey; diff --git a/backend/internal/audit-log.js b/backend/internal/audit-log.js index 02700dc5da..ef8171d787 100644 --- a/backend/internal/audit-log.js +++ b/backend/internal/audit-log.js @@ -1,4 +1,5 @@ import errs from "../lib/error.js"; +import { scrubAuditMeta } from "../lib/secrets/scrub.js"; import { castJsonIfNeed } from "../lib/helpers.js"; import auditLogModel from "../models/audit-log.js"; @@ -94,7 +95,7 @@ const internalAuditLog = { action: data.action, object_type: data.object_type || "", object_id: data.object_id || 0, - meta: data.meta || {}, + meta: scrubAuditMeta(data.meta || {}), }); }, }; diff --git a/backend/internal/certificate.js b/backend/internal/certificate.js index 6498422c61..542e77d7c1 100644 --- a/backend/internal/certificate.js +++ b/backend/internal/certificate.js @@ -18,15 +18,18 @@ import userModel from "../models/user.js"; import internalAuditLog from "./audit-log.js"; import internalHost from "./host.js"; import internalNginx from "./nginx.js"; +import internalWebhook from "./webhook.js"; +import { materializeCertbotCredentials } from "../lib/secrets/resolve.js"; const letsencryptConfig = "/etc/letsencrypt.ini"; const certbotCommand = "certbot"; const certbotLogsDir = "/data/logs"; const certbotWorkDir = "/tmp/letsencrypt-lib"; -const omissions = () => { - return ["is_deleted", "owner.is_deleted", "meta.dns_provider_credentials"]; -}; +const omissions = () => ["is_deleted", "owner.is_deleted"]; +const metaOmissions = () => ["dns_provider_credentials"]; + +const omitCertificate = () => utils.omitRow(omissions(), metaOmissions()); const internalCertificate = { allowedSslFiles: ["certificate", "certificate_key", "intermediate_certificate"], @@ -114,6 +117,20 @@ const internalCertificate = { * @param {Object} data * @returns {Promise} */ + prepareMetaForStorage: (meta) => { + if (!meta || typeof meta !== "object") { + return meta; + } + const prepared = { ...meta }; + if ( + (prepared.credential_ref?.type === "internal" && prepared.credential_ref.id) || + (prepared.credential_ref?.type === "external" && prepared.credential_ref.provider_id) + ) { + delete prepared.dns_provider_credentials; + } + return prepared; + }, + create: async (access, data) => { await access.can("certificates:create", data); data.owner_user_id = access.token.getUserId(1); @@ -122,6 +139,10 @@ const internalCertificate = { data.nice_name = data.domain_names.join(", "); } + if (data.meta) { + data.meta = internalCertificate.prepareMetaForStorage(data.meta); + } + // this command really should clean up and delete the cert if it can't fully succeed const certificate = await certificateModel.query().insertAndFetch(data); @@ -197,7 +218,7 @@ const internalCertificate = { .patchAndFetchById(certificate.id, { expires_on: moment(certInfo.dates.to, "X").format("YYYY-MM-DD HH:mm:ss"), }) - .then(utils.omitRow(omissions())); + .then(omitCertificate()); // Add cert data for audit log savedRow.meta = _.assign({}, savedRow.meta, { @@ -210,30 +231,44 @@ const internalCertificate = { } catch (err) { // Delete the certificate from the database if it was not created successfully await certificateModel.query().deleteById(certificate.id); + void internalWebhook.dispatch("certificate.failed", { + id: certificate.id, + domain_names: certificate.domain_names, + error: err.message, + }); throw err; } } } catch (err) { // Delete the certificate here. This is a hard delete, since it never existed properly - await certificateModel.query().deleteById(certificate.id); + if (certificate?.id) { + await certificateModel.query().deleteById(certificate.id); + void internalWebhook.dispatch("certificate.failed", { + id: certificate.id, + domain_names: data.domain_names, + error: err.message, + }); + } throw err; } data.meta = _.assign({}, data.meta || {}, certificate.meta); // Add to audit log - await internalCertificate.addCreatedAuditLog(access, certificate.id, utils.omitRow(omissions())(data)); + await internalCertificate.addCreatedAuditLog(access, certificate.id, omitCertificate()(data)); - return utils.omitRow(omissions())(certificate); + return omitCertificate()(certificate); }, addCreatedAuditLog: async (access, certificate_id, meta) => { + const sanitized = omitCertificate()(meta); await internalAuditLog.add(access, { action: "created", object_type: "certificate", object_id: certificate_id, - meta: meta, + meta: sanitized, }); + void internalWebhook.dispatch("certificate.created", { id: certificate_id }); }, /** @@ -255,10 +290,14 @@ const internalCertificate = { ); } + if (data.meta) { + data.meta = internalCertificate.prepareMetaForStorage(data.meta); + } + const savedRow = await certificateModel .query() .patchAndFetchById(row.id, data) - .then(utils.omitRow(omissions())); + .then(omitCertificate()); savedRow.meta = internalCertificate.cleanMeta(savedRow.meta); data.meta = internalCertificate.cleanMeta(data.meta); @@ -275,6 +314,7 @@ const internalCertificate = { object_id: row.id, meta: _.omit(data, ["expires_on"]), // this prevents json circular reference because expires_on might be raw }); + void internalWebhook.dispatch("certificate.updated", { id: savedRow.id }); return savedRow; }, @@ -304,7 +344,7 @@ const internalCertificate = { query.withGraphFetched(`[${data.expand.join(", ")}]`); } - const row = await query.then(utils.omitRow(omissions())); + const row = await query.then(omitCertificate()); if (!row?.id) { throw new error.ItemNotFoundError(data.id); } @@ -412,8 +452,9 @@ const internalCertificate = { action: "deleted", object_type: "certificate", object_id: row.id, - meta: _.omit(row, omissions()), + meta: omitCertificate()(row), }); + void internalWebhook.dispatch("certificate.deleted", { id: row.id }); if (row.provider === "letsencrypt") { // Revoke the cert @@ -755,6 +796,9 @@ const internalCertificate = { * @returns {Object} */ cleanMeta: (meta, remove) => { + if (meta && typeof meta === "object") { + delete meta.dns_provider_credentials; + } internalCertificate.allowedSslFiles.map((key) => { if (typeof meta[key] !== "undefined" && meta[key]) { if (remove) { @@ -828,9 +872,7 @@ const internalCertificate = { `Requesting LetsEncrypt certificates via ${dnsPlugin.name} for Cert #${certificate.id}: ${certificate.domain_names.join(", ")}`, ); - const credentialsLocation = `/etc/letsencrypt/credentials/credentials-${certificate.id}`; - fs.mkdirSync("/etc/letsencrypt/credentials", { recursive: true }); - fs.writeFileSync(credentialsLocation, certificate.meta.dns_provider_credentials, { mode: 0o600 }); + const credentialsLocation = await materializeCertbotCredentials(certificate); // Whether the plugin has a ---credentials argument const hasConfigArg = certificate.meta.dns_provider !== "route53"; @@ -917,8 +959,9 @@ const internalCertificate = { action: "renewed", object_type: "certificate", object_id: updatedCertificate.id, - meta: updatedCertificate, + meta: omitCertificate()(updatedCertificate), }); + void internalWebhook.dispatch("certificate.renewed", { id: updatedCertificate.id }); return updatedCertificate; } @@ -977,6 +1020,8 @@ const internalCertificate = { throw Error(`Unknown DNS provider '${certificate.meta.dns_provider}'`); } + await materializeCertbotCredentials(certificate); + logger.info( `Renewing LetsEncrypt certificates via ${dnsPlugin.name} for Cert #${certificate.id}: ${certificate.domain_names.join(", ")}`, ); diff --git a/backend/internal/credential-provider.js b/backend/internal/credential-provider.js new file mode 100644 index 0000000000..2f19b17106 --- /dev/null +++ b/backend/internal/credential-provider.js @@ -0,0 +1,148 @@ +import errs from "../lib/error.js"; +import { getProviderAccessToken, loadProvider, resolveFromProvider } from "../lib/secrets/resolvers/index.js"; +import { validateCredentialProviderPayload } from "../lib/secrets/validate-credential-provider.js"; +import { + deleteProviderSecret, + readProviderSecret, + writeProviderSecret, +} from "../lib/secrets/provider-storage.js"; +import { STORAGE_PATH_PLACEHOLDER } from "../lib/secrets/storage.js"; +import utils from "../lib/utils.js"; +import credentialProviderModel from "../models/credential_provider.js"; +import internalAuditLog from "./audit-log.js"; + +const omissions = () => ["is_deleted", "oidc_client_secret_path"]; + +const PROVIDER_TYPES = ["vault", "aws", "azure", "infisical", "http"]; + +const internalCredentialProvider = { + create: async (access, data) => { + await access.can("credential_providers:create", data); + + if (!PROVIDER_TYPES.includes(data.type)) { + throw new errs.ValidationError(`Invalid provider type. Must be one of: ${PROVIDER_TYPES.join(", ")}`); + } + + validateCredentialProviderPayload(data, { isCreate: true }); + + const row = await credentialProviderModel.query().insertAndFetch({ + name: data.name, + type: data.type, + owner_user_id: access.token.getUserId(1), + oidc_issuer: data.oidc_issuer || null, + oidc_client_id: data.oidc_client_id || null, + oidc_audience: data.oidc_audience || null, + oidc_scope: data.oidc_scope || null, + oidc_client_secret_path: STORAGE_PATH_PLACEHOLDER, + meta: data.meta || {}, + }); + + if (data.oidc_client_secret) { + const secretPath = writeProviderSecret(row.id, data.oidc_client_secret); + await credentialProviderModel.query().patchAndFetchById(row.id, { + oidc_client_secret_path: secretPath, + }); + } + + const saved = await internalCredentialProvider.get(access, { id: row.id }); + + await internalAuditLog.add(access, { + action: "created", + object_type: "credential-provider", + object_id: saved.id, + meta: { name: saved.name, type: saved.type }, + }); + + return saved; + }, + + update: async (access, data) => { + await access.can("credential_providers:update", data.id); + const row = await loadProvider(data.id); + + validateCredentialProviderPayload( + { + type: row.type, + name: typeof data.name !== "undefined" ? data.name : row.name, + oidc_issuer: typeof data.oidc_issuer !== "undefined" ? data.oidc_issuer : row.oidc_issuer, + oidc_client_id: typeof data.oidc_client_id !== "undefined" ? data.oidc_client_id : row.oidc_client_id, + oidc_client_secret: data.oidc_client_secret, + meta: typeof data.meta !== "undefined" ? data.meta : row.meta, + }, + { isCreate: false }, + ); + + const patch = {}; + if (typeof data.name !== "undefined") patch.name = data.name; + if (typeof data.oidc_issuer !== "undefined") patch.oidc_issuer = data.oidc_issuer; + if (typeof data.oidc_client_id !== "undefined") patch.oidc_client_id = data.oidc_client_id; + if (typeof data.oidc_audience !== "undefined") patch.oidc_audience = data.oidc_audience; + if (typeof data.oidc_scope !== "undefined") patch.oidc_scope = data.oidc_scope; + if (typeof data.meta !== "undefined") patch.meta = data.meta; + + if (typeof data.oidc_client_secret !== "undefined" && data.oidc_client_secret) { + const secretPath = writeProviderSecret(row.id, data.oidc_client_secret); + patch.oidc_client_secret_path = secretPath; + } + + await credentialProviderModel.query().patchAndFetchById(row.id, patch); + return internalCredentialProvider.get(access, { id: row.id }); + }, + + get: async (access, data) => { + await access.can("credential_providers:get", data.id); + const row = await credentialProviderModel + .query() + .where("id", data.id) + .andWhere("is_deleted", 0) + .first() + .then(utils.omitRow(omissions())); + + if (!row) { + throw new errs.ItemNotFoundError(data.id); + } + row.has_oidc_secret = !!readProviderSecret(row.id); + return row; + }, + + getAll: async (access) => { + await access.can("credential_providers:list"); + const rows = await credentialProviderModel + .query() + .where("is_deleted", 0) + .orderBy("name", "ASC") + .then(utils.omitRows(omissions())); + + return rows.map((row) => ({ + ...row, + has_oidc_secret: !!readProviderSecret(row.id), + })); + }, + + delete: async (access, data) => { + await access.can("credential_providers:delete", data.id); + const row = await loadProvider(data.id); + await credentialProviderModel.query().patchAndFetchById(row.id, { is_deleted: 1 }); + deleteProviderSecret(row.id); + return true; + }, + + test: async (access, data) => { + await access.can("credential_providers:get", data.id); + const provider = await loadProvider(data.id); + await getProviderAccessToken(provider); + return { ok: true, type: provider.type, name: provider.name }; + }, + + testResolve: async (access, data) => { + await access.can("credential_providers:get", data.id); + const provider = await loadProvider(data.id); + const ini = await resolveFromProvider(provider, { + path: data.path, + field: data.field, + }); + return { ok: true, bytes: ini.length }; + }, +}; + +export default internalCredentialProvider; diff --git a/backend/internal/credential.js b/backend/internal/credential.js new file mode 100644 index 0000000000..35f2738d28 --- /dev/null +++ b/backend/internal/credential.js @@ -0,0 +1,205 @@ +import dnsPlugins from "../certbot/dns-plugins.json" with { type: "json" }; +import errs from "../lib/error.js"; +import { validateDnsCredentialsFormat } from "../lib/secrets/resolve.js"; +import { + deleteCredentialFile, + readCredentialFile, + STORAGE_PATH_PLACEHOLDER, + writeCredentialFile, +} from "../lib/secrets/storage.js"; +import utils from "../lib/utils.js"; +import certificateModel from "../models/certificate.js"; +import credentialModel from "../models/credential.js"; +import internalAuditLog from "./audit-log.js"; + +const omissions = () => ["is_deleted", "storage_path", "encryption_key_id"]; + +const internalCredential = { + create: async (access, data) => { + await access.can("credentials:create", data); + validateDnsCredentialsFormat(data.dns_provider, data.credentials); + + const row = await credentialModel.query().insertAndFetch({ + name: data.name, + dns_provider: data.dns_provider, + owner_user_id: access.token.getUserId(1), + storage_path: STORAGE_PATH_PLACEHOLDER, + encryption_key_id: "v1", + }); + + const { storagePath, keyId } = writeCredentialFile(row.id, data.credentials); + const saved = await credentialModel + .query() + .patchAndFetchById(row.id, { + storage_path: storagePath, + encryption_key_id: keyId, + }) + .then(utils.omitRow(omissions())); + + await internalAuditLog.add(access, { + action: "created", + object_type: "credential", + object_id: saved.id, + meta: { name: saved.name, dns_provider: saved.dns_provider }, + }); + + return saved; + }, + + update: async (access, data) => { + await access.can("credentials:update", data.id); + const row = await internalCredential.get(access, { id: data.id }); + + const patch = {}; + if (typeof data.name !== "undefined") { + patch.name = data.name; + } + if (typeof data.dns_provider !== "undefined") { + patch.dns_provider = data.dns_provider; + } + + if (typeof data.credentials !== "undefined") { + const provider = data.dns_provider || row.dns_provider; + validateDnsCredentialsFormat(provider, data.credentials); + const { storagePath, keyId } = writeCredentialFile(row.id, data.credentials); + patch.storage_path = storagePath; + patch.encryption_key_id = keyId; + } + + const saved = await credentialModel.query().patchAndFetchById(row.id, patch).then(utils.omitRow(omissions())); + + await internalAuditLog.add(access, { + action: "updated", + object_type: "credential", + object_id: saved.id, + meta: { name: saved.name, dns_provider: saved.dns_provider }, + }); + + return saved; + }, + + get: async (access, data) => { + await access.can("credentials:get", data.id); + const row = await credentialModel + .query() + .where("id", data.id) + .andWhere("is_deleted", 0) + .first() + .then(utils.omitRow(omissions())); + + if (!row) { + throw new errs.ItemNotFoundError(data.id); + } + return row; + }, + + getAll: async (access) => { + await access.can("credentials:list"); + return credentialModel + .query() + .where("is_deleted", 0) + .orderBy("name", "ASC") + .then(utils.omitRows(omissions())); + }, + + delete: async (access, data) => { + await access.can("credentials:delete", data.id); + const row = await internalCredential.get(access, { id: data.id }); + + await credentialModel.query().patchAndFetchById(row.id, { is_deleted: 1 }); + deleteCredentialFile(row.id); + + await internalAuditLog.add(access, { + action: "deleted", + object_type: "credential", + object_id: row.id, + meta: { name: row.name, dns_provider: row.dns_provider }, + }); + + return true; + }, + + test: async (access, data) => { + await access.can("credentials:get", data.id); + const row = await credentialModel + .query() + .where("id", data.id) + .andWhere("is_deleted", 0) + .first(); + + if (!row) { + throw new errs.ItemNotFoundError(data.id); + } + + readCredentialFile(row.id); + const plugin = dnsPlugins[row.dns_provider]; + return { + ok: true, + dns_provider: row.dns_provider, + plugin_name: plugin?.name || row.dns_provider, + }; + }, + + /** + * Import plaintext DNS credentials from certificate.meta into the vault. + * @param {Access} access + * @param {Object} [data] + * @param {boolean} [data.dry_run] + */ + migrateLegacy: async (access, data = {}) => { + await access.can("credentials:create", {}); + + const certs = await certificateModel + .query() + .where("is_deleted", 0) + .andWhere("provider", "letsencrypt"); + + const results = []; + for (const cert of certs) { + const meta = cert.meta || {}; + if (!meta.dns_challenge || typeof meta.dns_provider_credentials !== "string") { + continue; + } + if (meta.credential_ref?.type) { + continue; + } + + const entry = { + certificate_id: cert.id, + domain_names: cert.domain_names, + dns_provider: meta.dns_provider, + status: "skipped", + }; + + if (!data.dry_run) { + const cred = await internalCredential.create(access, { + name: `Migrated cert #${cert.id}`, + dns_provider: meta.dns_provider, + credentials: meta.dns_provider_credentials, + }); + + const newMeta = { + ...meta, + credential_ref: { type: "internal", id: cred.id }, + }; + delete newMeta.dns_provider_credentials; + + await certificateModel.query().patchAndFetchById(cert.id, { meta: newMeta }); + entry.credential_id = cred.id; + entry.status = "migrated"; + } else { + entry.status = "would_migrate"; + } + + results.push(entry); + } + + return { + dry_run: !!data.dry_run, + count: results.length, + results, + }; + }, +}; + +export default internalCredential; diff --git a/backend/internal/ip_ranges.js b/backend/internal/ip_ranges.js index 6aa2b88a98..54aada579e 100644 --- a/backend/internal/ip_ranges.js +++ b/backend/internal/ip_ranges.js @@ -18,6 +18,27 @@ const CLOUDFARE_V6_URL = "https://www.cloudflare.com/ips-v6"; const regIpV4 = /^(\d+\.?){4}\/\d+/; const regIpV6 = /^(([\da-fA-F]+)?:)+\/\d+/; +const fetchFixedUrl = (fixedUrl) => { + const agent = new ProxyAgent(); + return new Promise((resolve, reject) => { + logger.info(`Fetching ${fixedUrl}`); + https + .get(fixedUrl, { agent }, (res) => { + res.setEncoding("utf8"); + let raw_data = ""; + res.on("data", (chunk) => { + raw_data += chunk; + }); + res.on("end", () => { + resolve(raw_data); + }); + }) + .on("error", (err) => { + reject(err); + }); + }); +}; + const internalIpRanges = { interval_timeout: 1000 * 60 * 60 * 6, // 6 hours interval: null, @@ -29,28 +50,6 @@ const internalIpRanges = { internalIpRanges.interval = setInterval(internalIpRanges.fetch, internalIpRanges.interval_timeout); }, - fetchUrl: (url) => { - const agent = new ProxyAgent(); - return new Promise((resolve, reject) => { - logger.info(`Fetching ${url}`); - return https - .get(url, { agent }, (res) => { - res.setEncoding("utf8"); - let raw_data = ""; - res.on("data", (chunk) => { - raw_data += chunk; - }); - - res.on("end", () => { - resolve(raw_data); - }); - }) - .on("error", (err) => { - reject(err); - }); - }); - }, - /** * Triggered at startup and then later by a timer, this will fetch the ip ranges from services and apply them to nginx. */ @@ -61,8 +60,7 @@ const internalIpRanges = { let ip_ranges = []; - return internalIpRanges - .fetchUrl(CLOUDFRONT_URL) + return fetchFixedUrl(CLOUDFRONT_URL) .then((cloudfront_data) => { const data = JSON.parse(cloudfront_data); @@ -85,14 +83,14 @@ const internalIpRanges = { } }) .then(() => { - return internalIpRanges.fetchUrl(CLOUDFARE_V4_URL); + return fetchFixedUrl(CLOUDFARE_V4_URL); }) .then((cloudfare_data) => { const items = cloudfare_data.split("\n").filter((line) => regIpV4.test(line)); ip_ranges = [...ip_ranges, ...items]; }) .then(() => { - return internalIpRanges.fetchUrl(CLOUDFARE_V6_URL); + return fetchFixedUrl(CLOUDFARE_V6_URL); }) .then((cloudfare_data) => { const items = cloudfare_data.split("\n").filter((line) => regIpV6.test(line)); diff --git a/backend/internal/job.js b/backend/internal/job.js new file mode 100644 index 0000000000..ec7f2d30ba --- /dev/null +++ b/backend/internal/job.js @@ -0,0 +1,114 @@ +import internalCertificate from "./certificate.js"; +import internalWebhook from "./webhook.js"; +import jobModel from "../models/job.js"; +import now from "../models/now_helper.js"; +import errs from "../lib/error.js"; +import utils from "../lib/utils.js"; + +const jobQueue = []; +let jobProcessing = false; + +const omissions = () => []; + +const processQueue = async () => { + if (jobProcessing || !jobQueue.length) { + return; + } + jobProcessing = true; + const { jobId, access, handler, onFail } = jobQueue.shift(); + try { + await jobModel.query().patchAndFetchById(jobId, { status: "running" }); + const result = await handler(); + await jobModel.query().patchAndFetchById(jobId, { + status: "completed", + result, + finished_on: now(), + }); + } catch (err) { + await jobModel.query().patchAndFetchById(jobId, { + status: "failed", + error: err.message, + finished_on: now(), + }); + if (typeof onFail === "function") { + try { + await onFail(err); + } catch { + // ignore webhook errors + } + } + } finally { + jobProcessing = false; + setImmediate(processQueue); + } +}; + +const internalJob = { + enqueue: async (access, type, payload, handler, onFail) => { + const row = await jobModel.query().insertAndFetch({ + owner_user_id: access.token.getUserId(1), + type, + status: "pending", + payload, + }); + + jobQueue.push({ jobId: row.id, access, handler, onFail }); + setImmediate(processQueue); + + return utils.omitRow(omissions())(row); + }, + + getAll: async (access, data = {}) => { + const query = jobModel.query().orderBy("id", "DESC").limit(data.limit || 50); + + if (!access.isAdmin()) { + query.where("owner_user_id", access.token.getUserId(1)); + } + + return query.then(utils.omitRows(omissions())); + }, + + get: async (access, data) => { + const row = await jobModel.query().where("id", data.id).first(); + if (!row) { + throw new errs.ItemNotFoundError(data.id); + } + if (row.owner_user_id !== access.token.getUserId(1) && !access.isAdmin()) { + throw new errs.PermissionError("Permission Denied"); + } + return utils.omitRow(omissions())(row); + }, + + runCertificateCreate: (access, payload) => { + return internalJob.enqueue( + access, + "certificate.create", + payload, + () => internalCertificate.create(access, payload), + async (err) => { + void internalWebhook.dispatch("certificate.failed", { + error: err.message, + domain_names: payload.domain_names, + }); + }, + ); + }, + + runCertificateRenew: (access, payload) => { + const certId = payload.id; + return internalJob.enqueue( + access, + "certificate.renew", + payload, + () => internalCertificate.renew(access, payload), + async (err) => { + void internalWebhook.dispatch("certificate.failed", { + id: certId, + error: err.message, + }); + }, + ); + }, +}; + +export default internalJob; diff --git a/backend/internal/proxy-host.js b/backend/internal/proxy-host.js index 2c159d48ad..e2917e18e0 100644 --- a/backend/internal/proxy-host.js +++ b/backend/internal/proxy-host.js @@ -7,6 +7,7 @@ import internalAuditLog from "./audit-log.js"; import internalCertificate from "./certificate.js"; import internalHost from "./host.js"; import internalNginx from "./nginx.js"; +import internalWebhook from "./webhook.js"; const omissions = () => { return ["is_deleted", "owner.is_deleted"]; @@ -102,6 +103,7 @@ const internalProxyHost = { meta: thisData, }) .then(() => { + void internalWebhook.dispatch("proxy_host.created", utils.omitRow(omissions())(row)); return row; }); }); @@ -198,6 +200,7 @@ const internalProxyHost = { meta: thisData, }) .then(() => { + void internalWebhook.dispatch("proxy_host.updated", saved_row); return saved_row; }); }); @@ -303,6 +306,9 @@ const internalProxyHost = { object_id: row.id, meta: _.omit(row, omissions()), }); + }) + .then(() => { + void internalWebhook.dispatch("proxy_host.deleted", { id: row.id }); }); }) .then(() => { @@ -354,6 +360,9 @@ const internalProxyHost = { object_id: row.id, meta: _.omit(row, omissions()), }); + }) + .then(() => { + void internalWebhook.dispatch("proxy_host.enabled", { id: row.id }); }); }) .then(() => { @@ -404,6 +413,9 @@ const internalProxyHost = { object_id: row.id, meta: _.omit(row, omissions()), }); + }) + .then(() => { + void internalWebhook.dispatch("proxy_host.disabled", { id: row.id }); }); }) .then(() => { diff --git a/backend/internal/user.js b/backend/internal/user.js index 56a5ea8598..be65c1f523 100644 --- a/backend/internal/user.js +++ b/backend/internal/user.js @@ -59,6 +59,7 @@ const internalUser = { streams: "manage", access_lists: "manage", certificates: "manage", + credentials: "manage", }); user = await internalUser.get(access, { id: user.id, expand: ["permissions"] }); diff --git a/backend/internal/webhook.js b/backend/internal/webhook.js new file mode 100644 index 0000000000..b11aa39c09 --- /dev/null +++ b/backend/internal/webhook.js @@ -0,0 +1,122 @@ +import crypto from "node:crypto"; +import { encrypt, decrypt } from "../lib/secrets/crypto.js"; +import { ensureCredentialDirs, STORAGE_PATH_PLACEHOLDER } from "../lib/secrets/storage.js"; +import fs from "node:fs"; +import path from "node:path"; +import webhookEndpointModel from "../models/webhook_endpoint.js"; +import utils from "../lib/utils.js"; +import { debug, express as logger } from "../logger.js"; + +const WEBHOOK_SECRETS_DIR = "/data/credentials/webhooks"; + +const omissions = () => ["is_deleted", "secret_path"]; + +const writeWebhookSecret = (id, secret) => { + ensureCredentialDirs(); + fs.mkdirSync(WEBHOOK_SECRETS_DIR, { recursive: true, mode: 0o700 }); + const { buffer } = encrypt(secret); + const filePath = path.join(WEBHOOK_SECRETS_DIR, `${id}.enc`); + fs.writeFileSync(filePath, buffer, { mode: 0o600 }); + return `${id}.enc`; +}; + +const readWebhookSecret = (id) => { + const filePath = path.join(WEBHOOK_SECRETS_DIR, `${id}.enc`); + if (!fs.existsSync(filePath)) { + return ""; + } + return decrypt(fs.readFileSync(filePath)); +}; + +const internalWebhook = { + create: async (access, data) => { + await access.can("webhooks:create", data); + const signingSecret = data.secret || crypto.randomBytes(32).toString("hex"); + + const row = await webhookEndpointModel.query().insertAndFetch({ + name: data.name, + url: data.url, + events: data.events, + owner_user_id: access.token.getUserId(1), + secret_path: STORAGE_PATH_PLACEHOLDER, + is_enabled: data.is_enabled !== false ? 1 : 0, + }); + + const secretPath = writeWebhookSecret(row.id, signingSecret); + const saved = await webhookEndpointModel + .query() + .patchAndFetchById(row.id, { secret_path: secretPath }) + .then(utils.omitRow(omissions())); + + if (data.secret) { + delete saved.secret; + } else { + saved.secret = signingSecret; + } + + return saved; + }, + + getAll: async (access) => { + await access.can("webhooks:list"); + return webhookEndpointModel + .query() + .where("is_deleted", 0) + .orderBy("name", "ASC") + .then(utils.omitRows(omissions())); + }, + + delete: async (access, data) => { + await access.can("webhooks:delete", data.id); + await webhookEndpointModel.query().patchAndFetchById(data.id, { is_deleted: 1 }); + return true; + }, + + dispatch: async (event, payload) => { + const endpoints = await webhookEndpointModel + .query() + .where("is_deleted", 0) + .andWhere("is_enabled", 1); + + const maxAttempts = 3; + + for (const endpoint of endpoints) { + if (!endpoint.events?.includes(event) && !endpoint.events?.includes("*")) { + continue; + } + + const secret = readWebhookSecret(endpoint.id); + const body = JSON.stringify({ event, payload, timestamp: new Date().toISOString() }); + const signature = crypto.createHmac("sha256", secret).update(body).digest("hex"); + + for (let attempt = 1; attempt <= maxAttempts; attempt++) { + try { + const response = await fetch(endpoint.url, { + method: "POST", + headers: { + "Content-Type": "application/json", + "X-NPM-Event": event, + "X-NPM-Signature": `sha256=${signature}`, + }, + body, + signal: AbortSignal.timeout(10000), + }); + + if (response.ok) { + break; + } + + debug(logger, `Webhook ${endpoint.id} returned ${response.status} (attempt ${attempt}/${maxAttempts})`); + } catch (err) { + debug(logger, `Webhook ${endpoint.id} failed: ${err.message} (attempt ${attempt}/${maxAttempts})`); + } + + if (attempt < maxAttempts) { + await new Promise((resolve) => setTimeout(resolve, attempt * 500)); + } + } + } + }, +}; + +export default internalWebhook; diff --git a/backend/lib/access.js b/backend/lib/access.js index a4dec5c4dd..4e041da31f 100644 --- a/backend/lib/access.js +++ b/backend/lib/access.js @@ -22,7 +22,7 @@ import errs from "./error.js"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); -export default function (tokenString) { +export default function (tokenString, permissionsOverride = null) { const Token = TokenModel(); let tokenData = null; let initialised = false; @@ -30,6 +30,7 @@ export default function (tokenString) { let allowInternalAccess = false; let userRoles = []; let permissions = {}; + const overridePermissions = permissionsOverride; /** * Loads the Token object from the token string @@ -83,6 +84,9 @@ export default function (tokenString) { initialised = true; userRoles = user.roles; permissions = user.permissions; + if (overridePermissions && typeof overridePermissions === "object") { + permissions = _.assign({}, permissions, overridePermissions); + } } else { throw new errs.AuthError("User cannot be loaded for Token"); } @@ -199,6 +203,8 @@ export default function (tokenString) { return { token: Token, + isAdmin: () => _.indexOf(userRoles, "admin") !== -1, + /** * * @param {Boolean} [allowInternal] @@ -241,6 +247,7 @@ export default function (tokenString) { permission_streams: permissions.streams, permission_access_lists: permissions.access_lists, permission_certificates: permissions.certificates, + permission_credentials: permissions.credentials, }, }; diff --git a/backend/lib/access/api_keys-create.json b/backend/lib/access/api_keys-create.json new file mode 100644 index 0000000000..aeadc94ba9 --- /dev/null +++ b/backend/lib/access/api_keys-create.json @@ -0,0 +1,7 @@ +{ + "anyOf": [ + { + "$ref": "roles#/definitions/admin" + } + ] +} diff --git a/backend/lib/access/api_keys-delete.json b/backend/lib/access/api_keys-delete.json new file mode 100644 index 0000000000..aeadc94ba9 --- /dev/null +++ b/backend/lib/access/api_keys-delete.json @@ -0,0 +1,7 @@ +{ + "anyOf": [ + { + "$ref": "roles#/definitions/admin" + } + ] +} diff --git a/backend/lib/access/api_keys-list.json b/backend/lib/access/api_keys-list.json new file mode 100644 index 0000000000..aeadc94ba9 --- /dev/null +++ b/backend/lib/access/api_keys-list.json @@ -0,0 +1,7 @@ +{ + "anyOf": [ + { + "$ref": "roles#/definitions/admin" + } + ] +} diff --git a/backend/lib/access/credential_providers-create.json b/backend/lib/access/credential_providers-create.json new file mode 100644 index 0000000000..3206784491 --- /dev/null +++ b/backend/lib/access/credential_providers-create.json @@ -0,0 +1,3 @@ +{ + "anyOf": [{ "$ref": "roles#/definitions/admin" }] +} diff --git a/backend/lib/access/credential_providers-delete.json b/backend/lib/access/credential_providers-delete.json new file mode 100644 index 0000000000..3206784491 --- /dev/null +++ b/backend/lib/access/credential_providers-delete.json @@ -0,0 +1,3 @@ +{ + "anyOf": [{ "$ref": "roles#/definitions/admin" }] +} diff --git a/backend/lib/access/credential_providers-get.json b/backend/lib/access/credential_providers-get.json new file mode 100644 index 0000000000..3206784491 --- /dev/null +++ b/backend/lib/access/credential_providers-get.json @@ -0,0 +1,3 @@ +{ + "anyOf": [{ "$ref": "roles#/definitions/admin" }] +} diff --git a/backend/lib/access/credential_providers-list.json b/backend/lib/access/credential_providers-list.json new file mode 100644 index 0000000000..3206784491 --- /dev/null +++ b/backend/lib/access/credential_providers-list.json @@ -0,0 +1,3 @@ +{ + "anyOf": [{ "$ref": "roles#/definitions/admin" }] +} diff --git a/backend/lib/access/credential_providers-update.json b/backend/lib/access/credential_providers-update.json new file mode 100644 index 0000000000..3206784491 --- /dev/null +++ b/backend/lib/access/credential_providers-update.json @@ -0,0 +1,3 @@ +{ + "anyOf": [{ "$ref": "roles#/definitions/admin" }] +} diff --git a/backend/lib/access/credentials-create.json b/backend/lib/access/credentials-create.json new file mode 100644 index 0000000000..08da91b034 --- /dev/null +++ b/backend/lib/access/credentials-create.json @@ -0,0 +1,23 @@ +{ + "anyOf": [ + { + "$ref": "roles#/definitions/admin" + }, + { + "type": "object", + "required": ["permission_credentials", "roles"], + "properties": { + "permission_credentials": { + "$ref": "perms#/definitions/manage" + }, + "roles": { + "type": "array", + "items": { + "type": "string", + "enum": ["user"] + } + } + } + } + ] +} diff --git a/backend/lib/access/credentials-delete.json b/backend/lib/access/credentials-delete.json new file mode 100644 index 0000000000..08da91b034 --- /dev/null +++ b/backend/lib/access/credentials-delete.json @@ -0,0 +1,23 @@ +{ + "anyOf": [ + { + "$ref": "roles#/definitions/admin" + }, + { + "type": "object", + "required": ["permission_credentials", "roles"], + "properties": { + "permission_credentials": { + "$ref": "perms#/definitions/manage" + }, + "roles": { + "type": "array", + "items": { + "type": "string", + "enum": ["user"] + } + } + } + } + ] +} diff --git a/backend/lib/access/credentials-get.json b/backend/lib/access/credentials-get.json new file mode 100644 index 0000000000..b96d4944a4 --- /dev/null +++ b/backend/lib/access/credentials-get.json @@ -0,0 +1,23 @@ +{ + "anyOf": [ + { + "$ref": "roles#/definitions/admin" + }, + { + "type": "object", + "required": ["permission_credentials", "roles"], + "properties": { + "permission_credentials": { + "$ref": "perms#/definitions/view" + }, + "roles": { + "type": "array", + "items": { + "type": "string", + "enum": ["user"] + } + } + } + } + ] +} diff --git a/backend/lib/access/credentials-list.json b/backend/lib/access/credentials-list.json new file mode 100644 index 0000000000..b96d4944a4 --- /dev/null +++ b/backend/lib/access/credentials-list.json @@ -0,0 +1,23 @@ +{ + "anyOf": [ + { + "$ref": "roles#/definitions/admin" + }, + { + "type": "object", + "required": ["permission_credentials", "roles"], + "properties": { + "permission_credentials": { + "$ref": "perms#/definitions/view" + }, + "roles": { + "type": "array", + "items": { + "type": "string", + "enum": ["user"] + } + } + } + } + ] +} diff --git a/backend/lib/access/credentials-update.json b/backend/lib/access/credentials-update.json new file mode 100644 index 0000000000..08da91b034 --- /dev/null +++ b/backend/lib/access/credentials-update.json @@ -0,0 +1,23 @@ +{ + "anyOf": [ + { + "$ref": "roles#/definitions/admin" + }, + { + "type": "object", + "required": ["permission_credentials", "roles"], + "properties": { + "permission_credentials": { + "$ref": "perms#/definitions/manage" + }, + "roles": { + "type": "array", + "items": { + "type": "string", + "enum": ["user"] + } + } + } + } + ] +} diff --git a/backend/lib/access/webhooks-create.json b/backend/lib/access/webhooks-create.json new file mode 100644 index 0000000000..aeadc94ba9 --- /dev/null +++ b/backend/lib/access/webhooks-create.json @@ -0,0 +1,7 @@ +{ + "anyOf": [ + { + "$ref": "roles#/definitions/admin" + } + ] +} diff --git a/backend/lib/access/webhooks-delete.json b/backend/lib/access/webhooks-delete.json new file mode 100644 index 0000000000..aeadc94ba9 --- /dev/null +++ b/backend/lib/access/webhooks-delete.json @@ -0,0 +1,7 @@ +{ + "anyOf": [ + { + "$ref": "roles#/definitions/admin" + } + ] +} diff --git a/backend/lib/access/webhooks-list.json b/backend/lib/access/webhooks-list.json new file mode 100644 index 0000000000..aeadc94ba9 --- /dev/null +++ b/backend/lib/access/webhooks-list.json @@ -0,0 +1,7 @@ +{ + "anyOf": [ + { + "$ref": "roles#/definitions/admin" + } + ] +} diff --git a/backend/lib/express/jwt-decode.js b/backend/lib/express/jwt-decode.js index 90fe241e46..19afbfcb9f 100644 --- a/backend/lib/express/jwt-decode.js +++ b/backend/lib/express/jwt-decode.js @@ -1,10 +1,41 @@ import Access from "../access.js"; +import errs from "../error.js"; +import internalApiKey from "../../internal/api-key.js"; +import userModel from "../../models/user.js"; +import TokenModel from "../../models/token.js"; export default () => { return async (_, res, next) => { try { res.locals.access = null; - const access = new Access(res.locals.token || null); + let token = res.locals.token || null; + let permissionsOverride = null; + + if (res.locals.apiKey) { + const apiKeyRow = await internalApiKey.authenticate(res.locals.apiKey); + const user = await userModel + .query() + .where("id", apiKeyRow.owner_user_id) + .andWhere("is_deleted", 0) + .andWhere("is_disabled", 0) + .first(); + + if (!user) { + throw new errs.AuthError("API key owner not found"); + } + + const Token = TokenModel(); + const signed = await Token.create({ + iss: "api-key", + scope: ["user"], + attrs: { id: user.id }, + expiresIn: "1h", + }); + token = signed.token; + permissionsOverride = apiKeyRow.permissions; + } + + const access = new Access(token, permissionsOverride); await access.load(); res.locals.access = access; next(); diff --git a/backend/lib/express/jwt.js b/backend/lib/express/jwt.js index ce907b6de9..dc2de1cd20 100644 --- a/backend/lib/express/jwt.js +++ b/backend/lib/express/jwt.js @@ -4,7 +4,11 @@ export default function () { const parts = req.headers.authorization.split(" "); if (parts && parts[0] === "Bearer" && parts[1]) { - res.locals.token = parts[1]; + if (parts[1].startsWith("npmak_")) { + res.locals.apiKey = parts[1]; + } else { + res.locals.token = parts[1]; + } } } diff --git a/backend/lib/secrets/crypto.js b/backend/lib/secrets/crypto.js new file mode 100644 index 0000000000..376cb5148b --- /dev/null +++ b/backend/lib/secrets/crypto.js @@ -0,0 +1,98 @@ +import crypto from "node:crypto"; +import fs from "node:fs"; +import path from "node:path"; + +const ALGORITHM = "aes-256-gcm"; +const IV_LENGTH = 12; +const KEY_LENGTH = 32; +const CURRENT_KEY_ID = "v1"; + +const secretsKeyFile = "/data/keys/secrets.json"; + +const getMasterKey = () => { + const envKey = process.env.NPM_SECRETS_ENCRYPTION_KEY; + if (envKey) { + const buf = Buffer.from(envKey, "base64"); + if (buf.length !== KEY_LENGTH) { + throw new Error("NPM_SECRETS_ENCRYPTION_KEY must be 32 bytes (base64-encoded)"); + } + return { key: buf, keyId: CURRENT_KEY_ID }; + } + + if (fs.existsSync(secretsKeyFile)) { + const data = JSON.parse(fs.readFileSync(secretsKeyFile, "utf8")); + const key = Buffer.from(data.key, "base64"); + if (key.length !== KEY_LENGTH) { + throw new Error("Invalid master key in secrets.json"); + } + return { key, keyId: data.keyId || CURRENT_KEY_ID }; + } + + fs.mkdirSync(path.dirname(secretsKeyFile), { recursive: true, mode: 0o700 }); + const key = crypto.randomBytes(KEY_LENGTH); + const payload = { + keyId: CURRENT_KEY_ID, + key: key.toString("base64"), + created: new Date().toISOString(), + }; + fs.writeFileSync(secretsKeyFile, JSON.stringify(payload, null, 2), { mode: 0o600 }); + return { key, keyId: CURRENT_KEY_ID }; +}; + +/** + * @param {string} plaintext + * @returns {{ buffer: Buffer, keyId: string }} + */ +export const encrypt = (plaintext) => { + const { key, keyId } = getMasterKey(); + const iv = crypto.randomBytes(IV_LENGTH); + const cipher = crypto.createCipheriv(ALGORITHM, key, iv); + const encrypted = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]); + const tag = cipher.getAuthTag(); + const buffer = Buffer.concat([ + Buffer.from([1]), + Buffer.from(keyId, "utf8"), + Buffer.from([0]), + iv, + tag, + encrypted, + ]); + return { buffer, keyId }; +}; + +/** + * @param {Buffer} buffer + * @returns {string} + */ +export const decrypt = (buffer) => { + if (buffer[0] !== 1) { + throw new Error("Unsupported credential encryption format"); + } + const keyIdEnd = buffer.indexOf(0, 1); + const keyId = buffer.subarray(1, keyIdEnd).toString("utf8"); + const ivStart = keyIdEnd + 1; + const iv = buffer.subarray(ivStart, ivStart + IV_LENGTH); + const tag = buffer.subarray(ivStart + IV_LENGTH, ivStart + IV_LENGTH + 16); + const encrypted = buffer.subarray(ivStart + IV_LENGTH + 16); + + const envKey = process.env.NPM_SECRETS_ENCRYPTION_KEY; + let key; + if (envKey) { + key = Buffer.from(envKey, "base64"); + } else if (fs.existsSync(secretsKeyFile)) { + const data = JSON.parse(fs.readFileSync(secretsKeyFile, "utf8")); + if (data.keyId !== keyId) { + throw new Error(`Unknown encryption key id: ${keyId}`); + } + key = Buffer.from(data.key, "base64"); + } else { + throw new Error("No master encryption key available"); + } + + const decipher = crypto.createDecipheriv(ALGORITHM, key, iv); + decipher.setAuthTag(tag); + return Buffer.concat([decipher.update(encrypted), decipher.final()]).toString("utf8"); +}; + +export const CREDENTIALS_DIR = "/data/credentials"; +export const PROVIDERS_DIR = "/data/credentials/providers"; diff --git a/backend/lib/secrets/format.js b/backend/lib/secrets/format.js new file mode 100644 index 0000000000..8950ac37c4 --- /dev/null +++ b/backend/lib/secrets/format.js @@ -0,0 +1,26 @@ +/** + * Convert fetched secret payload to certbot INI format. + * @param {*} payload - string or object from external store + * @param {string} [field] - optional key when payload is JSON object + */ +export const toCertbotIni = (payload, field) => { + if (typeof payload === "string") { + return payload.trim(); + } + + if (payload && typeof payload === "object") { + if (field && typeof payload[field] === "string") { + return payload[field].trim(); + } + if (field && payload[field] !== undefined) { + return String(payload[field]); + } + // Flat object -> ini lines + return Object.entries(payload) + .filter(([, v]) => v !== null && v !== undefined && String(v).length) + .map(([k, v]) => `${k} = ${v}`) + .join("\n"); + } + + throw new Error("Unsupported secret payload format"); +}; diff --git a/backend/lib/secrets/infisical-auth.js b/backend/lib/secrets/infisical-auth.js new file mode 100644 index 0000000000..8e4e94c002 --- /dev/null +++ b/backend/lib/secrets/infisical-auth.js @@ -0,0 +1,49 @@ +import errs from "../error.js"; +import { normalizeInfisicalMeta } from "./meta.js"; + +/** + * @param {string} host + * @param {string} clientId + * @param {string} clientSecret + */ +export const loginUniversalAuth = async (host, clientId, clientSecret) => { + const base = host.replace(/\/$/, ""); + const url = `${base}/api/v1/auth/universal-auth/login`; + + const response = await fetch(url, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ clientId, clientSecret }), + signal: AbortSignal.timeout(15000), + }); + + if (!response.ok) { + const text = await response.text(); + throw new errs.ValidationError( + `Infisical Universal Auth failed (${response.status}): ${text.slice(0, 200)}`, + ); + } + + const data = await response.json(); + const token = data.accessToken || data.access_token; + if (!token) { + throw new errs.ValidationError("Infisical Universal Auth response missing accessToken"); + } + + return token; +}; + +/** + * @param {Object} provider + * @param {string} [clientSecret] + */ +export const getInfisicalAccessToken = async (provider, clientSecret) => { + const meta = normalizeInfisicalMeta(provider.meta || {}); + const host = meta.host || "https://app.infisical.com"; + + if (!provider.oidc_client_id || !clientSecret) { + throw new errs.ValidationError("Infisical Universal Auth requires client ID and client secret"); + } + + return loginUniversalAuth(host, provider.oidc_client_id, clientSecret); +}; diff --git a/backend/lib/secrets/infisical-path.js b/backend/lib/secrets/infisical-path.js new file mode 100644 index 0000000000..0610389d58 --- /dev/null +++ b/backend/lib/secrets/infisical-path.js @@ -0,0 +1,53 @@ +import errs from "../error.js"; + +/** + * Split NPM credential_ref into Infisical API secretName + secretPath (folder). + * + * Supported path forms: + * - cloudflare-api-token → secret at / + * - /DNS/cloudflare-api-token → secret key under /DNS + * - DNS/cloudflare-api-token → same as above + * + * If field is set, path is the folder (default /) and field is the secret key. + * + * @param {{ path?: string, field?: string }} secretRef + */ +export const parseInfisicalSecretRef = (secretRef) => { + const field = typeof secretRef?.field === "string" ? secretRef.field.trim() : ""; + + if (field) { + const rawFolder = (secretRef?.path || "").trim(); + const secretPath = normalizeInfisicalFolder(rawFolder || "/"); + return { secretName: field, secretPath }; + } + + const raw = (secretRef?.path || "").trim(); + if (!raw || raw === "/") { + throw new errs.ValidationError( + "Infisical path must include a secret name (e.g. /DNS/cloudflare-api-token or cloudflare-api-token for root)", + ); + } + + const normalized = raw.startsWith("/") ? raw : `/${raw}`; + const segments = normalized.split("/").filter(Boolean); + if (segments.length === 0) { + throw new errs.ValidationError("Infisical path must include a secret name"); + } + + const secretName = segments[segments.length - 1]; + const folderSegments = segments.slice(0, -1); + const secretPath = folderSegments.length ? `/${folderSegments.join("/")}` : "/"; + + return { secretName, secretPath }; +}; + +/** + * @param {string} folder + */ +const normalizeInfisicalFolder = (folder) => { + const trimmed = folder.trim(); + if (!trimmed || trimmed === "/") { + return "/"; + } + return trimmed.startsWith("/") ? trimmed : `/${trimmed}`; +}; diff --git a/backend/lib/secrets/meta.js b/backend/lib/secrets/meta.js new file mode 100644 index 0000000000..8854bb1590 --- /dev/null +++ b/backend/lib/secrets/meta.js @@ -0,0 +1,14 @@ +/** + * Normalize provider meta (supports legacy camelCase keys from early UI). + * @param {Record|null|undefined} meta + */ +export const normalizeInfisicalMeta = (meta) => { + const m = meta && typeof meta === "object" ? meta : {}; + return { + host: (m.host || "https://app.infisical.com").toString().replace(/\/$/, ""), + workspace_id: (m.workspace_id || m.workspaceId || "").toString().trim(), + environment_slug: (m.environment_slug || m.environmentSlug || "prod").toString().trim(), + auth_method: "universal", + token_url: (m.token_url || m.tokenUrl || "").toString().trim(), + }; +}; diff --git a/backend/lib/secrets/oidc.js b/backend/lib/secrets/oidc.js new file mode 100644 index 0000000000..8bf9e7e1a6 --- /dev/null +++ b/backend/lib/secrets/oidc.js @@ -0,0 +1,74 @@ +import errs from "../error.js"; + +/** + * OAuth2 client credentials token fetch. + * @param {Object} config + * @param {string} config.issuer + * @param {string} config.clientId + * @param {string} config.clientSecret + * @param {string} [config.audience] + * @param {string} [config.scope] + */ +export const fetchClientCredentialsToken = async (config) => { + const tokenUrl = config.tokenUrl || `${config.issuer.replace(/\/$/, "")}/oauth/token`; + + const body = new URLSearchParams({ + grant_type: "client_credentials", + client_id: config.clientId, + client_secret: config.clientSecret, + }); + + if (config.audience) { + body.set("audience", config.audience); + } + if (config.scope) { + body.set("scope", config.scope); + } + + const response = await fetch(tokenUrl, { + method: "POST", + headers: { "Content-Type": "application/x-www-form-urlencoded" }, + body: body.toString(), + signal: AbortSignal.timeout(15000), + }); + + if (!response.ok) { + const text = await response.text(); + throw new errs.ValidationError(`OIDC token request failed (${response.status}): ${text.slice(0, 200)}`); + } + + const data = await response.json(); + if (!data.access_token) { + throw new errs.ValidationError("OIDC response missing access_token"); + } + + return data.access_token; +}; + +/** + * Azure AD client credentials. + */ +export const fetchAzureAdToken = async ({ tenantId, clientId, clientSecret, scope }) => { + const tokenUrl = `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`; + const body = new URLSearchParams({ + grant_type: "client_credentials", + client_id: clientId, + client_secret: clientSecret, + scope: scope || "https://vault.azure.net/.default", + }); + + const response = await fetch(tokenUrl, { + method: "POST", + headers: { "Content-Type": "application/x-www-form-urlencoded" }, + body: body.toString(), + signal: AbortSignal.timeout(15000), + }); + + if (!response.ok) { + const text = await response.text(); + throw new errs.ValidationError(`Azure AD token failed (${response.status}): ${text.slice(0, 200)}`); + } + + const data = await response.json(); + return data.access_token; +}; diff --git a/backend/lib/secrets/provider-storage.js b/backend/lib/secrets/provider-storage.js new file mode 100644 index 0000000000..adc1ecea69 --- /dev/null +++ b/backend/lib/secrets/provider-storage.js @@ -0,0 +1,28 @@ +import fs from "node:fs"; +import path from "node:path"; +import { PROVIDERS_DIR, decrypt, encrypt } from "./crypto.js"; + +export const writeProviderSecret = (providerId, plaintext) => { + fs.mkdirSync(PROVIDERS_DIR, { recursive: true, mode: 0o700 }); + const { buffer } = encrypt(plaintext); + const target = path.join(PROVIDERS_DIR, `${providerId}.enc`); + const temp = `${target}.tmp`; + fs.writeFileSync(temp, buffer, { mode: 0o600 }); + fs.renameSync(temp, target); + return `${providerId}.enc`; +}; + +export const readProviderSecret = (providerId) => { + const filePath = path.join(PROVIDERS_DIR, `${providerId}.enc`); + if (!fs.existsSync(filePath)) { + return null; + } + return decrypt(fs.readFileSync(filePath)); +}; + +export const deleteProviderSecret = (providerId) => { + const filePath = path.join(PROVIDERS_DIR, `${providerId}.enc`); + if (fs.existsSync(filePath)) { + fs.unlinkSync(filePath); + } +}; diff --git a/backend/lib/secrets/resolve.js b/backend/lib/secrets/resolve.js new file mode 100644 index 0000000000..7c2b346369 --- /dev/null +++ b/backend/lib/secrets/resolve.js @@ -0,0 +1,69 @@ +import dnsPlugins from "../../certbot/dns-plugins.json" with { type: "json" }; +import errs from "../error.js"; +import credentialModel from "../../models/credential.js"; +import now from "../../models/now_helper.js"; +import { resolveExternalCredential } from "./resolvers/external.js"; +import { readCredentialFile, writeCertbotCredentialsFile } from "./storage.js"; + +/** + * Resolve DNS certbot credentials plaintext for a certificate. + * @param {Object} certificate + * @returns {Promise} + */ +export const resolveDnsCredentials = async (certificate) => { + const meta = certificate.meta || {}; + + if (meta.credential_ref?.type === "external") { + return resolveExternalCredential(meta.credential_ref); + } + + if (meta.credential_ref?.type === "internal" && meta.credential_ref.id) { + const credential = await credentialModel + .query() + .where("id", meta.credential_ref.id) + .andWhere("is_deleted", 0) + .first(); + + if (!credential) { + throw new errs.ValidationError("Referenced credential not found"); + } + + if (credential.dns_provider !== meta.dns_provider) { + throw new errs.ValidationError("Credential DNS provider does not match certificate"); + } + + const plaintext = readCredentialFile(credential.id); + await credentialModel.query().patchAndFetchById(credential.id, { + last_used_at: now(), + }); + return plaintext; + } + + if (typeof meta.dns_provider_credentials === "string" && meta.dns_provider_credentials.length) { + return meta.dns_provider_credentials; + } + + throw new errs.ValidationError("DNS credentials are required (credential_ref or dns_provider_credentials)"); +}; + +/** + * @param {Object} certificate + * @returns {Promise} + */ +export const materializeCertbotCredentials = async (certificate) => { + const plaintext = await resolveDnsCredentials(certificate); + return writeCertbotCredentialsFile(certificate.id, plaintext); +}; + +/** + * @param {string} provider + * @param {string} credentialsIni + */ +export const validateDnsCredentialsFormat = (provider, credentialsIni) => { + if (!dnsPlugins[provider]) { + throw new errs.ValidationError(`Unknown DNS provider: ${provider}`); + } + if (!credentialsIni || typeof credentialsIni !== "string" || !credentialsIni.trim()) { + throw new errs.ValidationError("Credentials cannot be empty"); + } +}; diff --git a/backend/lib/secrets/resolvers/aws.js b/backend/lib/secrets/resolvers/aws.js new file mode 100644 index 0000000000..d32b9e5814 --- /dev/null +++ b/backend/lib/secrets/resolvers/aws.js @@ -0,0 +1,152 @@ +import crypto from "node:crypto"; +import errs from "../../error.js"; +import { toCertbotIni } from "../format.js"; + +/** + * AWS Secrets Manager via OIDC web identity + STS + GetSecretValue (REST, no SDK). + * meta: { region, role_arn } + * secretRef.path: secret id or ARN + */ +export const assumeRoleWithWebIdentity = async ({ region, roleArn, webIdentityToken }) => { + const params = new URLSearchParams({ + Action: "AssumeRoleWithWebIdentity", + Version: "2011-06-15", + RoleArn: roleArn, + RoleSessionName: "npm-credential-resolver", + WebIdentityToken: webIdentityToken, + DurationSeconds: "900", + }); + + const response = await fetch(`https://sts.${region}.amazonaws.com/`, { + method: "POST", + headers: { "Content-Type": "application/x-www-form-urlencoded" }, + body: params.toString(), + signal: AbortSignal.timeout(15000), + }); + + const text = await response.text(); + if (!response.ok) { + throw new errs.ValidationError(`AWS STS failed (${response.status})`); + } + + const key = (name) => { + const match = text.match(new RegExp(`<${name}>([^<]+)`)); + return match?.[1]; + }; + + return { + accessKeyId: key("AccessKeyId"), + secretAccessKey: key("SecretAccessKey"), + sessionToken: key("SessionToken"), + }; +}; + +const sha256 = async (message) => { + const data = new TextEncoder().encode(message); + const hash = await crypto.subtle.digest("SHA-256", data); + return Buffer.from(hash).toString("hex"); +}; + +const hmac = async (key, message) => { + const cryptoKey = await crypto.subtle.importKey( + "raw", + typeof key === "string" ? new TextEncoder().encode(key) : key, + { name: "HMAC", hash: "SHA-256" }, + false, + ["sign"], + ); + const sig = await crypto.subtle.sign("HMAC", cryptoKey, new TextEncoder().encode(message)); + return Buffer.from(sig); +}; + +const getSignatureKey = async (key, dateStamp, regionName, serviceName) => { + const kDate = await hmac(`AWS4${key}`, dateStamp); + const kRegion = await hmac(kDate, regionName); + const kService = await hmac(kRegion, serviceName); + return hmac(kService, "aws4_request"); +}; + +const signRequest = async ({ method, url, headers, body, credentials, region, service }) => { + const urlObj = new URL(url); + const amzDate = headers["x-amz-date"]; + const dateStamp = amzDate.slice(0, 8); + const canonicalHeaders = `${Object.keys(headers) + .sort() + .map((k) => `${k.toLowerCase()}:${headers[k].trim()}\n`) + .join("")}host:${urlObj.host}\n`; + const signedHeaders = `${Object.keys(headers) + .sort() + .map((k) => k.toLowerCase()) + .join(";")};host`; + const payloadHash = await sha256(body || ""); + const canonicalRequest = [method, urlObj.pathname + urlObj.search, "", canonicalHeaders, signedHeaders, payloadHash].join( + "\n", + ); + const credentialScope = `${dateStamp}/${region}/${service}/aws4_request`; + const stringToSign = ["AWS4-HMAC-SHA256", amzDate, credentialScope, await sha256(canonicalRequest)].join("\n"); + const signingKey = await getSignatureKey(credentials.secretAccessKey, dateStamp, region, service); + const signature = (await hmac(signingKey, stringToSign)).toString("hex"); + + return `AWS4-HMAC-SHA256 Credential=${credentials.accessKeyId}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`; +}; + +export const resolveAws = async (provider, secretRef, oidcToken) => { + const { region = "us-east-1", role_arn } = provider.meta || {}; + if (!role_arn) { + throw new errs.ValidationError("AWS provider requires role_arn in meta"); + } + + const credentials = await assumeRoleWithWebIdentity({ + region, + roleArn: role_arn, + webIdentityToken: oidcToken, + }); + + const secretId = secretRef.path?.replace(/^\//, ""); + const host = `secretsmanager.${region}.amazonaws.com`; + const url = `https://${host}/`; + const body = JSON.stringify({ SecretId: secretId }); + const now = new Date(); + const amzDate = now.toISOString().replace(/[:-]|\.\d{3}/g, ""); + const headers = { + "Content-Type": "application/x-amz-json-1.1", + "X-Amz-Target": "secretsmanager.GetSecretValue", + "X-Amz-Date": amzDate, + "X-Amz-Security-Token": credentials.sessionToken, + Host: host, + }; + + headers.Authorization = await signRequest({ + method: "POST", + url, + headers, + body, + credentials, + region, + service: "secretsmanager", + }); + + const response = await fetch(url, { + method: "POST", + headers, + body, + signal: AbortSignal.timeout(15000), + }); + + if (!response.ok) { + const text = await response.text(); + throw new errs.ValidationError(`AWS Secrets Manager failed (${response.status}): ${text.slice(0, 200)}`); + } + + const data = await response.json(); + let payload = data.SecretString; + if (!payload && data.SecretBinary) { + payload = Buffer.from(data.SecretBinary, "base64").toString("utf8"); + } + try { + payload = JSON.parse(payload); + } catch { + // keep string + } + return toCertbotIni(payload, secretRef.field); +}; diff --git a/backend/lib/secrets/resolvers/azure.js b/backend/lib/secrets/resolvers/azure.js new file mode 100644 index 0000000000..a0596be119 --- /dev/null +++ b/backend/lib/secrets/resolvers/azure.js @@ -0,0 +1,35 @@ +import errs from "../../error.js"; +import { fetchAzureAdToken } from "../oidc.js"; +import { toCertbotIni } from "../format.js"; + +/** + * Azure Key Vault secret. + * meta: { tenant_id, vault_url } — vault_url e.g. https://myvault.vault.azure.net + */ +export const resolveAzure = async (provider, secretRef, clientSecret) => { + const { tenant_id, vault_url } = provider.meta || {}; + if (!tenant_id || !vault_url) { + throw new errs.ValidationError("Azure provider requires tenant_id and vault_url in meta"); + } + + const token = await fetchAzureAdToken({ + tenantId: tenant_id, + clientId: provider.oidc_client_id, + clientSecret, + }); + + const secretName = secretRef.path?.replace(/^\//, ""); + const url = `${vault_url.replace(/\/$/, "")}/secrets/${secretName}?api-version=7.4`; + + const response = await fetch(url, { + headers: { Authorization: `Bearer ${token}` }, + signal: AbortSignal.timeout(15000), + }); + + if (!response.ok) { + throw new errs.ValidationError(`Azure Key Vault read failed (${response.status})`); + } + + const data = await response.json(); + return toCertbotIni(data.value, secretRef.field); +}; diff --git a/backend/lib/secrets/resolvers/external.js b/backend/lib/secrets/resolvers/external.js new file mode 100644 index 0000000000..67558faf46 --- /dev/null +++ b/backend/lib/secrets/resolvers/external.js @@ -0,0 +1,19 @@ +import { loadProvider, resolveFromProvider } from "./index.js"; + +/** + * Resolve credentials from an external store (Vault, AWS, Azure, Infisical, HTTP). + * @param {Object} credentialRef + * @returns {Promise} + */ +export const resolveExternalCredential = async (credentialRef) => { + if (credentialRef?.type !== "external") { + throw new errs.ValidationError("Invalid external credential reference"); + } + + if (!credentialRef.provider_id) { + throw new errs.ValidationError("external credential_ref requires provider_id"); + } + + const provider = await loadProvider(credentialRef.provider_id); + return resolveFromProvider(provider, credentialRef); +}; diff --git a/backend/lib/secrets/resolvers/http.js b/backend/lib/secrets/resolvers/http.js new file mode 100644 index 0000000000..b70c3d1732 --- /dev/null +++ b/backend/lib/secrets/resolvers/http.js @@ -0,0 +1,40 @@ +import errs from "../../error.js"; +import { toCertbotIni } from "../format.js"; + +/** + * Generic HTTP secret endpoint. + * meta: { url_template } — use {path} placeholder, e.g. https://vault.example/secrets/{path} + */ +export const resolveHttp = async (provider, secretRef, accessToken) => { + const { url_template, method = "GET", headers: extraHeaders = {} } = provider.meta || {}; + if (!url_template) { + throw new errs.ValidationError("HTTP provider requires url_template in meta"); + } + + const path = secretRef.path || ""; + const url = url_template.replace("{path}", encodeURIComponent(path.replace(/^\//, ""))); + + const headers = { + Authorization: `Bearer ${accessToken}`, + Accept: "application/json", + ...extraHeaders, + }; + + const response = await fetch(url, { + method, + headers, + signal: AbortSignal.timeout(15000), + }); + + if (!response.ok) { + throw new errs.ValidationError(`HTTP secret fetch failed (${response.status})`); + } + + const contentType = response.headers.get("content-type") || ""; + if (contentType.includes("application/json")) { + const data = await response.json(); + return toCertbotIni(data, secretRef.field); + } + + return toCertbotIni(await response.text(), secretRef.field); +}; diff --git a/backend/lib/secrets/resolvers/index.js b/backend/lib/secrets/resolvers/index.js new file mode 100644 index 0000000000..441930ffa4 --- /dev/null +++ b/backend/lib/secrets/resolvers/index.js @@ -0,0 +1,67 @@ +import credentialProviderModel from "../../../models/credential_provider.js"; +import errs from "../../error.js"; +import { getInfisicalAccessToken } from "../infisical-auth.js"; +import { fetchClientCredentialsToken } from "../oidc.js"; +import { readProviderSecret } from "../provider-storage.js"; +import { resolveAws } from "./aws.js"; +import { resolveAzure } from "./azure.js"; +import { resolveHttp } from "./http.js"; +import { resolveInfisical } from "./infisical.js"; +import { resolveVault } from "./vault.js"; + +const resolvers = { + vault: resolveVault, + aws: resolveAws, + azure: resolveAzure, + infisical: resolveInfisical, + http: resolveHttp, +}; + +export const loadProvider = async (providerId) => { + const provider = await credentialProviderModel + .query() + .where("id", providerId) + .andWhere("is_deleted", 0) + .first(); + + if (!provider) { + throw new errs.ValidationError(`Credential provider ${providerId} not found`); + } + + return provider; +}; + +export const getProviderAccessToken = async (provider) => { + if (provider.type === "infisical") { + const clientSecret = readProviderSecret(provider.id); + return getInfisicalAccessToken(provider, clientSecret); + } + + const clientSecret = readProviderSecret(provider.id); + if (!provider.oidc_client_id || !clientSecret) { + throw new errs.ValidationError("Provider OIDC client_id and client_secret are required"); + } + + return fetchClientCredentialsToken({ + issuer: provider.oidc_issuer, + tokenUrl: provider.meta?.token_url, + clientId: provider.oidc_client_id, + clientSecret, + audience: provider.oidc_audience, + scope: provider.oidc_scope, + }); +}; + +/** + * @param {Object} provider + * @param {Object} secretRef + */ +export const resolveFromProvider = async (provider, secretRef) => { + const resolver = resolvers[provider.type]; + if (!resolver) { + throw new errs.ValidationError(`Unknown credential provider type: ${provider.type}`); + } + + const accessToken = await getProviderAccessToken(provider); + return resolver(provider, secretRef, accessToken); +}; diff --git a/backend/lib/secrets/resolvers/infisical.js b/backend/lib/secrets/resolvers/infisical.js new file mode 100644 index 0000000000..46092bf449 --- /dev/null +++ b/backend/lib/secrets/resolvers/infisical.js @@ -0,0 +1,53 @@ +import errs from "../../error.js"; +import { parseInfisicalSecretRef } from "../infisical-path.js"; +import { toCertbotIni } from "../format.js"; +import { normalizeInfisicalMeta } from "../meta.js"; + +/** + * Infisical Universal Auth. + * secretRef.path: folder + secret key (e.g. /DNS/cloudflare-api-token) or key only at / + * secretRef.field: optional secret key when path is folder only (e.g. path /DNS, field cloudflare-api-token) + */ +export const resolveInfisical = async (provider, secretRef, accessToken) => { + const { host, workspace_id, environment_slug } = normalizeInfisicalMeta(provider.meta); + + if (!workspace_id) { + throw new errs.ValidationError("Infisical provider requires workspace_id in meta"); + } + + const { secretName, secretPath } = parseInfisicalSecretRef(secretRef); + const params = new URLSearchParams({ + workspaceId: workspace_id, + environment: environment_slug, + secretPath, + }); + const base = host.replace(/\/$/, ""); + const url = `${base}/api/v3/secrets/raw/${encodeURIComponent(secretName)}?${params}`; + + const response = await fetch(url, { + headers: { Authorization: `Bearer ${accessToken}` }, + signal: AbortSignal.timeout(15000), + }); + + if (!response.ok) { + const text = await response.text(); + let detail = text.slice(0, 200); + try { + const body = JSON.parse(text); + if (body.message) detail = body.message; + } catch { + // keep raw snippet + } + throw new errs.ValidationError(`Infisical secret fetch failed (${response.status}): ${detail}`); + } + + const data = await response.json(); + const secret = data.secret || data; + if (secretRef.field && secret?.secretKey === secretRef.field) { + return toCertbotIni(secret.secretValue); + } + if (typeof secret === "object" && secret.secretValue) { + return toCertbotIni(secret.secretValue); + } + return toCertbotIni(data, secretRef.field); +}; diff --git a/backend/lib/secrets/resolvers/vault.js b/backend/lib/secrets/resolvers/vault.js new file mode 100644 index 0000000000..7dbbfee13c --- /dev/null +++ b/backend/lib/secrets/resolvers/vault.js @@ -0,0 +1,47 @@ +import errs from "../../error.js"; +import { toCertbotIni } from "../format.js"; + +/** + * HashiCorp Vault KV v2 via JWT/OIDC login. + * meta: { address, mount, role, jwt_auth_path } + */ +export const resolveVault = async (provider, secretRef, accessToken) => { + const { address, mount = "secret", role, jwt_auth_path = "jwt" } = provider.meta || {}; + if (!address) { + throw new errs.ValidationError("Vault address is required in provider meta"); + } + + const base = address.replace(/\/$/, ""); + let vaultToken = accessToken; + + if (role) { + const loginRes = await fetch(`${base}/v1/auth/${jwt_auth_path}/login`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ role, jwt: accessToken }), + signal: AbortSignal.timeout(15000), + }); + if (!loginRes.ok) { + throw new errs.ValidationError(`Vault JWT login failed (${loginRes.status})`); + } + const loginData = await loginRes.json(); + vaultToken = loginData.auth?.client_token; + if (!vaultToken) { + throw new errs.ValidationError("Vault login did not return client_token"); + } + } + + const path = secretRef.path?.replace(/^\//, ""); + const secretRes = await fetch(`${base}/v1/${mount}/data/${path}`, { + headers: { "X-Vault-Token": vaultToken }, + signal: AbortSignal.timeout(15000), + }); + + if (!secretRes.ok) { + throw new errs.ValidationError(`Vault read failed (${secretRes.status})`); + } + + const secretData = await secretRes.json(); + const payload = secretData.data?.data ?? secretData.data; + return toCertbotIni(payload, secretRef.field); +}; diff --git a/backend/lib/secrets/scrub.js b/backend/lib/secrets/scrub.js new file mode 100644 index 0000000000..5e6d58f023 --- /dev/null +++ b/backend/lib/secrets/scrub.js @@ -0,0 +1,46 @@ +const SENSITIVE_META_KEYS = [ + "dns_provider_credentials", + "certificate_key", + "certificate", + "intermediate_certificate", + "oidc_client_secret", +]; + +const SENSITIVE_REF_KEYS = ["credentials"]; + +/** + * Deep-clone and redact secrets from audit log / API meta payloads. + * @param {*} meta + * @returns {*} + */ +export const scrubAuditMeta = (meta) => { + if (!meta || typeof meta !== "object") { + return meta; + } + + if (Array.isArray(meta)) { + return meta.map(scrubAuditMeta); + } + + const out = {}; + for (const [key, value] of Object.entries(meta)) { + if (SENSITIVE_META_KEYS.includes(key)) { + out[key] = "[redacted]"; + continue; + } + if (key === "meta" && value && typeof value === "object") { + out.meta = scrubAuditMeta(value); + continue; + } + if (key === "credential_ref" && value && typeof value === "object") { + out.credential_ref = { ...value }; + continue; + } + if (typeof value === "object" && value !== null) { + out[key] = scrubAuditMeta(value); + } else { + out[key] = value; + } + } + return out; +}; diff --git a/backend/lib/secrets/storage.js b/backend/lib/secrets/storage.js new file mode 100644 index 0000000000..92bb859fa1 --- /dev/null +++ b/backend/lib/secrets/storage.js @@ -0,0 +1,64 @@ +import fs from "node:fs"; +import path from "node:path"; +import { CREDENTIALS_DIR, PROVIDERS_DIR, decrypt, encrypt } from "./crypto.js"; + +/** DB placeholder before encrypted file is written (not a secret). */ +export const STORAGE_PATH_PLACEHOLDER = "__uninitialized__"; + +export const ensureCredentialDirs = () => { + fs.mkdirSync(CREDENTIALS_DIR, { recursive: true, mode: 0o700 }); + fs.mkdirSync(PROVIDERS_DIR, { recursive: true, mode: 0o700 }); +}; + +/** + * @param {number} id + * @returns {string} + */ +export const getCredentialPath = (id) => path.join(CREDENTIALS_DIR, `${id}.enc`); + +/** + * @param {number} id + * @param {string} plaintext + */ +export const writeCredentialFile = (id, plaintext) => { + ensureCredentialDirs(); + const { buffer, keyId } = encrypt(plaintext); + const target = getCredentialPath(id); + const temp = `${target}.tmp`; + fs.writeFileSync(temp, buffer, { mode: 0o600 }); + fs.renameSync(temp, target); + return { storagePath: `${id}.enc`, keyId }; +}; + +/** + * @param {number} id + * @returns {string} + */ +export const readCredentialFile = (id) => { + const filePath = getCredentialPath(id); + if (!fs.existsSync(filePath)) { + throw new Error(`Credential file not found for id ${id}`); + } + return decrypt(fs.readFileSync(filePath)); +}; + +/** + * @param {number} id + */ +export const deleteCredentialFile = (id) => { + const filePath = getCredentialPath(id); + if (fs.existsSync(filePath)) { + fs.unlinkSync(filePath); + } +}; + +/** + * @param {number} certificateId + * @param {string} plaintext + */ +export const writeCertbotCredentialsFile = (certificateId, plaintext) => { + const credentialsLocation = `/etc/letsencrypt/credentials/credentials-${certificateId}`; + fs.mkdirSync("/etc/letsencrypt/credentials", { recursive: true }); + fs.writeFileSync(credentialsLocation, plaintext, { mode: 0o600 }); + return credentialsLocation; +}; diff --git a/backend/lib/secrets/validate-credential-provider.js b/backend/lib/secrets/validate-credential-provider.js new file mode 100644 index 0000000000..932e1b0679 --- /dev/null +++ b/backend/lib/secrets/validate-credential-provider.js @@ -0,0 +1,83 @@ +import errs from "../error.js"; +import { normalizeInfisicalMeta } from "./meta.js"; + +const PROVIDER_TYPES = ["vault", "aws", "azure", "infisical", "http"]; + +const requireString = (value, label) => { + if (typeof value !== "string" || !value.trim()) { + throw new errs.ValidationError(`${label} is required`); + } + return value.trim(); +}; + +/** + * @param {Object} data + * @param {{ isCreate?: boolean }} options + */ +export const validateCredentialProviderPayload = (data, { isCreate = false } = {}) => { + if (!PROVIDER_TYPES.includes(data.type)) { + throw new errs.ValidationError(`Invalid provider type. Must be one of: ${PROVIDER_TYPES.join(", ")}`); + } + + requireString(data.name, "name"); + const meta = data.meta && typeof data.meta === "object" ? data.meta : {}; + + switch (data.type) { + case "infisical": { + const rawAuth = meta.auth_method || meta.authMethod; + if (rawAuth === "oidc") { + throw new errs.ValidationError( + "Infisical OIDC Auth is no longer supported; use Universal Auth (client ID and client secret)", + ); + } + const inf = normalizeInfisicalMeta(meta); + if (!inf.workspace_id) { + throw new errs.ValidationError("Infisical provider requires workspace_id in meta"); + } + if (isCreate) { + requireString(data.oidc_client_id, "client ID"); + requireString(data.oidc_client_secret, "client secret"); + } + break; + } + case "vault": { + requireString(meta.address, "Vault address in meta"); + if (isCreate) { + requireString(data.oidc_issuer, "issuer"); + requireString(data.oidc_client_id, "client ID"); + requireString(data.oidc_client_secret, "client secret"); + } + break; + } + case "aws": { + requireString(meta.region, "AWS region in meta"); + requireString(meta.role_arn || meta.roleArn, "AWS role_arn in meta"); + if (isCreate) { + requireString(data.oidc_issuer, "issuer"); + requireString(data.oidc_client_id, "client ID"); + requireString(data.oidc_client_secret, "client secret"); + } + break; + } + case "azure": { + requireString(meta.tenant_id || meta.tenantId, "Azure tenant_id in meta"); + requireString(meta.vault_url || meta.vaultUrl, "Azure vault_url in meta"); + if (isCreate) { + requireString(data.oidc_client_id, "client ID"); + requireString(data.oidc_client_secret, "client secret"); + } + break; + } + case "http": { + requireString(meta.url_template || meta.urlTemplate, "HTTP url_template in meta"); + if (isCreate) { + requireString(data.oidc_issuer, "issuer"); + requireString(data.oidc_client_id, "client ID"); + requireString(data.oidc_client_secret, "client secret"); + } + break; + } + default: + break; + } +}; diff --git a/backend/lib/utils.js b/backend/lib/utils.js index a19142af03..dc08028321 100644 --- a/backend/lib/utils.js +++ b/backend/lib/utils.js @@ -51,13 +51,28 @@ const execFile = (cmd, args, options) => { * @param {Array} omissions * @returns {Function} */ -const omitRow = (omissions) => { +const omitNestedMeta = (row, metaKeys) => { + if (!row || typeof row !== "object" || !row.meta || typeof row.meta !== "object") { + return row; + } + const meta = { ...row.meta }; + for (const key of metaKeys) { + delete meta[key]; + } + return { ...row, meta }; +}; + +const omitRow = (omissions, metaOmissions = []) => { /** * @param {Object} row * @returns {Object} */ return (row) => { - return _.omit(row, omissions); + let result = _.omit(row, omissions); + if (metaOmissions.length) { + result = omitNestedMeta(result, metaOmissions); + } + return result; }; }; @@ -67,14 +82,14 @@ const omitRow = (omissions) => { * @param {Array} omissions * @returns {Function} */ -const omitRows = (omissions) => { +const omitRows = (omissions, metaOmissions = []) => { /** * @param {Array} rows * @returns {Object} */ return (rows) => { rows.forEach((row, idx) => { - rows[idx] = _.omit(row, omissions); + rows[idx] = omitRow(omissions, metaOmissions)(row); }); return rows; }; diff --git a/backend/migrations/20260603120000_credentials.js b/backend/migrations/20260603120000_credentials.js new file mode 100644 index 0000000000..5a3d92f19f --- /dev/null +++ b/backend/migrations/20260603120000_credentials.js @@ -0,0 +1,41 @@ +import { migrate as logger } from "../logger.js"; + +const migrateName = "credentials"; + +const up = (knex) => { + logger.info(`[${migrateName}] Migrating Up...`); + + return knex.schema + .createTable("credential", (table) => { + table.increments().primary(); + table.dateTime("created_on").notNull(); + table.dateTime("modified_on").notNull(); + table.integer("owner_user_id").notNull().unsigned(); + table.integer("is_deleted").notNull().unsigned().defaultTo(0); + table.string("name", 255).notNull(); + table.string("dns_provider", 100).notNull(); + table.string("storage_path", 255).notNull(); + table.string("encryption_key_id", 32).notNull().defaultTo("v1"); + table.dateTime("last_used_at").nullable(); + }) + .then(() => { + logger.info(`[${migrateName}] credential table created`); + return knex.schema.table("user_permission", (table) => { + table.string("credentials", 20).notNull().defaultTo("manage"); + }); + }) + .then(() => { + logger.info(`[${migrateName}] user_permission.credentials column added`); + }); +}; + +const down = (knex) => { + logger.info(`[${migrateName}] Migrating Down...`); + return knex.schema + .table("user_permission", (table) => { + table.dropColumn("credentials"); + }) + .then(() => knex.schema.dropTableIfExists("credential")); +}; + +export { up, down }; diff --git a/backend/migrations/20260603120100_automation.js b/backend/migrations/20260603120100_automation.js new file mode 100644 index 0000000000..34c6157c91 --- /dev/null +++ b/backend/migrations/20260603120100_automation.js @@ -0,0 +1,65 @@ +import { migrate as logger } from "../logger.js"; + +const migrateName = "automation"; + +const up = (knex) => { + logger.info(`[${migrateName}] Migrating Up...`); + + return knex.schema + .createTable("api_key", (table) => { + table.increments().primary(); + table.dateTime("created_on").notNull(); + table.dateTime("modified_on").notNull(); + table.integer("owner_user_id").notNull().unsigned(); + table.integer("is_deleted").notNull().unsigned().defaultTo(0); + table.integer("is_revoked").notNull().unsigned().defaultTo(0); + table.string("name", 255).notNull(); + table.string("key_prefix", 16).notNull(); + table.string("key_hash", 255).notNull(); + table.json("permissions").notNull(); + table.dateTime("expires_on").nullable(); + table.dateTime("last_used_at").nullable(); + }) + .then(() => { + logger.info(`[${migrateName}] api_key table created`); + return knex.schema.createTable("job", (table) => { + table.increments().primary(); + table.dateTime("created_on").notNull(); + table.dateTime("modified_on").notNull(); + table.integer("owner_user_id").notNull().unsigned(); + table.string("type", 64).notNull(); + table.string("status", 32).notNull(); + table.json("payload").notNull(); + table.json("result").nullable(); + table.text("error").nullable(); + table.dateTime("finished_on").nullable(); + }); + }) + .then(() => { + logger.info(`[${migrateName}] job table created`); + return knex.schema.createTable("webhook_endpoint", (table) => { + table.increments().primary(); + table.dateTime("created_on").notNull(); + table.dateTime("modified_on").notNull(); + table.integer("owner_user_id").notNull().unsigned(); + table.integer("is_deleted").notNull().unsigned().defaultTo(0); + table.integer("is_enabled").notNull().unsigned().defaultTo(1); + table.string("name", 255).notNull(); + table.string("url", 2048).notNull(); + table.string("secret_path", 255).notNull(); + table.json("events").notNull(); + }); + }) + .then(() => { + logger.info(`[${migrateName}] webhook_endpoint table created`); + }); +}; + +const down = (knex) => { + return knex.schema + .dropTableIfExists("webhook_endpoint") + .then(() => knex.schema.dropTableIfExists("job")) + .then(() => knex.schema.dropTableIfExists("api_key")); +}; + +export { up, down }; diff --git a/backend/migrations/20260603120200_credential_providers.js b/backend/migrations/20260603120200_credential_providers.js new file mode 100644 index 0000000000..414c95cc32 --- /dev/null +++ b/backend/migrations/20260603120200_credential_providers.js @@ -0,0 +1,27 @@ +import { migrate as logger } from "../logger.js"; + +const migrateName = "credential_providers"; + +const up = (knex) => { + logger.info(`[${migrateName}] Migrating Up...`); + + return knex.schema.createTable("credential_provider", (table) => { + table.increments().primary(); + table.dateTime("created_on").notNull(); + table.dateTime("modified_on").notNull(); + table.integer("owner_user_id").notNull().unsigned(); + table.integer("is_deleted").notNull().unsigned().defaultTo(0); + table.string("name", 255).notNull(); + table.string("type", 32).notNull(); + table.string("oidc_issuer", 2048).nullable(); + table.string("oidc_client_id", 512).nullable(); + table.string("oidc_client_secret_path", 255).nullable(); + table.string("oidc_audience", 512).nullable(); + table.string("oidc_scope", 512).nullable(); + table.json("meta").notNull(); + }); +}; + +const down = (knex) => knex.schema.dropTableIfExists("credential_provider"); + +export { up, down }; diff --git a/backend/models/api_key.js b/backend/models/api_key.js new file mode 100644 index 0000000000..47cf6b3220 --- /dev/null +++ b/backend/models/api_key.js @@ -0,0 +1,30 @@ +import { Model } from "objection"; +import db from "../db.js"; +import now from "./now_helper.js"; + +Model.knex(db()); + +class ApiKey extends Model { + $beforeInsert() { + this.created_on = now(); + this.modified_on = now(); + } + + $beforeUpdate() { + this.modified_on = now(); + } + + static get name() { + return "ApiKey"; + } + + static get tableName() { + return "api_key"; + } + + static get jsonAttributes() { + return ["permissions"]; + } +} + +export default ApiKey; diff --git a/backend/models/credential.js b/backend/models/credential.js new file mode 100644 index 0000000000..475e6f5d3d --- /dev/null +++ b/backend/models/credential.js @@ -0,0 +1,26 @@ +import { Model } from "objection"; +import db from "../db.js"; +import now from "./now_helper.js"; + +Model.knex(db()); + +class Credential extends Model { + $beforeInsert() { + this.created_on = now(); + this.modified_on = now(); + } + + $beforeUpdate() { + this.modified_on = now(); + } + + static get name() { + return "Credential"; + } + + static get tableName() { + return "credential"; + } +} + +export default Credential; diff --git a/backend/models/credential_provider.js b/backend/models/credential_provider.js new file mode 100644 index 0000000000..43b428e3b7 --- /dev/null +++ b/backend/models/credential_provider.js @@ -0,0 +1,33 @@ +import { Model } from "objection"; +import db from "../db.js"; +import now from "./now_helper.js"; + +Model.knex(db()); + +class CredentialProvider extends Model { + $beforeInsert() { + this.created_on = now(); + this.modified_on = now(); + if (typeof this.meta === "undefined") { + this.meta = {}; + } + } + + $beforeUpdate() { + this.modified_on = now(); + } + + static get name() { + return "CredentialProvider"; + } + + static get tableName() { + return "credential_provider"; + } + + static get jsonAttributes() { + return ["meta"]; + } +} + +export default CredentialProvider; diff --git a/backend/models/job.js b/backend/models/job.js new file mode 100644 index 0000000000..a348f0767b --- /dev/null +++ b/backend/models/job.js @@ -0,0 +1,30 @@ +import { Model } from "objection"; +import db from "../db.js"; +import now from "./now_helper.js"; + +Model.knex(db()); + +class Job extends Model { + $beforeInsert() { + this.created_on = now(); + this.modified_on = now(); + } + + $beforeUpdate() { + this.modified_on = now(); + } + + static get name() { + return "Job"; + } + + static get tableName() { + return "job"; + } + + static get jsonAttributes() { + return ["payload", "result"]; + } +} + +export default Job; diff --git a/backend/models/webhook_endpoint.js b/backend/models/webhook_endpoint.js new file mode 100644 index 0000000000..46379d2230 --- /dev/null +++ b/backend/models/webhook_endpoint.js @@ -0,0 +1,30 @@ +import { Model } from "objection"; +import db from "../db.js"; +import now from "./now_helper.js"; + +Model.knex(db()); + +class WebhookEndpoint extends Model { + $beforeInsert() { + this.created_on = now(); + this.modified_on = now(); + } + + $beforeUpdate() { + this.modified_on = now(); + } + + static get name() { + return "WebhookEndpoint"; + } + + static get tableName() { + return "webhook_endpoint"; + } + + static get jsonAttributes() { + return ["events"]; + } +} + +export default WebhookEndpoint; diff --git a/backend/package-lock.json b/backend/package-lock.json new file mode 100644 index 0000000000..2bb993cf31 --- /dev/null +++ b/backend/package-lock.json @@ -0,0 +1,4390 @@ +{ + "name": "nginx-proxy-manager", + "version": "3.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "nginx-proxy-manager", + "version": "3.0.0", + "license": "MIT", + "dependencies": { + "@apidevtools/json-schema-ref-parser": "^15.3.5", + "ajv": "^8.20.0", + "archiver": "^8.0.0", + "batchflow": "^0.4.0", + "bcrypt": "^6.0.0", + "better-sqlite3": "^12.10.0", + "body-parser": "^2.2.2", + "chalk": "5.6.2", + "compression": "^1.8.1", + "express": "^5.2.1", + "express-fileupload": "^1.5.2", + "gravatar": "^1.8.2", + "jsonwebtoken": "^9.0.3", + "knex": "3.2.10", + "liquidjs": "10.27.0", + "lodash": "^4.18.1", + "moment": "^2.30.1", + "mysql2": "^3.22.3", + "node-rsa": "^1.1.1", + "objection": "3.1.5", + "otplib": "^13.4.0", + "path": "^0.12.7", + "pg": "^8.21.0", + "proxy-agent": "^8.0.1", + "signale": "1.4.0", + "sqlite3": "^6.0.1", + "temp-write": "^6.0.1" + }, + "devDependencies": { + "@apidevtools/swagger-parser": "^12.1.0", + "@biomejs/biome": "^2.4.15", + "nodemon": "^3.1.14" + } + }, + "node_modules/@apidevtools/json-schema-ref-parser": { + "version": "15.3.5", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-15.3.5.tgz", + "integrity": "sha512-orNOYXw3hYXxxisXMldjzjBzqqTLBPbwOtHg7ovBPvfBHDue1qM9YJENZ3W2BQuS+7z4ThogMbEzEsov57Itkg==", + "license": "MIT", + "dependencies": { + "js-yaml": "^4.1.1" + }, + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "@types/json-schema": "^7.0.15" + } + }, + "node_modules/@apidevtools/openapi-schemas": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz", + "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/@apidevtools/swagger-methods": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", + "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@apidevtools/swagger-parser": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-12.1.0.tgz", + "integrity": "sha512-e5mJoswsnAX0jG+J09xHFYQXb/bUc5S3pLpMxUuRUA2H8T2kni3yEoyz2R3Dltw5f4A6j6rPNMpWTK+iVDFlng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@apidevtools/json-schema-ref-parser": "14.0.1", + "@apidevtools/openapi-schemas": "^2.1.0", + "@apidevtools/swagger-methods": "^3.0.2", + "ajv": "^8.17.1", + "ajv-draft-04": "^1.0.0", + "call-me-maybe": "^1.0.2" + }, + "peerDependencies": { + "openapi-types": ">=7" + } + }, + "node_modules/@apidevtools/swagger-parser/node_modules/@apidevtools/json-schema-ref-parser": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-14.0.1.tgz", + "integrity": "sha512-Oc96zvmxx1fqoSEdUmfmvvb59/KDOnUoJ7s2t7bISyAn0XEz57LCCw8k2Y4Pf3mwKaZLMciESALORLgfe2frCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.15", + "js-yaml": "^4.1.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/philsturgeon" + } + }, + "node_modules/@biomejs/biome": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.4.15.tgz", + "integrity": "sha512-j5VH3a/h/HXTKBM50MDMxRCzkeLv9S2XJcW2WgnZT1+xyisi+0bISrXR82gCX+8S9lvK0skEvHJRN+3Ktr2hlw==", + "dev": true, + "license": "MIT OR Apache-2.0", + "bin": { + "biome": "bin/biome" + }, + "engines": { + "node": ">=14.21.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/biome" + }, + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "2.4.15", + "@biomejs/cli-darwin-x64": "2.4.15", + "@biomejs/cli-linux-arm64": "2.4.15", + "@biomejs/cli-linux-arm64-musl": "2.4.15", + "@biomejs/cli-linux-x64": "2.4.15", + "@biomejs/cli-linux-x64-musl": "2.4.15", + "@biomejs/cli-win32-arm64": "2.4.15", + "@biomejs/cli-win32-x64": "2.4.15" + } + }, + "node_modules/@biomejs/cli-darwin-arm64": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.4.15.tgz", + "integrity": "sha512-rF3PPqLq1yoST79zaQbDjVJwsuIeci/O+9bgNmC5QpgOqz6aqYuzA4abyAGx+mgyiDXn4A049xAN8gijbuR1Qg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-darwin-x64": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.4.15.tgz", + "integrity": "sha512-/5KHXYMfSJs1fNXiX30xFtI8JcCFV6zaVVLxOa0M2sfqBKHkpQhRTv94yxQWxeTY2lzo2OuTlNvPC+hDQt2wcQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.4.15.tgz", + "integrity": "sha512-owaAMZD/T4LrD0ELNCk0Km3qrRHuM0X6EAyVE1FSqGY0rbLoiDLrO4Us2tllm6cAeB2Ioa9C2C08NZPdr8+0Ug==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64-musl": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.4.15.tgz", + "integrity": "sha512-ZPcxznxm0pogHBLZhYntyR3sR+MrZjqJIKEr7ZqVen0Rl+P/4upVmfYXjftizi9RoqZntg33fv/1fbdhbYXpEQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.4.15.tgz", + "integrity": "sha512-0jj7THz12GbUOLmMibktK6DZjqz2zV64KFxyBtcFTKPiiOIY0a7vns1elpO1dERvxpsZ5ik0oFfz0oGwFde1+g==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64-musl": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.4.15.tgz", + "integrity": "sha512-CNq/9W38SYSH023lfcQ4KKU8K0YX8T//FZUhcgtMMRABDojx5XsMV7jlweAvGSl389wJQB29Qo6Zb/a+jdvt+w==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-arm64": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.4.15.tgz", + "integrity": "sha512-ouhkYdlhp/1GghEJPdWwD/Vi3gQ1nFxuSpMolWsbq3Lsq3QUR4jl6UdhhscdCugKU5vOEuMiJhvKj66O0OCq+w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.4.15.tgz", + "integrity": "sha512-zBrGq5mx5wwpnow4+2BxUvleDM+GNd4sLbPaMapsSLQLD0NGRCquqPBTgN+7XkUteHvj7M+BstuI8tmnV7+HgQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@noble/hashes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz", + "integrity": "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@otplib/core": { + "version": "13.4.0", + "resolved": "https://registry.npmjs.org/@otplib/core/-/core-13.4.0.tgz", + "integrity": "sha512-JqOGcvZQi2wIkEQo8f3/iAjstavpXy6gouIDMHygjNuH6Q0FjbHOiXMdcE94RwfgDNMABhzwUmvaPsxvgm9NYw==", + "license": "MIT" + }, + "node_modules/@otplib/hotp": { + "version": "13.4.0", + "resolved": "https://registry.npmjs.org/@otplib/hotp/-/hotp-13.4.0.tgz", + "integrity": "sha512-MJjE0x06mn2ptymz5qZmQveb+vWFuaIftqE0b5/TZZqUOK7l97cV8lRTmid5BpAQMwJDNLW6RnYxGeCRiNdekw==", + "license": "MIT", + "dependencies": { + "@otplib/core": "13.4.0", + "@otplib/uri": "13.4.0" + } + }, + "node_modules/@otplib/plugin-base32-scure": { + "version": "13.4.0", + "resolved": "https://registry.npmjs.org/@otplib/plugin-base32-scure/-/plugin-base32-scure-13.4.0.tgz", + "integrity": "sha512-/t9YWJmMbB8bF5z8mXrBZc2FXBe8B/3hG5FhWr9K8cFwFhyxScbPysmZe8s1UTzSA6N+s8Uv8aIfCtVXPNjJWw==", + "license": "MIT", + "dependencies": { + "@otplib/core": "13.4.0", + "@scure/base": "^2.0.0" + } + }, + "node_modules/@otplib/plugin-crypto-noble": { + "version": "13.4.0", + "resolved": "https://registry.npmjs.org/@otplib/plugin-crypto-noble/-/plugin-crypto-noble-13.4.0.tgz", + "integrity": "sha512-KrvE4m7Zv+TT1944HzgqFJWJpKb6AyoxDbvhPStmBqdMlv5Gekb80d66cuFRL08kkPgJ5gXUSb5SFpYeB+bACg==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "^2.0.1", + "@otplib/core": "13.4.0" + } + }, + "node_modules/@otplib/totp": { + "version": "13.4.0", + "resolved": "https://registry.npmjs.org/@otplib/totp/-/totp-13.4.0.tgz", + "integrity": "sha512-dK+vl0f0ekzf6mCENRI9AKS2NJUC7OjI3+X8e7QSnhQ2WM7I+i4PGpb3QxKi5hxjTtwVuoZwXR2CFtXdcRtNdQ==", + "license": "MIT", + "dependencies": { + "@otplib/core": "13.4.0", + "@otplib/hotp": "13.4.0", + "@otplib/uri": "13.4.0" + } + }, + "node_modules/@otplib/uri": { + "version": "13.4.0", + "resolved": "https://registry.npmjs.org/@otplib/uri/-/uri-13.4.0.tgz", + "integrity": "sha512-x1ozBa5bPbdZCrrTL/HK21qchiK7jYElTu+0ft22abeEhiLYgH1+SIULvOcVk3CK8YwF4kdcidvkq4ciejucJA==", + "license": "MIT", + "dependencies": { + "@otplib/core": "13.4.0" + } + }, + "node_modules/@scure/base": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-2.0.0.tgz", + "integrity": "sha512-3E1kpuZginKkek01ovG8krQ0Z44E3DHPjc5S2rjJw9lZn3KSQOs8S7wqikF/AH7iRanHypj85uGyxk0XAyC37w==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "25.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.1.tgz", + "integrity": "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==", + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": ">=7.24.0 <7.24.7" + } + }, + "node_modules/abbrev": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-4.0.0.tgz", + "integrity": "sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA==", + "license": "ISC", + "optional": true, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/agent-base": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-9.0.0.tgz", + "integrity": "sha512-TQf59BsZnytt8GdJKLPfUZ54g/iaUL2OWDSFCCvMOhsHduDQxO8xC4PNeyIkVcA5KwL2phPSv0douC0fgWzmnA==", + "license": "MIT", + "engines": { + "node": ">= 20" + } + }, + "node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-draft-04": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", + "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^8.5.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/archiver": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-8.0.0.tgz", + "integrity": "sha512-fV1orZfsnPn9BaSByR/qE67rJCLJEy2Ox5bq7nJh+jquWaNh6Sfec75kJ2T6PtdGUbPQlrVoSVCEOa5SdiTQ1g==", + "license": "MIT", + "dependencies": { + "async": "^3.2.4", + "buffer-crc32": "^1.0.0", + "is-stream": "^4.0.0", + "lazystream": "^1.0.0", + "normalize-path": "^3.0.0", + "readable-stream": "^4.0.0", + "readdir-glob": "^3.0.0", + "tar-stream": "^3.0.0", + "zip-stream": "^7.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "license": "MIT", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" + }, + "node_modules/aws-ssl-profiles": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", + "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==", + "license": "MIT", + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/b4a": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.0.tgz", + "integrity": "sha512-qRuSmNSkGQaHwNbM7J78Wwy+ghLEYF1zNrSeMxj4Kgw6y33O3mXcQ6Ie9fRvfU/YnxWkOchPXbaLb73TkIsfdg==", + "license": "Apache-2.0", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } + }, + "node_modules/balanced-match": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.3.tgz", + "integrity": "sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g==", + "license": "MIT", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/bare-events": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", + "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", + "license": "Apache-2.0", + "peerDependencies": { + "bare-abort-controller": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + } + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/basic-ftp": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.1.tgz", + "integrity": "sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/batchflow": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/batchflow/-/batchflow-0.4.0.tgz", + "integrity": "sha512-XwQQoCGPUjdLWzmpAvRNZc91wnBYuKLmj52d9LLZ1Ww06ow5RBqBt8kUmU9/3ZvPq88j7Elh3V4cEhgNKXbIlQ==" + }, + "node_modules/bcrypt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz", + "integrity": "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.3.0", + "node-gyp-build": "^4.8.4" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/better-sqlite3": { + "version": "12.10.0", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.10.0.tgz", + "integrity": "sha512-CyzaZRQKyHkB2ZInfTTl2nvT33EbDpjkLEbE8/Zck3Ll6O0qqvuGdrJ45HgtH+HykRg88ITY3AdreBGN70aBSQ==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "bindings": "^1.5.0", + "prebuild-install": "^7.1.1" + }, + "engines": { + "node": "20.x || 22.x || 23.x || 24.x || 25.x || 26.x" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "license": "MIT", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/blueimp-md5": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz", + "integrity": "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==", + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", + "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.3", + "http-errors": "^2.0.0", + "iconv-lite": "^0.7.0", + "on-finished": "^2.4.1", + "qs": "^6.14.1", + "raw-body": "^3.0.1", + "type-is": "^2.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/brace-expansion": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-crc32": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", + "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "license": "MIT" + }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/compress-commons": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-7.0.1.tgz", + "integrity": "sha512-g0S8KAD8qf4+V//pr3BfB1aBnARLXNz2Gx+jmHU0LEriUuoQUOPOulVquHKTJ8+EAIIO7fhseNDr9wK5Q9FKBQ==", + "license": "MIT", + "dependencies": { + "crc-32": "^1.2.0", + "crc32-stream": "^7.0.1", + "is-stream": "^4.0.0", + "normalize-path": "^3.0.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/content-disposition": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/crc32-stream": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-7.0.1.tgz", + "integrity": "sha512-IBWsY8xznyQrcHn8h4bC8/4ErNke5elzgG8GcqF4RFPw6aHkWWRc7Tgw6upjaTX/CT/yQgqYENkxYsTYN+hW2g==", + "license": "MIT", + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-8.0.0.tgz", + "integrity": "sha512-6UHfyCux51b8PTGDgveqtz1tvphBku5DrMKKJbFAZAJOI2zsjDpDoYE1+QGj7FOMS4BdTFNJsJiR3zEB0xH0yQ==", + "license": "MIT", + "engines": { + "node": ">= 20" + } + }, + "node_modules/db-errors": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/db-errors/-/db-errors-0.2.3.tgz", + "integrity": "sha512-OOgqgDuCavHXjYSJoV2yGhv6SeG8nk42aoCSoyXLZUH7VwFG27rxbavU1z+VrZbZjphw5UkDQwUlD21MwZpUng==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/degenerator": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-7.0.1.tgz", + "integrity": "sha512-ABErK0IefDSyHjlPH7WUEenIAX2rPPnrDcDM+TS3z3+zu9TfyKKi07BQM+8rmxpdE2y1v5fjjdoAS/x4D2U60w==", + "license": "MIT", + "dependencies": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "quickjs-wasi": "^2.2.0" + } + }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/email-validator": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/email-validator/-/email-validator-2.0.4.tgz", + "integrity": "sha512-gYCwo7kh5S3IDyZPLZf6hSS0MnZT8QmJFqYvbqlDZSbwdZlY6QZWxJ4i/6UhITOJ4XzyI647Bm2MXKCLqnJ4nQ==", + "engines": { + "node": ">4.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/events-universal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.7.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } + }, + "node_modules/exponential-backoff": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", + "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", + "license": "Apache-2.0", + "optional": true + }, + "node_modules/express": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", + "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.1", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "depd": "^2.0.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express-fileupload": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/express-fileupload/-/express-fileupload-1.5.2.tgz", + "integrity": "sha512-wxUJn2vTHvj/kZCVmc5/bJO15C7aSMyHeuXYY3geKpeKibaAoQGcEv5+sM6nHS2T7VF+QHS4hTWPiY2mKofEdg==", + "license": "MIT", + "dependencies": { + "busboy": "^1.6.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "license": "MIT" + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", + "license": "MIT", + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "license": "MIT" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "license": "MIT", + "dependencies": { + "is-property": "^1.0.2" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-uri": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-8.0.0.tgz", + "integrity": "sha512-CqtZlMKvfJeY0Zxv8wazDwXmSKmnMnsmNy8j8+wudi8EyG/pMUB1NqHc+Tv1QaNtpYsK9nOYjb7r7Ufu32RPSw==", + "license": "MIT", + "dependencies": { + "basic-ftp": "^5.2.0", + "data-uri-to-buffer": "8.0.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/getopts": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/getopts/-/getopts-2.3.0.tgz", + "integrity": "sha512-5eDf9fuSXwxBL6q5HX+dhDj+dslFGWzU5thZ9kNKUkcPtaPdatmUFKwHFrLb/uf/WpA4BHET+AX3Scl56cAjpA==", + "license": "MIT" + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "license": "MIT" + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/gravatar": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/gravatar/-/gravatar-1.8.2.tgz", + "integrity": "sha512-GdRwLM3oYpFQKy47MKuluw9hZ2gaCtiKPbDGdcDEuYDKlc8eNnW27KYL9LVbIDzEsx88WtDWQm2ClBcsgBnj6w==", + "license": "MIT", + "dependencies": { + "blueimp-md5": "^2.16.0", + "email-validator": "^2.0.4", + "querystring": "0.2.0", + "yargs": "^15.4.1" + }, + "bin": { + "gravatar": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/http-proxy-agent": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-9.0.0.tgz", + "integrity": "sha512-FcF8VhXYLQcxWCnt/cCpT2apKsRDUGeVEeMqGu4HSTu29U8Yw0TLOjdYIlDsYk3IkUh+taX4IDWpPcCqKDhCjA==", + "license": "MIT", + "dependencies": { + "agent-base": "9.0.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/https-proxy-agent": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-9.0.0.tgz", + "integrity": "sha512-/MVmHp58WkOypgFhCLk4fzpPcFQvTJ/e6LBI7irpIO2HfxUbpmYoHF+KzipzJpxxzJu7aJNWQ0xojJ/dzV2G5g==", + "license": "MIT", + "dependencies": { + "agent-base": "9.0.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true, + "license": "ISC" + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/ip-address": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", + "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", + "license": "MIT" + }, + "node_modules/is-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", + "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", + "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==", + "license": "BlueOak-1.0.0", + "optional": true, + "engines": { + "node": ">=20" + } + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/jsonwebtoken": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", + "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", + "license": "MIT", + "dependencies": { + "jws": "^4.0.1", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/knex": { + "version": "3.2.10", + "resolved": "https://registry.npmjs.org/knex/-/knex-3.2.10.tgz", + "integrity": "sha512-oypTHfrc9i72iyxaUQBKHOxhcr0xM65MPf6FpN02nimsftXwzXprIkLjfXdubvhbu4PMWLp023q8o8CYvHSuZw==", + "license": "MIT", + "dependencies": { + "colorette": "2.0.19", + "commander": "^10.0.0", + "debug": "4.3.4", + "escalade": "^3.1.1", + "esm": "^3.2.25", + "get-package-type": "^0.1.0", + "getopts": "2.3.0", + "interpret": "^2.2.0", + "lodash": "^4.18.1", + "pg-connection-string": "2.6.2", + "rechoir": "^0.8.0", + "resolve-from": "^5.0.0", + "tarn": "^3.0.2", + "tildify": "2.0.0" + }, + "bin": { + "knex": "bin/cli.js" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "pg-query-stream": "^4.14.0" + }, + "peerDependenciesMeta": { + "better-sqlite3": { + "optional": true + }, + "mysql": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-native": { + "optional": true + }, + "pg-query-stream": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "tedious": { + "optional": true + } + } + }, + "node_modules/knex/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/knex/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "license": "MIT" + }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "license": "MIT", + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/lazystream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/lazystream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/lazystream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/liquidjs": { + "version": "10.27.0", + "resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-10.27.0.tgz", + "integrity": "sha512-tw/OA59K7aIBlMKIrKlumr37fiZUheShVHXY8cVctWisgY1p9mc5hreOvlreoS0wTiwlWk14Ya7305c2a/Cg5w==", + "license": "MIT", + "dependencies": { + "commander": "^10.0.0" + }, + "bin": { + "liquid": "bin/liquid.js", + "liquidjs": "bin/liquid.js" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/liquidjs" + } + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "license": "MIT", + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "license": "MIT" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, + "node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/lru.min": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.4.tgz", + "integrity": "sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA==", + "license": "MIT", + "engines": { + "bun": ">=1.0.0", + "deno": ">=1.30.0", + "node": ">=8.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wellwelwel" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "license": "MIT" + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/mysql2": { + "version": "3.22.3", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.22.3.tgz", + "integrity": "sha512-uWWxvZSRvRhtBdh2CdcuK83YcOfPdmEeEYB069bAmPnV93QApDGVPuvCQOLjlh7tYHEWdgQPrn6kosDxHBVLkA==", + "license": "MIT", + "dependencies": { + "aws-ssl-profiles": "^1.1.2", + "denque": "^2.1.0", + "generate-function": "^2.3.1", + "iconv-lite": "^0.7.2", + "long": "^5.3.2", + "lru.min": "^1.1.4", + "named-placeholders": "^1.1.6", + "sql-escaper": "^1.3.3" + }, + "engines": { + "node": ">= 8.0" + }, + "peerDependencies": { + "@types/node": ">= 8" + } + }, + "node_modules/named-placeholders": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.6.tgz", + "integrity": "sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w==", + "license": "MIT", + "dependencies": { + "lru.min": "^1.1.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/node-abi": { + "version": "3.87.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.87.0.tgz", + "integrity": "sha512-+CGM1L1CgmtheLcBuleyYOn7NWPVu0s0EJH2C4puxgEZb9h8QpR9G2dBfZJOAUhi7VQxuBPMd0hiISWcTyiYyQ==", + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.5.0.tgz", + "integrity": "sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, + "node_modules/node-gyp": { + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-12.3.0.tgz", + "integrity": "sha512-QNcUWM+HgJplcPzBvFBZ9VXacyGZ4+VTOb80PwWR+TlVzoHbRKULNEzpRsnaoxG3Wzr7Qh7BYxGDU3CbKib2Yg==", + "license": "MIT", + "optional": true, + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "graceful-fs": "^4.2.6", + "nopt": "^9.0.0", + "proc-log": "^6.0.0", + "semver": "^7.3.5", + "tar": "^7.5.4", + "tinyglobby": "^0.2.12", + "undici": "^6.25.0", + "which": "^6.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-rsa": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/node-rsa/-/node-rsa-1.1.1.tgz", + "integrity": "sha512-Jd4cvbJMryN21r5HgxQOpMEqv+ooke/korixNNK3mGqfGJmy0M77WDDzo/05969+OkMy3XW1UuZsSmW9KQm7Fw==", + "license": "MIT", + "dependencies": { + "asn1": "^0.2.4" + } + }, + "node_modules/nodemon": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.14.tgz", + "integrity": "sha512-jakjZi93UtB3jHMWsXL68FXSAosbLfY0In5gtKq3niLSkrWznrVBzXFNOEMJUfc9+Ke7SHWoAZsiMkNP3vq6Jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^10.2.1", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nopt": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-9.0.0.tgz", + "integrity": "sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw==", + "license": "ISC", + "optional": true, + "dependencies": { + "abbrev": "^4.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/objection": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/objection/-/objection-3.1.5.tgz", + "integrity": "sha512-Hx/ipAwXSuRBbOMWFKtRsAN0yITafqXtWB4OT4Z9wED7ty1h7bOnBdhLtcNus23GwLJqcMsRWdodL2p5GwlnfQ==", + "license": "MIT", + "dependencies": { + "ajv": "^8.17.1", + "ajv-formats": "^2.1.1", + "db-errors": "^0.2.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "knex": ">=1.0.1" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/openapi-types": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/otplib": { + "version": "13.4.0", + "resolved": "https://registry.npmjs.org/otplib/-/otplib-13.4.0.tgz", + "integrity": "sha512-RUcYcRMCgRWhUE/XabRppXpUwCwaWBNHe5iPXhdvP8wwDGpGpsIf/kxX/ec3zFsOaM1Oq8lEhUqDwk6W7DHkwg==", + "license": "MIT", + "dependencies": { + "@otplib/core": "13.4.0", + "@otplib/hotp": "13.4.0", + "@otplib/plugin-base32-scure": "13.4.0", + "@otplib/plugin-crypto-noble": "13.4.0", + "@otplib/totp": "13.4.0", + "@otplib/uri": "13.4.0" + } + }, + "node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "license": "MIT", + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "license": "MIT", + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/pac-proxy-agent": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-9.0.1.tgz", + "integrity": "sha512-3ZOSpLboOlpW4yp8Cuv21KlTULRqyJ5Uuad3wXpSKFrxdNgcHEyoa22GRaZ2UlgCVuR6z+5BiavtYVvbajL/Yw==", + "license": "MIT", + "dependencies": { + "agent-base": "9.0.0", + "debug": "^4.3.4", + "get-uri": "8.0.0", + "http-proxy-agent": "9.0.0", + "https-proxy-agent": "9.0.0", + "pac-resolver": "9.0.1", + "quickjs-wasi": "^2.2.0", + "socks-proxy-agent": "10.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/pac-resolver": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-9.0.1.tgz", + "integrity": "sha512-lJbS008tmkj08VhoM8Hzuv/VE5tK9MS0OIQ/7+s0lIF+BYhiQWFYzkSpML7lXs9iBu2jfmzBTLzhe9n6BX+dYw==", + "license": "MIT", + "dependencies": { + "degenerator": "7.0.1", + "netmask": "^2.0.2" + }, + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "quickjs-wasi": "^2.2.0" + } + }, + "node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "license": "MIT", + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path": { + "version": "0.12.7", + "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", + "integrity": "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==", + "license": "MIT", + "dependencies": { + "process": "^0.11.1", + "util": "^0.10.3" + } + }, + "node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz", + "integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/pg": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.21.0.tgz", + "integrity": "sha512-AUP1EYJuHraQGsVoCQVIcM7TEJVGtDzxWtGFZd8rds9d+CCXlU5Js1rYgfLNvxy9iJrpHjGrRjoi/3BT9fRyiA==", + "license": "MIT", + "dependencies": { + "pg-connection-string": "^2.13.0", + "pg-pool": "^3.14.0", + "pg-protocol": "^1.14.0", + "pg-types": "2.2.0", + "pgpass": "1.0.5" + }, + "engines": { + "node": ">= 16.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.4.0" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-cloudflare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.4.0.tgz", + "integrity": "sha512-Vo7z/6rrQYxpNRylp4Tlob2elzbh+N/MOQbxFVWCxS7oEx6jF53GTJFxK2WWpKuBRkmiin4Mt+xofFDjx09R0A==", + "license": "MIT", + "optional": true + }, + "node_modules/pg-connection-string": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", + "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==", + "license": "MIT" + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "license": "ISC", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-pool": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.14.0.tgz", + "integrity": "sha512-gKtPkFdQPU3DksooVLi9LsjZxrsBUZIpa+7aVx+LV5pNh0KzP4Zleud2po+ConrxbuXGBJ6Hfer6hdgpIBpBaw==", + "license": "MIT", + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.14.0.tgz", + "integrity": "sha512-n5taZ1kO3s9ngDTVxsEznOqCyToTgz0FLuPq0B33COy5pPpuWJpY3/2oRBVETuOgzdqRXfWpM9HIhp2LBBT1BA==", + "license": "MIT" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "license": "MIT", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pg/node_modules/pg-connection-string": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.13.0.tgz", + "integrity": "sha512-EMnU9E2fSULdsbErBbMaXJvFeD9B4+nPcM3f+4lsiCR0BHLPrLVjv3DbyM2hgQQviKJaTWIRRTjKjWlHg3p2ig==", + "license": "MIT" + }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "license": "MIT", + "dependencies": { + "split2": "^4.1.0" + } + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.1.0.tgz", + "integrity": "sha512-C+VUP+8jis7EsQZIhDYmS5qlNtjv2yP4SNtjXK9AP1ZcTRlnSfuumaTnRfYZnYgUUYVIKqL0fRvmUGDV2fmp6g==", + "license": "MIT", + "dependencies": { + "find-up": "^2.0.0", + "load-json-file": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.1.tgz", + "integrity": "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/proc-log": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", + "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==", + "license": "ISC", + "optional": true, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-agent": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-8.0.1.tgz", + "integrity": "sha512-kccqGBqHZXR8onQhY/ganJjoO8QIKKRiFBhPOzbTZK16attzSZ/0XSmp9H7jrRxPKHjhGyx1q32lMPrJ3uLFgA==", + "license": "MIT", + "dependencies": { + "agent-base": "9.0.0", + "debug": "^4.3.4", + "http-proxy-agent": "9.0.0", + "https-proxy-agent": "9.0.0", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "9.0.1", + "proxy-from-env": "^2.0.0", + "socks-proxy-agent": "10.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true, + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/qs": { + "version": "6.15.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", + "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/quickjs-wasi": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/quickjs-wasi/-/quickjs-wasi-2.2.0.tgz", + "integrity": "sha512-zQxXmQMrEoD3S+jQdYsloq4qAuaxKFHZj6hHqOYGwB2iQZH+q9e/lf5zQPXCKOk0WJuAjzRFbO4KwHIp2D05Iw==", + "license": "MIT" + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/readdir-glob": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-3.0.0.tgz", + "integrity": "sha512-AhNB2KgKeVJr16nK9LLZbJNWnYoT23ZrumNKFDebHBdkC8KHSqWo871JAUhoWC/RtjEVdqNMFpM6qrwRbaUqpw==", + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^10.2.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/yqnn" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "license": "MIT", + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "license": "ISC" + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/serve-static": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", + "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/signale/-/signale-1.4.0.tgz", + "integrity": "sha512-iuh+gPf28RkltuJC7W5MRi6XAjTDCAPC/prJUpQoG4vIP3MJZ+GTydVnodXA7pwvTKb2cA0m9OFZW/cdWy/I/w==", + "license": "MIT", + "dependencies": { + "chalk": "^2.3.2", + "figures": "^2.0.0", + "pkg-conf": "^2.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/signale/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/signale/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/signale/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/signale/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "license": "MIT" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.7", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", + "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", + "license": "MIT", + "dependencies": { + "ip-address": "^10.0.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-10.0.0.tgz", + "integrity": "sha512-pyp2YR3mNxAMu0mGLtzs4g7O3uT4/9sQOLAKcViAkaS9fJWkud7nmaf6ZREFqQEi24IPkBcjfHjXhPTUWjo3uA==", + "license": "MIT", + "dependencies": { + "agent-base": "9.0.0", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/sql-escaper": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/sql-escaper/-/sql-escaper-1.3.3.tgz", + "integrity": "sha512-BsTCV265VpTp8tm1wyIm1xqQCS+Q9NHx2Sr+WcnUrgLrQ6yiDIvHYJV5gHxsj1lMBy2zm5twLaZao8Jd+S8JJw==", + "license": "MIT", + "engines": { + "bun": ">=1.0.0", + "deno": ">=2.0.0", + "node": ">=12.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/mysqljs/sql-escaper?sponsor=1" + } + }, + "node_modules/sqlite3": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-6.0.1.tgz", + "integrity": "sha512-X0czUUMG2tmSqJpEQa3tCuZSHKIx8PwM53vLZzKp/o6Rpy25fiVfjdbnZ988M8+O3ZWR1ih0K255VumCb3MAnQ==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "bindings": "^1.5.0", + "node-addon-api": "^8.0.0", + "prebuild-install": "^7.1.3", + "tar": "^7.5.10" + }, + "engines": { + "node": ">=20.17.0" + }, + "optionalDependencies": { + "node-gyp": "12.x" + }, + "peerDependencies": { + "node-gyp": "12.x" + }, + "peerDependenciesMeta": { + "node-gyp": { + "optional": true + } + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/streamx": { + "version": "2.23.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", + "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==", + "license": "MIT", + "dependencies": { + "events-universal": "^1.0.0", + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tar": { + "version": "7.5.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.15.tgz", + "integrity": "sha512-dzGK0boVlC4W5QFuQN1EFSl3bIDYsk7Tj40U6eIBnK2k/8ml7TZ5agbI5j5+qnoVcAA+rNtBml8SEiLxZpNqRQ==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC" + }, + "node_modules/tar-fs/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/tar-fs/node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "license": "MIT", + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "node_modules/tarn": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tarn/-/tarn-3.0.2.tgz", + "integrity": "sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/temp-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", + "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==", + "license": "MIT", + "engines": { + "node": ">=14.16" + } + }, + "node_modules/temp-write": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/temp-write/-/temp-write-6.0.1.tgz", + "integrity": "sha512-6bj9LlNld+knzEOQvnZK6YxiPF+foOUjvG/WoWj1/Mt9c6f2kQCPsh8KZ+NyTk0AejubTQSPpx2alcswE1bF8g==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.11", + "is-stream": "^4.0.1", + "temp-dir": "^3.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/text-decoder": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.7.tgz", + "integrity": "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==", + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, + "node_modules/tildify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-2.0.0.tgz", + "integrity": "sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "license": "MIT", + "optional": true, + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "dev": true, + "license": "ISC", + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true, + "license": "MIT" + }, + "node_modules/undici": { + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.25.0.tgz", + "integrity": "sha512-ZgpWDC5gmNiuY9CnLVXEH8rl50xhRCuLNA97fAUnKi8RRuV4E6KG31pDTsLVUKnohJE0I3XDrTeEydAXRw47xg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18.17" + } + }, + "node_modules/undici-types": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", + "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", + "license": "MIT", + "peer": true + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "license": "MIT", + "dependencies": { + "inherits": "2.0.3" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/util/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "license": "ISC" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/which": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", + "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", + "license": "ISC", + "optional": true, + "dependencies": { + "isexe": "^4.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "license": "ISC" + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "license": "ISC" + }, + "node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/zip-stream": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-7.0.5.tgz", + "integrity": "sha512-dSvYKdvLsAHCDqPOhIwk/q5CvuWtTB3Dgpoe0uVEFjTzIOAmsQpprX25InCvrvJsirEbu1OHyy67n/kAj1Sw/w==", + "license": "MIT", + "dependencies": { + "compress-commons": "^7.0.0", + "normalize-path": "^3.0.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + } + } +} diff --git a/backend/routes/api-keys.js b/backend/routes/api-keys.js new file mode 100644 index 0000000000..5bdadc1ab0 --- /dev/null +++ b/backend/routes/api-keys.js @@ -0,0 +1,68 @@ +import express from "express"; +import internalApiKey from "../internal/api-key.js"; +import jwtdecode from "../lib/express/jwt-decode.js"; +import validator from "../lib/validator/index.js"; +import { debug, express as logger } from "../logger.js"; + +const router = express.Router({ + caseSensitive: true, + strict: true, + mergeParams: true, +}); + +router + .route("/") + .options((_, res) => { + res.sendStatus(204); + }) + .all(jwtdecode()) + .get(async (req, res, next) => { + try { + const rows = await internalApiKey.getAll(res.locals.access); + res.status(200).json(rows); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }) + .post(async (req, res, next) => { + try { + const payload = await validator( + { + additionalProperties: false, + required: ["name"], + properties: { + name: { type: "string", minLength: 1, maxLength: 255 }, + permissions: { type: "object" }, + expires_on: { type: ["string", "null"] }, + }, + }, + req.body, + ); + const result = await internalApiKey.create(res.locals.access, payload); + res.status(201).json(result); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }); + +router + .route("/:api_key_id") + .options((_, res) => { + res.sendStatus(204); + }) + .all(jwtdecode()) + .delete(async (req, res, next) => { + try { + await internalApiKey.delete(res.locals.access, { + id: Number.parseInt(req.params.api_key_id, 10), + }); + res.status(200).send(true); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }); + +export default router; diff --git a/backend/routes/audit-log.js b/backend/routes/audit-log.js index c40b1628d8..2c419783ad 100644 --- a/backend/routes/audit-log.js +++ b/backend/routes/audit-log.js @@ -45,7 +45,7 @@ router }, ); const rows = await internalAuditLog.getAll(res.locals.access, data.expand, data.query); - res.status(200).send(rows); + res.status(200).json(rows); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -97,7 +97,7 @@ router id: data.event_id, expand: data.expand, }); - res.status(200).send(item); + res.status(200).json(item); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); diff --git a/backend/routes/ci.js b/backend/routes/ci.js index a6f8be03a2..c63ade6699 100644 --- a/backend/routes/ci.js +++ b/backend/routes/ci.js @@ -24,7 +24,7 @@ router // Return all certbot plugins .get(async (_req, res, _next) => { - res.status(200).send(dnsPlugins); + res.status(200).json(dnsPlugins); }); /** @@ -39,10 +39,9 @@ router // Install a certbot plugin .post(async (req, res, next) => { try { - const pluginName = req.params.plugin; - // check if plugin exists - if (!dnsPlugins[pluginName]) { - return res.status(404).send({ + const pluginName = String(req.params.plugin ?? ""); + if (!/^[a-z0-9_-]+$/i.test(pluginName) || !Object.hasOwn(dnsPlugins, pluginName)) { + return res.status(404).json({ error: "Plugin not found", }); } diff --git a/backend/routes/credential-providers.js b/backend/routes/credential-providers.js new file mode 100644 index 0000000000..f98e38f05f --- /dev/null +++ b/backend/routes/credential-providers.js @@ -0,0 +1,135 @@ +import express from "express"; +import internalCredentialProvider from "../internal/credential-provider.js"; +import jwtdecode from "../lib/express/jwt-decode.js"; +import validator from "../lib/validator/index.js"; +import { debug, express as logger } from "../logger.js"; + +const router = express.Router({ + caseSensitive: true, + strict: true, + mergeParams: true, +}); + +const providerBodySchema = { + additionalProperties: false, + properties: { + name: { type: "string", minLength: 1 }, + type: { type: "string", enum: ["vault", "aws", "azure", "infisical", "http"] }, + oidc_issuer: { type: "string" }, + oidc_client_id: { type: "string" }, + oidc_client_secret: { type: "string" }, + oidc_audience: { type: "string" }, + oidc_scope: { type: "string" }, + meta: { type: "object" }, + }, +}; + +router + .route("/") + .options((_, res) => res.sendStatus(204)) + .all(jwtdecode()) + .get(async (req, res, next) => { + try { + res.status(200).send(await internalCredentialProvider.getAll(res.locals.access)); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }) + .post(async (req, res, next) => { + try { + const payload = await validator( + { ...providerBodySchema, required: ["name", "type"] }, + req.body, + ); + const result = await internalCredentialProvider.create(res.locals.access, payload); + res.status(201).json(result); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }); + +router + .route("/:provider_id") + .options((_, res) => res.sendStatus(204)) + .all(jwtdecode()) + .get(async (req, res, next) => { + try { + const result = await internalCredentialProvider.get(res.locals.access, { + id: Number.parseInt(req.params.provider_id, 10), + }); + res.status(200).json(result); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }) + .put(async (req, res, next) => { + try { + const payload = await validator(providerBodySchema, req.body); + payload.id = Number.parseInt(req.params.provider_id, 10); + const result = await internalCredentialProvider.update(res.locals.access, payload); + res.status(200).json(result); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }) + .delete(async (req, res, next) => { + try { + await internalCredentialProvider.delete(res.locals.access, { + id: Number.parseInt(req.params.provider_id, 10), + }); + res.status(200).send(true); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }); + +router + .route("/:provider_id/test") + .options((_, res) => res.sendStatus(204)) + .all(jwtdecode()) + .post(async (req, res, next) => { + try { + const result = await internalCredentialProvider.test(res.locals.access, { + id: Number.parseInt(req.params.provider_id, 10), + }); + res.status(200).json(result); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }); + +router + .route("/:provider_id/test-resolve") + .options((_, res) => res.sendStatus(204)) + .all(jwtdecode()) + .post(async (req, res, next) => { + try { + const body = await validator( + { + additionalProperties: false, + required: ["path"], + properties: { + path: { type: "string", minLength: 1 }, + field: { type: "string" }, + }, + }, + req.body, + ); + const result = await internalCredentialProvider.testResolve(res.locals.access, { + id: Number.parseInt(req.params.provider_id, 10), + ...body, + }); + res.status(200).json(result); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }); + +export default router; diff --git a/backend/routes/credentials.js b/backend/routes/credentials.js new file mode 100644 index 0000000000..90a85ef498 --- /dev/null +++ b/backend/routes/credentials.js @@ -0,0 +1,122 @@ +import express from "express"; +import internalCredential from "../internal/credential.js"; +import jwtdecode from "../lib/express/jwt-decode.js"; +import apiValidator from "../lib/validator/api.js"; +import validator from "../lib/validator/index.js"; +import { debug, express as logger } from "../logger.js"; +import { getValidationSchema } from "../schema/index.js"; + +const router = express.Router({ + caseSensitive: true, + strict: true, + mergeParams: true, +}); + +router + .route("/") + .options((_, res) => { + res.sendStatus(204); + }) + .all(jwtdecode()) + .get(async (req, res, next) => { + try { + const rows = await internalCredential.getAll(res.locals.access); + res.status(200).json(rows); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }) + .post(async (req, res, next) => { + try { + const payload = await apiValidator(getValidationSchema("/credentials", "post"), req.body); + const result = await internalCredential.create(res.locals.access, payload); + res.status(201).json(result); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }); + +router + .route("/migrate-legacy") + .options((_, res) => res.sendStatus(204)) + .all(jwtdecode()) + .post(async (req, res, next) => { + try { + const payload = await validator( + { + additionalProperties: false, + properties: { + dry_run: { type: "boolean" }, + }, + }, + req.body || {}, + ); + const result = await internalCredential.migrateLegacy(res.locals.access, payload); + res.status(200).json(result); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }); + +router + .route("/:credential_id") + .options((_, res) => { + res.sendStatus(204); + }) + .all(jwtdecode()) + .get(async (req, res, next) => { + try { + const result = await internalCredential.get(res.locals.access, { + id: Number.parseInt(req.params.credential_id, 10), + }); + res.status(200).json(result); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }) + .put(async (req, res, next) => { + try { + const payload = await apiValidator(getValidationSchema("/credentials/{credentialID}", "put"), req.body); + payload.id = Number.parseInt(req.params.credential_id, 10); + const result = await internalCredential.update(res.locals.access, payload); + res.status(200).json(result); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }) + .delete(async (req, res, next) => { + try { + await internalCredential.delete(res.locals.access, { + id: Number.parseInt(req.params.credential_id, 10), + }); + res.status(200).send(true); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }); + +router + .route("/:credential_id/test") + .options((_, res) => { + res.sendStatus(204); + }) + .all(jwtdecode()) + .post(async (req, res, next) => { + try { + const result = await internalCredential.test(res.locals.access, { + id: Number.parseInt(req.params.credential_id, 10), + }); + res.status(200).json(result); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }); + +export default router; diff --git a/backend/routes/jobs.js b/backend/routes/jobs.js new file mode 100644 index 0000000000..dd4bb1cb55 --- /dev/null +++ b/backend/routes/jobs.js @@ -0,0 +1,45 @@ +import express from "express"; +import internalJob from "../internal/job.js"; +import jwtdecode from "../lib/express/jwt-decode.js"; +import { debug, express as logger } from "../logger.js"; + +const router = express.Router({ + caseSensitive: true, + strict: true, + mergeParams: true, +}); + +router + .route("/") + .options((_, res) => res.sendStatus(204)) + .all(jwtdecode()) + .get(async (req, res, next) => { + try { + const limit = req.query.limit ? Number.parseInt(req.query.limit, 10) : 50; + const rows = await internalJob.getAll(res.locals.access, { limit }); + res.status(200).json(rows); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }); + +router + .route("/:job_id") + .options((_, res) => { + res.sendStatus(204); + }) + .all(jwtdecode()) + .get(async (req, res, next) => { + try { + const result = await internalJob.get(res.locals.access, { + id: Number.parseInt(req.params.job_id, 10), + }); + res.status(200).json(result); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }); + +export default router; diff --git a/backend/routes/main.js b/backend/routes/main.js index a308ea6179..511127d4a0 100644 --- a/backend/routes/main.js +++ b/backend/routes/main.js @@ -8,6 +8,11 @@ import auditLogRoutes from "./audit-log.js"; import ciRoutes from "./ci.js"; import accessListsRoutes from "./nginx/access_lists.js"; import certificatesHostsRoutes from "./nginx/certificates.js"; +import apiKeysRoutes from "./api-keys.js"; +import credentialProvidersRoutes from "./credential-providers.js"; +import credentialsRoutes from "./credentials.js"; +import jobsRoutes from "./jobs.js"; +import webhooksRoutes from "./webhooks.js"; import deadHostsRoutes from "./nginx/dead_hosts.js"; import proxyHostsRoutes from "./nginx/proxy_hosts.js"; import redirectionHostsRoutes from "./nginx/redirection_hosts.js"; @@ -32,16 +37,20 @@ router.use(logRequest); * GET /api */ router.get("/", async (_, res /*, next*/) => { - const version = pjson.version.split("-").shift().split("."); + const parts = pjson.version.split("-").shift().split("."); + const major = Number.parseInt(parts[0], 10); + const minor = Number.parseInt(parts[1], 10); + const revision = Number.parseInt(parts[2], 10); const setup = await isSetup(); - res.status(200).send({ + res.status(200).json({ status: "OK", setup, version: { - major: Number.parseInt(version.shift(), 10), - minor: Number.parseInt(version.shift(), 10), - revision: Number.parseInt(version.shift(), 10), + major, + minor, + revision, + string: `v${major}.${minor}.${revision}`, }, }); }); @@ -59,6 +68,11 @@ router.use("/nginx/dead-hosts", deadHostsRoutes); router.use("/nginx/streams", streamsRoutes); router.use("/nginx/access-lists", accessListsRoutes); router.use("/nginx/certificates", certificatesHostsRoutes); +router.use("/credentials", credentialsRoutes); +router.use("/credential-providers", credentialProvidersRoutes); +router.use("/api-keys", apiKeysRoutes); +router.use("/jobs", jobsRoutes); +router.use("/webhooks", webhooksRoutes); // Only include CI routes if we're in a CI environment if (isCI()) { diff --git a/backend/routes/nginx/access_lists.js b/backend/routes/nginx/access_lists.js index 9dfcf7ec31..7c4a2f3aca 100644 --- a/backend/routes/nginx/access_lists.js +++ b/backend/routes/nginx/access_lists.js @@ -47,7 +47,7 @@ router }, ); const rows = await internalAccessList.getAll(res.locals.access, data.expand, data.query); - res.status(200).send(rows); + res.status(200).json(rows); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -63,7 +63,7 @@ router try { const payload = await apiValidator(getValidationSchema("/nginx/access-lists", "post"), req.body); const result = await internalAccessList.create(res.locals.access, payload); - res.status(201).send(result); + res.status(201).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -111,7 +111,7 @@ router id: Number.parseInt(data.list_id, 10), expand: data.expand, }); - res.status(200).send(row); + res.status(200).json(row); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -128,7 +128,7 @@ router const payload = await apiValidator(getValidationSchema("/nginx/access-lists/{listID}", "put"), req.body); payload.id = Number.parseInt(req.params.list_id, 10); const result = await internalAccessList.update(res.locals.access, payload); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -145,7 +145,7 @@ router const result = await internalAccessList.delete(res.locals.access, { id: Number.parseInt(req.params.list_id, 10), }); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); diff --git a/backend/routes/nginx/certificates.js b/backend/routes/nginx/certificates.js index 99f429b446..6226f00413 100644 --- a/backend/routes/nginx/certificates.js +++ b/backend/routes/nginx/certificates.js @@ -1,6 +1,7 @@ import express from "express"; import dnsPlugins from "../../certbot/dns-plugins.json" with { type: "json" }; import internalCertificate from "../../internal/certificate.js"; +import internalJob from "../../internal/job.js"; import errs from "../../lib/error.js"; import jwtdecode from "../../lib/express/jwt-decode.js"; import apiValidator from "../../lib/validator/api.js"; @@ -56,7 +57,7 @@ router data.expand, data.query, ); - res.status(200).send(rows); + res.status(200).json(rows); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -75,11 +76,15 @@ router req.body, ); req.setTimeout(900000); // 15 minutes timeout - const result = await internalCertificate.create( - res.locals.access, - payload, - ); - res.status(201).send(result); + + if (req.query.async === "true") { + const job = await internalJob.runCertificateCreate(res.locals.access, payload); + res.status(202).json({ job_id: job.id, status: job.status }); + return; + } + + const result = await internalCertificate.create(res.locals.access, payload); + res.status(201).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -113,7 +118,7 @@ router })); clean.sort((a, b) => a.name.localeCompare(b.name)); - res.status(200).send(clean); + res.status(200).json(clean); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -149,7 +154,7 @@ router res.locals.access, payload, ); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -175,7 +180,7 @@ router */ .post(async (req, res, next) => { if (!req.files) { - res.status(400).send({ error: "No files were uploaded" }); + res.status(400).json({ error: "No files were uploaded" }); return; } @@ -183,7 +188,7 @@ router const result = await internalCertificate.validate({ files: req.files, }); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -234,7 +239,37 @@ router id: Number.parseInt(data.certificate_id, 10), expand: data.expand, }); - res.status(200).send(row); + res.status(200).json(row); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }) + + /** + * PUT /api/nginx/certificates/123 + * + * Update an existing certificate + */ + .put(async (req, res, next) => { + try { + const payload = await validator( + { + additionalProperties: false, + properties: { + nice_name: { type: "string" }, + domain_names: { + type: "array", + items: { type: "string" }, + }, + meta: { type: "object" }, + }, + }, + req.body, + ); + payload.id = Number.parseInt(req.params.certificate_id, 10); + const result = await internalCertificate.update(res.locals.access, payload); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -244,14 +279,14 @@ router /** * DELETE /api/nginx/certificates/123 * - * Update and existing certificate + * Delete an existing certificate */ .delete(async (req, res, next) => { try { const result = await internalCertificate.delete(res.locals.access, { id: Number.parseInt(req.params.certificate_id, 10), }); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -277,7 +312,7 @@ router */ .post(async (req, res, next) => { if (!req.files) { - res.status(400).send({ error: "No files were uploaded" }); + res.status(400).json({ error: "No files were uploaded" }); return; } @@ -286,7 +321,7 @@ router id: Number.parseInt(req.params.certificate_id, 10), files: req.files, }); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -313,10 +348,18 @@ router .post(async (req, res, next) => { req.setTimeout(900000); // 15 minutes timeout try { + const certId = Number.parseInt(req.params.certificate_id, 10); + + if (req.query.async === "true") { + const job = await internalJob.runCertificateRenew(res.locals.access, { id: certId }); + res.status(202).json({ job_id: job.id, status: job.status }); + return; + } + const result = await internalCertificate.renew(res.locals.access, { - id: Number.parseInt(req.params.certificate_id, 10), + id: certId, }); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); diff --git a/backend/routes/nginx/dead_hosts.js b/backend/routes/nginx/dead_hosts.js index 31f7043635..4d72d3283f 100644 --- a/backend/routes/nginx/dead_hosts.js +++ b/backend/routes/nginx/dead_hosts.js @@ -47,7 +47,7 @@ router }, ); const rows = await internalDeadHost.getAll(res.locals.access, data.expand, data.query); - res.status(200).send(rows); + res.status(200).json(rows); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -63,7 +63,7 @@ router try { const payload = await apiValidator(getValidationSchema("/nginx/dead-hosts", "post"), req.body); const result = await internalDeadHost.create(res.locals.access, payload); - res.status(201).send(result); + res.status(201).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -111,7 +111,7 @@ router id: Number.parseInt(data.host_id, 10), expand: data.expand, }); - res.status(200).send(row); + res.status(200).json(row); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -128,7 +128,7 @@ router const payload = await apiValidator(getValidationSchema("/nginx/dead-hosts/{hostID}", "put"), req.body); payload.id = Number.parseInt(req.params.host_id, 10); const result = await internalDeadHost.update(res.locals.access, payload); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -145,7 +145,7 @@ router const result = await internalDeadHost.delete(res.locals.access, { id: Number.parseInt(req.params.host_id, 10), }); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -172,7 +172,7 @@ router const result = await internalDeadHost.enable(res.locals.access, { id: Number.parseInt(req.params.host_id, 10), }); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -197,7 +197,7 @@ router .post((req, res, next) => { try { const result = internalDeadHost.disable(res.locals.access, { id: Number.parseInt(req.params.host_id, 10) }); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); diff --git a/backend/routes/nginx/proxy_hosts.js b/backend/routes/nginx/proxy_hosts.js index 7045a195cc..7e2fab22b1 100644 --- a/backend/routes/nginx/proxy_hosts.js +++ b/backend/routes/nginx/proxy_hosts.js @@ -47,7 +47,7 @@ router }, ); const rows = await internalProxyHost.getAll(res.locals.access, data.expand, data.query); - res.status(200).send(rows); + res.status(200).json(rows); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -63,7 +63,7 @@ router try { const payload = await apiValidator(getValidationSchema("/nginx/proxy-hosts", "post"), req.body); const result = await internalProxyHost.create(res.locals.access, payload); - res.status(201).send(result); + res.status(201).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err} ${JSON.stringify(err.debug, null, 2)}`); next(err); @@ -111,7 +111,7 @@ router id: Number.parseInt(data.host_id, 10), expand: data.expand, }); - res.status(200).send(row); + res.status(200).json(row); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -128,7 +128,7 @@ router const payload = await apiValidator(getValidationSchema("/nginx/proxy-hosts/{hostID}", "put"), req.body); payload.id = Number.parseInt(req.params.host_id, 10); const result = await internalProxyHost.update(res.locals.access, payload); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -145,7 +145,7 @@ router const result = await internalProxyHost.delete(res.locals.access, { id: Number.parseInt(req.params.host_id, 10), }); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -172,7 +172,7 @@ router const result = await internalProxyHost.enable(res.locals.access, { id: Number.parseInt(req.params.host_id, 10), }); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -199,7 +199,7 @@ router const result = await internalProxyHost.disable(res.locals.access, { id: Number.parseInt(req.params.host_id, 10), }); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); diff --git a/backend/routes/nginx/redirection_hosts.js b/backend/routes/nginx/redirection_hosts.js index 9b5b5b374d..ea13e44027 100644 --- a/backend/routes/nginx/redirection_hosts.js +++ b/backend/routes/nginx/redirection_hosts.js @@ -47,7 +47,7 @@ router }, ); const rows = await internalRedirectionHost.getAll(res.locals.access, data.expand, data.query); - res.status(200).send(rows); + res.status(200).json(rows); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -63,7 +63,7 @@ router try { const payload = await apiValidator(getValidationSchema("/nginx/redirection-hosts", "post"), req.body); const result = await internalRedirectionHost.create(res.locals.access, payload); - res.status(201).send(result); + res.status(201).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -111,7 +111,7 @@ router id: Number.parseInt(data.host_id, 10), expand: data.expand, }); - res.status(200).send(row); + res.status(200).json(row); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -131,7 +131,7 @@ router ); payload.id = Number.parseInt(req.params.host_id, 10); const result = await internalRedirectionHost.update(res.locals.access, payload); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -148,7 +148,7 @@ router const result = await internalRedirectionHost.delete(res.locals.access, { id: Number.parseInt(req.params.host_id, 10), }); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -175,7 +175,7 @@ router const result = await internalRedirectionHost.enable(res.locals.access, { id: Number.parseInt(req.params.host_id, 10), }); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -202,7 +202,7 @@ router const result = await internalRedirectionHost.disable(res.locals.access, { id: Number.parseInt(req.params.host_id, 10), }); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); diff --git a/backend/routes/nginx/streams.js b/backend/routes/nginx/streams.js index dec2e1a13f..e533dba015 100644 --- a/backend/routes/nginx/streams.js +++ b/backend/routes/nginx/streams.js @@ -47,7 +47,7 @@ router }, ); const rows = await internalStream.getAll(res.locals.access, data.expand, data.query); - res.status(200).send(rows); + res.status(200).json(rows); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -63,7 +63,7 @@ router try { const payload = await apiValidator(getValidationSchema("/nginx/streams", "post"), req.body); const result = await internalStream.create(res.locals.access, payload); - res.status(201).send(result); + res.status(201).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -111,7 +111,7 @@ router id: Number.parseInt(data.stream_id, 10), expand: data.expand, }); - res.status(200).send(row); + res.status(200).json(row); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -128,7 +128,7 @@ router const payload = await apiValidator(getValidationSchema("/nginx/streams/{streamID}", "put"), req.body); payload.id = Number.parseInt(req.params.stream_id, 10); const result = await internalStream.update(res.locals.access, payload); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -145,7 +145,7 @@ router const result = await internalStream.delete(res.locals.access, { id: Number.parseInt(req.params.stream_id, 10), }); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -172,7 +172,7 @@ router const result = await internalStream.enable(res.locals.access, { id: Number.parseInt(req.params.host_id, 10), }); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -199,7 +199,7 @@ router const result = await internalStream.disable(res.locals.access, { id: Number.parseInt(req.params.host_id, 10), }); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); diff --git a/backend/routes/reports.js b/backend/routes/reports.js index df9962ab11..150bc432af 100644 --- a/backend/routes/reports.js +++ b/backend/routes/reports.js @@ -22,7 +22,7 @@ router .get(async (req, res, next) => { try { const data = await internalReport.getHostsReport(res.locals.access); - res.status(200).send(data); + res.status(200).json(data); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); diff --git a/backend/routes/schema.js b/backend/routes/schema.js index 0a57c57c87..145481c871 100644 --- a/backend/routes/schema.js +++ b/backend/routes/schema.js @@ -34,7 +34,7 @@ router swaggerJSON.info.version = PACKAGE.version; swaggerJSON.servers[0].url = `${origin}/api`; - res.status(200).send(swaggerJSON); + res.status(200).json(swaggerJSON); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); diff --git a/backend/routes/settings.js b/backend/routes/settings.js index ca4af656b3..bd56a83216 100644 --- a/backend/routes/settings.js +++ b/backend/routes/settings.js @@ -30,7 +30,7 @@ router .get(async (req, res, next) => { try { const rows = await internalSetting.getAll(res.locals.access); - res.status(200).send(rows); + res.status(200).json(rows); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -74,7 +74,7 @@ router const row = await internalSetting.get(res.locals.access, { id: data.setting_id, }); - res.status(200).send(row); + res.status(200).json(row); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -91,7 +91,7 @@ router const payload = await apiValidator(getValidationSchema("/settings/{settingID}", "put"), req.body); payload.id = req.params.setting_id; const result = await internalSetting.update(res.locals.access, payload); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); diff --git a/backend/routes/tokens.js b/backend/routes/tokens.js index 8a6a1bc0fb..63e1855ca5 100644 --- a/backend/routes/tokens.js +++ b/backend/routes/tokens.js @@ -30,7 +30,7 @@ router expiry: typeof req.query.expiry !== "undefined" ? req.query.expiry : null, scope: typeof req.query.scope !== "undefined" ? req.query.scope : null, }); - res.status(200).send(data); + res.status(200).json(data); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -46,7 +46,7 @@ router try { const data = await apiValidator(getValidationSchema("/tokens", "post"), req.body); const result = await internalToken.getTokenFromEmail(data); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -68,7 +68,7 @@ router try { const { challenge_token, code } = await apiValidator(getValidationSchema("/tokens/2fa", "post"), req.body); const result = await internalToken.verify2FA(challenge_token, code); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); diff --git a/backend/routes/users.js b/backend/routes/users.js index 7c3da8c1d1..047fc120e2 100644 --- a/backend/routes/users.js +++ b/backend/routes/users.js @@ -50,7 +50,10 @@ router { expand: typeof req.query.expand === "string" - ? req.query.expand.split(",") + ? req.query.expand + .split(",") + .map((part) => part.trim()) + .filter((part) => typeof part === "string" && part.length > 0) : null, query: typeof req.query.query === "string" ? req.query.query : null, }, @@ -60,7 +63,7 @@ router data.expand, data.query, ); - res.status(200).send(users); + res.status(200).json(users); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -83,24 +86,26 @@ router const access = new Access(null); await access.load(true); res.locals.access = access; - - // We are in setup mode, set some defaults for this first new user, such as making - // them an admin. body.is_disabled = false; - if (typeof body.roles !== "object" || body.roles === null) { - body.roles = []; - } - if (body.roles.indexOf("admin") === -1) { - body.roles.push("admin"); - } } const payload = await apiValidator( getValidationSchema("/users", "post"), body, ); + + if (!setup) { + const roles = Array.isArray(payload.roles) + ? payload.roles.filter((role) => typeof role === "string") + : []; + if (!roles.includes("admin")) { + roles.push("admin"); + } + payload.roles = roles; + } + const user = await internalUser.create(res.locals.access, payload); - res.status(201).send(user); + res.status(201).json(user); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -184,7 +189,7 @@ router data.user_id, ), }); - res.status(200).send(user); + res.status(200).json(user); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -204,7 +209,7 @@ router ); payload.id = req.params.user_id; const result = await internalUser.update(res.locals.access, payload); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -221,7 +226,7 @@ router const result = await internalUser.delete(res.locals.access, { id: req.params.user_id, }); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -254,7 +259,7 @@ router ); payload.id = req.params.user_id; const result = await internalUser.setPassword(res.locals.access, payload); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -290,7 +295,7 @@ router res.locals.access, payload, ); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -319,7 +324,7 @@ router const result = await internalUser.loginAs(res.locals.access, { id: Number.parseInt(req.params.user_id, 10), }); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -347,7 +352,7 @@ router .post(async (req, res, next) => { try { const result = await internal2FA.startSetup(res.locals.access, req.params.user_id); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -362,7 +367,7 @@ router .get(async (req, res, next) => { try { const status = await internal2FA.getStatus(res.locals.access, req.params.user_id); - res.status(200).send(status); + res.status(200).json(status); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -413,7 +418,7 @@ router req.body, ); const result = await internal2FA.enable(res.locals.access, req.params.user_id, code); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); @@ -445,7 +450,7 @@ router req.body, ); const result = await internal2FA.regenerateBackupCodes(res.locals.access, req.params.user_id, code); - res.status(200).send(result); + res.status(200).json(result); } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); diff --git a/backend/routes/version.js b/backend/routes/version.js index 266e56fff7..5de9dfca11 100644 --- a/backend/routes/version.js +++ b/backend/routes/version.js @@ -25,11 +25,11 @@ router .get(async (req, res, _next) => { try { const data = await internalRemoteVersion.get(); - res.status(200).send(data); + res.status(200).json(data); } catch (error) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${error}`); // Send 200 even though there's an error to avoid triggering update checks repeatedly - res.status(200).send({ + res.status(200).json({ current: null, latest: null, update_available: false, diff --git a/backend/routes/webhooks.js b/backend/routes/webhooks.js new file mode 100644 index 0000000000..32b77bf3b6 --- /dev/null +++ b/backend/routes/webhooks.js @@ -0,0 +1,70 @@ +import express from "express"; +import internalWebhook from "../internal/webhook.js"; +import jwtdecode from "../lib/express/jwt-decode.js"; +import validator from "../lib/validator/index.js"; +import { debug, express as logger } from "../logger.js"; + +const router = express.Router({ + caseSensitive: true, + strict: true, + mergeParams: true, +}); + +router + .route("/") + .options((_, res) => { + res.sendStatus(204); + }) + .all(jwtdecode()) + .get(async (req, res, next) => { + try { + const rows = await internalWebhook.getAll(res.locals.access); + res.status(200).json(rows); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }) + .post(async (req, res, next) => { + try { + const payload = await validator( + { + additionalProperties: false, + required: ["name", "url", "events"], + properties: { + name: { type: "string", minLength: 1 }, + url: { type: "string", minLength: 1 }, + events: { type: "array", items: { type: "string" }, minItems: 1 }, + secret: { type: "string" }, + is_enabled: { type: "boolean" }, + }, + }, + req.body, + ); + const result = await internalWebhook.create(res.locals.access, payload); + res.status(201).json(result); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }); + +router + .route("/:webhook_id") + .options((_, res) => { + res.sendStatus(204); + }) + .all(jwtdecode()) + .delete(async (req, res, next) => { + try { + await internalWebhook.delete(res.locals.access, { + id: Number.parseInt(req.params.webhook_id, 10), + }); + res.status(200).send(true); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }); + +export default router; diff --git a/backend/schema/components/api-key-list.json b/backend/schema/components/api-key-list.json new file mode 100644 index 0000000000..2695c5632c --- /dev/null +++ b/backend/schema/components/api-key-list.json @@ -0,0 +1,7 @@ +{ + "type": "array", + "description": "API key list", + "items": { + "$ref": "./api-key-object.json" + } +} diff --git a/backend/schema/components/api-key-object.json b/backend/schema/components/api-key-object.json new file mode 100644 index 0000000000..01dace65ed --- /dev/null +++ b/backend/schema/components/api-key-object.json @@ -0,0 +1,57 @@ +{ + "type": "object", + "description": "Automation API key metadata (secret hash is never returned)", + "required": ["id", "created_on", "modified_on", "owner_user_id", "name", "permissions"], + "additionalProperties": false, + "properties": { + "id": { + "$ref": "../common.json#/properties/id" + }, + "created_on": { + "$ref": "../common.json#/properties/created_on" + }, + "modified_on": { + "$ref": "../common.json#/properties/modified_on" + }, + "owner_user_id": { + "$ref": "../common.json#/properties/user_id" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "Cypress automation key" + }, + "permissions": { + "type": "object", + "description": "Scoped permissions granted to this API key", + "additionalProperties": { + "type": "string" + }, + "example": { + "proxy_hosts": "manage", + "certificates": "manage", + "credentials": "manage" + } + }, + "expires_on": { + "type": ["string", "null"], + "example": null + }, + "last_used_at": { + "type": ["string", "null"], + "example": null + }, + "is_revoked": { + "type": "integer", + "enum": [0, 1], + "example": 0 + }, + "key": { + "type": "string", + "description": "Raw API key; returned only on create", + "pattern": "^npmak_", + "example": "npmak_a1b2c3d4_base64urlsecret" + } + } +} diff --git a/backend/schema/components/certificate-async-object.json b/backend/schema/components/certificate-async-object.json new file mode 100644 index 0000000000..84b895e1af --- /dev/null +++ b/backend/schema/components/certificate-async-object.json @@ -0,0 +1,18 @@ +{ + "type": "object", + "description": "Async certificate request accepted; poll the job endpoint for completion", + "required": ["job_id", "status"], + "additionalProperties": false, + "properties": { + "job_id": { + "type": "integer", + "minimum": 1, + "example": 1 + }, + "status": { + "type": "string", + "enum": ["pending", "running", "completed", "failed"], + "example": "pending" + } + } +} diff --git a/backend/schema/components/certificate-object.json b/backend/schema/components/certificate-object.json index 80cd92befe..975833d2e9 100644 --- a/backend/schema/components/certificate-object.json +++ b/backend/schema/components/certificate-object.json @@ -62,6 +62,30 @@ "dns_provider_credentials": { "type": "string" }, + "credential_ref": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": ["internal", "external"] + }, + "id": { + "type": "integer", + "minimum": 1 + }, + "provider_id": { + "type": "integer", + "minimum": 1 + }, + "path": { + "type": "string" + }, + "field": { + "type": "string" + } + } + }, "dns_provider": { "type": "string" }, diff --git a/backend/schema/components/credential-list.json b/backend/schema/components/credential-list.json new file mode 100644 index 0000000000..1e3a5cdb8f --- /dev/null +++ b/backend/schema/components/credential-list.json @@ -0,0 +1,7 @@ +{ + "type": "array", + "description": "Stored DNS credential list", + "items": { + "$ref": "./credential-object.json" + } +} diff --git a/backend/schema/components/credential-object.json b/backend/schema/components/credential-object.json new file mode 100644 index 0000000000..e52f149979 --- /dev/null +++ b/backend/schema/components/credential-object.json @@ -0,0 +1,35 @@ +{ + "type": "object", + "description": "Credential metadata (secret stored on persistent volume)", + "required": ["id", "created_on", "modified_on", "owner_user_id", "name", "dns_provider"], + "additionalProperties": false, + "properties": { + "id": { + "$ref": "../common.json#/properties/id" + }, + "created_on": { + "$ref": "../common.json#/properties/created_on" + }, + "modified_on": { + "$ref": "../common.json#/properties/modified_on" + }, + "owner_user_id": { + "$ref": "../common.json#/properties/user_id" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "Cloudflare Production" + }, + "dns_provider": { + "type": "string", + "minLength": 1, + "example": "cloudflare" + }, + "last_used_at": { + "type": ["string", "null"], + "example": "2026-06-03T12:00:00.000Z" + } + } +} diff --git a/backend/schema/components/credential-provider-list.json b/backend/schema/components/credential-provider-list.json new file mode 100644 index 0000000000..85b27efb69 --- /dev/null +++ b/backend/schema/components/credential-provider-list.json @@ -0,0 +1,7 @@ +{ + "type": "array", + "description": "Credential provider list", + "items": { + "$ref": "./credential-provider-object.json" + } +} diff --git a/backend/schema/components/credential-provider-object.json b/backend/schema/components/credential-provider-object.json new file mode 100644 index 0000000000..7f3c73f372 --- /dev/null +++ b/backend/schema/components/credential-provider-object.json @@ -0,0 +1,61 @@ +{ + "type": "object", + "description": "External credential store provider configuration", + "required": ["id", "created_on", "modified_on", "owner_user_id", "name", "type", "meta", "has_oidc_secret"], + "additionalProperties": false, + "properties": { + "id": { + "$ref": "../common.json#/properties/id" + }, + "created_on": { + "$ref": "../common.json#/properties/created_on" + }, + "modified_on": { + "$ref": "../common.json#/properties/modified_on" + }, + "owner_user_id": { + "$ref": "../common.json#/properties/user_id" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "Cypress vault stub" + }, + "type": { + "type": "string", + "enum": ["vault", "aws", "azure", "infisical", "http"], + "example": "vault" + }, + "oidc_issuer": { + "type": ["string", "null"], + "example": "https://issuer.example/oauth2" + }, + "oidc_client_id": { + "type": ["string", "null"], + "example": "npm-test" + }, + "oidc_audience": { + "type": ["string", "null"], + "example": null + }, + "oidc_scope": { + "type": ["string", "null"], + "example": null + }, + "meta": { + "type": "object", + "description": "Provider-specific configuration", + "example": { + "address": "http://127.0.0.1:65535", + "mount": "secret", + "role": "npm" + } + }, + "has_oidc_secret": { + "type": "boolean", + "description": "Whether an OIDC client secret is stored for this provider", + "example": true + } + } +} diff --git a/backend/schema/components/credential-provider-test-object.json b/backend/schema/components/credential-provider-test-object.json new file mode 100644 index 0000000000..3b9e83ffbd --- /dev/null +++ b/backend/schema/components/credential-provider-test-object.json @@ -0,0 +1,20 @@ +{ + "type": "object", + "description": "Credential provider connectivity test result", + "required": ["ok"], + "additionalProperties": false, + "properties": { + "ok": { + "type": "boolean", + "example": true + }, + "type": { + "type": "string", + "example": "vault" + }, + "name": { + "type": "string", + "example": "Cypress vault stub" + } + } +} diff --git a/backend/schema/components/health-object.json b/backend/schema/components/health-object.json index 592ead2ca4..facdc6796a 100644 --- a/backend/schema/components/health-object.json +++ b/backend/schema/components/health-object.json @@ -20,10 +20,11 @@ "example": { "major": 2, "minor": 0, - "revision": 0 + "revision": 0, + "string": "v2.0.0" }, "additionalProperties": false, - "required": ["major", "minor", "revision"], + "required": ["major", "minor", "revision", "string"], "properties": { "major": { "type": "integer", @@ -39,6 +40,11 @@ "type": "integer", "minimum": 0, "example": 1 + }, + "string": { + "type": "string", + "description": "Semantic version string", + "example": "v2.10.1" } } } diff --git a/backend/schema/components/job-list.json b/backend/schema/components/job-list.json new file mode 100644 index 0000000000..6af61c8ec8 --- /dev/null +++ b/backend/schema/components/job-list.json @@ -0,0 +1,7 @@ +{ + "type": "array", + "description": "Background job list", + "items": { + "$ref": "./job-object.json" + } +} diff --git a/backend/schema/components/job-object.json b/backend/schema/components/job-object.json new file mode 100644 index 0000000000..30dd8be842 --- /dev/null +++ b/backend/schema/components/job-object.json @@ -0,0 +1,51 @@ +{ + "type": "object", + "description": "Asynchronous background job", + "required": ["id", "created_on", "modified_on", "owner_user_id", "type", "status", "payload"], + "additionalProperties": false, + "properties": { + "id": { + "$ref": "../common.json#/properties/id" + }, + "created_on": { + "$ref": "../common.json#/properties/created_on" + }, + "modified_on": { + "$ref": "../common.json#/properties/modified_on" + }, + "owner_user_id": { + "$ref": "../common.json#/properties/user_id" + }, + "type": { + "type": "string", + "minLength": 1, + "maxLength": 64, + "example": "certificate.create" + }, + "status": { + "type": "string", + "enum": ["pending", "running", "completed", "failed"], + "example": "pending" + }, + "payload": { + "type": "object", + "description": "Job input payload", + "example": {} + }, + "result": { + "type": ["object", "null"], + "description": "Job result when completed", + "example": null + }, + "error": { + "type": ["string", "null"], + "description": "Error message when failed", + "example": null + }, + "finished_on": { + "type": ["string", "null"], + "description": "Completion timestamp", + "example": null + } + } +} diff --git a/backend/schema/components/permission-object.json b/backend/schema/components/permission-object.json index cae9d26c02..43d6bcbc2f 100644 --- a/backend/schema/components/permission-object.json +++ b/backend/schema/components/permission-object.json @@ -43,6 +43,12 @@ "description": "Certificates Permissions", "enum": ["hidden", "view", "manage"], "example": "hidden" + }, + "credentials": { + "type": "string", + "description": "Stored DNS Credentials Permissions", + "enum": ["hidden", "view", "manage"], + "example": "manage" } } } diff --git a/backend/schema/components/user-object.json b/backend/schema/components/user-object.json index 7acd0a4290..91dc5d8178 100644 --- a/backend/schema/components/user-object.json +++ b/backend/schema/components/user-object.json @@ -65,7 +65,8 @@ "dead_hosts", "streams", "access_lists", - "certificates" + "certificates", + "credentials" ], "properties": { "visibility": { @@ -109,6 +110,12 @@ "description": "Certificates access level", "example": "view", "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" } } } diff --git a/backend/schema/components/webhook-list.json b/backend/schema/components/webhook-list.json new file mode 100644 index 0000000000..b6f4d0b9ba --- /dev/null +++ b/backend/schema/components/webhook-list.json @@ -0,0 +1,7 @@ +{ + "type": "array", + "description": "Webhook endpoint list", + "items": { + "$ref": "./webhook-object.json" + } +} diff --git a/backend/schema/components/webhook-object.json b/backend/schema/components/webhook-object.json new file mode 100644 index 0000000000..cf346d216a --- /dev/null +++ b/backend/schema/components/webhook-object.json @@ -0,0 +1,59 @@ +{ + "type": "object", + "description": "Outbound webhook endpoint configuration", + "required": ["id", "created_on", "modified_on", "owner_user_id", "name", "url", "events", "is_enabled"], + "additionalProperties": false, + "properties": { + "id": { + "$ref": "../common.json#/properties/id" + }, + "created_on": { + "$ref": "../common.json#/properties/created_on" + }, + "modified_on": { + "$ref": "../common.json#/properties/modified_on" + }, + "owner_user_id": { + "$ref": "../common.json#/properties/user_id" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "Cypress webhook" + }, + "url": { + "type": "string", + "minLength": 1, + "maxLength": 2048, + "example": "http://127.0.0.1:65535/npm-webhook-test" + }, + "events": { + "type": "array", + "minItems": 1, + "items": { + "type": "string" + }, + "example": ["certificate.created"] + }, + "is_enabled": { + "description": "Whether the endpoint receives events", + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "integer", + "enum": [0, 1] + } + ], + "example": 1 + }, + "secret": { + "type": "string", + "description": "HMAC signing secret; returned only on create when generated by the server", + "minLength": 1, + "example": "ff387bfac72d5913371afd9d8c651e61369f2ba886b2d72a9402f441913aa279" + } + } +} diff --git a/backend/schema/paths/api-keys/apiKeyID/delete.json b/backend/schema/paths/api-keys/apiKeyID/delete.json new file mode 100644 index 0000000000..a2310bb748 --- /dev/null +++ b/backend/schema/paths/api-keys/apiKeyID/delete.json @@ -0,0 +1,31 @@ +{ + "operationId": "deleteApiKey", + "summary": "Revoke an API key", + "tags": [ + "api-keys" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "description": "Revokes an API key by id. Revoked keys fail authentication immediately.", + "parameters": [ + { + "in": "path", + "name": "apiKeyID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "API key ID", + "example": 1 + } + ], + "responses": { + "200": { + "description": "OK" + } + } +} diff --git a/backend/schema/paths/api-keys/get.json b/backend/schema/paths/api-keys/get.json new file mode 100644 index 0000000000..72ee32a541 --- /dev/null +++ b/backend/schema/paths/api-keys/get.json @@ -0,0 +1,26 @@ +{ + "operationId": "listApiKeys", + "summary": "List API keys", + "tags": [ + "api-keys" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "description": "Lists automation API keys. Secrets are never returned; each entry indicates whether a key is still configured.", + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "example": [], + "schema": { + "$ref": "../../components/api-key-list.json" + } + } + } + } + } +} diff --git a/backend/schema/paths/api-keys/post.json b/backend/schema/paths/api-keys/post.json new file mode 100644 index 0000000000..573ac36e86 --- /dev/null +++ b/backend/schema/paths/api-keys/post.json @@ -0,0 +1,78 @@ +{ + "operationId": "createApiKey", + "summary": "Create an API key", + "tags": [ + "api-keys" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "description": "Creates a long-lived API key for automation. The raw key is returned once in the response and cannot be retrieved again.", + "requestBody": { + "description": "API key configuration", + "required": true, + "content": { + "application/json": { + "example": { + "name": "Cypress automation key", + "permissions": { + "proxy_hosts": "manage" + } + }, + "schema": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string", + "example": "Cypress automation key" + }, + "permissions": { + "type": "object", + "example": { + "proxy_hosts": "manage" + } + }, + "expires_on": { + "type": [ + "string", + "null" + ], + "example": null + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "example": { + "id": 1, + "created_on": "2026-06-05T06:20:47.000Z", + "modified_on": "2026-06-05T06:20:47.000Z", + "owner_user_id": 1, + "name": "Cypress automation key", + "permissions": { + "proxy_hosts": "manage" + }, + "expires_on": null, + "last_used_at": null, + "is_revoked": 0, + "key": "npmak_a1b2c3d4_base64urlsecret" + }, + "schema": { + "$ref": "../../components/api-key-object.json" + } + } + } + } + } +} diff --git a/backend/schema/paths/audit-log/get.json b/backend/schema/paths/audit-log/get.json index 62c09ce169..9655ba8b93 100644 --- a/backend/schema/paths/audit-log/get.json +++ b/backend/schema/paths/audit-log/get.json @@ -1,12 +1,17 @@ { "operationId": "getAuditLogs", "summary": "Get Audit Logs", - "tags": ["audit-log"], + "tags": [ + "audit-log" + ], "security": [ { - "bearerAuth": ["admin"] + "bearerAuth": [ + "admin" + ] } ], + "description": "Returns paginated audit log entries for administrative review.", "responses": { "200": { "description": "200 response", diff --git a/backend/schema/paths/audit-log/id/get.json b/backend/schema/paths/audit-log/id/get.json index 38ff1c762b..28600912cb 100644 --- a/backend/schema/paths/audit-log/id/get.json +++ b/backend/schema/paths/audit-log/id/get.json @@ -1,7 +1,9 @@ { "operationId": "getAuditLog", "summary": "Get Audit Log Event", - "tags": ["audit-log"], + "tags": [ + "audit-log" + ], "security": [ { "bearerAuth": [ @@ -9,6 +11,7 @@ ] } ], + "description": "Returns a single audit log entry by id.", "parameters": [ { "in": "path", diff --git a/backend/schema/paths/credential-providers/get.json b/backend/schema/paths/credential-providers/get.json new file mode 100644 index 0000000000..13803298d6 --- /dev/null +++ b/backend/schema/paths/credential-providers/get.json @@ -0,0 +1,26 @@ +{ + "operationId": "listCredentialProviders", + "summary": "List credential providers", + "tags": [ + "credential-providers" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "description": "Lists external credential store providers (Vault, AWS, Azure, Infisical, HTTP). Client secrets are not included in responses.", + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "example": [], + "schema": { + "$ref": "../../components/credential-provider-list.json" + } + } + } + } + } +} diff --git a/backend/schema/paths/credential-providers/post.json b/backend/schema/paths/credential-providers/post.json new file mode 100644 index 0000000000..e7d4ac24cf --- /dev/null +++ b/backend/schema/paths/credential-providers/post.json @@ -0,0 +1,43 @@ +{ + "operationId": "createCredentialProvider", + "summary": "Create credential provider", + "tags": [ + "credential-providers" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "description": "Registers an external credential store provider. OIDC or Universal Auth credentials are stored encrypted under the data volume.", + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "example": { + "id": 1, + "created_on": "2026-06-05T06:20:47.000Z", + "modified_on": "2026-06-05T06:20:47.000Z", + "owner_user_id": 1, + "name": "Cypress vault stub", + "type": "vault", + "oidc_issuer": "https://issuer.example/oauth2", + "oidc_client_id": "npm-test", + "oidc_audience": null, + "oidc_scope": null, + "meta": { + "address": "http://127.0.0.1:65535", + "mount": "secret", + "role": "npm" + }, + "has_oidc_secret": true + }, + "schema": { + "$ref": "../../components/credential-provider-object.json" + } + } + } + } + } +} diff --git a/backend/schema/paths/credential-providers/providerID/delete.json b/backend/schema/paths/credential-providers/providerID/delete.json new file mode 100644 index 0000000000..3d4845e40a --- /dev/null +++ b/backend/schema/paths/credential-providers/providerID/delete.json @@ -0,0 +1,26 @@ +{ + "operationId": "deleteCredentialProvider", + "summary": "Delete credential provider", + "tags": [ + "credential-providers" + ], + "description": "Soft-deletes a credential provider. Existing certificate references may fail resolution until updated.", + "parameters": [ + { + "in": "path", + "name": "providerID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "Credential provider ID", + "example": 1 + } + ], + "responses": { + "200": { + "description": "OK" + } + } +} diff --git a/backend/schema/paths/credential-providers/providerID/get.json b/backend/schema/paths/credential-providers/providerID/get.json new file mode 100644 index 0000000000..3d658383f5 --- /dev/null +++ b/backend/schema/paths/credential-providers/providerID/get.json @@ -0,0 +1,47 @@ +{ + "operationId": "getCredentialProvider", + "summary": "Get credential provider", + "tags": [ + "credential-providers" + ], + "description": "Returns one credential provider configuration by id without secret material.", + "parameters": [ + { + "in": "path", + "name": "providerID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "Credential provider ID", + "example": 1 + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "example": { + "id": 1, + "created_on": "2026-06-05T06:20:47.000Z", + "modified_on": "2026-06-05T06:20:47.000Z", + "owner_user_id": 1, + "name": "Cypress vault stub", + "type": "vault", + "oidc_issuer": "https://issuer.example/oauth2", + "oidc_client_id": "npm-test", + "oidc_audience": null, + "oidc_scope": null, + "meta": {}, + "has_oidc_secret": true + }, + "schema": { + "$ref": "../../../components/credential-provider-object.json" + } + } + } + } + } +} diff --git a/backend/schema/paths/credential-providers/providerID/put.json b/backend/schema/paths/credential-providers/providerID/put.json new file mode 100644 index 0000000000..54c174b88e --- /dev/null +++ b/backend/schema/paths/credential-providers/providerID/put.json @@ -0,0 +1,26 @@ +{ + "operationId": "updateCredentialProvider", + "summary": "Update credential provider", + "tags": [ + "credential-providers" + ], + "description": "Updates provider settings. Omit secret fields to keep existing encrypted values.", + "parameters": [ + { + "in": "path", + "name": "providerID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "Credential provider ID", + "example": 1 + } + ], + "responses": { + "200": { + "description": "OK" + } + } +} diff --git a/backend/schema/paths/credential-providers/providerID/test-resolve/post.json b/backend/schema/paths/credential-providers/providerID/test-resolve/post.json new file mode 100644 index 0000000000..dfd26cd6ba --- /dev/null +++ b/backend/schema/paths/credential-providers/providerID/test-resolve/post.json @@ -0,0 +1,26 @@ +{ + "operationId": "testCredentialProviderResolve", + "summary": "Test secret resolution", + "tags": [ + "credential-providers" + ], + "description": "Tests resolving a secret path through the provider without returning secret contents (response includes byte length only).", + "parameters": [ + { + "in": "path", + "name": "providerID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "Credential provider ID", + "example": 1 + } + ], + "responses": { + "200": { + "description": "OK" + } + } +} diff --git a/backend/schema/paths/credential-providers/providerID/test/post.json b/backend/schema/paths/credential-providers/providerID/test/post.json new file mode 100644 index 0000000000..b13f128456 --- /dev/null +++ b/backend/schema/paths/credential-providers/providerID/test/post.json @@ -0,0 +1,38 @@ +{ + "operationId": "testCredentialProvider", + "summary": "Test provider authentication", + "tags": [ + "credential-providers" + ], + "description": "Verifies that the provider can obtain an access token (OIDC client credentials or Infisical Universal Auth).", + "parameters": [ + { + "in": "path", + "name": "providerID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "Credential provider ID", + "example": 1 + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "example": { + "ok": true, + "type": "vault", + "name": "Cypress vault stub" + }, + "schema": { + "$ref": "../../../../components/credential-provider-test-object.json" + } + } + } + } + } +} diff --git a/backend/schema/paths/credentials/credentialID/delete.json b/backend/schema/paths/credentials/credentialID/delete.json new file mode 100644 index 0000000000..6907cad36d --- /dev/null +++ b/backend/schema/paths/credentials/credentialID/delete.json @@ -0,0 +1,40 @@ +{ + "operationId": "deleteCredential", + "summary": "Delete a stored DNS credential", + "tags": [ + "credentials" + ], + "security": [ + { + "bearerAuth": [ + "credentials.manage" + ] + } + ], + "description": "Deletes a stored DNS credential from the vault.", + "parameters": [ + { + "in": "path", + "name": "credentialID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "Credential ID", + "example": 1 + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "boolean" + } + } + } + } + } +} diff --git a/backend/schema/paths/credentials/credentialID/get.json b/backend/schema/paths/credentials/credentialID/get.json new file mode 100644 index 0000000000..da0b337fed --- /dev/null +++ b/backend/schema/paths/credentials/credentialID/get.json @@ -0,0 +1,40 @@ +{ + "operationId": "getCredential", + "summary": "Get a stored DNS credential", + "tags": [ + "credentials" + ], + "security": [ + { + "bearerAuth": [ + "credentials.view" + ] + } + ], + "description": "Returns metadata for one stored DNS credential. Secret payload is not exposed.", + "parameters": [ + { + "in": "path", + "name": "credentialID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "Credential ID", + "example": 1 + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "../../../components/credential-object.json" + } + } + } + } + } +} diff --git a/backend/schema/paths/credentials/credentialID/put.json b/backend/schema/paths/credentials/credentialID/put.json new file mode 100644 index 0000000000..b4e63f5ef5 --- /dev/null +++ b/backend/schema/paths/credentials/credentialID/put.json @@ -0,0 +1,73 @@ +{ + "operationId": "updateCredential", + "summary": "Update a stored DNS credential", + "tags": [ + "credentials" + ], + "security": [ + { + "bearerAuth": [ + "credentials.manage" + ] + } + ], + "description": "Updates a stored DNS credential name or encrypted provider configuration.", + "parameters": [ + { + "in": "path", + "name": "credentialID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "Credential ID", + "example": 1 + } + ], + "requestBody": { + "description": "Credential update payload", + "required": true, + "content": { + "application/json": { + "example": { + "name": "Updated credential name" + }, + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "Updated credential name" + }, + "dns_provider": { + "type": "string", + "minLength": 1, + "example": "acmedns" + }, + "credentials": { + "type": "string", + "minLength": 1, + "example": "dns_acmedns_api_url = http://127.0.0.1:80/" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "../../../components/credential-object.json" + } + } + } + } + } +} diff --git a/backend/schema/paths/credentials/credentialID/test/post.json b/backend/schema/paths/credentials/credentialID/test/post.json new file mode 100644 index 0000000000..b3e5ad15d2 --- /dev/null +++ b/backend/schema/paths/credentials/credentialID/test/post.json @@ -0,0 +1,59 @@ +{ + "operationId": "testCredential", + "summary": "Verify a stored credential can be read from the vault", + "tags": [ + "credentials" + ], + "security": [ + { + "bearerAuth": [ + "credentials.view" + ] + } + ], + "description": "Validates that a stored credential can be decrypted and parsed for the configured DNS provider.", + "parameters": [ + { + "in": "path", + "name": "credentialID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "Credential ID", + "example": 1 + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "example": { + "ok": true, + "dns_provider": "acmedns", + "plugin_name": "ACME DNS" + }, + "schema": { + "type": "object", + "properties": { + "ok": { + "type": "boolean", + "example": true + }, + "dns_provider": { + "type": "string", + "example": "acmedns" + }, + "plugin_name": { + "type": "string", + "example": "ACME DNS" + } + } + } + } + } + } + } +} diff --git a/backend/schema/paths/credentials/get.json b/backend/schema/paths/credentials/get.json new file mode 100644 index 0000000000..6c3cf821a5 --- /dev/null +++ b/backend/schema/paths/credentials/get.json @@ -0,0 +1,27 @@ +{ + "operationId": "listCredentials", + "summary": "List stored DNS credentials", + "tags": [ + "credentials" + ], + "security": [ + { + "bearerAuth": [ + "credentials.view" + ] + } + ], + "description": "Lists DNS credentials stored in the encrypted NPM vault on the data volume.", + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "../../components/credential-list.json" + } + } + } + } + } +} diff --git a/backend/schema/paths/credentials/migrate-legacy/post.json b/backend/schema/paths/credentials/migrate-legacy/post.json new file mode 100644 index 0000000000..7472ecceb0 --- /dev/null +++ b/backend/schema/paths/credentials/migrate-legacy/post.json @@ -0,0 +1,98 @@ +{ + "operationId": "migrateLegacyCredentials", + "summary": "Migrate plaintext DNS credentials from certificates into the vault", + "tags": [ + "credentials" + ], + "security": [ + { + "bearerAuth": [ + "credentials.manage" + ] + } + ], + "description": "Moves inline DNS provider credentials from certificates into the vault. Supports dry-run preview before apply.", + "requestBody": { + "description": "Migration options", + "content": { + "application/json": { + "example": { + "dry_run": true + }, + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "dry_run": { + "type": "boolean", + "example": true + } + } + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "example": { + "dry_run": true, + "count": 0, + "results": [] + }, + "schema": { + "type": "object", + "required": [ + "dry_run", + "count", + "results" + ], + "properties": { + "dry_run": { + "type": "boolean", + "example": true + }, + "count": { + "type": "integer", + "example": 0 + }, + "results": { + "type": "array", + "example": [], + "items": { + "type": "object", + "required": ["certificate_id", "status"], + "properties": { + "certificate_id": { + "type": "integer", + "minimum": 1 + }, + "domain_names": { + "type": "array", + "items": { + "type": "string" + } + }, + "dns_provider": { + "type": "string" + }, + "status": { + "type": "string", + "enum": ["skipped", "migrated", "would_migrate"] + }, + "credential_id": { + "type": "integer", + "minimum": 1 + } + } + } + } + } + } + } + } + } + } +} diff --git a/backend/schema/paths/credentials/post.json b/backend/schema/paths/credentials/post.json new file mode 100644 index 0000000000..30ea090025 --- /dev/null +++ b/backend/schema/paths/credentials/post.json @@ -0,0 +1,68 @@ +{ + "operationId": "createCredential", + "summary": "Create a stored DNS credential", + "tags": [ + "credentials" + ], + "security": [ + { + "bearerAuth": [ + "credentials.manage" + ] + } + ], + "description": "Creates a named DNS credential (certbot provider INI) in the internal vault for certificate issuance.", + "requestBody": { + "description": "DNS credential payload", + "required": true, + "content": { + "application/json": { + "example": { + "name": "Cypress test credential", + "dns_provider": "acmedns", + "credentials": "dns_acmedns_api_url = http://127.0.0.1:80/" + }, + "schema": { + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "dns_provider", + "credentials" + ], + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "Cypress test credential" + }, + "dns_provider": { + "type": "string", + "minLength": 1, + "example": "acmedns" + }, + "credentials": { + "type": "string", + "minLength": 1, + "description": "Certbot DNS plugin credentials file content (INI format)", + "example": "dns_acmedns_api_url = http://127.0.0.1:80/" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "../../components/credential-object.json" + } + } + } + } + } +} diff --git a/backend/schema/paths/get.json b/backend/schema/paths/get.json index 9f6ba2a984..8d0347b8e5 100644 --- a/backend/schema/paths/get.json +++ b/backend/schema/paths/get.json @@ -1,7 +1,10 @@ { "operationId": "health", "summary": "Returns the API health status", - "tags": ["public"], + "tags": [ + "public" + ], + "description": "Public health check for the admin API. Returns setup status and semantic version fields without authentication.", "responses": { "200": { "description": "200 response", @@ -15,7 +18,8 @@ "version": { "major": 2, "minor": 1, - "revision": 0 + "revision": 0, + "string": "v2.1.0" } } } diff --git a/backend/schema/paths/jobs/get.json b/backend/schema/paths/jobs/get.json new file mode 100644 index 0000000000..a00143eb5d --- /dev/null +++ b/backend/schema/paths/jobs/get.json @@ -0,0 +1,26 @@ +{ + "operationId": "listJobs", + "summary": "List recent async jobs", + "tags": [ + "jobs" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "description": "Lists recent asynchronous automation jobs (certificate issuance, migrations, etc.).", + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "example": [], + "schema": { + "$ref": "../../components/job-list.json" + } + } + } + } + } +} diff --git a/backend/schema/paths/jobs/jobID/get.json b/backend/schema/paths/jobs/jobID/get.json new file mode 100644 index 0000000000..54e217f34c --- /dev/null +++ b/backend/schema/paths/jobs/jobID/get.json @@ -0,0 +1,50 @@ +{ + "operationId": "getJob", + "summary": "Get async job status", + "tags": [ + "jobs" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "description": "Returns status and result metadata for one background job by id.", + "parameters": [ + { + "in": "path", + "name": "jobID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "Job ID", + "example": 1 + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "example": { + "id": 1, + "created_on": "2026-06-05T06:20:47.000Z", + "modified_on": "2026-06-05T06:20:47.000Z", + "owner_user_id": 1, + "type": "certificate.create", + "status": "pending", + "payload": {}, + "result": null, + "error": null, + "finished_on": null + }, + "schema": { + "$ref": "../../../components/job-object.json" + } + } + } + } + } +} diff --git a/backend/schema/paths/nginx/access-lists/get.json b/backend/schema/paths/nginx/access-lists/get.json index ada40f5bf7..f22ad720bd 100644 --- a/backend/schema/paths/nginx/access-lists/get.json +++ b/backend/schema/paths/nginx/access-lists/get.json @@ -1,7 +1,9 @@ { "operationId": "getAccessLists", "summary": "Get all access lists", - "tags": ["access-lists"], + "tags": [ + "access-lists" + ], "security": [ { "bearerAuth": [ @@ -9,6 +11,7 @@ ] } ], + "description": "Returns all access lists (HTTP authentication and access rules) configured in NPM.", "parameters": [ { "in": "query", diff --git a/backend/schema/paths/nginx/access-lists/listID/delete.json b/backend/schema/paths/nginx/access-lists/listID/delete.json index 182a883a11..de144d8a4a 100644 --- a/backend/schema/paths/nginx/access-lists/listID/delete.json +++ b/backend/schema/paths/nginx/access-lists/listID/delete.json @@ -1,12 +1,17 @@ { "operationId": "deleteAccessList", "summary": "Delete a Access List", - "tags": ["access-lists"], + "tags": [ + "access-lists" + ], "security": [ { - "bearerAuth": ["access_lists.manage"] + "bearerAuth": [ + "access_lists.manage" + ] } ], + "description": "Deletes an access list. Hosts referencing it must be updated separately.", "parameters": [ { "in": "path", diff --git a/backend/schema/paths/nginx/access-lists/listID/get.json b/backend/schema/paths/nginx/access-lists/listID/get.json index 9705826f20..70956ffa31 100644 --- a/backend/schema/paths/nginx/access-lists/listID/get.json +++ b/backend/schema/paths/nginx/access-lists/listID/get.json @@ -1,54 +1,55 @@ { - "operationId": "getAccessList", - "summary": "Get a access List", - "tags": [ - "access-lists" - ], - "security": [ - { - "bearerAuth": [ - "access_lists.view" - ] - } - ], - "parameters": [ - { - "in": "path", - "name": "listID", - "description": "Access List ID", - "schema": { - "type": "integer", - "minimum": 1 - }, - "required": true, - "example": 1 - } - ], - "responses": { - "200": { - "description": "200 response", - "content": { - "application/json": { - "examples": { - "default": { - "value": { - "id": 1, - "created_on": "2025-10-28T04:06:55.000Z", - "modified_on": "2025-10-29T22:48:20.000Z", - "owner_user_id": 1, - "name": "My Access List", - "meta": {}, - "satisfy_any": false, - "pass_auth": false, - "proxy_host_count": 1 - } - } - }, - "schema": { - "$ref": "../../../../components/access-list-object.json" - } - } - } - } - } + "operationId": "getAccessList", + "summary": "Get a access List", + "tags": [ + "access-lists" + ], + "security": [ + { + "bearerAuth": [ + "access_lists.view" + ] + } + ], + "description": "Returns one access list including authorization and access rule entries.", + "parameters": [ + { + "in": "path", + "name": "listID", + "description": "Access List ID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 1 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "id": 1, + "created_on": "2025-10-28T04:06:55.000Z", + "modified_on": "2025-10-29T22:48:20.000Z", + "owner_user_id": 1, + "name": "My Access List", + "meta": {}, + "satisfy_any": false, + "pass_auth": false, + "proxy_host_count": 1 + } + } + }, + "schema": { + "$ref": "../../../../components/access-list-object.json" + } + } + } + } + } } diff --git a/backend/schema/paths/nginx/access-lists/listID/put.json b/backend/schema/paths/nginx/access-lists/listID/put.json index 61e8044013..9b02c71f91 100644 --- a/backend/schema/paths/nginx/access-lists/listID/put.json +++ b/backend/schema/paths/nginx/access-lists/listID/put.json @@ -1,12 +1,17 @@ { "operationId": "updateAccessList", "summary": "Update a Access List", - "tags": ["access-lists"], + "tags": [ + "access-lists" + ], "security": [ { - "bearerAuth": ["access_lists.manage"] + "bearerAuth": [ + "access_lists.manage" + ] } ], + "description": "Updates an access list and its nested auth or access items.", "parameters": [ { "in": "path", @@ -93,7 +98,9 @@ "name": "Administrator", "nickname": "some guy", "avatar": "//www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?default=mm", - "roles": ["admin"] + "roles": [ + "admin" + ] }, "items": [ { diff --git a/backend/schema/paths/nginx/access-lists/post.json b/backend/schema/paths/nginx/access-lists/post.json index 38b7003a1e..8f89b0fefd 100644 --- a/backend/schema/paths/nginx/access-lists/post.json +++ b/backend/schema/paths/nginx/access-lists/post.json @@ -1,7 +1,9 @@ { "operationId": "createAccessList", "summary": "Create a Access List", - "tags": ["access-lists"], + "tags": [ + "access-lists" + ], "security": [ { "bearerAuth": [ @@ -9,6 +11,7 @@ ] } ], + "description": "Creates an access list for use on proxy hosts, redirection hosts, or streams.", "requestBody": { "description": "Access List Payload", "required": true, diff --git a/backend/schema/paths/nginx/certificates/certID/delete.json b/backend/schema/paths/nginx/certificates/certID/delete.json index a99f619d69..4d2aa0fb11 100644 --- a/backend/schema/paths/nginx/certificates/certID/delete.json +++ b/backend/schema/paths/nginx/certificates/certID/delete.json @@ -1,12 +1,17 @@ { "operationId": "deleteCertificate", "summary": "Delete a Certificate", - "tags": ["certificates"], + "tags": [ + "certificates" + ], "security": [ { - "bearerAuth": ["certificates.manage"] + "bearerAuth": [ + "certificates.manage" + ] } ], + "description": "Deletes a certificate record. Does not remove files already deployed to disk until nginx is reloaded.", "parameters": [ { "in": "path", diff --git a/backend/schema/paths/nginx/certificates/certID/download/get.json b/backend/schema/paths/nginx/certificates/certID/download/get.json index 7c18d019dd..efea0037ec 100644 --- a/backend/schema/paths/nginx/certificates/certID/download/get.json +++ b/backend/schema/paths/nginx/certificates/certID/download/get.json @@ -1,12 +1,17 @@ { "operationId": "downloadCertificate", "summary": "Downloads a Certificate", - "tags": ["certificates"], + "tags": [ + "certificates" + ], "security": [ { - "bearerAuth": ["certificates.manage"] + "bearerAuth": [ + "certificates.manage" + ] } ], + "description": "Downloads certificate and private key material for a certificate id (requires permission).", "parameters": [ { "in": "path", diff --git a/backend/schema/paths/nginx/certificates/certID/get.json b/backend/schema/paths/nginx/certificates/certID/get.json index 46afbf8753..9634220814 100644 --- a/backend/schema/paths/nginx/certificates/certID/get.json +++ b/backend/schema/paths/nginx/certificates/certID/get.json @@ -1,12 +1,17 @@ { "operationId": "getCertificate", "summary": "Get a Certificate", - "tags": ["certificates"], + "tags": [ + "certificates" + ], "security": [ { - "bearerAuth": ["certificates.view"] + "bearerAuth": [ + "certificates.view" + ] } ], + "description": "Returns one certificate record and metadata by id.", "parameters": [ { "in": "path", @@ -34,7 +39,9 @@ "owner_user_id": 1, "provider": "letsencrypt", "nice_name": "test.example.com", - "domain_names": ["test.example.com"], + "domain_names": [ + "test.example.com" + ], "expires_on": "2025-01-07T04:34:18.000Z", "meta": { "dns_challenge": false diff --git a/backend/schema/paths/nginx/certificates/certID/put.json b/backend/schema/paths/nginx/certificates/certID/put.json new file mode 100644 index 0000000000..265c1f6c90 --- /dev/null +++ b/backend/schema/paths/nginx/certificates/certID/put.json @@ -0,0 +1,52 @@ +{ + "operationId": "updateCertificate", + "summary": "Update a Certificate", + "tags": [ + "certificates" + ], + "security": [ + { + "bearerAuth": [ + "certificates.manage" + ] + } + ], + "description": "Updates certificate metadata such as friendly name or linked hosts.", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "nice_name": { + "type": "string" + }, + "domain_names": { + "type": "array", + "items": { + "type": "string" + } + }, + "meta": { + "type": "object" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "../../../../components/certificate-object.json" + } + } + } + } + } +} diff --git a/backend/schema/paths/nginx/certificates/certID/renew/post.json b/backend/schema/paths/nginx/certificates/certID/renew/post.json index 4466d38d30..4d0aee0f8e 100644 --- a/backend/schema/paths/nginx/certificates/certID/renew/post.json +++ b/backend/schema/paths/nginx/certificates/certID/renew/post.json @@ -1,12 +1,17 @@ { "operationId": "renewCertificate", "summary": "Renews a Certificate", - "tags": ["certificates"], + "tags": [ + "certificates" + ], "security": [ { - "bearerAuth": ["certificates.manage"] + "bearerAuth": [ + "certificates.manage" + ] } ], + "description": "Triggers renewal for an existing managed certificate.", "parameters": [ { "in": "path", @@ -35,7 +40,9 @@ "owner_user_id": 1, "provider": "letsencrypt", "nice_name": "My Test Cert", - "domain_names": ["test.jc21.supernerd.pro"], + "domain_names": [ + "test.jc21.supernerd.pro" + ], "meta": { "dns_challenge": false } diff --git a/backend/schema/paths/nginx/certificates/certID/upload/post.json b/backend/schema/paths/nginx/certificates/certID/upload/post.json index 2b1ba3e610..bdb4cdcb56 100644 --- a/backend/schema/paths/nginx/certificates/certID/upload/post.json +++ b/backend/schema/paths/nginx/certificates/certID/upload/post.json @@ -1,12 +1,17 @@ { "operationId": "uploadCertificate", "summary": "Uploads a custom Certificate", - "tags": ["certificates"], + "tags": [ + "certificates" + ], "security": [ { - "bearerAuth": ["certificates.manage"] + "bearerAuth": [ + "certificates.manage" + ] } ], + "description": "Uploads custom certificate and key files for use on proxy hosts.", "parameters": [ { "in": "path", @@ -39,7 +44,10 @@ "schema": { "type": "object", "additionalProperties": false, - "required": ["certificate", "certificate_key"], + "required": [ + "certificate", + "certificate_key" + ], "properties": { "certificate": { "type": "string", diff --git a/backend/schema/paths/nginx/certificates/dns-providers/get.json b/backend/schema/paths/nginx/certificates/dns-providers/get.json index 3efb1a0696..8b41d87057 100644 --- a/backend/schema/paths/nginx/certificates/dns-providers/get.json +++ b/backend/schema/paths/nginx/certificates/dns-providers/get.json @@ -1,12 +1,17 @@ { "operationId": "getDNSProviders", "summary": "Get DNS Providers for Certificates", - "tags": ["certificates"], + "tags": [ + "certificates" + ], "security": [ { - "bearerAuth": ["certificates.view"] + "bearerAuth": [ + "certificates.view" + ] } ], + "description": "Lists DNS providers supported for ACME DNS challenge certificate issuance.", "responses": { "200": { "description": "200 response", diff --git a/backend/schema/paths/nginx/certificates/get.json b/backend/schema/paths/nginx/certificates/get.json index 5884c97299..f97e909995 100644 --- a/backend/schema/paths/nginx/certificates/get.json +++ b/backend/schema/paths/nginx/certificates/get.json @@ -1,12 +1,17 @@ { "operationId": "getCertificates", "summary": "Get all certificates", - "tags": ["certificates"], + "tags": [ + "certificates" + ], "security": [ { - "bearerAuth": ["certificates.view"] + "bearerAuth": [ + "certificates.view" + ] } ], + "description": "Lists SSL certificates known to NPM including managed, custom, and in-progress orders.", "parameters": [ { "in": "query", @@ -14,7 +19,9 @@ "description": "Expansions", "schema": { "type": "string", - "enum": ["owner"] + "enum": [ + "owner" + ] } } ], @@ -33,7 +40,9 @@ "owner_user_id": 1, "provider": "letsencrypt", "nice_name": "test.example.com", - "domain_names": ["test.example.com"], + "domain_names": [ + "test.example.com" + ], "expires_on": "2025-01-07T04:34:18.000Z", "meta": { "dns_challenge": false diff --git a/backend/schema/paths/nginx/certificates/post.json b/backend/schema/paths/nginx/certificates/post.json index 15406c8b3d..6d3972db97 100644 --- a/backend/schema/paths/nginx/certificates/post.json +++ b/backend/schema/paths/nginx/certificates/post.json @@ -1,12 +1,17 @@ { "operationId": "createCertificate", "summary": "Create a Certificate", - "tags": ["certificates"], + "tags": [ + "certificates" + ], "security": [ { - "bearerAuth": ["certificates.manage"] + "bearerAuth": [ + "certificates.manage" + ] } ], + "description": "Requests a new certificate (HTTP, DNS, or custom workflow depending on payload).", "requestBody": { "description": "Certificate Payload", "required": true, @@ -15,7 +20,9 @@ "schema": { "type": "object", "additionalProperties": false, - "required": ["provider"], + "required": [ + "provider" + ], "properties": { "provider": { "$ref": "../../../components/certificate-object.json#/properties/provider" @@ -33,7 +40,9 @@ }, "example": { "provider": "letsencrypt", - "domain_names": ["test.example.com"], + "domain_names": [ + "test.example.com" + ], "meta": { "dns_challenge": false } @@ -56,7 +65,9 @@ "owner_user_id": 1, "provider": "letsencrypt", "nice_name": "test.example.com", - "domain_names": ["test.example.com"], + "domain_names": [ + "test.example.com" + ], "meta": { "dns_challenge": false, "letsencrypt_certificate": { @@ -77,6 +88,20 @@ } } }, + "202": { + "description": "Async acceptance when query parameter async=true", + "content": { + "application/json": { + "example": { + "job_id": 1, + "status": "pending" + }, + "schema": { + "$ref": "../../../components/certificate-async-object.json" + } + } + } + }, "400": { "description": "400 response", "content": { diff --git a/backend/schema/paths/nginx/certificates/test-http/post.json b/backend/schema/paths/nginx/certificates/test-http/post.json index 4d738d0187..554fee0850 100644 --- a/backend/schema/paths/nginx/certificates/test-http/post.json +++ b/backend/schema/paths/nginx/certificates/test-http/post.json @@ -1,12 +1,17 @@ { "operationId": "testHttpReach", "summary": "Test HTTP Reachability", - "tags": ["certificates"], + "tags": [ + "certificates" + ], "security": [ { - "bearerAuth": ["certificates.view"] + "bearerAuth": [ + "certificates.view" + ] } ], + "description": "Tests HTTP reachability for domain validation prior to certificate issuance.", "requestBody": { "description": "Test Payload", "required": true, @@ -15,7 +20,9 @@ "schema": { "type": "object", "additionalProperties": false, - "required": ["domains"], + "required": [ + "domains" + ], "properties": { "domains": { "$ref": "../../../../common.json#/properties/domain_names" diff --git a/backend/schema/paths/nginx/certificates/validate/post.json b/backend/schema/paths/nginx/certificates/validate/post.json index 9fa2bd126d..2ae42fbeed 100644 --- a/backend/schema/paths/nginx/certificates/validate/post.json +++ b/backend/schema/paths/nginx/certificates/validate/post.json @@ -1,12 +1,17 @@ { "operationId": "validateCertificates", "summary": "Validates given Custom Certificates", - "tags": ["certificates"], + "tags": [ + "certificates" + ], "security": [ { - "bearerAuth": ["certificates.manage"] + "bearerAuth": [ + "certificates.manage" + ] } ], + "description": "Validates stored certificates and reports expiry or configuration issues.", "requestBody": { "$ref": "../../../../common.json#/properties/certificate_files" }, @@ -33,12 +38,19 @@ "schema": { "type": "object", "additionalProperties": false, - "required": ["certificate", "certificate_key"], + "required": [ + "certificate", + "certificate_key" + ], "properties": { "certificate": { "type": "object", "additionalProperties": false, - "required": ["cn", "issuer", "dates"], + "required": [ + "cn", + "issuer", + "dates" + ], "properties": { "cn": { "type": "string", @@ -51,7 +63,10 @@ "dates": { "type": "object", "additionalProperties": false, - "required": ["from", "to"], + "required": [ + "from", + "to" + ], "properties": { "from": { "type": "integer" diff --git a/backend/schema/paths/nginx/dead-hosts/get.json b/backend/schema/paths/nginx/dead-hosts/get.json index feb04ff227..eefdc58d20 100644 --- a/backend/schema/paths/nginx/dead-hosts/get.json +++ b/backend/schema/paths/nginx/dead-hosts/get.json @@ -1,12 +1,17 @@ { "operationId": "getDeadHosts", "summary": "Get all 404 hosts", - "tags": ["404-hosts"], + "tags": [ + "404-hosts" + ], "security": [ { - "bearerAuth": ["dead_hosts.view"] + "bearerAuth": [ + "dead_hosts.view" + ] } ], + "description": "Lists 404 / catch-all hosts (dead hosts) configured in NPM.", "parameters": [ { "in": "query", @@ -14,7 +19,10 @@ "description": "Expansions", "schema": { "type": "string", - "enum": ["owner", "certificate"] + "enum": [ + "owner", + "certificate" + ] } } ], @@ -31,7 +39,9 @@ "created_on": "2024-10-09T01:38:52.000Z", "modified_on": "2024-10-09T01:38:52.000Z", "owner_user_id": 1, - "domain_names": ["test.example.com"], + "domain_names": [ + "test.example.com" + ], "certificate_id": 0, "ssl_forced": false, "advanced_config": "", diff --git a/backend/schema/paths/nginx/dead-hosts/hostID/delete.json b/backend/schema/paths/nginx/dead-hosts/hostID/delete.json index eed0ebc016..d4a16fc73d 100644 --- a/backend/schema/paths/nginx/dead-hosts/hostID/delete.json +++ b/backend/schema/paths/nginx/dead-hosts/hostID/delete.json @@ -1,12 +1,17 @@ { "operationId": "deleteDeadHost", "summary": "Delete a 404 Host", - "tags": ["404-hosts"], + "tags": [ + "404-hosts" + ], "security": [ { - "bearerAuth": ["dead_hosts.manage"] + "bearerAuth": [ + "dead_hosts.manage" + ] } ], + "description": "Deletes a 404 host by id.", "parameters": [ { "in": "path", diff --git a/backend/schema/paths/nginx/dead-hosts/hostID/disable/post.json b/backend/schema/paths/nginx/dead-hosts/hostID/disable/post.json index 2a4d08aebd..ff1f84fa99 100644 --- a/backend/schema/paths/nginx/dead-hosts/hostID/disable/post.json +++ b/backend/schema/paths/nginx/dead-hosts/hostID/disable/post.json @@ -1,12 +1,17 @@ { "operationId": "disableDeadHost", "summary": "Disable a 404 Host", - "tags": ["404-hosts"], + "tags": [ + "404-hosts" + ], "security": [ { - "bearerAuth": ["dead_hosts.manage"] + "bearerAuth": [ + "dead_hosts.manage" + ] } ], + "description": "Disables a 404 host without deleting its configuration.", "parameters": [ { "in": "path", diff --git a/backend/schema/paths/nginx/dead-hosts/hostID/enable/post.json b/backend/schema/paths/nginx/dead-hosts/hostID/enable/post.json index 512c2a0af0..9089f18007 100644 --- a/backend/schema/paths/nginx/dead-hosts/hostID/enable/post.json +++ b/backend/schema/paths/nginx/dead-hosts/hostID/enable/post.json @@ -1,12 +1,17 @@ { "operationId": "enableDeadHost", "summary": "Enable a 404 Host", - "tags": ["404-hosts"], + "tags": [ + "404-hosts" + ], "security": [ { - "bearerAuth": ["dead_hosts.manage"] + "bearerAuth": [ + "dead_hosts.manage" + ] } ], + "description": "Enables a previously disabled 404 host and reloads nginx when required.", "parameters": [ { "in": "path", diff --git a/backend/schema/paths/nginx/dead-hosts/hostID/get.json b/backend/schema/paths/nginx/dead-hosts/hostID/get.json index a3c24edc34..142043afe6 100644 --- a/backend/schema/paths/nginx/dead-hosts/hostID/get.json +++ b/backend/schema/paths/nginx/dead-hosts/hostID/get.json @@ -1,12 +1,17 @@ { "operationId": "getDeadHost", "summary": "Get a 404 Host", - "tags": ["404-hosts"], + "tags": [ + "404-hosts" + ], "security": [ { - "bearerAuth": ["dead_hosts.view"] + "bearerAuth": [ + "dead_hosts.view" + ] } ], + "description": "Returns one 404 host configuration by id.", "parameters": [ { "in": "path", @@ -32,7 +37,9 @@ "created_on": "2024-10-09T01:38:52.000Z", "modified_on": "2024-10-09T01:38:52.000Z", "owner_user_id": 1, - "domain_names": ["test.example.com"], + "domain_names": [ + "test.example.com" + ], "certificate_id": 0, "ssl_forced": false, "advanced_config": "", diff --git a/backend/schema/paths/nginx/dead-hosts/hostID/put.json b/backend/schema/paths/nginx/dead-hosts/hostID/put.json index e07217c45c..9882711fa9 100644 --- a/backend/schema/paths/nginx/dead-hosts/hostID/put.json +++ b/backend/schema/paths/nginx/dead-hosts/hostID/put.json @@ -1,12 +1,17 @@ { "operationId": "updateDeadHost", "summary": "Update a 404 Host", - "tags": ["404-hosts"], + "tags": [ + "404-hosts" + ], "security": [ { - "bearerAuth": ["dead_hosts.manage"] + "bearerAuth": [ + "dead_hosts.manage" + ] } ], + "description": "Updates a 404 host domain names, forwarding, or enabled state.", "parameters": [ { "in": "path", @@ -71,7 +76,9 @@ "created_on": "2024-10-09T01:38:52.000Z", "modified_on": "2024-10-09T01:46:06.000Z", "owner_user_id": 1, - "domain_names": ["test.example.com"], + "domain_names": [ + "test.example.com" + ], "certificate_id": 0, "ssl_forced": false, "advanced_config": "", @@ -92,7 +99,9 @@ "name": "Administrator", "nickname": "Admin", "avatar": "", - "roles": ["admin"] + "roles": [ + "admin" + ] }, "certificate": null } diff --git a/backend/schema/paths/nginx/dead-hosts/post.json b/backend/schema/paths/nginx/dead-hosts/post.json index 1ec38720c8..166a348fbb 100644 --- a/backend/schema/paths/nginx/dead-hosts/post.json +++ b/backend/schema/paths/nginx/dead-hosts/post.json @@ -1,7 +1,9 @@ { "operationId": "create404Host", "summary": "Create a 404 Host", - "tags": ["404-hosts"], + "tags": [ + "404-hosts" + ], "security": [ { "bearerAuth": [ @@ -9,6 +11,7 @@ ] } ], + "description": "Creates a 404 host that serves a default site when no other host matches.", "requestBody": { "description": "404 Host Payload", "required": true, diff --git a/backend/schema/paths/nginx/proxy-hosts/get.json b/backend/schema/paths/nginx/proxy-hosts/get.json index 301e28bfdf..2f6170369e 100644 --- a/backend/schema/paths/nginx/proxy-hosts/get.json +++ b/backend/schema/paths/nginx/proxy-hosts/get.json @@ -1,7 +1,9 @@ { "operationId": "getProxyHosts", "summary": "Get all proxy hosts", - "tags": ["proxy-hosts"], + "tags": [ + "proxy-hosts" + ], "security": [ { "bearerAuth": [ @@ -9,6 +11,7 @@ ] } ], + "description": "Lists reverse proxy hosts (domain to upstream mapping).", "parameters": [ { "in": "query", diff --git a/backend/schema/paths/nginx/proxy-hosts/hostID/delete.json b/backend/schema/paths/nginx/proxy-hosts/hostID/delete.json index da67944d57..ab6f447949 100644 --- a/backend/schema/paths/nginx/proxy-hosts/hostID/delete.json +++ b/backend/schema/paths/nginx/proxy-hosts/hostID/delete.json @@ -1,12 +1,17 @@ { "operationId": "deleteProxyHost", "summary": "Delete a Proxy Host", - "tags": ["proxy-hosts"], + "tags": [ + "proxy-hosts" + ], "security": [ { - "bearerAuth": ["proxy_hosts.manage"] + "bearerAuth": [ + "proxy_hosts.manage" + ] } ], + "description": "Deletes a proxy host by id.", "parameters": [ { "in": "path", diff --git a/backend/schema/paths/nginx/proxy-hosts/hostID/disable/post.json b/backend/schema/paths/nginx/proxy-hosts/hostID/disable/post.json index 14c2689c0d..693830af4c 100644 --- a/backend/schema/paths/nginx/proxy-hosts/hostID/disable/post.json +++ b/backend/schema/paths/nginx/proxy-hosts/hostID/disable/post.json @@ -1,12 +1,17 @@ { "operationId": "disableProxyHost", "summary": "Disable a Proxy Host", - "tags": ["proxy-hosts"], + "tags": [ + "proxy-hosts" + ], "security": [ { - "bearerAuth": ["proxy_hosts.manage"] + "bearerAuth": [ + "proxy_hosts.manage" + ] } ], + "description": "Disables a proxy host in nginx without removing the database record.", "parameters": [ { "in": "path", diff --git a/backend/schema/paths/nginx/proxy-hosts/hostID/enable/post.json b/backend/schema/paths/nginx/proxy-hosts/hostID/enable/post.json index fe504b781d..2d64b8f6e5 100644 --- a/backend/schema/paths/nginx/proxy-hosts/hostID/enable/post.json +++ b/backend/schema/paths/nginx/proxy-hosts/hostID/enable/post.json @@ -1,12 +1,17 @@ { "operationId": "enableProxyHost", "summary": "Enable a Proxy Host", - "tags": ["proxy-hosts"], + "tags": [ + "proxy-hosts" + ], "security": [ { - "bearerAuth": ["proxy_hosts.manage"] + "bearerAuth": [ + "proxy_hosts.manage" + ] } ], + "description": "Enables a proxy host and applies nginx configuration.", "parameters": [ { "in": "path", diff --git a/backend/schema/paths/nginx/proxy-hosts/hostID/get.json b/backend/schema/paths/nginx/proxy-hosts/hostID/get.json index 2e677fed32..607289d107 100644 --- a/backend/schema/paths/nginx/proxy-hosts/hostID/get.json +++ b/backend/schema/paths/nginx/proxy-hosts/hostID/get.json @@ -1,7 +1,9 @@ { "operationId": "getProxyHost", "summary": "Get a Proxy Host", - "tags": ["proxy-hosts"], + "tags": [ + "proxy-hosts" + ], "security": [ { "bearerAuth": [ @@ -9,6 +11,7 @@ ] } ], + "description": "Returns one proxy host by id.", "parameters": [ { "in": "path", diff --git a/backend/schema/paths/nginx/proxy-hosts/hostID/put.json b/backend/schema/paths/nginx/proxy-hosts/hostID/put.json index fc3198456b..63688aaaaa 100644 --- a/backend/schema/paths/nginx/proxy-hosts/hostID/put.json +++ b/backend/schema/paths/nginx/proxy-hosts/hostID/put.json @@ -1,7 +1,9 @@ { "operationId": "updateProxyHost", "summary": "Update a Proxy Host", - "tags": ["proxy-hosts"], + "tags": [ + "proxy-hosts" + ], "security": [ { "bearerAuth": [ @@ -9,6 +11,7 @@ ] } ], + "description": "Updates proxy host domains, upstream, advanced options, or certificate linkage.", "parameters": [ { "in": "path", @@ -57,7 +60,7 @@ "$ref": "../../../../components/proxy-host-object.json#/properties/hsts_subdomains" }, "trust_forwarded_proto": { - "$ref": "../../../../components/proxy-host-object.json#/properties/trust_forwarded_proto" + "$ref": "../../../../components/proxy-host-object.json#/properties/trust_forwarded_proto" }, "http2_support": { "$ref": "../../../../components/proxy-host-object.json#/properties/http2_support" diff --git a/backend/schema/paths/nginx/proxy-hosts/post.json b/backend/schema/paths/nginx/proxy-hosts/post.json index 28ddad8fc2..2726e4d880 100644 --- a/backend/schema/paths/nginx/proxy-hosts/post.json +++ b/backend/schema/paths/nginx/proxy-hosts/post.json @@ -1,7 +1,9 @@ { "operationId": "createProxyHost", "summary": "Create a Proxy Host", - "tags": ["proxy-hosts"], + "tags": [ + "proxy-hosts" + ], "security": [ { "bearerAuth": [ @@ -9,6 +11,7 @@ ] } ], + "description": "Creates a proxy host with domain names, upstream target, and optional TLS and access settings.", "requestBody": { "description": "Proxy Host Payload", "required": true, @@ -49,7 +52,7 @@ "$ref": "../../../components/proxy-host-object.json#/properties/hsts_subdomains" }, "trust_forwarded_proto": { - "$ref": "../../../components/proxy-host-object.json#/properties/trust_forwarded_proto" + "$ref": "../../../components/proxy-host-object.json#/properties/trust_forwarded_proto" }, "http2_support": { "$ref": "../../../components/proxy-host-object.json#/properties/http2_support" diff --git a/backend/schema/paths/nginx/redirection-hosts/get.json b/backend/schema/paths/nginx/redirection-hosts/get.json index dfeb60497b..7e02ce6983 100644 --- a/backend/schema/paths/nginx/redirection-hosts/get.json +++ b/backend/schema/paths/nginx/redirection-hosts/get.json @@ -1,12 +1,17 @@ { "operationId": "getRedirectionHosts", "summary": "Get all Redirection hosts", - "tags": ["redirection-hosts"], + "tags": [ + "redirection-hosts" + ], "security": [ { - "bearerAuth": ["redirection_hosts.view"] + "bearerAuth": [ + "redirection_hosts.view" + ] } ], + "description": "Lists HTTP redirection hosts (domain-level redirects).", "parameters": [ { "in": "query", @@ -14,7 +19,10 @@ "description": "Expansions", "schema": { "type": "string", - "enum": ["owner", "certificate"] + "enum": [ + "owner", + "certificate" + ] } } ], @@ -31,7 +39,9 @@ "created_on": "2024-10-09T01:13:12.000Z", "modified_on": "2024-10-09T01:13:13.000Z", "owner_user_id": 1, - "domain_names": ["test.example.com"], + "domain_names": [ + "test.example.com" + ], "forward_domain_name": "something-else.com", "preserve_path": false, "certificate_id": 0, diff --git a/backend/schema/paths/nginx/redirection-hosts/hostID/delete.json b/backend/schema/paths/nginx/redirection-hosts/hostID/delete.json index 0b3232e810..be2eca5922 100644 --- a/backend/schema/paths/nginx/redirection-hosts/hostID/delete.json +++ b/backend/schema/paths/nginx/redirection-hosts/hostID/delete.json @@ -1,12 +1,17 @@ { "operationId": "deleteRedirectionHost", "summary": "Delete a Redirection Host", - "tags": ["redirection-hosts"], + "tags": [ + "redirection-hosts" + ], "security": [ { - "bearerAuth": ["redirection_hosts.manage"] + "bearerAuth": [ + "redirection_hosts.manage" + ] } ], + "description": "Deletes a redirection host by id.", "parameters": [ { "in": "path", diff --git a/backend/schema/paths/nginx/redirection-hosts/hostID/disable/post.json b/backend/schema/paths/nginx/redirection-hosts/hostID/disable/post.json index f44af11fd2..a6d4d42d01 100644 --- a/backend/schema/paths/nginx/redirection-hosts/hostID/disable/post.json +++ b/backend/schema/paths/nginx/redirection-hosts/hostID/disable/post.json @@ -1,12 +1,17 @@ { "operationId": "disableRedirectionHost", "summary": "Disable a Redirection Host", - "tags": ["redirection-hosts"], + "tags": [ + "redirection-hosts" + ], "security": [ { - "bearerAuth": ["redirection_hosts.manage"] + "bearerAuth": [ + "redirection_hosts.manage" + ] } ], + "description": "Disables a redirection host without deleting configuration.", "parameters": [ { "in": "path", diff --git a/backend/schema/paths/nginx/redirection-hosts/hostID/enable/post.json b/backend/schema/paths/nginx/redirection-hosts/hostID/enable/post.json index 07bf44dd3b..392f71bdbd 100644 --- a/backend/schema/paths/nginx/redirection-hosts/hostID/enable/post.json +++ b/backend/schema/paths/nginx/redirection-hosts/hostID/enable/post.json @@ -1,12 +1,17 @@ { "operationId": "enableRedirectionHost", "summary": "Enable a Redirection Host", - "tags": ["redirection-hosts"], + "tags": [ + "redirection-hosts" + ], "security": [ { - "bearerAuth": ["redirection_hosts.manage"] + "bearerAuth": [ + "redirection_hosts.manage" + ] } ], + "description": "Enables a redirection host in nginx.", "parameters": [ { "in": "path", diff --git a/backend/schema/paths/nginx/redirection-hosts/hostID/get.json b/backend/schema/paths/nginx/redirection-hosts/hostID/get.json index 577b5144a9..742e02ddcb 100644 --- a/backend/schema/paths/nginx/redirection-hosts/hostID/get.json +++ b/backend/schema/paths/nginx/redirection-hosts/hostID/get.json @@ -1,12 +1,17 @@ { "operationId": "getRedirectionHost", "summary": "Get a Redirection Host", - "tags": ["redirection-hosts"], + "tags": [ + "redirection-hosts" + ], "security": [ { - "bearerAuth": ["redirection_hosts.view"] + "bearerAuth": [ + "redirection_hosts.view" + ] } ], + "description": "Returns one redirection host by id.", "parameters": [ { "in": "path", @@ -32,7 +37,9 @@ "created_on": "2024-10-09T01:13:12.000Z", "modified_on": "2024-10-09T01:13:13.000Z", "owner_user_id": 1, - "domain_names": ["test.example.com"], + "domain_names": [ + "test.example.com" + ], "forward_domain_name": "something-else.com", "preserve_path": false, "certificate_id": 0, diff --git a/backend/schema/paths/nginx/redirection-hosts/hostID/put.json b/backend/schema/paths/nginx/redirection-hosts/hostID/put.json index 454a38805e..0636b4eb0f 100644 --- a/backend/schema/paths/nginx/redirection-hosts/hostID/put.json +++ b/backend/schema/paths/nginx/redirection-hosts/hostID/put.json @@ -1,12 +1,17 @@ { "operationId": "updateRedirectionHost", "summary": "Update a Redirection Host", - "tags": ["redirection-hosts"], + "tags": [ + "redirection-hosts" + ], "security": [ { - "bearerAuth": ["redirection_hosts.manage"] + "bearerAuth": [ + "redirection_hosts.manage" + ] } ], + "description": "Updates redirection host matching rules and destination.", "parameters": [ { "in": "path", @@ -86,7 +91,9 @@ "created_on": "2024-10-09T01:13:12.000Z", "modified_on": "2024-10-09T01:18:11.000Z", "owner_user_id": 1, - "domain_names": ["test.example.com"], + "domain_names": [ + "test.example.com" + ], "forward_domain_name": "something-else.com", "preserve_path": false, "certificate_id": 0, @@ -112,7 +119,9 @@ "name": "Administrator", "nickname": "Admin", "avatar": "", - "roles": ["admin"] + "roles": [ + "admin" + ] }, "certificate": null } diff --git a/backend/schema/paths/nginx/redirection-hosts/post.json b/backend/schema/paths/nginx/redirection-hosts/post.json index 6aa533010e..ebf587bf46 100644 --- a/backend/schema/paths/nginx/redirection-hosts/post.json +++ b/backend/schema/paths/nginx/redirection-hosts/post.json @@ -1,7 +1,9 @@ { "operationId": "createRedirectionHost", "summary": "Create a Redirection Host", - "tags": ["redirection-hosts"], + "tags": [ + "redirection-hosts" + ], "security": [ { "bearerAuth": [ @@ -9,6 +11,7 @@ ] } ], + "description": "Creates a redirection host with source domains and target URL or scheme.", "requestBody": { "description": "Redirection Host Payload", "required": true, diff --git a/backend/schema/paths/nginx/streams/get.json b/backend/schema/paths/nginx/streams/get.json index 6dda8e346b..e5027c4cc9 100644 --- a/backend/schema/paths/nginx/streams/get.json +++ b/backend/schema/paths/nginx/streams/get.json @@ -1,12 +1,17 @@ { "operationId": "getStreams", "summary": "Get all streams", - "tags": ["streams"], + "tags": [ + "streams" + ], "security": [ { - "bearerAuth": ["streams.view"] + "bearerAuth": [ + "streams.view" + ] } ], + "description": "Lists TCP/UDP stream proxies configured in NPM.", "parameters": [ { "in": "query", @@ -14,7 +19,10 @@ "description": "Expansions", "schema": { "type": "string", - "enum": ["owner", "certificate"] + "enum": [ + "owner", + "certificate" + ] } } ], diff --git a/backend/schema/paths/nginx/streams/post.json b/backend/schema/paths/nginx/streams/post.json index 0c986de8fa..b3822b6213 100644 --- a/backend/schema/paths/nginx/streams/post.json +++ b/backend/schema/paths/nginx/streams/post.json @@ -1,7 +1,9 @@ { "operationId": "createStream", "summary": "Create a Stream", - "tags": ["streams"], + "tags": [ + "streams" + ], "security": [ { "bearerAuth": [ @@ -9,6 +11,7 @@ ] } ], + "description": "Creates a layer-4 stream forwarding entry.", "requestBody": { "description": "Stream Payload", "required": true, diff --git a/backend/schema/paths/nginx/streams/streamID/delete.json b/backend/schema/paths/nginx/streams/streamID/delete.json index 585cd82d19..3da18b4669 100644 --- a/backend/schema/paths/nginx/streams/streamID/delete.json +++ b/backend/schema/paths/nginx/streams/streamID/delete.json @@ -1,12 +1,17 @@ { "operationId": "deleteStream", "summary": "Delete a Stream", - "tags": ["streams"], + "tags": [ + "streams" + ], "security": [ { - "bearerAuth": ["streams.manage"] + "bearerAuth": [ + "streams.manage" + ] } ], + "description": "Deletes a stream by id.", "parameters": [ { "in": "path", diff --git a/backend/schema/paths/nginx/streams/streamID/disable/post.json b/backend/schema/paths/nginx/streams/streamID/disable/post.json index 61de851682..6e3a61b2b1 100644 --- a/backend/schema/paths/nginx/streams/streamID/disable/post.json +++ b/backend/schema/paths/nginx/streams/streamID/disable/post.json @@ -1,12 +1,17 @@ { "operationId": "disableStream", "summary": "Disable a Stream", - "tags": ["streams"], + "tags": [ + "streams" + ], "security": [ { - "bearerAuth": ["streams.manage"] + "bearerAuth": [ + "streams.manage" + ] } ], + "description": "Disables a stream in nginx without deleting the record.", "parameters": [ { "in": "path", diff --git a/backend/schema/paths/nginx/streams/streamID/enable/post.json b/backend/schema/paths/nginx/streams/streamID/enable/post.json index d27ce5265e..56718a7cd9 100644 --- a/backend/schema/paths/nginx/streams/streamID/enable/post.json +++ b/backend/schema/paths/nginx/streams/streamID/enable/post.json @@ -1,12 +1,17 @@ { "operationId": "enableStream", "summary": "Enable a Stream", - "tags": ["streams"], + "tags": [ + "streams" + ], "security": [ { - "bearerAuth": ["streams.manage"] + "bearerAuth": [ + "streams.manage" + ] } ], + "description": "Enables a stream and reloads nginx configuration.", "parameters": [ { "in": "path", diff --git a/backend/schema/paths/nginx/streams/streamID/get.json b/backend/schema/paths/nginx/streams/streamID/get.json index 22fae8872b..f8962a6530 100644 --- a/backend/schema/paths/nginx/streams/streamID/get.json +++ b/backend/schema/paths/nginx/streams/streamID/get.json @@ -1,12 +1,17 @@ { "operationId": "getStream", "summary": "Get a Stream", - "tags": ["streams"], + "tags": [ + "streams" + ], "security": [ { - "bearerAuth": ["streams.view"] + "bearerAuth": [ + "streams.view" + ] } ], + "description": "Returns one stream definition by id.", "parameters": [ { "in": "path", diff --git a/backend/schema/paths/nginx/streams/streamID/put.json b/backend/schema/paths/nginx/streams/streamID/put.json index 21ae71ef7a..d13494af8b 100644 --- a/backend/schema/paths/nginx/streams/streamID/put.json +++ b/backend/schema/paths/nginx/streams/streamID/put.json @@ -1,12 +1,17 @@ { "operationId": "updateStream", "summary": "Update a Stream", - "tags": ["streams"], + "tags": [ + "streams" + ], "security": [ { - "bearerAuth": ["streams.manage"] + "bearerAuth": [ + "streams.manage" + ] } ], + "description": "Updates stream listen ports, upstream, or protocol options.", "parameters": [ { "in": "path", @@ -87,7 +92,9 @@ "name": "Administrator", "nickname": "Admin", "avatar": "", - "roles": ["admin"] + "roles": [ + "admin" + ] }, "certificate_id": 0 } diff --git a/backend/schema/paths/reports/hosts/get.json b/backend/schema/paths/reports/hosts/get.json index 682a97b882..2b81584b14 100644 --- a/backend/schema/paths/reports/hosts/get.json +++ b/backend/schema/paths/reports/hosts/get.json @@ -1,12 +1,15 @@ { "operationId": "reportsHosts", "summary": "Report on Host Statistics", - "tags": ["reports"], + "tags": [ + "reports" + ], "security": [ { "bearerAuth": [] } ], + "description": "Returns reporting data about configured hosts for dashboards and diagnostics.", "responses": { "200": { "description": "200 response", diff --git a/backend/schema/paths/schema/get.json b/backend/schema/paths/schema/get.json index c9e601eab9..c07e73ee89 100644 --- a/backend/schema/paths/schema/get.json +++ b/backend/schema/paths/schema/get.json @@ -1,7 +1,10 @@ { "operationId": "schema", "summary": "Returns this swagger API schema", - "tags": ["public"], + "tags": [ + "public" + ], + "description": "Returns the fully dereferenced OpenAPI document for this running instance. Used by dev Swagger on port 3082 and for live schema inspection.", "responses": { "200": { "description": "200 response" diff --git a/backend/schema/paths/settings/get.json b/backend/schema/paths/settings/get.json index a99f7f2206..d58b7a503a 100644 --- a/backend/schema/paths/settings/get.json +++ b/backend/schema/paths/settings/get.json @@ -1,12 +1,17 @@ { "operationId": "getSettings", "summary": "Get all settings", - "tags": ["settings"], + "tags": [ + "settings" + ], "security": [ { - "bearerAuth": ["admin"] + "bearerAuth": [ + "admin" + ] } ], + "description": "Lists application settings keys and values visible to the authenticated administrator.", "responses": { "200": { "description": "200 response", diff --git a/backend/schema/paths/settings/settingID/get.json b/backend/schema/paths/settings/settingID/get.json index 929f3e5f37..3083edaae7 100644 --- a/backend/schema/paths/settings/settingID/get.json +++ b/backend/schema/paths/settings/settingID/get.json @@ -1,12 +1,17 @@ { "operationId": "getSetting", "summary": "Get a setting", - "tags": ["settings"], + "tags": [ + "settings" + ], "security": [ { - "bearerAuth": ["admin"] + "bearerAuth": [ + "admin" + ] } ], + "description": "Returns one setting by id or key identifier.", "parameters": [ { "in": "path", diff --git a/backend/schema/paths/settings/settingID/put.json b/backend/schema/paths/settings/settingID/put.json index 050ad44125..366afff155 100644 --- a/backend/schema/paths/settings/settingID/put.json +++ b/backend/schema/paths/settings/settingID/put.json @@ -1,12 +1,17 @@ { "operationId": "updateSetting", "summary": "Update a setting", - "tags": ["settings"], + "tags": [ + "settings" + ], "security": [ { - "bearerAuth": ["admin"] + "bearerAuth": [ + "admin" + ] } ], + "description": "Updates a single application setting value.", "parameters": [ { "in": "path", @@ -14,7 +19,9 @@ "schema": { "type": "string", "minLength": 1, - "enum": ["default-site"] + "enum": [ + "default-site" + ] }, "required": true, "description": "Setting ID", @@ -34,7 +41,13 @@ "value": { "type": "string", "minLength": 1, - "enum": ["congratulations", "404", "444", "redirect", "html"], + "enum": [ + "congratulations", + "404", + "444", + "redirect", + "html" + ], "example": "html" }, "meta": { diff --git a/backend/schema/paths/tokens/2fa/post.json b/backend/schema/paths/tokens/2fa/post.json index c37af8d3a2..5e0222c53d 100644 --- a/backend/schema/paths/tokens/2fa/post.json +++ b/backend/schema/paths/tokens/2fa/post.json @@ -1,7 +1,10 @@ { "operationId": "loginWith2FA", "summary": "Verify 2FA code and get full token", - "tags": ["tokens"], + "tags": [ + "tokens" + ], + "description": "Completes login when two-factor authentication is required for the account.", "requestBody": { "description": "2fa Challenge Payload", "required": true, @@ -22,7 +25,10 @@ "example": "012345" } }, - "required": ["challenge_token", "code"], + "required": [ + "challenge_token", + "code" + ], "type": "object" }, "example": { diff --git a/backend/schema/paths/tokens/get.json b/backend/schema/paths/tokens/get.json index 4e6ae2449c..84189d3e88 100644 --- a/backend/schema/paths/tokens/get.json +++ b/backend/schema/paths/tokens/get.json @@ -1,12 +1,15 @@ { "operationId": "refreshToken", "summary": "Refresh your access token", - "tags": ["tokens"], + "tags": [ + "tokens" + ], "security": [ { "bearerAuth": [] } ], + "description": "Refreshes an existing JWT using a valid refresh token cookie or body field.", "responses": { "200": { "description": "200 response", diff --git a/backend/schema/paths/tokens/post.json b/backend/schema/paths/tokens/post.json index 470be30314..03ab054d2f 100644 --- a/backend/schema/paths/tokens/post.json +++ b/backend/schema/paths/tokens/post.json @@ -1,7 +1,10 @@ { "operationId": "requestToken", "summary": "Request a new access token from credentials", - "tags": ["tokens"], + "tags": [ + "tokens" + ], + "description": "Authenticates with email and password and returns JWT access and refresh tokens.", "requestBody": { "description": "Credentials Payload", "required": true, @@ -18,7 +21,9 @@ "scope": { "minLength": 1, "type": "string", - "enum": ["user"], + "enum": [ + "user" + ], "example": "user" }, "secret": { @@ -27,7 +32,10 @@ "example": "bigredhorsebanana" } }, - "required": ["identity", "secret"], + "required": [ + "identity", + "secret" + ], "type": "object" }, "example": { diff --git a/backend/schema/paths/users/get.json b/backend/schema/paths/users/get.json index 79c31ba808..15638a563f 100644 --- a/backend/schema/paths/users/get.json +++ b/backend/schema/paths/users/get.json @@ -1,12 +1,17 @@ { "operationId": "getUsers", "summary": "Get all users", - "tags": ["users"], + "tags": [ + "users" + ], "security": [ { - "bearerAuth": ["admin"] + "bearerAuth": [ + "admin" + ] } ], + "description": "Lists administrator accounts and role assignments.", "parameters": [ { "in": "query", @@ -14,7 +19,9 @@ "description": "Expansions", "schema": { "type": "string", - "enum": ["permissions"] + "enum": [ + "permissions" + ] } } ], @@ -35,7 +42,9 @@ "name": "Jamie Curnow", "nickname": "James", "avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm", - "roles": ["admin"] + "roles": [ + "admin" + ] } ] }, @@ -50,7 +59,9 @@ "name": "Jamie Curnow", "nickname": "James", "avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm", - "roles": ["admin"], + "roles": [ + "admin" + ], "permissions": { "visibility": "all", "proxy_hosts": "manage", @@ -58,7 +69,8 @@ "dead_hosts": "manage", "streams": "manage", "access_lists": "manage", - "certificates": "manage" + "certificates": "manage", + "credentials": "manage" } } ] diff --git a/backend/schema/paths/users/post.json b/backend/schema/paths/users/post.json index 49025e3250..db4ac5067c 100644 --- a/backend/schema/paths/users/post.json +++ b/backend/schema/paths/users/post.json @@ -1,12 +1,17 @@ { "operationId": "createUser", "summary": "Create a User", - "tags": ["users"], + "tags": [ + "users" + ], "security": [ { - "bearerAuth": ["admin"] + "bearerAuth": [ + "admin" + ] } ], + "description": "Creates a new administrator user with roles and permissions.", "requestBody": { "description": "User Payload", "required": true, @@ -15,7 +20,11 @@ "schema": { "type": "object", "additionalProperties": false, - "required": ["name", "nickname", "email"], + "required": [ + "name", + "nickname", + "email" + ], "properties": { "name": { "$ref": "../../components/user-object.json#/properties/name" @@ -61,7 +70,9 @@ "name": "Jamie Curnow", "nickname": "James", "avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm", - "roles": ["admin"], + "roles": [ + "admin" + ], "permissions": { "id": 3, "created_on": "2020-01-30T09:41:04.000Z", @@ -73,7 +84,8 @@ "dead_hosts": "manage", "streams": "manage", "access_lists": "manage", - "certificates": "manage" + "certificates": "manage", + "credentials": "manage" } } } diff --git a/backend/schema/paths/users/userID/2fa/backup-codes/post.json b/backend/schema/paths/users/userID/2fa/backup-codes/post.json index 00cb9d5f10..233fe56d3a 100644 --- a/backend/schema/paths/users/userID/2fa/backup-codes/post.json +++ b/backend/schema/paths/users/userID/2fa/backup-codes/post.json @@ -1,7 +1,10 @@ { "operationId": "regenUser2faCodes", "summary": "Regenerate 2FA backup codes", - "tags": ["users"], + "tags": [ + "users" + ], + "description": "Regenerates one-time backup codes after verifying an existing TOTP code.", "parameters": [ { "in": "path", @@ -30,7 +33,9 @@ "example": "123456" } }, - "required": ["code"], + "required": [ + "code" + ], "type": "object" }, "example": { @@ -61,7 +66,9 @@ }, "schema": { "type": "object", - "required": ["backup_codes"], + "required": [ + "backup_codes" + ], "additionalProperties": false, "properties": { "backup_codes": { diff --git a/backend/schema/paths/users/userID/2fa/delete.json b/backend/schema/paths/users/userID/2fa/delete.json index bff292d829..53092babf0 100644 --- a/backend/schema/paths/users/userID/2fa/delete.json +++ b/backend/schema/paths/users/userID/2fa/delete.json @@ -1,7 +1,10 @@ { "operationId": "disableUser2fa", "summary": "Disable 2fa for user", - "tags": ["users"], + "tags": [ + "users" + ], + "description": "Disables two-factor authentication for a user (requires administrative permission).", "parameters": [ { "in": "path", diff --git a/backend/schema/paths/users/userID/2fa/enable/post.json b/backend/schema/paths/users/userID/2fa/enable/post.json index 74c9854085..3a790e0827 100644 --- a/backend/schema/paths/users/userID/2fa/enable/post.json +++ b/backend/schema/paths/users/userID/2fa/enable/post.json @@ -1,7 +1,10 @@ { "operationId": "enableUser2fa", "summary": "Verify code and enable 2FA", - "tags": ["users"], + "tags": [ + "users" + ], + "description": "Confirms TOTP enrollment with a verification code and enables 2FA.", "parameters": [ { "in": "path", @@ -30,7 +33,9 @@ "example": "123456" } }, - "required": ["code"], + "required": [ + "code" + ], "type": "object" }, "example": { @@ -61,7 +66,9 @@ }, "schema": { "type": "object", - "required": ["backup_codes"], + "required": [ + "backup_codes" + ], "additionalProperties": false, "properties": { "backup_codes": { diff --git a/backend/schema/paths/users/userID/2fa/get.json b/backend/schema/paths/users/userID/2fa/get.json index 78ce1886a8..b4102e1bd9 100644 --- a/backend/schema/paths/users/userID/2fa/get.json +++ b/backend/schema/paths/users/userID/2fa/get.json @@ -1,12 +1,15 @@ { "operationId": "getUser2faStatus", "summary": "Get user 2fa Status", - "tags": ["users"], + "tags": [ + "users" + ], "security": [ { "bearerAuth": [] } ], + "description": "Returns whether two-factor authentication is enabled for the user.", "parameters": [ { "in": "path", @@ -36,7 +39,10 @@ "schema": { "type": "object", "additionalProperties": false, - "required": ["enabled", "backup_codes_remaining"], + "required": [ + "enabled", + "backup_codes_remaining" + ], "properties": { "enabled": { "type": "boolean", diff --git a/backend/schema/paths/users/userID/2fa/post.json b/backend/schema/paths/users/userID/2fa/post.json index cef5d196e1..1bf26c1df1 100644 --- a/backend/schema/paths/users/userID/2fa/post.json +++ b/backend/schema/paths/users/userID/2fa/post.json @@ -1,7 +1,10 @@ { "operationId": "setupUser2fa", "summary": "Start 2FA setup, returns QR code URL", - "tags": ["users"], + "tags": [ + "users" + ], + "description": "Starts TOTP enrollment and returns QR code / secret material for the user.", "parameters": [ { "in": "path", @@ -29,7 +32,10 @@ }, "schema": { "type": "object", - "required": ["secret", "otpauth_url"], + "required": [ + "secret", + "otpauth_url" + ], "additionalProperties": false, "properties": { "secret": { diff --git a/backend/schema/paths/users/userID/auth/put.json b/backend/schema/paths/users/userID/auth/put.json index 3dba45b5a1..99882fd00e 100644 --- a/backend/schema/paths/users/userID/auth/put.json +++ b/backend/schema/paths/users/userID/auth/put.json @@ -1,12 +1,17 @@ { "operationId": "updateUserAuth", "summary": "Update a User's Authentication", - "tags": ["users"], + "tags": [ + "users" + ], "security": [ { - "bearerAuth": ["admin"] + "bearerAuth": [ + "admin" + ] } ], + "description": "Updates password or authentication-related fields for a user.", "parameters": [ { "in": "path", @@ -35,7 +40,10 @@ "application/json": { "schema": { "type": "object", - "required": ["type", "secret"], + "required": [ + "type", + "secret" + ], "properties": { "type": { "type": "string", diff --git a/backend/schema/paths/users/userID/delete.json b/backend/schema/paths/users/userID/delete.json index 767edfe89d..0c7579b481 100644 --- a/backend/schema/paths/users/userID/delete.json +++ b/backend/schema/paths/users/userID/delete.json @@ -1,12 +1,17 @@ { "operationId": "deleteUser", "summary": "Delete a User", - "tags": ["users"], + "tags": [ + "users" + ], "security": [ { - "bearerAuth": ["admin"] + "bearerAuth": [ + "admin" + ] } ], + "description": "Deletes a user account by id.", "parameters": [ { "in": "path", diff --git a/backend/schema/paths/users/userID/get.json b/backend/schema/paths/users/userID/get.json index 2cf5587d9f..597f78a34a 100644 --- a/backend/schema/paths/users/userID/get.json +++ b/backend/schema/paths/users/userID/get.json @@ -1,12 +1,17 @@ { "operationId": "getUser", "summary": "Get a user", - "tags": ["users"], + "tags": [ + "users" + ], "security": [ { - "bearerAuth": ["admin"] + "bearerAuth": [ + "admin" + ] } ], + "description": "Returns one user record by id.", "parameters": [ { "in": "path", @@ -44,7 +49,9 @@ "name": "Jamie Curnow", "nickname": "James", "avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm", - "roles": ["admin"] + "roles": [ + "admin" + ] } } }, diff --git a/backend/schema/paths/users/userID/login/post.json b/backend/schema/paths/users/userID/login/post.json index 46001d2ec3..b741b02dbc 100644 --- a/backend/schema/paths/users/userID/login/post.json +++ b/backend/schema/paths/users/userID/login/post.json @@ -1,12 +1,17 @@ { "operationId": "loginAsUser", "summary": "Login as this user", - "tags": ["users"], + "tags": [ + "users" + ], "security": [ { - "bearerAuth": ["admin"] + "bearerAuth": [ + "admin" + ] } ], + "description": "Issues a session token for the target user (administrative impersonation).", "parameters": [ { "in": "path", @@ -47,7 +52,11 @@ "schema": { "type": "object", "description": "Login object", - "required": ["expires", "token", "user"], + "required": [ + "expires", + "token", + "user" + ], "additionalProperties": false, "properties": { "token": { diff --git a/backend/schema/paths/users/userID/permissions/put.json b/backend/schema/paths/users/userID/permissions/put.json index 764e7466cc..fcf167f54f 100644 --- a/backend/schema/paths/users/userID/permissions/put.json +++ b/backend/schema/paths/users/userID/permissions/put.json @@ -1,12 +1,17 @@ { "operationId": "updateUserPermissions", "summary": "Update a User's Permissions", - "tags": ["users"], + "tags": [ + "users" + ], "security": [ { - "bearerAuth": ["admin"] + "bearerAuth": [ + "admin" + ] } ], + "description": "Updates fine-grained permissions and roles assigned to a user.", "parameters": [ { "in": "path", diff --git a/backend/schema/paths/users/userID/put.json b/backend/schema/paths/users/userID/put.json index eabaa3a0ea..6a12ffc5e7 100644 --- a/backend/schema/paths/users/userID/put.json +++ b/backend/schema/paths/users/userID/put.json @@ -1,12 +1,17 @@ { "operationId": "updateUser", "summary": "Update a User", - "tags": ["users"], + "tags": [ + "users" + ], "security": [ { - "bearerAuth": ["admin"] + "bearerAuth": [ + "admin" + ] } ], + "description": "Updates user profile fields such as name or email.", "parameters": [ { "in": "path", @@ -74,7 +79,9 @@ "name": "Jamie Curnow", "nickname": "James", "avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm", - "roles": ["admin"] + "roles": [ + "admin" + ] } } }, diff --git a/backend/schema/paths/version/check/get.json b/backend/schema/paths/version/check/get.json index cbc576a7f5..fc84a5825a 100644 --- a/backend/schema/paths/version/check/get.json +++ b/backend/schema/paths/version/check/get.json @@ -1,7 +1,10 @@ { "operationId": "checkVersion", "summary": "Returns any new version data from github", - "tags": ["public"], + "tags": [ + "public" + ], + "description": "Checks whether a newer upstream release is available compared to the running version.", "responses": { "200": { "description": "200 response", diff --git a/backend/schema/paths/webhooks/get.json b/backend/schema/paths/webhooks/get.json new file mode 100644 index 0000000000..c81f9f19b5 --- /dev/null +++ b/backend/schema/paths/webhooks/get.json @@ -0,0 +1,26 @@ +{ + "operationId": "listWebhooks", + "summary": "List webhook endpoints", + "tags": [ + "webhooks" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "description": "Lists outbound webhook endpoints configured for automation events.", + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "example": [], + "schema": { + "$ref": "../../components/webhook-list.json" + } + } + } + } + } +} diff --git a/backend/schema/paths/webhooks/post.json b/backend/schema/paths/webhooks/post.json new file mode 100644 index 0000000000..6977003060 --- /dev/null +++ b/backend/schema/paths/webhooks/post.json @@ -0,0 +1,82 @@ +{ + "operationId": "createWebhook", + "summary": "Create a webhook endpoint", + "tags": [ + "webhooks" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "description": "Creates a webhook endpoint with optional HMAC signing secret.", + "requestBody": { + "description": "Webhook endpoint configuration", + "required": true, + "content": { + "application/json": { + "example": { + "name": "Cypress webhook", + "url": "http://127.0.0.1:65535/npm-webhook-test", + "events": ["certificate.created"] + }, + "schema": { + "type": "object", + "required": [ + "name", + "url", + "events" + ], + "properties": { + "name": { + "type": "string", + "example": "Cypress webhook" + }, + "url": { + "type": "string", + "example": "http://127.0.0.1:65535/npm-webhook-test" + }, + "events": { + "type": "array", + "items": { + "type": "string" + }, + "example": ["certificate.created"] + }, + "secret": { + "type": "string", + "example": "custom-signing-secret" + }, + "is_enabled": { + "type": "boolean", + "example": true + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "example": { + "id": 1, + "created_on": "2026-06-05T06:20:47.000Z", + "modified_on": "2026-06-05T06:20:47.000Z", + "owner_user_id": 1, + "name": "Cypress webhook", + "url": "http://127.0.0.1:65535/npm-webhook-test", + "events": ["certificate.created"], + "is_enabled": 1, + "secret": "ff387bfac72d5913371afd9d8c651e61369f2ba886b2d72a9402f441913aa279" + }, + "schema": { + "$ref": "../../components/webhook-object.json" + } + } + } + } + } +} diff --git a/backend/schema/paths/webhooks/webhookID/delete.json b/backend/schema/paths/webhooks/webhookID/delete.json new file mode 100644 index 0000000000..990a03bcc3 --- /dev/null +++ b/backend/schema/paths/webhooks/webhookID/delete.json @@ -0,0 +1,31 @@ +{ + "operationId": "deleteWebhook", + "summary": "Delete a webhook endpoint", + "tags": [ + "webhooks" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "description": "Deletes a webhook configuration by id.", + "parameters": [ + { + "in": "path", + "name": "webhookID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "Webhook endpoint ID", + "example": 1 + } + ], + "responses": { + "200": { + "description": "OK" + } + } +} diff --git a/backend/schema/scripts/apply-operation-descriptions.mjs b/backend/schema/scripts/apply-operation-descriptions.mjs new file mode 100644 index 0000000000..7317509d09 --- /dev/null +++ b/backend/schema/scripts/apply-operation-descriptions.mjs @@ -0,0 +1,62 @@ +#!/usr/bin/env node +/** + * Add operation-level `description` to path fragment JSON files (Vacuum operation-description). + * Run from repo root: node backend/schema/scripts/apply-operation-descriptions.mjs + */ +import { readFileSync, writeFileSync, readdirSync, statSync } from "node:fs"; +import { join, dirname } from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const PATHS_DIR = join(__dirname, "..", "paths"); + +/** operationId → operation description (min quality for Vacuum / Redoc) */ +const DESCRIPTIONS = JSON.parse( + readFileSync(join(__dirname, "operation-descriptions.json"), "utf8"), +); + + +const walk = (dir, files = []) => { + for (const name of readdirSync(dir)) { + const p = join(dir, name); + if (statSync(p).isDirectory()) walk(p, files); + else if (name.endsWith(".json")) files.push(p); + } + return files; +}; + +let updated = 0; +let skipped = 0; + +for (const file of walk(PATHS_DIR)) { + const raw = readFileSync(file, "utf8"); + const op = JSON.parse(raw); + if (!op.operationId) { + skipped++; + continue; + } + const text = DESCRIPTIONS[op.operationId]; + if (!text) { + console.warn(`No description mapping for ${op.operationId} in ${file}`); + skipped++; + continue; + } + if (op.description === text) { + skipped++; + continue; + } + const ordered = { ...op, description: text }; + const { operationId, summary, tags, security, description, ...rest } = ordered; + const out = { + operationId, + summary, + ...(tags ? { tags } : {}), + ...(security ? { security } : {}), + description, + ...rest, + }; + writeFileSync(file, `${JSON.stringify(out, null, "\t")}\n`, "utf8"); + updated++; +} + +console.log(`Updated ${updated} path files, skipped ${skipped}.`); diff --git a/backend/schema/scripts/operation-descriptions.json b/backend/schema/scripts/operation-descriptions.json new file mode 100644 index 0000000000..f14766a93a --- /dev/null +++ b/backend/schema/scripts/operation-descriptions.json @@ -0,0 +1,93 @@ +{ + "health": "Public health check for the admin API. Returns setup status and semantic version fields without authentication.", + "schema": "Returns the fully dereferenced OpenAPI document for this running instance. Used by dev Swagger on port 3082 and for live schema inspection.", + "listApiKeys": "Lists automation tokens. Secrets are never returned; each entry indicates whether a token is still configured.", + "createApiKey": "Creates a long-lived automation token. The raw value is returned once in the response and cannot be retrieved again.", + "deleteApiKey": "Revokes an automation token by id. Revoked tokens fail authentication immediately.", + "getAuditLogs": "Returns paginated audit log entries for administrative review.", + "getAuditLog": "Returns a single audit log entry by id.", + "listCredentialProviders": "Lists external credential store providers (Vault, AWS, Azure, Infisical, HTTP). Client secrets are not included in responses.", + "createCredentialProvider": "Registers an external credential store provider. OIDC or Universal Auth credentials are stored encrypted under the data volume.", + "getCredentialProvider": "Returns one credential provider configuration by id without secret material.", + "updateCredentialProvider": "Updates provider settings. Omit secret fields to keep existing encrypted values.", + "deleteCredentialProvider": "Soft-deletes a credential provider. Existing certificate references may fail resolution until updated.", + "testCredentialProvider": "Verifies that the provider can obtain an access token (Vault/AWS/HTTP OIDC client credentials or Infisical Universal Auth).", + "testCredentialProviderResolve": "Tests resolving a secret path through the provider without returning secret contents (response includes byte length only).", + "listCredentials": "Lists DNS credentials stored in the encrypted NPM vault on the data volume.", + "createCredential": "Creates a named DNS credential (certbot provider INI) in the internal vault for certificate issuance.", + "getCredential": "Returns metadata for one stored DNS credential. Secret payload is not exposed.", + "updateCredential": "Updates a stored DNS credential name or encrypted provider configuration.", + "deleteCredential": "Deletes a stored DNS credential from the vault.", + "testCredential": "Validates that a stored credential can be decrypted and parsed for the configured DNS provider.", + "migrateLegacyCredentials": "Moves inline DNS provider credentials from certificates into the vault. Supports dry-run preview before apply.", + "listJobs": "Lists recent asynchronous automation jobs (certificate issuance, migrations, etc.).", + "getJob": "Returns status and result metadata for one background job by id.", + "listWebhooks": "Lists outbound webhook endpoints configured for automation events.", + "createWebhook": "Creates a webhook endpoint with optional HMAC signing secret.", + "deleteWebhook": "Deletes a webhook configuration by id.", + "getAccessLists": "Returns all access lists (HTTP authentication and access rules) configured in NPM.", + "createAccessList": "Creates an access list for use on proxy hosts, redirection hosts, or streams.", + "getAccessList": "Returns one access list including authorization and access rule entries.", + "updateAccessList": "Updates an access list and its nested auth or access items.", + "deleteAccessList": "Deletes an access list. Hosts referencing it must be updated separately.", + "getCertificates": "Lists SSL certificates known to NPM including managed, custom, and in-progress orders.", + "createCertificate": "Requests a new certificate (HTTP, DNS, or custom workflow depending on payload).", + "getCertificate": "Returns one certificate record and metadata by id.", + "updateCertificate": "Updates certificate metadata such as friendly name or linked hosts.", + "deleteCertificate": "Deletes a certificate record. Does not remove files already deployed to disk until nginx is reloaded.", + "downloadCertificate": "Downloads certificate and private key material for a certificate id (requires permission).", + "renewCertificate": "Triggers renewal for an existing managed certificate.", + "uploadCertificate": "Uploads custom certificate and key files for use on proxy hosts.", + "getDNSProviders": "Lists DNS providers supported for ACME DNS challenge certificate issuance.", + "testHttpReach": "Tests HTTP reachability for domain validation prior to certificate issuance.", + "validateCertificates": "Validates stored certificates and reports expiry or configuration issues.", + "getDeadHosts": "Lists 404 / catch-all hosts (dead hosts) configured in NPM.", + "create404Host": "Creates a 404 host that serves a default site when no other host matches.", + "getDeadHost": "Returns one 404 host configuration by id.", + "updateDeadHost": "Updates a 404 host domain names, forwarding, or enabled state.", + "deleteDeadHost": "Deletes a 404 host by id.", + "disableDeadHost": "Disables a 404 host without deleting its configuration.", + "enableDeadHost": "Enables a previously disabled 404 host and reloads nginx when required.", + "getProxyHosts": "Lists reverse proxy hosts (domain to upstream mapping).", + "createProxyHost": "Creates a proxy host with domain names, upstream target, and optional TLS and access settings.", + "getProxyHost": "Returns one proxy host by id.", + "updateProxyHost": "Updates proxy host domains, upstream, advanced options, or certificate linkage.", + "deleteProxyHost": "Deletes a proxy host by id.", + "disableProxyHost": "Disables a proxy host in nginx without removing the database record.", + "enableProxyHost": "Enables a proxy host and applies nginx configuration.", + "getRedirectionHosts": "Lists HTTP redirection hosts (domain-level redirects).", + "createRedirectionHost": "Creates a redirection host with source domains and target URL or scheme.", + "getRedirectionHost": "Returns one redirection host by id.", + "updateRedirectionHost": "Updates redirection host matching rules and destination.", + "deleteRedirectionHost": "Deletes a redirection host by id.", + "disableRedirectionHost": "Disables a redirection host without deleting configuration.", + "enableRedirectionHost": "Enables a redirection host in nginx.", + "getStreams": "Lists TCP/UDP stream proxies configured in NPM.", + "createStream": "Creates a layer-4 stream forwarding entry.", + "getStream": "Returns one stream definition by id.", + "updateStream": "Updates stream listen ports, upstream, or protocol options.", + "deleteStream": "Deletes a stream by id.", + "disableStream": "Disables a stream in nginx without deleting the record.", + "enableStream": "Enables a stream and reloads nginx configuration.", + "reportsHosts": "Returns reporting data about configured hosts for dashboards and diagnostics.", + "getSettings": "Lists application settings keys and values visible to the authenticated administrator.", + "getSetting": "Returns one setting by id or key identifier.", + "updateSetting": "Updates a single application setting value.", + "refreshToken": "Refreshes an existing JWT using a valid refresh token cookie or body field.", + "requestToken": "Authenticates with email and password and returns JWT access and refresh tokens.", + "loginWith2FA": "Completes login when two-factor authentication is required for the account.", + "getUsers": "Lists administrator accounts and role assignments.", + "createUser": "Creates a new administrator user with roles and permissions.", + "getUser": "Returns one user record by id.", + "updateUser": "Updates user profile fields such as name or email.", + "deleteUser": "Deletes a user account by id.", + "disableUser2fa": "Disables two-factor authentication for a user (requires administrative permission).", + "getUser2faStatus": "Returns whether two-factor authentication is enabled for the user.", + "setupUser2fa": "Starts TOTP enrollment and returns QR code / secret material for the user.", + "regenUser2faCodes": "Regenerates one-time backup codes after verifying an existing TOTP code.", + "enableUser2fa": "Confirms TOTP enrollment with a verification code and enables 2FA.", + "updateUserAuth": "Updates password or authentication-related fields for a user.", + "loginAsUser": "Issues a session token for the target user (administrative impersonation).", + "updateUserPermissions": "Updates fine-grained permissions and roles assigned to a user.", + "checkVersion": "Checks whether a newer upstream release is available compared to the running version." +} diff --git a/backend/schema/swagger.json b/backend/schema/swagger.json index 4222f19ddd..27f17b695b 100644 --- a/backend/schema/swagger.json +++ b/backend/schema/swagger.json @@ -32,6 +32,26 @@ "name": "certificates", "description": "Endpoints related to Certificates" }, + { + "name": "credentials", + "description": "Endpoints related to stored DNS credentials" + }, + { + "name": "credential-providers", + "description": "External secret store providers (Vault, AWS, Azure, Infisical)" + }, + { + "name": "api-keys", + "description": "Endpoints for automation API keys" + }, + { + "name": "jobs", + "description": "Endpoints for async background jobs" + }, + { + "name": "webhooks", + "description": "Endpoints for outbound webhook configuration" + }, { "name": "404-hosts", "description": "Endpoints related to 404 Hosts" @@ -357,6 +377,100 @@ "post": { "$ref": "./paths/users/userID/login/post.json" } + }, + "/credentials": { + "get": { + "$ref": "./paths/credentials/get.json" + }, + "post": { + "$ref": "./paths/credentials/post.json" + } + }, + "/credentials/migrate-legacy": { + "post": { + "$ref": "./paths/credentials/migrate-legacy/post.json" + } + }, + "/credentials/{credentialID}": { + "get": { + "$ref": "./paths/credentials/credentialID/get.json" + }, + "put": { + "$ref": "./paths/credentials/credentialID/put.json" + }, + "delete": { + "$ref": "./paths/credentials/credentialID/delete.json" + } + }, + "/credentials/{credentialID}/test": { + "post": { + "$ref": "./paths/credentials/credentialID/test/post.json" + } + }, + "/credential-providers": { + "get": { + "$ref": "./paths/credential-providers/get.json" + }, + "post": { + "$ref": "./paths/credential-providers/post.json" + } + }, + "/credential-providers/{providerID}": { + "get": { + "$ref": "./paths/credential-providers/providerID/get.json" + }, + "put": { + "$ref": "./paths/credential-providers/providerID/put.json" + }, + "delete": { + "$ref": "./paths/credential-providers/providerID/delete.json" + } + }, + "/credential-providers/{providerID}/test": { + "post": { + "$ref": "./paths/credential-providers/providerID/test/post.json" + } + }, + "/credential-providers/{providerID}/test-resolve": { + "post": { + "$ref": "./paths/credential-providers/providerID/test-resolve/post.json" + } + }, + "/api-keys": { + "get": { + "$ref": "./paths/api-keys/get.json" + }, + "post": { + "$ref": "./paths/api-keys/post.json" + } + }, + "/api-keys/{apiKeyID}": { + "delete": { + "$ref": "./paths/api-keys/apiKeyID/delete.json" + } + }, + "/jobs": { + "get": { + "$ref": "./paths/jobs/get.json" + } + }, + "/jobs/{jobID}": { + "get": { + "$ref": "./paths/jobs/jobID/get.json" + } + }, + "/webhooks": { + "get": { + "$ref": "./paths/webhooks/get.json" + }, + "post": { + "$ref": "./paths/webhooks/post.json" + } + }, + "/webhooks/{webhookID}": { + "delete": { + "$ref": "./paths/webhooks/webhookID/delete.json" + } } } } diff --git a/backend/setup.js b/backend/setup.js index 84f42793ea..99279d9c5a 100644 --- a/backend/setup.js +++ b/backend/setup.js @@ -1,4 +1,6 @@ import { installPlugins } from "./lib/certbot.js"; +import { materializeCertbotCredentials } from "./lib/secrets/resolve.js"; +import { ensureCredentialDirs } from "./lib/secrets/storage.js"; import utils from "./lib/utils.js"; import { setup as logger } from "./logger.js"; import authModel from "./models/auth.js"; @@ -61,6 +63,7 @@ const setupDefaultUser = async () => { user_id: user.id, visibility: "all", proxy_hosts: "manage", + credentials: "manage", redirection_hosts: "manage", dead_hosts: "manage", streams: "manage", @@ -118,15 +121,18 @@ const setupCertbotPlugins = async () => { plugins.push(certificate.meta.dns_provider); } - // Make sure credentials file exists - const credentials_loc = `/etc/letsencrypt/credentials/credentials-${certificate.id}`; - // Escape single quotes and backslashes - if (typeof certificate.meta.dns_provider_credentials === "string") { - const escapedCredentials = certificate.meta.dns_provider_credentials - .replaceAll("'", "\\'") - .replaceAll("\\", "\\\\"); - const credentials_cmd = `[ -f '${credentials_loc}' ] || { mkdir -p /etc/letsencrypt/credentials 2> /dev/null; echo '${escapedCredentials}' > '${credentials_loc}' && chmod 600 '${credentials_loc}'; }`; - promises.push(utils.exec(credentials_cmd)); + // Make sure credentials file exists (from vault or legacy meta) + if ( + certificate.meta?.credential_ref?.type === "internal" || + typeof certificate.meta.dns_provider_credentials === "string" + ) { + promises.push( + materializeCertbotCredentials(certificate).catch((err) => { + logger.warn( + `Could not restore credentials for certificate #${certificate.id}: ${err.message}`, + ); + }), + ); } } return true; @@ -163,4 +169,10 @@ const setupLogrotation = () => { return runLogrotate(); }; -export default () => setupDefaultUser().then(setupDefaultSettings).then(setupCertbotPlugins).then(setupLogrotation); +export default () => { + ensureCredentialDirs(); + return setupDefaultUser() + .then(setupDefaultSettings) + .then(setupCertbotPlugins) + .then(setupLogrotation); +}; diff --git a/backend/yarn.lock b/backend/yarn.lock deleted file mode 100644 index 427e834fa1..0000000000 --- a/backend/yarn.lock +++ /dev/null @@ -1,2495 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@apidevtools/json-schema-ref-parser@14.0.1": - version "14.0.1" - resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-14.0.1.tgz#3bc445ed2eddf72bc2f9eb2e295c696bdc5be725" - integrity sha512-Oc96zvmxx1fqoSEdUmfmvvb59/KDOnUoJ7s2t7bISyAn0XEz57LCCw8k2Y4Pf3mwKaZLMciESALORLgfe2frCw== - dependencies: - "@types/json-schema" "^7.0.15" - js-yaml "^4.1.0" - -"@apidevtools/json-schema-ref-parser@^15.3.5": - version "15.3.5" - resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-15.3.5.tgz#503726178d8d792eea7b195566272aaee6837e2f" - integrity sha512-orNOYXw3hYXxxisXMldjzjBzqqTLBPbwOtHg7ovBPvfBHDue1qM9YJENZ3W2BQuS+7z4ThogMbEzEsov57Itkg== - dependencies: - js-yaml "^4.1.1" - -"@apidevtools/openapi-schemas@^2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz#9fa08017fb59d80538812f03fc7cac5992caaa17" - integrity sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ== - -"@apidevtools/swagger-methods@^3.0.2": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz#b789a362e055b0340d04712eafe7027ddc1ac267" - integrity sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg== - -"@apidevtools/swagger-parser@^12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@apidevtools/swagger-parser/-/swagger-parser-12.1.0.tgz#ef73e5f9e32c2becef6d95b90fb4481b0fec8fe4" - integrity sha512-e5mJoswsnAX0jG+J09xHFYQXb/bUc5S3pLpMxUuRUA2H8T2kni3yEoyz2R3Dltw5f4A6j6rPNMpWTK+iVDFlng== - dependencies: - "@apidevtools/json-schema-ref-parser" "14.0.1" - "@apidevtools/openapi-schemas" "^2.1.0" - "@apidevtools/swagger-methods" "^3.0.2" - ajv "^8.17.1" - ajv-draft-04 "^1.0.0" - call-me-maybe "^1.0.2" - -"@biomejs/biome@^2.4.15": - version "2.4.15" - resolved "https://registry.yarnpkg.com/@biomejs/biome/-/biome-2.4.15.tgz#cb84ad6eb4235e7230b3c105a825e9bc03399944" - integrity sha512-j5VH3a/h/HXTKBM50MDMxRCzkeLv9S2XJcW2WgnZT1+xyisi+0bISrXR82gCX+8S9lvK0skEvHJRN+3Ktr2hlw== - optionalDependencies: - "@biomejs/cli-darwin-arm64" "2.4.15" - "@biomejs/cli-darwin-x64" "2.4.15" - "@biomejs/cli-linux-arm64" "2.4.15" - "@biomejs/cli-linux-arm64-musl" "2.4.15" - "@biomejs/cli-linux-x64" "2.4.15" - "@biomejs/cli-linux-x64-musl" "2.4.15" - "@biomejs/cli-win32-arm64" "2.4.15" - "@biomejs/cli-win32-x64" "2.4.15" - -"@biomejs/cli-darwin-arm64@2.4.15": - version "2.4.15" - resolved "https://registry.yarnpkg.com/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.4.15.tgz#3469daa56ac3ff4f16588a120df706381a96f65c" - integrity sha512-rF3PPqLq1yoST79zaQbDjVJwsuIeci/O+9bgNmC5QpgOqz6aqYuzA4abyAGx+mgyiDXn4A049xAN8gijbuR1Qg== - -"@biomejs/cli-darwin-x64@2.4.15": - version "2.4.15" - resolved "https://registry.yarnpkg.com/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.4.15.tgz#0697b81089409635da16682ac1e539165c262006" - integrity sha512-/5KHXYMfSJs1fNXiX30xFtI8JcCFV6zaVVLxOa0M2sfqBKHkpQhRTv94yxQWxeTY2lzo2OuTlNvPC+hDQt2wcQ== - -"@biomejs/cli-linux-arm64-musl@2.4.15": - version "2.4.15" - resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.4.15.tgz#c6af054e3732c361e9ad8c44070f909666b5616f" - integrity sha512-ZPcxznxm0pogHBLZhYntyR3sR+MrZjqJIKEr7ZqVen0Rl+P/4upVmfYXjftizi9RoqZntg33fv/1fbdhbYXpEQ== - -"@biomejs/cli-linux-arm64@2.4.15": - version "2.4.15" - resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.4.15.tgz#527cef60339649a442d51a9cd129ae9dfe9da926" - integrity sha512-owaAMZD/T4LrD0ELNCk0Km3qrRHuM0X6EAyVE1FSqGY0rbLoiDLrO4Us2tllm6cAeB2Ioa9C2C08NZPdr8+0Ug== - -"@biomejs/cli-linux-x64-musl@2.4.15": - version "2.4.15" - resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.4.15.tgz#b39292ad106c3d5a612bf3c61ba3119f66833013" - integrity sha512-CNq/9W38SYSH023lfcQ4KKU8K0YX8T//FZUhcgtMMRABDojx5XsMV7jlweAvGSl389wJQB29Qo6Zb/a+jdvt+w== - -"@biomejs/cli-linux-x64@2.4.15": - version "2.4.15" - resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-x64/-/cli-linux-x64-2.4.15.tgz#7360b7f81ff03ec6d9350bedc76b89f783b0945d" - integrity sha512-0jj7THz12GbUOLmMibktK6DZjqz2zV64KFxyBtcFTKPiiOIY0a7vns1elpO1dERvxpsZ5ik0oFfz0oGwFde1+g== - -"@biomejs/cli-win32-arm64@2.4.15": - version "2.4.15" - resolved "https://registry.yarnpkg.com/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.4.15.tgz#9542aac679174892a9379267e0c0048f8eee4d9f" - integrity sha512-ouhkYdlhp/1GghEJPdWwD/Vi3gQ1nFxuSpMolWsbq3Lsq3QUR4jl6UdhhscdCugKU5vOEuMiJhvKj66O0OCq+w== - -"@biomejs/cli-win32-x64@2.4.15": - version "2.4.15" - resolved "https://registry.yarnpkg.com/@biomejs/cli-win32-x64/-/cli-win32-x64-2.4.15.tgz#80288e4eea8f916fc5c876e9a486baadb8de537d" - integrity sha512-zBrGq5mx5wwpnow4+2BxUvleDM+GNd4sLbPaMapsSLQLD0NGRCquqPBTgN+7XkUteHvj7M+BstuI8tmnV7+HgQ== - -"@isaacs/fs-minipass@^4.0.0": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz#2d59ae3ab4b38fb4270bfa23d30f8e2e86c7fe32" - integrity sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w== - dependencies: - minipass "^7.0.4" - -"@noble/hashes@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-2.0.1.tgz#fc1a928061d1232b0a52bb754393c37a5216c89e" - integrity sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw== - -"@otplib/core@13.4.0": - version "13.4.0" - resolved "https://registry.yarnpkg.com/@otplib/core/-/core-13.4.0.tgz#14db803de5bd09f7c412eba86c7d193a09d57187" - integrity sha512-JqOGcvZQi2wIkEQo8f3/iAjstavpXy6gouIDMHygjNuH6Q0FjbHOiXMdcE94RwfgDNMABhzwUmvaPsxvgm9NYw== - -"@otplib/hotp@13.4.0": - version "13.4.0" - resolved "https://registry.yarnpkg.com/@otplib/hotp/-/hotp-13.4.0.tgz#e12a69cc54c000213e4bf2d92dc9741a6897d3a2" - integrity sha512-MJjE0x06mn2ptymz5qZmQveb+vWFuaIftqE0b5/TZZqUOK7l97cV8lRTmid5BpAQMwJDNLW6RnYxGeCRiNdekw== - dependencies: - "@otplib/core" "13.4.0" - "@otplib/uri" "13.4.0" - -"@otplib/plugin-base32-scure@13.4.0": - version "13.4.0" - resolved "https://registry.yarnpkg.com/@otplib/plugin-base32-scure/-/plugin-base32-scure-13.4.0.tgz#04c3b31075bc733ed3fb54d3335a65813faed0fe" - integrity sha512-/t9YWJmMbB8bF5z8mXrBZc2FXBe8B/3hG5FhWr9K8cFwFhyxScbPysmZe8s1UTzSA6N+s8Uv8aIfCtVXPNjJWw== - dependencies: - "@otplib/core" "13.4.0" - "@scure/base" "^2.0.0" - -"@otplib/plugin-crypto-noble@13.4.0": - version "13.4.0" - resolved "https://registry.yarnpkg.com/@otplib/plugin-crypto-noble/-/plugin-crypto-noble-13.4.0.tgz#048c6ad84fd718a2b66f108048aa2f7fd118e5d8" - integrity sha512-KrvE4m7Zv+TT1944HzgqFJWJpKb6AyoxDbvhPStmBqdMlv5Gekb80d66cuFRL08kkPgJ5gXUSb5SFpYeB+bACg== - dependencies: - "@noble/hashes" "^2.0.1" - "@otplib/core" "13.4.0" - -"@otplib/totp@13.4.0": - version "13.4.0" - resolved "https://registry.yarnpkg.com/@otplib/totp/-/totp-13.4.0.tgz#f43543435f9ea4c7798913ef8f975462f80fce63" - integrity sha512-dK+vl0f0ekzf6mCENRI9AKS2NJUC7OjI3+X8e7QSnhQ2WM7I+i4PGpb3QxKi5hxjTtwVuoZwXR2CFtXdcRtNdQ== - dependencies: - "@otplib/core" "13.4.0" - "@otplib/hotp" "13.4.0" - "@otplib/uri" "13.4.0" - -"@otplib/uri@13.4.0": - version "13.4.0" - resolved "https://registry.yarnpkg.com/@otplib/uri/-/uri-13.4.0.tgz#23fa0b727bec026bb871afd42e1c3e5ff57bed1d" - integrity sha512-x1ozBa5bPbdZCrrTL/HK21qchiK7jYElTu+0ft22abeEhiLYgH1+SIULvOcVk3CK8YwF4kdcidvkq4ciejucJA== - dependencies: - "@otplib/core" "13.4.0" - -"@scure/base@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@scure/base/-/base-2.0.0.tgz#ba6371fddf92c2727e88ad6ab485db6e624f9a98" - integrity sha512-3E1kpuZginKkek01ovG8krQ0Z44E3DHPjc5S2rjJw9lZn3KSQOs8S7wqikF/AH7iRanHypj85uGyxk0XAyC37w== - -"@types/json-schema@^7.0.15": - version "7.0.15" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" - integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== - -abbrev@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-4.0.0.tgz#ec933f0e27b6cd60e89b5c6b2a304af42209bb05" - integrity sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA== - -abort-controller@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" - integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== - dependencies: - event-target-shim "^5.0.0" - -accepts@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-2.0.0.tgz#bbcf4ba5075467f3f2131eab3cffc73c2f5d7895" - integrity sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng== - dependencies: - mime-types "^3.0.0" - negotiator "^1.0.0" - -agent-base@9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-9.0.0.tgz#ec9efb08314e1e75b0852d74aabf9a387f99834e" - integrity sha512-TQf59BsZnytt8GdJKLPfUZ54g/iaUL2OWDSFCCvMOhsHduDQxO8xC4PNeyIkVcA5KwL2phPSv0douC0fgWzmnA== - -ajv-draft-04@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz#3b64761b268ba0b9e668f0b41ba53fce0ad77fc8" - integrity sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw== - -ajv-formats@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" - integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== - dependencies: - ajv "^8.0.0" - -ajv@^8.0.0, ajv@^8.17.1: - version "8.18.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.18.0.tgz#8864186b6738d003eb3a933172bb3833e10cefbc" - integrity sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A== - dependencies: - fast-deep-equal "^3.1.3" - fast-uri "^3.0.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - -ajv@^8.20.0: - version "8.20.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.20.0.tgz#304b3636add88ba7d936760dd50ece006dea95f9" - integrity sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA== - dependencies: - fast-deep-equal "^3.1.3" - fast-uri "^3.0.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -anymatch@~3.1.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" - integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -archiver@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/archiver/-/archiver-8.0.0.tgz#b02b8d0b978488e6dbebf1e0ebbc4103f5ffae3b" - integrity sha512-fV1orZfsnPn9BaSByR/qE67rJCLJEy2Ox5bq7nJh+jquWaNh6Sfec75kJ2T6PtdGUbPQlrVoSVCEOa5SdiTQ1g== - dependencies: - async "^3.2.4" - buffer-crc32 "^1.0.0" - is-stream "^4.0.0" - lazystream "^1.0.0" - normalize-path "^3.0.0" - readable-stream "^4.0.0" - readdir-glob "^3.0.0" - tar-stream "^3.0.0" - zip-stream "^7.0.2" - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -asn1@^0.2.4: - version "0.2.6" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" - integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== - dependencies: - safer-buffer "~2.1.0" - -ast-types@^0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.4.tgz#ee0d77b343263965ecc3fb62da16e7222b2b6782" - integrity sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w== - dependencies: - tslib "^2.0.1" - -async@^3.2.4: - version "3.2.6" - resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce" - integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA== - -aws-ssl-profiles@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz#157dd77e9f19b1d123678e93f120e6f193022641" - integrity sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g== - -b4a@^1.6.4: - version "1.8.0" - resolved "https://registry.yarnpkg.com/b4a/-/b4a-1.8.0.tgz#1ca3ba0edc9469aaabef5647e769a83d50180b1a" - integrity sha512-qRuSmNSkGQaHwNbM7J78Wwy+ghLEYF1zNrSeMxj4Kgw6y33O3mXcQ6Ie9fRvfU/YnxWkOchPXbaLb73TkIsfdg== - -balanced-match@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-4.0.3.tgz#6337a2f23e0604a30481423432f99eac603599f9" - integrity sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g== - -bare-events@^2.7.0: - version "2.8.2" - resolved "https://registry.yarnpkg.com/bare-events/-/bare-events-2.8.2.tgz#7b3e10bd8e1fc80daf38bb516921678f566ab89f" - integrity sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ== - -base64-js@^1.3.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - -basic-ftp@^5.2.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/basic-ftp/-/basic-ftp-5.3.1.tgz#3148ee9af43c0522514a4f973fecb1d3cbb6d71e" - integrity sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw== - -batchflow@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/batchflow/-/batchflow-0.4.0.tgz#7d419df79b6b7587b06f9ea34f96ccef6f74e5b5" - integrity sha512-XwQQoCGPUjdLWzmpAvRNZc91wnBYuKLmj52d9LLZ1Ww06ow5RBqBt8kUmU9/3ZvPq88j7Elh3V4cEhgNKXbIlQ== - -bcrypt@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/bcrypt/-/bcrypt-6.0.0.tgz#86643fddde9bcd0ad91400b063003fa4b0312835" - integrity sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg== - dependencies: - node-addon-api "^8.3.0" - node-gyp-build "^4.8.4" - -better-sqlite3@^12.10.0: - version "12.10.0" - resolved "https://registry.yarnpkg.com/better-sqlite3/-/better-sqlite3-12.10.0.tgz#bde622d14a18008583a53bc53501ae98f1a12221" - integrity sha512-CyzaZRQKyHkB2ZInfTTl2nvT33EbDpjkLEbE8/Zck3Ll6O0qqvuGdrJ45HgtH+HykRg88ITY3AdreBGN70aBSQ== - dependencies: - bindings "^1.5.0" - prebuild-install "^7.1.1" - -binary-extensions@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" - integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== - -bindings@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" - integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== - dependencies: - file-uri-to-path "1.0.0" - -bl@^4.0.3: - version "4.1.0" - resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" - integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== - dependencies: - buffer "^5.5.0" - inherits "^2.0.4" - readable-stream "^3.4.0" - -blueimp-md5@^2.16.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.19.0.tgz#b53feea5498dcb53dc6ec4b823adb84b729c4af0" - integrity sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w== - -body-parser@^2.2.1, body-parser@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-2.2.2.tgz#1a32cdb966beaf68de50a9dfbe5b58f83cb8890c" - integrity sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA== - dependencies: - bytes "^3.1.2" - content-type "^1.0.5" - debug "^4.4.3" - http-errors "^2.0.0" - iconv-lite "^0.7.0" - on-finished "^2.4.1" - qs "^6.14.1" - raw-body "^3.0.1" - type-is "^2.0.1" - -brace-expansion@^5.0.5: - version "5.0.6" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-5.0.6.tgz#ec68fe0a641a29d8711579caf641d05bae1f2285" - integrity sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g== - dependencies: - balanced-match "^4.0.2" - -braces@~3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" - integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== - dependencies: - fill-range "^7.1.1" - -buffer-crc32@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-1.0.0.tgz#a10993b9055081d55304bd9feb4a072de179f405" - integrity sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w== - -buffer-equal-constant-time@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" - integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== - -buffer@^5.5.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" - integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.1.13" - -buffer@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" - integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.2.1" - -busboy@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" - integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== - dependencies: - streamsearch "^1.1.0" - -bytes@3.1.2, bytes@^3.1.2, bytes@~3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" - integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== - -call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" - integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== - dependencies: - es-errors "^1.3.0" - function-bind "^1.1.2" - -call-bound@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a" - integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== - dependencies: - call-bind-apply-helpers "^1.0.2" - get-intrinsic "^1.3.0" - -call-me-maybe@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.2.tgz#03f964f19522ba643b1b0693acb9152fe2074baa" - integrity sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ== - -camelcase@^5.0.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -chalk@5.6.2: - version "5.6.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.6.2.tgz#b1238b6e23ea337af71c7f8a295db5af0c158aea" - integrity sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA== - -chalk@^2.3.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chokidar@^3.5.2: - version "3.6.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" - integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - -chownr@^1.1.1: - version "1.1.4" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" - integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== - -chownr@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-3.0.0.tgz#9855e64ecd240a9cc4267ce8a4aa5d24a1da15e4" - integrity sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g== - -cliui@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" - integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.0" - wrap-ansi "^6.2.0" - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -colorette@2.0.19: - version "2.0.19" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" - integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== - -commander@^10.0.0: - version "10.0.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" - integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== - -compress-commons@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-7.0.1.tgz#280665524f98e02d704b0df511842c2da19077fd" - integrity sha512-g0S8KAD8qf4+V//pr3BfB1aBnARLXNz2Gx+jmHU0LEriUuoQUOPOulVquHKTJ8+EAIIO7fhseNDr9wK5Q9FKBQ== - dependencies: - crc-32 "^1.2.0" - crc32-stream "^7.0.1" - is-stream "^4.0.0" - normalize-path "^3.0.0" - readable-stream "^4.0.0" - -compressible@~2.0.18: - version "2.0.18" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" - integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== - dependencies: - mime-db ">= 1.43.0 < 2" - -compression@^1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/compression/-/compression-1.8.1.tgz#4a45d909ac16509195a9a28bd91094889c180d79" - integrity sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w== - dependencies: - bytes "3.1.2" - compressible "~2.0.18" - debug "2.6.9" - negotiator "~0.6.4" - on-headers "~1.1.0" - safe-buffer "5.2.1" - vary "~1.1.2" - -content-disposition@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-1.0.1.tgz#a8b7bbeb2904befdfb6787e5c0c086959f605f9b" - integrity sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q== - -content-type@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" - integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== - -cookie-signature@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.2.2.tgz#57c7fc3cc293acab9fec54d73e15690ebe4a1793" - integrity sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg== - -cookie@^0.7.1: - version "0.7.2" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" - integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== - -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - -crc-32@^1.2.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" - integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== - -crc32-stream@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-7.0.1.tgz#e573ff657b789e8b5a131cb298f731d7d12e0f42" - integrity sha512-IBWsY8xznyQrcHn8h4bC8/4ErNke5elzgG8GcqF4RFPw6aHkWWRc7Tgw6upjaTX/CT/yQgqYENkxYsTYN+hW2g== - dependencies: - crc-32 "^1.2.0" - readable-stream "^4.0.0" - -data-uri-to-buffer@8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-8.0.0.tgz#c642ffbc96d8fae76cccecbad43cbddd7818c785" - integrity sha512-6UHfyCux51b8PTGDgveqtz1tvphBku5DrMKKJbFAZAJOI2zsjDpDoYE1+QGj7FOMS4BdTFNJsJiR3zEB0xH0yQ== - -db-errors@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/db-errors/-/db-errors-0.2.3.tgz#a6a38952e00b20e790f2695a6446b3c65497ffa2" - integrity sha512-OOgqgDuCavHXjYSJoV2yGhv6SeG8nk42aoCSoyXLZUH7VwFG27rxbavU1z+VrZbZjphw5UkDQwUlD21MwZpUng== - -debug@2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - -debug@^4, debug@^4.3.4, debug@^4.4.0, debug@^4.4.3: - version "4.4.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" - integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== - dependencies: - ms "^2.1.3" - -decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== - -decompress-response@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" - integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== - dependencies: - mimic-response "^3.1.0" - -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - -degenerator@7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-7.0.1.tgz#9b057747a2e5d058b0ef8fd753faccc109957467" - integrity sha512-ABErK0IefDSyHjlPH7WUEenIAX2rPPnrDcDM+TS3z3+zu9TfyKKi07BQM+8rmxpdE2y1v5fjjdoAS/x4D2U60w== - dependencies: - ast-types "^0.13.4" - escodegen "^2.1.0" - esprima "^4.0.1" - -denque@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1" - integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw== - -depd@^2.0.0, depd@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== - -detect-libc@^2.0.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.1.2.tgz#689c5dcdc1900ef5583a4cb9f6d7b473742074ad" - integrity sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ== - -dunder-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" - integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== - dependencies: - call-bind-apply-helpers "^1.0.1" - es-errors "^1.3.0" - gopd "^1.2.0" - -ecdsa-sig-formatter@1.0.11: - version "1.0.11" - resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" - integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== - dependencies: - safe-buffer "^5.0.1" - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== - -email-validator@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/email-validator/-/email-validator-2.0.4.tgz#b8dfaa5d0dae28f1b03c95881d904d4e40bfe7ed" - integrity sha512-gYCwo7kh5S3IDyZPLZf6hSS0MnZT8QmJFqYvbqlDZSbwdZlY6QZWxJ4i/6UhITOJ4XzyI647Bm2MXKCLqnJ4nQ== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -encodeurl@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" - integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== - -end-of-stream@^1.1.0, end-of-stream@^1.4.1: - version "1.4.5" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.5.tgz#7344d711dea40e0b74abc2ed49778743ccedb08c" - integrity sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg== - dependencies: - once "^1.4.0" - -env-paths@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" - integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== - -error-ex@^1.3.1: - version "1.3.4" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.4.tgz#b3a8d8bb6f92eecc1629e3e27d3c8607a8a32414" - integrity sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ== - dependencies: - is-arrayish "^0.2.1" - -es-define-property@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" - integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== - -es-errors@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" - integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== - -es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" - integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== - dependencies: - es-errors "^1.3.0" - -escalade@^3.1.1: - version "3.2.0" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" - integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== - -escape-html@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - -escodegen@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.1.0.tgz#ba93bbb7a43986d29d6041f99f5262da773e2e17" - integrity sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w== - dependencies: - esprima "^4.0.1" - estraverse "^5.2.0" - esutils "^2.0.2" - optionalDependencies: - source-map "~0.6.1" - -esm@^3.2.25: - version "3.2.25" - resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10" - integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA== - -esprima@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -estraverse@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -etag@^1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== - -event-target-shim@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" - integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== - -events-universal@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/events-universal/-/events-universal-1.0.1.tgz#b56a84fd611b6610e0a2d0f09f80fdf931e2dfe6" - integrity sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw== - dependencies: - bare-events "^2.7.0" - -events@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== - -expand-template@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" - integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== - -exponential-backoff@^3.1.1: - version "3.1.3" - resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.3.tgz#51cf92c1c0493c766053f9d3abee4434c244d2f6" - integrity sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA== - -express-fileupload@^1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/express-fileupload/-/express-fileupload-1.5.2.tgz#4da70ba6f2ffd4c736eab0776445865a9dbd9bfa" - integrity sha512-wxUJn2vTHvj/kZCVmc5/bJO15C7aSMyHeuXYY3geKpeKibaAoQGcEv5+sM6nHS2T7VF+QHS4hTWPiY2mKofEdg== - dependencies: - busboy "^1.6.0" - -express@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/express/-/express-5.2.1.tgz#8f21d15b6d327f92b4794ecf8cb08a72f956ac04" - integrity sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw== - dependencies: - accepts "^2.0.0" - body-parser "^2.2.1" - content-disposition "^1.0.0" - content-type "^1.0.5" - cookie "^0.7.1" - cookie-signature "^1.2.1" - debug "^4.4.0" - depd "^2.0.0" - encodeurl "^2.0.0" - escape-html "^1.0.3" - etag "^1.8.1" - finalhandler "^2.1.0" - fresh "^2.0.0" - http-errors "^2.0.0" - merge-descriptors "^2.0.0" - mime-types "^3.0.0" - on-finished "^2.4.1" - once "^1.4.0" - parseurl "^1.3.3" - proxy-addr "^2.0.7" - qs "^6.14.0" - range-parser "^1.2.1" - router "^2.2.0" - send "^1.1.0" - serve-static "^2.2.0" - statuses "^2.0.1" - type-is "^2.0.1" - vary "^1.1.2" - -fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-fifo@^1.2.0, fast-fifo@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c" - integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ== - -fast-uri@^3.0.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.2.tgz#8af3d4fc9d3e71b11572cc2673b514a7d1a8c8ec" - integrity sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ== - -fdir@^6.5.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350" - integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== - -figures@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" - integrity sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA== - dependencies: - escape-string-regexp "^1.0.5" - -file-uri-to-path@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" - integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== - -fill-range@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" - integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== - dependencies: - to-regex-range "^5.0.1" - -finalhandler@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-2.1.1.tgz#a2c517a6559852bcdb06d1f8bd7f51b68fad8099" - integrity sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA== - dependencies: - debug "^4.4.0" - encodeurl "^2.0.0" - escape-html "^1.0.3" - on-finished "^2.4.1" - parseurl "^1.3.3" - statuses "^2.0.1" - -find-up@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== - dependencies: - locate-path "^2.0.0" - -find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -forwarded@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" - integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== - -fresh@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-2.0.0.tgz#8dd7df6a1b3a1b3a5cf186c05a5dd267622635a4" - integrity sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A== - -fs-constants@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" - integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== - -fsevents@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - -function-bind@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - -generate-function@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.3.1.tgz#f069617690c10c868e73b8465746764f97c3479f" - integrity sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ== - dependencies: - is-property "^1.0.2" - -get-caller-file@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-intrinsic@^1.2.5, get-intrinsic@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" - integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== - dependencies: - call-bind-apply-helpers "^1.0.2" - es-define-property "^1.0.1" - es-errors "^1.3.0" - es-object-atoms "^1.1.1" - function-bind "^1.1.2" - get-proto "^1.0.1" - gopd "^1.2.0" - has-symbols "^1.1.0" - hasown "^2.0.2" - math-intrinsics "^1.1.0" - -get-package-type@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" - integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== - -get-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" - integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== - dependencies: - dunder-proto "^1.0.1" - es-object-atoms "^1.0.0" - -get-uri@8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-8.0.0.tgz#3ac2e278c4bd8a717be70c8f8f8841e7d6aead93" - integrity sha512-CqtZlMKvfJeY0Zxv8wazDwXmSKmnMnsmNy8j8+wudi8EyG/pMUB1NqHc+Tv1QaNtpYsK9nOYjb7r7Ufu32RPSw== - dependencies: - basic-ftp "^5.2.0" - data-uri-to-buffer "8.0.0" - debug "^4.3.4" - -getopts@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/getopts/-/getopts-2.3.0.tgz#71e5593284807e03e2427449d4f6712a268666f4" - integrity sha512-5eDf9fuSXwxBL6q5HX+dhDj+dslFGWzU5thZ9kNKUkcPtaPdatmUFKwHFrLb/uf/WpA4BHET+AX3Scl56cAjpA== - -github-from-package@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" - integrity sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw== - -glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -gopd@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" - integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== - -graceful-fs@^4.1.2, graceful-fs@^4.2.11, graceful-fs@^4.2.6: - version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - -gravatar@^1.8.2: - version "1.8.2" - resolved "https://registry.yarnpkg.com/gravatar/-/gravatar-1.8.2.tgz#f298642b1562ed685af2ae938dbe31ec0c542cc1" - integrity sha512-GdRwLM3oYpFQKy47MKuluw9hZ2gaCtiKPbDGdcDEuYDKlc8eNnW27KYL9LVbIDzEsx88WtDWQm2ClBcsgBnj6w== - dependencies: - blueimp-md5 "^2.16.0" - email-validator "^2.0.4" - querystring "0.2.0" - yargs "^15.4.1" - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - -has-symbols@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" - integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== - -hasown@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" - integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== - dependencies: - function-bind "^1.1.2" - -http-errors@^2.0.0, http-errors@^2.0.1, http-errors@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.1.tgz#36d2f65bc909c8790018dd36fb4d93da6caae06b" - integrity sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ== - dependencies: - depd "~2.0.0" - inherits "~2.0.4" - setprototypeof "~1.2.0" - statuses "~2.0.2" - toidentifier "~1.0.1" - -http-proxy-agent@9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-9.0.0.tgz#473fe9c2b8ffea87611f8c68dfb9872b835c91d1" - integrity sha512-FcF8VhXYLQcxWCnt/cCpT2apKsRDUGeVEeMqGu4HSTu29U8Yw0TLOjdYIlDsYk3IkUh+taX4IDWpPcCqKDhCjA== - dependencies: - agent-base "9.0.0" - debug "^4.3.4" - -https-proxy-agent@9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-9.0.0.tgz#89256adf9dc20926fe43ea1d3ca0feb9e23cc4bd" - integrity sha512-/MVmHp58WkOypgFhCLk4fzpPcFQvTJ/e6LBI7irpIO2HfxUbpmYoHF+KzipzJpxxzJu7aJNWQ0xojJ/dzV2G5g== - dependencies: - agent-base "9.0.0" - debug "^4.3.4" - -iconv-lite@^0.7.0, iconv-lite@^0.7.2, iconv-lite@~0.7.0: - version "0.7.2" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.7.2.tgz#d0bdeac3f12b4835b7359c2ad89c422a4d1cc72e" - integrity sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw== - dependencies: - safer-buffer ">= 2.1.2 < 3.0.0" - -ieee754@^1.1.13, ieee754@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - -ignore-by-default@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" - integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA== - -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== - -inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3, inherits@~2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -ini@~1.3.0: - version "1.3.8" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" - integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== - -interpret@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" - integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== - -ip-address@^10.0.1: - version "10.2.0" - resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-10.2.0.tgz#805fc178b20c518bd4c8548b24fe30892d7f3206" - integrity sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA== - -ipaddr.js@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" - integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-core-module@^2.16.1: - version "2.16.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" - integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== - dependencies: - hasown "^2.0.2" - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-glob@^4.0.1, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-promise@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-4.0.0.tgz#42ff9f84206c1991d26debf520dd5c01042dd2f3" - integrity sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ== - -is-property@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" - integrity sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g== - -is-stream@^4.0.0, is-stream@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-4.0.1.tgz#375cf891e16d2e4baec250b85926cffc14720d9b" - integrity sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A== - -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== - -isexe@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-4.0.0.tgz#48f6576af8e87a18feb796b7ed5e2e5903b43dca" - integrity sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw== - -js-yaml@^4.1.0, js-yaml@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b" - integrity sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA== - dependencies: - argparse "^2.0.1" - -json-parse-better-errors@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - -json-schema-traverse@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" - integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== - -jsonwebtoken@^9.0.3: - version "9.0.3" - resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz#6cd57ab01e9b0ac07cb847d53d3c9b6ee31f7ae2" - integrity sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g== - dependencies: - jws "^4.0.1" - lodash.includes "^4.3.0" - lodash.isboolean "^3.0.3" - lodash.isinteger "^4.0.4" - lodash.isnumber "^3.0.3" - lodash.isplainobject "^4.0.6" - lodash.isstring "^4.0.1" - lodash.once "^4.0.0" - ms "^2.1.1" - semver "^7.5.4" - -jwa@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/jwa/-/jwa-2.0.1.tgz#bf8176d1ad0cd72e0f3f58338595a13e110bc804" - integrity sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg== - dependencies: - buffer-equal-constant-time "^1.0.1" - ecdsa-sig-formatter "1.0.11" - safe-buffer "^5.0.1" - -jws@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/jws/-/jws-4.0.1.tgz#07edc1be8fac20e677b283ece261498bd38f0690" - integrity sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA== - dependencies: - jwa "^2.0.1" - safe-buffer "^5.0.1" - -knex@3.2.10: - version "3.2.10" - resolved "https://registry.yarnpkg.com/knex/-/knex-3.2.10.tgz#ca8f77a10851b1e18b26463a6dc995e563c3b165" - integrity sha512-oypTHfrc9i72iyxaUQBKHOxhcr0xM65MPf6FpN02nimsftXwzXprIkLjfXdubvhbu4PMWLp023q8o8CYvHSuZw== - dependencies: - colorette "2.0.19" - commander "^10.0.0" - debug "4.3.4" - escalade "^3.1.1" - esm "^3.2.25" - get-package-type "^0.1.0" - getopts "2.3.0" - interpret "^2.2.0" - lodash "^4.18.1" - pg-connection-string "2.6.2" - rechoir "^0.8.0" - resolve-from "^5.0.0" - tarn "^3.0.2" - tildify "2.0.0" - -lazystream@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.1.tgz#494c831062f1f9408251ec44db1cba29242a2638" - integrity sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw== - dependencies: - readable-stream "^2.0.5" - -liquidjs@10.27.0: - version "10.27.0" - resolved "https://registry.yarnpkg.com/liquidjs/-/liquidjs-10.27.0.tgz#e31dc4c539e1a26aee46c847b4e60a6ede32564a" - integrity sha512-tw/OA59K7aIBlMKIrKlumr37fiZUheShVHXY8cVctWisgY1p9mc5hreOvlreoS0wTiwlWk14Ya7305c2a/Cg5w== - dependencies: - commander "^10.0.0" - -load-json-file@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" - integrity sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw== - dependencies: - graceful-fs "^4.1.2" - parse-json "^4.0.0" - pify "^3.0.0" - strip-bom "^3.0.0" - -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -lodash.includes@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" - integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w== - -lodash.isboolean@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" - integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg== - -lodash.isinteger@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" - integrity sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA== - -lodash.isnumber@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" - integrity sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw== - -lodash.isplainobject@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" - integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== - -lodash.isstring@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" - integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== - -lodash.once@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" - integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== - -lodash@^4.18.1: - version "4.18.1" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.18.1.tgz#ff2b66c1f6326d59513de2407bf881439812771c" - integrity sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q== - -long@^5.3.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/long/-/long-5.3.2.tgz#1d84463095999262d7d7b7f8bfd4a8cc55167f83" - integrity sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA== - -lru-cache@^7.14.1: - version "7.18.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89" - integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== - -lru.min@^1.1.0, lru.min@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/lru.min/-/lru.min-1.1.4.tgz#6ea1737a8c1ba2300cc87ad46910a4bdffa0117b" - integrity sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA== - -math-intrinsics@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" - integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== - -media-typer@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-1.1.0.tgz#6ab74b8f2d3320f2064b2a87a38e7931ff3a5561" - integrity sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw== - -merge-descriptors@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-2.0.0.tgz#ea922f660635a2249ee565e0449f951e6b603808" - integrity sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g== - -"mime-db@>= 1.43.0 < 2", mime-db@^1.54.0: - version "1.54.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.54.0.tgz#cddb3ee4f9c64530dff640236661d42cb6a314f5" - integrity sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ== - -mime-types@^3.0.0, mime-types@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-3.0.2.tgz#39002d4182575d5af036ffa118100f2524b2e2ab" - integrity sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A== - dependencies: - mime-db "^1.54.0" - -mimic-response@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" - integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== - -minimatch@^10.2.1, minimatch@^10.2.2: - version "10.2.5" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.2.5.tgz#bd48687a0be38ed2961399105600f832095861d1" - integrity sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg== - dependencies: - brace-expansion "^5.0.5" - -minimist@^1.2.0, minimist@^1.2.3: - version "1.2.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" - integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== - -minipass@^7.0.4, minipass@^7.1.2: - version "7.1.3" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.3.tgz#79389b4eb1bb2d003a9bba87d492f2bd37bdc65b" - integrity sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A== - -minizlib@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-3.1.0.tgz#6ad76c3a8f10227c9b51d1c9ac8e30b27f5a251c" - integrity sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw== - dependencies: - minipass "^7.1.2" - -mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" - integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== - -moment@^2.30.1: - version "2.30.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" - integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@^2.1.1, ms@^2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -mysql2@^3.22.3: - version "3.22.3" - resolved "https://registry.yarnpkg.com/mysql2/-/mysql2-3.22.3.tgz#884a36a1171501ef752ba90057dbcde528f322e3" - integrity sha512-uWWxvZSRvRhtBdh2CdcuK83YcOfPdmEeEYB069bAmPnV93QApDGVPuvCQOLjlh7tYHEWdgQPrn6kosDxHBVLkA== - dependencies: - aws-ssl-profiles "^1.1.2" - denque "^2.1.0" - generate-function "^2.3.1" - iconv-lite "^0.7.2" - long "^5.3.2" - lru.min "^1.1.4" - named-placeholders "^1.1.6" - sql-escaper "^1.3.3" - -named-placeholders@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/named-placeholders/-/named-placeholders-1.1.6.tgz#c50c6920b43f258f59c16add1e56654f5cc02bb5" - integrity sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w== - dependencies: - lru.min "^1.1.0" - -napi-build-utils@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-2.0.0.tgz#13c22c0187fcfccce1461844136372a47ddc027e" - integrity sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA== - -negotiator@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-1.0.0.tgz#b6c91bb47172d69f93cfd7c357bbb529019b5f6a" - integrity sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg== - -negotiator@~0.6.4: - version "0.6.4" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.4.tgz#777948e2452651c570b712dd01c23e262713fff7" - integrity sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w== - -netmask@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/netmask/-/netmask-2.0.2.tgz#8b01a07644065d536383835823bc52004ebac5e7" - integrity sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg== - -node-abi@^3.3.0: - version "3.87.0" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.87.0.tgz#423e28fea5c2f195fddd98acded9938c001ae6dd" - integrity sha512-+CGM1L1CgmtheLcBuleyYOn7NWPVu0s0EJH2C4puxgEZb9h8QpR9G2dBfZJOAUhi7VQxuBPMd0hiISWcTyiYyQ== - dependencies: - semver "^7.3.5" - -node-addon-api@^8.0.0: - version "8.7.0" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-8.7.0.tgz#f64f8413456ecbe900221305a3f883c37666473f" - integrity sha512-9MdFxmkKaOYVTV+XVRG8ArDwwQ77XIgIPyKASB1k3JPq3M8fGQQQE3YpMOrKm6g//Ktx8ivZr8xo1Qmtqub+GA== - -node-addon-api@^8.3.0: - version "8.5.0" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-8.5.0.tgz#c91b2d7682fa457d2e1c388150f0dff9aafb8f3f" - integrity sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A== - -node-gyp-build@^4.8.4: - version "4.8.4" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.4.tgz#8a70ee85464ae52327772a90d66c6077a900cfc8" - integrity sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ== - -node-gyp@12.x: - version "12.3.0" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-12.3.0.tgz#a0e0d9364779451eaf4148b6f9a7366f98000b3f" - integrity sha512-QNcUWM+HgJplcPzBvFBZ9VXacyGZ4+VTOb80PwWR+TlVzoHbRKULNEzpRsnaoxG3Wzr7Qh7BYxGDU3CbKib2Yg== - dependencies: - env-paths "^2.2.0" - exponential-backoff "^3.1.1" - graceful-fs "^4.2.6" - nopt "^9.0.0" - proc-log "^6.0.0" - semver "^7.3.5" - tar "^7.5.4" - tinyglobby "^0.2.12" - undici "^6.25.0" - which "^6.0.0" - -node-rsa@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/node-rsa/-/node-rsa-1.1.1.tgz#efd9ad382097782f506153398496f79e4464434d" - integrity sha512-Jd4cvbJMryN21r5HgxQOpMEqv+ooke/korixNNK3mGqfGJmy0M77WDDzo/05969+OkMy3XW1UuZsSmW9KQm7Fw== - dependencies: - asn1 "^0.2.4" - -nodemon@^3.1.14: - version "3.1.14" - resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.1.14.tgz#8487ca379c515301d221ec007f27f24ecafa2b51" - integrity sha512-jakjZi93UtB3jHMWsXL68FXSAosbLfY0In5gtKq3niLSkrWznrVBzXFNOEMJUfc9+Ke7SHWoAZsiMkNP3vq6Jw== - dependencies: - chokidar "^3.5.2" - debug "^4" - ignore-by-default "^1.0.1" - minimatch "^10.2.1" - pstree.remy "^1.1.8" - semver "^7.5.3" - simple-update-notifier "^2.0.0" - supports-color "^5.5.0" - touch "^3.1.0" - undefsafe "^2.0.5" - -nopt@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-9.0.0.tgz#6bff0836b2964d24508b6b41b5a9a49c4f4a1f96" - integrity sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw== - dependencies: - abbrev "^4.0.0" - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -object-inspect@^1.13.3: - version "1.13.4" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" - integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== - -objection@3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/objection/-/objection-3.1.5.tgz#53c32f6b6cba2958bc28cf723de96c2676da8286" - integrity sha512-Hx/ipAwXSuRBbOMWFKtRsAN0yITafqXtWB4OT4Z9wED7ty1h7bOnBdhLtcNus23GwLJqcMsRWdodL2p5GwlnfQ== - dependencies: - ajv "^8.17.1" - ajv-formats "^2.1.1" - db-errors "^0.2.3" - -on-finished@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" - integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== - dependencies: - ee-first "1.1.1" - -on-headers@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.1.0.tgz#59da4f91c45f5f989c6e4bcedc5a3b0aed70ff65" - integrity sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A== - -once@^1.3.1, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -otplib@^13.4.0: - version "13.4.0" - resolved "https://registry.yarnpkg.com/otplib/-/otplib-13.4.0.tgz#5743391a7fe1900cb1ac364af0bbb407a72af76b" - integrity sha512-RUcYcRMCgRWhUE/XabRppXpUwCwaWBNHe5iPXhdvP8wwDGpGpsIf/kxX/ec3zFsOaM1Oq8lEhUqDwk6W7DHkwg== - dependencies: - "@otplib/core" "13.4.0" - "@otplib/hotp" "13.4.0" - "@otplib/plugin-base32-scure" "13.4.0" - "@otplib/plugin-crypto-noble" "13.4.0" - "@otplib/totp" "13.4.0" - "@otplib/uri" "13.4.0" - -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== - dependencies: - p-try "^1.0.0" - -p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg== - dependencies: - p-limit "^1.1.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -pac-proxy-agent@9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-9.0.1.tgz#9cee1f8b41b00c53418f10824a8a41b3e07587dd" - integrity sha512-3ZOSpLboOlpW4yp8Cuv21KlTULRqyJ5Uuad3wXpSKFrxdNgcHEyoa22GRaZ2UlgCVuR6z+5BiavtYVvbajL/Yw== - dependencies: - agent-base "9.0.0" - debug "^4.3.4" - get-uri "8.0.0" - http-proxy-agent "9.0.0" - https-proxy-agent "9.0.0" - pac-resolver "9.0.1" - quickjs-wasi "^2.2.0" - socks-proxy-agent "10.0.0" - -pac-resolver@9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-9.0.1.tgz#a90b1518e4e832b3fcb197ada974d6f6ceaa7f8a" - integrity sha512-lJbS008tmkj08VhoM8Hzuv/VE5tK9MS0OIQ/7+s0lIF+BYhiQWFYzkSpML7lXs9iBu2jfmzBTLzhe9n6BX+dYw== - dependencies: - degenerator "7.0.1" - netmask "^2.0.2" - -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw== - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - -parseurl@^1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-to-regexp@^8.0.0: - version "8.4.2" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-8.4.2.tgz#795c420c4f7ca45c5b887366f622ee0c9852cccd" - integrity sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA== - -path@^0.12.7: - version "0.12.7" - resolved "https://registry.yarnpkg.com/path/-/path-0.12.7.tgz#d4dc2a506c4ce2197eb481ebfcd5b36c0140b10f" - integrity sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q== - dependencies: - process "^0.11.1" - util "^0.10.3" - -pg-cloudflare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/pg-cloudflare/-/pg-cloudflare-1.4.0.tgz#4b4c20e6d8ae531d400730f4804571a8d62f1497" - integrity sha512-Vo7z/6rrQYxpNRylp4Tlob2elzbh+N/MOQbxFVWCxS7oEx6jF53GTJFxK2WWpKuBRkmiin4Mt+xofFDjx09R0A== - -pg-connection-string@2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.6.2.tgz#713d82053de4e2bd166fab70cd4f26ad36aab475" - integrity sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA== - -pg-connection-string@^2.13.0: - version "2.13.0" - resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.13.0.tgz#8678113465a5af3cc977dcb51eadc847b27aa2de" - integrity sha512-EMnU9E2fSULdsbErBbMaXJvFeD9B4+nPcM3f+4lsiCR0BHLPrLVjv3DbyM2hgQQviKJaTWIRRTjKjWlHg3p2ig== - -pg-int8@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" - integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== - -pg-pool@^3.14.0: - version "3.14.0" - resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.14.0.tgz#f35ae4eb846780cad71af24099b3edfa9781ad90" - integrity sha512-gKtPkFdQPU3DksooVLi9LsjZxrsBUZIpa+7aVx+LV5pNh0KzP4Zleud2po+ConrxbuXGBJ6Hfer6hdgpIBpBaw== - -pg-protocol@^1.14.0: - version "1.14.0" - resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.14.0.tgz#c1f045b74274b007078c687147141f785f59b8de" - integrity sha512-n5taZ1kO3s9ngDTVxsEznOqCyToTgz0FLuPq0B33COy5pPpuWJpY3/2oRBVETuOgzdqRXfWpM9HIhp2LBBT1BA== - -pg-types@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3" - integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA== - dependencies: - pg-int8 "1.0.1" - postgres-array "~2.0.0" - postgres-bytea "~1.0.0" - postgres-date "~1.0.4" - postgres-interval "^1.1.0" - -pg@^8.21.0: - version "8.21.0" - resolved "https://registry.yarnpkg.com/pg/-/pg-8.21.0.tgz#d7fa2118d960cec5cc7d2b24525f9850dd5932b0" - integrity sha512-AUP1EYJuHraQGsVoCQVIcM7TEJVGtDzxWtGFZd8rds9d+CCXlU5Js1rYgfLNvxy9iJrpHjGrRjoi/3BT9fRyiA== - dependencies: - pg-connection-string "^2.13.0" - pg-pool "^3.14.0" - pg-protocol "^1.14.0" - pg-types "2.2.0" - pgpass "1.0.5" - optionalDependencies: - pg-cloudflare "^1.4.0" - -pgpass@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.5.tgz#9b873e4a564bb10fa7a7dbd55312728d422a223d" - integrity sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug== - dependencies: - split2 "^4.1.0" - -picomatch@^2.0.4, picomatch@^2.2.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.2.tgz#5a942915e26b372dc0f0e6753149a16e6b1c5601" - integrity sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA== - -picomatch@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.4.tgz#fd6f5e00a143086e074dffe4c924b8fb293b0589" - integrity sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A== - -pify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - integrity sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg== - -pkg-conf@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/pkg-conf/-/pkg-conf-2.1.0.tgz#2126514ca6f2abfebd168596df18ba57867f0058" - integrity sha512-C+VUP+8jis7EsQZIhDYmS5qlNtjv2yP4SNtjXK9AP1ZcTRlnSfuumaTnRfYZnYgUUYVIKqL0fRvmUGDV2fmp6g== - dependencies: - find-up "^2.0.0" - load-json-file "^4.0.0" - -postgres-array@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" - integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA== - -postgres-bytea@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.1.tgz#c40b3da0222c500ff1e51c5d7014b60b79697c7a" - integrity sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ== - -postgres-date@~1.0.4: - version "1.0.7" - resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.7.tgz#51bc086006005e5061c591cee727f2531bf641a8" - integrity sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q== - -postgres-interval@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.2.0.tgz#b460c82cb1587507788819a06aa0fffdb3544695" - integrity sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ== - dependencies: - xtend "^4.0.0" - -prebuild-install@^7.1.1, prebuild-install@^7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.3.tgz#d630abad2b147443f20a212917beae68b8092eec" - integrity sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug== - dependencies: - detect-libc "^2.0.0" - expand-template "^2.0.3" - github-from-package "0.0.0" - minimist "^1.2.3" - mkdirp-classic "^0.5.3" - napi-build-utils "^2.0.0" - node-abi "^3.3.0" - pump "^3.0.0" - rc "^1.2.7" - simple-get "^4.0.0" - tar-fs "^2.0.0" - tunnel-agent "^0.6.0" - -proc-log@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-6.1.0.tgz#18519482a37d5198e231133a70144a50f21f0215" - integrity sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ== - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -process@^0.11.1, process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== - -proxy-addr@^2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" - integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== - dependencies: - forwarded "0.2.0" - ipaddr.js "1.9.1" - -proxy-agent@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-8.0.1.tgz#4819c7b14637c6940424aeed840e9883a378a15d" - integrity sha512-kccqGBqHZXR8onQhY/ganJjoO8QIKKRiFBhPOzbTZK16attzSZ/0XSmp9H7jrRxPKHjhGyx1q32lMPrJ3uLFgA== - dependencies: - agent-base "9.0.0" - debug "^4.3.4" - http-proxy-agent "9.0.0" - https-proxy-agent "9.0.0" - lru-cache "^7.14.1" - pac-proxy-agent "9.0.1" - proxy-from-env "^2.0.0" - socks-proxy-agent "10.0.0" - -proxy-from-env@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-2.1.0.tgz#a7487568adad577cfaaa7e88c49cab3ab3081aba" - integrity sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA== - -pstree.remy@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" - integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== - -pump@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.3.tgz#151d979f1a29668dc0025ec589a455b53282268d" - integrity sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -qs@^6.14.0, qs@^6.14.1: - version "6.15.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.15.2.tgz#fd55426d710403ddccc45e0f9eab16db7727ece9" - integrity sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw== - dependencies: - side-channel "^1.1.0" - -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g== - -quickjs-wasi@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/quickjs-wasi/-/quickjs-wasi-2.2.0.tgz#85d8984aa1b048546e5634c764165034c6e22d48" - integrity sha512-zQxXmQMrEoD3S+jQdYsloq4qAuaxKFHZj6hHqOYGwB2iQZH+q9e/lf5zQPXCKOk0WJuAjzRFbO4KwHIp2D05Iw== - -range-parser@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-3.0.2.tgz#3e3ada5ae5568f9095d84376fd3a49b8fb000a51" - integrity sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA== - dependencies: - bytes "~3.1.2" - http-errors "~2.0.1" - iconv-lite "~0.7.0" - unpipe "~1.0.0" - -rc@^1.2.7: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -readable-stream@^2.0.5: - version "2.3.8" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" - integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.1.1, readable-stream@^3.4.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readable-stream@^4.0.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.7.0.tgz#cedbd8a1146c13dfff8dab14068028d58c15ac91" - integrity sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg== - dependencies: - abort-controller "^3.0.0" - buffer "^6.0.3" - events "^3.3.0" - process "^0.11.10" - string_decoder "^1.3.0" - -readdir-glob@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/readdir-glob/-/readdir-glob-3.0.0.tgz#a3545e0cef84d88c30fe44118d1a7e20496e9245" - integrity sha512-AhNB2KgKeVJr16nK9LLZbJNWnYoT23ZrumNKFDebHBdkC8KHSqWo871JAUhoWC/RtjEVdqNMFpM6qrwRbaUqpw== - dependencies: - minimatch "^10.2.2" - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -rechoir@^0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22" - integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ== - dependencies: - resolve "^1.20.0" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -require-from-string@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== - -require-main-filename@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" - integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== - -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - -resolve@^1.20.0: - version "1.22.11" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.11.tgz#aad857ce1ffb8bfa9b0b1ac29f1156383f68c262" - integrity sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ== - dependencies: - is-core-module "^2.16.1" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -router@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/router/-/router-2.2.0.tgz#019be620b711c87641167cc79b99090f00b146ef" - integrity sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ== - dependencies: - debug "^4.4.0" - depd "^2.0.0" - is-promise "^4.0.0" - parseurl "^1.3.3" - path-to-regexp "^8.0.0" - -safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -"safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@~2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -semver@^7.3.5, semver@^7.5.3, semver@^7.5.4: - version "7.7.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.4.tgz#28464e36060e991fa7a11d0279d2d3f3b57a7e8a" - integrity sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA== - -send@^1.1.0, send@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/send/-/send-1.2.1.tgz#9eab743b874f3550f40a26867bf286ad60d3f3ed" - integrity sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ== - dependencies: - debug "^4.4.3" - encodeurl "^2.0.0" - escape-html "^1.0.3" - etag "^1.8.1" - fresh "^2.0.0" - http-errors "^2.0.1" - mime-types "^3.0.2" - ms "^2.1.3" - on-finished "^2.4.1" - range-parser "^1.2.1" - statuses "^2.0.2" - -serve-static@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-2.2.1.tgz#7f186a4a4e5f5b663ad7a4294ff1bf37cf0e98a9" - integrity sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw== - dependencies: - encodeurl "^2.0.0" - escape-html "^1.0.3" - parseurl "^1.3.3" - send "^1.2.0" - -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== - -setprototypeof@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" - integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== - -side-channel-list@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad" - integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA== - dependencies: - es-errors "^1.3.0" - object-inspect "^1.13.3" - -side-channel-map@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42" - integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA== - dependencies: - call-bound "^1.0.2" - es-errors "^1.3.0" - get-intrinsic "^1.2.5" - object-inspect "^1.13.3" - -side-channel-weakmap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea" - integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== - dependencies: - call-bound "^1.0.2" - es-errors "^1.3.0" - get-intrinsic "^1.2.5" - object-inspect "^1.13.3" - side-channel-map "^1.0.1" - -side-channel@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" - integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== - dependencies: - es-errors "^1.3.0" - object-inspect "^1.13.3" - side-channel-list "^1.0.0" - side-channel-map "^1.0.1" - side-channel-weakmap "^1.0.2" - -signale@1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/signale/-/signale-1.4.0.tgz#c4be58302fb0262ac00fc3d886a7c113759042f1" - integrity sha512-iuh+gPf28RkltuJC7W5MRi6XAjTDCAPC/prJUpQoG4vIP3MJZ+GTydVnodXA7pwvTKb2cA0m9OFZW/cdWy/I/w== - dependencies: - chalk "^2.3.2" - figures "^2.0.0" - pkg-conf "^2.1.0" - -simple-concat@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" - integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== - -simple-get@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543" - integrity sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA== - dependencies: - decompress-response "^6.0.0" - once "^1.3.1" - simple-concat "^1.0.0" - -simple-update-notifier@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz#d70b92bdab7d6d90dfd73931195a30b6e3d7cebb" - integrity sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w== - dependencies: - semver "^7.5.3" - -smart-buffer@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" - integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== - -socks-proxy-agent@10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-10.0.0.tgz#e94a497f890d790a67274c19837c5bbe3f182220" - integrity sha512-pyp2YR3mNxAMu0mGLtzs4g7O3uT4/9sQOLAKcViAkaS9fJWkud7nmaf6ZREFqQEi24IPkBcjfHjXhPTUWjo3uA== - dependencies: - agent-base "9.0.0" - debug "^4.3.4" - socks "^2.8.3" - -socks@^2.8.3: - version "2.8.7" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.8.7.tgz#e2fb1d9a603add75050a2067db8c381a0b5669ea" - integrity sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A== - dependencies: - ip-address "^10.0.1" - smart-buffer "^4.2.0" - -source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -split2@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" - integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== - -sql-escaper@^1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/sql-escaper/-/sql-escaper-1.3.3.tgz#65faf89f048d26bb9a75566b82b5990ddf8a5b7f" - integrity sha512-BsTCV265VpTp8tm1wyIm1xqQCS+Q9NHx2Sr+WcnUrgLrQ6yiDIvHYJV5gHxsj1lMBy2zm5twLaZao8Jd+S8JJw== - -sqlite3@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/sqlite3/-/sqlite3-6.0.1.tgz#c0956e7834931c406b283c87b66771c847a6abfc" - integrity sha512-X0czUUMG2tmSqJpEQa3tCuZSHKIx8PwM53vLZzKp/o6Rpy25fiVfjdbnZ988M8+O3ZWR1ih0K255VumCb3MAnQ== - dependencies: - bindings "^1.5.0" - node-addon-api "^8.0.0" - prebuild-install "^7.1.3" - tar "^7.5.10" - optionalDependencies: - node-gyp "12.x" - -statuses@^2.0.1, statuses@^2.0.2, statuses@~2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.2.tgz#8f75eecef765b5e1cfcdc080da59409ed424e382" - integrity sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw== - -streamsearch@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" - integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== - -streamx@^2.15.0: - version "2.23.0" - resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.23.0.tgz#7d0f3d00d4a6c5de5728aecd6422b4008d66fd0b" - integrity sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg== - dependencies: - events-universal "^1.0.0" - fast-fifo "^1.3.2" - text-decoder "^1.1.0" - -string-width@^4.1.0, string-width@^4.2.0: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string_decoder@^1.1.1, string_decoder@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== - -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== - -supports-color@^5.3.0, supports-color@^5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -tar-fs@^2.0.0: - version "2.1.4" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.4.tgz#800824dbf4ef06ded9afea4acafe71c67c76b930" - integrity sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ== - dependencies: - chownr "^1.1.1" - mkdirp-classic "^0.5.2" - pump "^3.0.0" - tar-stream "^2.1.4" - -tar-stream@^2.1.4: - version "2.2.0" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" - integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== - dependencies: - bl "^4.0.3" - end-of-stream "^1.4.1" - fs-constants "^1.0.0" - inherits "^2.0.3" - readable-stream "^3.1.1" - -tar-stream@^3.0.0: - version "3.1.7" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-3.1.7.tgz#24b3fb5eabada19fe7338ed6d26e5f7c482e792b" - integrity sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ== - dependencies: - b4a "^1.6.4" - fast-fifo "^1.2.0" - streamx "^2.15.0" - -tar@^7.5.10, tar@^7.5.4: - version "7.5.15" - resolved "https://registry.yarnpkg.com/tar/-/tar-7.5.15.tgz#afe6d1316cddf614a566e3813e42fe01aed46fee" - integrity sha512-dzGK0boVlC4W5QFuQN1EFSl3bIDYsk7Tj40U6eIBnK2k/8ml7TZ5agbI5j5+qnoVcAA+rNtBml8SEiLxZpNqRQ== - dependencies: - "@isaacs/fs-minipass" "^4.0.0" - chownr "^3.0.0" - minipass "^7.1.2" - minizlib "^3.1.0" - yallist "^5.0.0" - -tarn@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/tarn/-/tarn-3.0.2.tgz#73b6140fbb881b71559c4f8bfde3d9a4b3d27693" - integrity sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ== - -temp-dir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-3.0.0.tgz#7f147b42ee41234cc6ba3138cd8e8aa2302acffa" - integrity sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw== - -temp-write@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/temp-write/-/temp-write-6.0.1.tgz#b1ed81e80e120ba4957db3e01e010669d7c15870" - integrity sha512-6bj9LlNld+knzEOQvnZK6YxiPF+foOUjvG/WoWj1/Mt9c6f2kQCPsh8KZ+NyTk0AejubTQSPpx2alcswE1bF8g== - dependencies: - graceful-fs "^4.2.11" - is-stream "^4.0.1" - temp-dir "^3.0.0" - -text-decoder@^1.1.0: - version "1.2.7" - resolved "https://registry.yarnpkg.com/text-decoder/-/text-decoder-1.2.7.tgz#5d073a9a74b9c0a9d28dfadcab96b604af57d8ba" - integrity sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ== - dependencies: - b4a "^1.6.4" - -tildify@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/tildify/-/tildify-2.0.0.tgz#f205f3674d677ce698b7067a99e949ce03b4754a" - integrity sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw== - -tinyglobby@^0.2.12: - version "0.2.16" - resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.16.tgz#1c3b7eb953fce42b226bc5a1ee06428281aff3d6" - integrity sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg== - dependencies: - fdir "^6.5.0" - picomatch "^4.0.4" - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -toidentifier@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" - integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== - -touch@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.1.tgz#097a23d7b161476435e5c1344a95c0f75b4a5694" - integrity sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA== - -tslib@^2.0.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" - integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== - dependencies: - safe-buffer "^5.0.1" - -type-is@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-2.0.1.tgz#64f6cf03f92fce4015c2b224793f6bdd4b068c97" - integrity sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw== - dependencies: - content-type "^1.0.5" - media-typer "^1.1.0" - mime-types "^3.0.0" - -undefsafe@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" - integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA== - -undici@^6.25.0: - version "6.25.0" - resolved "https://registry.yarnpkg.com/undici/-/undici-6.25.0.tgz#8c4efb8c998dc187fc1cfb5dde1ef19a211849fb" - integrity sha512-ZgpWDC5gmNiuY9CnLVXEH8rl50xhRCuLNA97fAUnKi8RRuV4E6KG31pDTsLVUKnohJE0I3XDrTeEydAXRw47xg== - -unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== - -util-deprecate@^1.0.1, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== - -util@^0.10.3: - version "0.10.4" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" - integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== - dependencies: - inherits "2.0.3" - -vary@^1.1.2, vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== - -which-module@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" - integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== - -which@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/which/-/which-6.0.1.tgz#021642443a198fb93b784a5606721cb18cfcbfce" - integrity sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg== - dependencies: - isexe "^4.0.0" - -wrap-ansi@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" - integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -xtend@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -y18n@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" - integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== - -yallist@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-5.0.0.tgz#00e2de443639ed0d78fd87de0d27469fbcffb533" - integrity sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw== - -yargs-parser@^18.1.2: - version "18.1.3" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" - integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs@^15.4.1: - version "15.4.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" - integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== - dependencies: - cliui "^6.0.0" - decamelize "^1.2.0" - find-up "^4.1.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^4.2.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^18.1.2" - -zip-stream@^7.0.2: - version "7.0.5" - resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-7.0.5.tgz#57b25db7c1be3cb4934ab480338dea490eb5ab8c" - integrity sha512-dSvYKdvLsAHCDqPOhIwk/q5CvuWtTB3Dgpoe0uVEFjTzIOAmsQpprX25InCvrvJsirEbu1OHyy67n/kAj1Sw/w== - dependencies: - compress-commons "^7.0.0" - normalize-path "^3.0.0" - readable-stream "^4.0.0" diff --git a/docker/Dockerfile b/docker/Dockerfile index 01b478b0e1..bf12df6df1 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -3,8 +3,8 @@ # This file assumes that the frontend has been built using ./scripts/frontend-build -ARG BASE_IMAGE=nginxproxymanager/nginx-full:certbot-node -FROM nginxproxymanager/testca AS testca +ARG BASE_IMAGE=docker.io/nginxproxymanager/nginx-full:certbot-node +FROM docker.io/nginxproxymanager/testca AS testca FROM $BASE_IMAGE ARG TARGETPLATFORM @@ -47,8 +47,8 @@ WORKDIR /etc/ssl/certs RUN ln -s NginxProxyManager.crt 1d0e3f10.0 && update-ca-certificates WORKDIR /app -RUN yarn install \ - && yarn cache clean +RUN npm ci --omit=dev \ + && npm cache clean --force # Remove frontend service not required for prod, dev nginx config as well RUN rm -rf /etc/s6-overlay/s6-rc.d/user/contents.d/frontend /etc/nginx/conf.d/dev.conf \ diff --git a/docker/dev/Dockerfile b/docker/dev/Dockerfile index 8593fd5ef6..9e4cf49fe2 100644 --- a/docker/dev/Dockerfile +++ b/docker/dev/Dockerfile @@ -1,5 +1,5 @@ -FROM nginxproxymanager/testca AS testca -FROM nginxproxymanager/nginx-full:certbot-node +FROM docker.io/nginxproxymanager/testca AS testca +FROM docker.io/nginxproxymanager/nginx-full:certbot-node LABEL maintainer="Jamie Curnow " SHELL ["/bin/bash", "-o", "pipefail", "-c"] diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml index d6b07ec012..5fd86c3421 100644 --- a/docker/docker-compose.dev.yml +++ b/docker/docker-compose.dev.yml @@ -13,6 +13,7 @@ services: networks: nginx_proxy_manager: aliases: + - npm - website1.example.com - website2.example.com - website3.example.com @@ -39,6 +40,8 @@ services: DB_POSTGRES_NAME: "npm" # DB_SQLITE_FILE: "/data/database.sqlite" # DISABLE_IPV6: "true" + # Optional: fixed 32-byte base64 key for /data credential vault (else auto-generated under /data/keys/secrets.json) + # NPM_SECRETS_ENCRYPTION_KEY: "your-base64-32-byte-key" # Required for DNS Certificate provisioning testing: LE_SERVER: "https://ca.internal/acme/acme/directory" REQUESTS_CA_BUNDLE: "/etc/ssl/certs/NginxProxyManager.crt" @@ -112,13 +115,14 @@ services: networks: - nginx_proxy_manager + # Live OpenAPI from the running backend (GET /api/schema). Bundled Redoc/Swagger: http://localhost:3081/documentation swagger: image: swaggerapi/swagger-ui:latest container_name: npm2dev.swagger ports: - 3082:80 environment: - URL: "http://npm:81/api/schema" + URL: "http://fullstack:81/api/schema" PORT: "80" depends_on: - fullstack @@ -240,6 +244,22 @@ services: - authentik-redis - db-postgres + # Optional: HashiCorp Vault dev server for credential provider integration tests + # Start with: docker compose -f docker/docker-compose.dev.yml --profile vault up -d vault-dev + vault-dev: + profiles: ["vault"] + image: hashicorp/vault:1.15 + container_name: npm2dev.vault + networks: + - nginx_proxy_manager + environment: + VAULT_DEV_ROOT_TOKEN_ID: npm-dev-root + VAULT_DEV_LISTEN_ADDRESS: 0.0.0.0:8200 + ports: + - 8200:8200 + cap_add: + - IPC_LOCK + authentik-ldap: image: ghcr.io/goauthentik/ldap:2024.10.1 container_name: npm2dev.authentik-ldap diff --git a/docker/docs-api-proxy.conf.example b/docker/docs-api-proxy.conf.example new file mode 100644 index 0000000000..53e37f4c1b --- /dev/null +++ b/docker/docs-api-proxy.conf.example @@ -0,0 +1,39 @@ +# Example: host bundled VitePress docs and proxy /api to NPM for Swagger UI "Try it out". +# +# Requirements: +# - Static files from frontend/dist (includes docs/ under /docs/) +# - NPM admin API on port 81 (or upstream of your choice) +# - TLS and authentication at the edge strongly recommended for production +# +# Adjust server_name, root, and proxy_pass to match your deployment. + +server { + listen 443 ssl http2; + server_name docs.example.com; + + # ssl_certificate ...; + # ssl_certificate_key ...; + + root /var/www/npm-frontend; + index index.html; + + # VitePress build output (copied to dist/docs/) + location /docs/ { + try_files $uri $uri/ /docs/index.html; + } + + # React admin SPA (optional if same host serves UI) + location / { + try_files $uri $uri/ /index.html; + } + + # Swagger UI in /docs/api-reference/swagger uses server URL /api + location /api/ { + proxy_pass http://127.0.0.1:81/api/; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} diff --git a/docker/rootfs/etc/s6-overlay/s6-rc.d/backend/run b/docker/rootfs/etc/s6-overlay/s6-rc.d/backend/run index b140257b75..cf4337390c 100755 --- a/docker/rootfs/etc/s6-overlay/s6-rc.d/backend/run +++ b/docker/rootfs/etc/s6-overlay/s6-rc.d/backend/run @@ -10,7 +10,7 @@ cd /app || exit 1 log_info 'Starting backend ...' if [ "${DEVELOPMENT:-}" = 'true' ]; then - s6-setuidgid "$PUID:$PGID" yarn install + s6-setuidgid "$PUID:$PGID" npm install exec s6-setuidgid "$PUID:$PGID" bash -c "export HOME=$NPMHOME;export CERTBOT_VERSION=$CERTBOT_VERSION;node --max_old_space_size=250 --abort_on_uncaught_exception node_modules/nodemon/bin/nodemon.js" else while : diff --git a/docker/rootfs/etc/s6-overlay/s6-rc.d/frontend/run b/docker/rootfs/etc/s6-overlay/s6-rc.d/frontend/run index 91ed3fa805..590166405c 100755 --- a/docker/rootfs/etc/s6-overlay/s6-rc.d/frontend/run +++ b/docker/rootfs/etc/s6-overlay/s6-rc.d/frontend/run @@ -14,8 +14,8 @@ if [ "$DEVELOPMENT" = 'true' ]; then chown -R "$PUID:$PGID" /frontend/dist log_info 'Starting frontend ...' - s6-setuidgid "$PUID:$PGID" yarn install - exec s6-setuidgid "$PUID:$PGID" yarn dev + s6-setuidgid "$PUID:$PGID" npm install + exec s6-setuidgid "$PUID:$PGID" npm run dev else exit 0 fi diff --git a/docker/rootfs/etc/s6-overlay/s6-rc.d/prepare/20-paths.sh b/docker/rootfs/etc/s6-overlay/s6-rc.d/prepare/20-paths.sh index 2f59ef41ac..f95ca78073 100755 --- a/docker/rootfs/etc/s6-overlay/s6-rc.d/prepare/20-paths.sh +++ b/docker/rootfs/etc/s6-overlay/s6-rc.d/prepare/20-paths.sh @@ -28,6 +28,8 @@ mkdir -p \ /data/nginx/dead_host \ /data/nginx/temp \ /data/letsencrypt-acme-challenge \ + /data/credentials \ + /data/credentials/providers \ /run/nginx \ /tmp/nginx/body \ /var/log/nginx \ @@ -35,6 +37,8 @@ mkdir -p \ /var/lib/nginx/cache/private \ /var/cache/nginx/proxy_temp +chmod 700 /data/credentials /data/credentials/providers 2>/dev/null || true + touch /var/log/nginx/error.log || true chmod 777 /var/log/nginx/error.log || true chmod -R 777 /var/cache/nginx || true diff --git a/docs/.gitignore b/docs/.gitignore index b8acd7be74..331db85ddd 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -5,10 +5,5 @@ ts .cache .vitepress/cache -.yarn/* -!.yarn/releases -!.yarn/plugins -!.yarn/sdks -!.yarn/versions *.gz *.tgz diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index b6f6f3f660..dacbb3cd5f 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -2,6 +2,7 @@ import { defineConfig } from "vitepress"; // https://vitepress.dev/reference/site-config export default defineConfig({ + base: "/docs/", title: "Nginx Proxy Manager", description: "Expose your services easily and securely", head: [ @@ -70,6 +71,14 @@ export default defineConfig({ metaChunk: true, srcDir: "./src", outDir: "./dist", + vite: { + optimizeDeps: { + include: ["redoc", "swagger-ui-dist"], + }, + ssr: { + noExternal: ["swagger-ui-dist"], + }, + }, themeConfig: { // https://vitepress.dev/reference/default-theme-config logo: { src: "/logo.svg", width: 24, height: 24 }, @@ -82,6 +91,9 @@ export default defineConfig({ { text: "Screenshots", link: "/screenshots/" }, { text: "Setup Instructions", link: "/setup/" }, { text: "Advanced Configuration", link: "/advanced-config/" }, + { text: "Automation API", link: "/advanced/automation-api" }, + { text: "API Reference (Redoc)", link: "/api-reference/" }, + { text: "API Reference (Swagger UI)", link: "/api-reference/swagger" }, { text: "Upgrading", link: "/upgrading/" }, { text: "Frequently Asked Questions", link: "/faq/" }, { text: "Certbot", link: "/certbot/" }, diff --git a/docs/.vitepress/theme/components/ApiReferenceRedoc.vue b/docs/.vitepress/theme/components/ApiReferenceRedoc.vue new file mode 100644 index 0000000000..d65c0affb4 --- /dev/null +++ b/docs/.vitepress/theme/components/ApiReferenceRedoc.vue @@ -0,0 +1,35 @@ + + + diff --git a/docs/.vitepress/theme/components/ApiReferenceSwagger.vue b/docs/.vitepress/theme/components/ApiReferenceSwagger.vue new file mode 100644 index 0000000000..663df7cb35 --- /dev/null +++ b/docs/.vitepress/theme/components/ApiReferenceSwagger.vue @@ -0,0 +1,30 @@ + + + diff --git a/docs/.vitepress/theme/custom.css b/docs/.vitepress/theme/custom.css index 2e3cda7d06..1a1afdae4f 100644 --- a/docs/.vitepress/theme/custom.css +++ b/docs/.vitepress/theme/custom.css @@ -26,3 +26,15 @@ display: inline; margin-right: 8px; } + +/* Full-width API reference viewers below VitePress content padding */ +.vp-doc .api-reference-redoc, +.vp-doc .api-reference-swagger { + margin-left: calc(-1 * var(--vp-layout-content-padding, 24px)); + margin-right: calc(-1 * var(--vp-layout-content-padding, 24px)); + min-height: 75vh; +} + +.vp-doc .api-reference-swagger .swagger-ui { + font-family: inherit; +} diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts index 42fe9a9361..77b327ebfa 100644 --- a/docs/.vitepress/theme/index.ts +++ b/docs/.vitepress/theme/index.ts @@ -1,4 +1,12 @@ -import DefaultTheme from 'vitepress/theme' -import './custom.css' +import DefaultTheme from "vitepress/theme"; +import ApiReferenceRedoc from "./components/ApiReferenceRedoc.vue"; +import ApiReferenceSwagger from "./components/ApiReferenceSwagger.vue"; +import "./custom.css"; -export default DefaultTheme +export default { + extends: DefaultTheme, + enhanceApp({ app }) { + app.component("ApiReferenceRedoc", ApiReferenceRedoc); + app.component("ApiReferenceSwagger", ApiReferenceSwagger); + }, +}; diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000000..bf72c66612 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,49 @@ +# Nginx Proxy Manager documentation (VitePress) + +Production builds are bundled under **`/docs/`** on the admin UI static root (port 81). The React app exposes them at **`/documentation`** (iframe; deep links use **`?section=`** with allowlisted Help section names, e.g. `/documentation?section=Settings`). Build via `scripts/frontend-build`, which copies `docs/dist` to `frontend/dist/docs/`. + +VitePress `base` is `/docs/` — see [`.vitepress/config.mts`](.vitepress/config.mts). + +## Development + +```bash +cd docs +npm install +npm run dev +``` + +`predev` / `prebuild` run `generate:openapi`, which dereferences [`../backend/schema/swagger.json`](../backend/schema/swagger.json) into [`src/public/openapi.json`](src/public/openapi.json). + +## API reference pages + +| URL (under `/docs/` in production) | Viewer | +|-----|--------| +| `/docs/api-reference/` | Redoc (read-only) | +| `/docs/api-reference/swagger` | Swagger UI (try-it-out against `/api` on the same host) | + +### Swagger “Try it out” on a separate docs hostname + +Bundled Swagger uses server URL `/api` on the **same origin** as the docs. To host static docs on another domain and still try requests, reverse-proxy `/api` to the NPM admin API (port 81). Sample config: `docker/docs-api-proxy.conf.example` in the repository. + +On a single NPM instance, open **http://host:81/documentation** or static **http://host:81/docs/** — no extra proxy required. + +### Dev: live schema vs bundled docs + +| URL | Purpose | +|-----|---------| +| `http://localhost:3082` | Swagger UI → live `GET /api/schema` from dev stack (`docker/docker-compose.dev.yml`) | +| `http://localhost:3081/documentation` | Bundled Redoc/Swagger from last frontend build | + +## When you change the API schema + +If you edit files under `backend/schema/`, add or refresh operation descriptions (Vacuum), then regenerate and commit the bundle: + +```bash +# Add or edit entries in backend/schema/scripts/operation-descriptions.json, then: +node backend/schema/scripts/apply-operation-descriptions.mjs +cd docs +npm run generate:openapi +git add src/public/openapi.json +``` + +See [VERSIONING.md](VERSIONING.md) and [SECURITY.md](../SECURITY.md). diff --git a/docs/VERSIONING.md b/docs/VERSIONING.md new file mode 100644 index 0000000000..2c4595781f --- /dev/null +++ b/docs/VERSIONING.md @@ -0,0 +1,34 @@ +# Versioning + +Nginx Proxy Manager uses [Semantic Versioning](https://semver.org/). The release number in [`.version`](../.version) is the canonical **`X.Y.Z`** value for the tree. + +## Source of truth + +| File | Purpose | +|------|---------| +| [`.version`](../.version) | Release number (e.g. `2.15.1`) | +| [`backend/package.json`](../backend/package.json) | API / runtime package version | +| [`frontend/package.json`](../frontend/package.json) | Frontend package version | +| [`backend/schema/swagger.json`](../backend/schema/swagger.json) | OpenAPI `info.version` | +| [`docs/src/public/openapi.json`](src/public/openapi.json) | Bundled spec for VitePress (regenerate after schema changes) | + +Sync package and schema versions from `.version`: + +```bash +./scripts/sync-version +``` + +## Releases + +Official images are published as **`jc21/nginx-proxy-manager`** on Docker Hub. Release tags follow **`vX.Y.Z`** (and related major/minor tags) on [GitHub Releases](https://github.com/NginxProxyManager/nginx-proxy-manager/releases). + +Maintainers typically: + +1. Update [`.version`](../.version) (or run `./scripts/sync-version X.Y.Z` when that workflow is enabled for the release). +2. Refresh OpenAPI operation descriptions if needed (`node backend/schema/scripts/apply-operation-descriptions.mjs`). +3. Regenerate the docs bundle: `cd docs && npm install && npm run generate:openapi`. +4. Tag `vX.Y.Z` and publish the release image. + +## API version string + +`GET /api` returns `version.major`, `version.minor`, `version.revision`, and `version.string` (for example `v2.15.1`). diff --git a/docs/package-lock.json b/docs/package-lock.json new file mode 100644 index 0000000000..02631817dc --- /dev/null +++ b/docs/package-lock.json @@ -0,0 +1,4374 @@ +{ + "name": "docs", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "devDependencies": { + "redoc": "^2.5.2", + "swagger-ui-dist": "^5.31.0", + "vitepress": "^1.6.4" + } + }, + "node_modules/@algolia/abtesting": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.12.2.tgz", + "integrity": "sha512-oWknd6wpfNrmRcH0vzed3UPX0i17o4kYLM5OMITyMVM2xLgaRbIafoxL0e8mcrNNb0iORCJA0evnNDKRYth5WQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2", + "@algolia/requester-browser-xhr": "5.46.2", + "@algolia/requester-fetch": "5.46.2", + "@algolia/requester-node-http": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/abtesting/node_modules/@algolia/client-common": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.46.2.tgz", + "integrity": "sha512-Hj8gswSJNKZ0oyd0wWissqyasm+wTz1oIsv5ZmLarzOZAp3vFEda8bpDQ8PUhO+DfkbiLyVnAxsPe4cGzWtqkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/abtesting/node_modules/@algolia/requester-browser-xhr": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.46.2.tgz", + "integrity": "sha512-ekotpCwpSp033DIIrsTpYlGUCF6momkgupRV/FA3m62SreTSZUKjgK6VTNyG7TtYfq9YFm/pnh65bATP/ZWJEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/abtesting/node_modules/@algolia/requester-fetch": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.46.2.tgz", + "integrity": "sha512-gKE+ZFi/6y7saTr34wS0SqYFDcjHW4Wminv8PDZEi0/mE99+hSrbKgJWxo2ztb5eqGirQTgIh1AMVacGGWM1iw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/abtesting/node_modules/@algolia/requester-node-http": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.46.2.tgz", + "integrity": "sha512-ciPihkletp7ttweJ8Zt+GukSVLp2ANJHU+9ttiSxsJZThXc4Y2yJ8HGVWesW5jN1zrsZsezN71KrMx/iZsOYpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/autocomplete-core": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.17.7.tgz", + "integrity": "sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-plugin-algolia-insights": "1.17.7", + "@algolia/autocomplete-shared": "1.17.7" + } + }, + "node_modules/@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.17.7.tgz", + "integrity": "sha512-Jca5Ude6yUOuyzjnz57og7Et3aXjbwCSDf/8onLHSQgw1qW3ALl9mrMWaXb5FmPVkV3EtkD2F/+NkT6VHyPu9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-shared": "1.17.7" + }, + "peerDependencies": { + "search-insights": ">= 1 < 3" + } + }, + "node_modules/@algolia/autocomplete-preset-algolia": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.17.7.tgz", + "integrity": "sha512-ggOQ950+nwbWROq2MOCIL71RE0DdQZsceqrg32UqnhDz8FlO9rL8ONHNsI2R1MH0tkgVIDKI/D0sMiUchsFdWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-shared": "1.17.7" + }, + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/autocomplete-shared": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.17.7.tgz", + "integrity": "sha512-o/1Vurr42U/qskRSuhBH+VKxMvkkUVTLU6WZQr+L5lGZZLYWyhdzWjW0iGXY7EkwRTjBqvN2EsR81yCTGV/kmg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/client-abtesting": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.46.2.tgz", + "integrity": "sha512-oRSUHbylGIuxrlzdPA8FPJuwrLLRavOhAmFGgdAvMcX47XsyM+IOGa9tc7/K5SPvBqn4nhppOCEz7BrzOPWc4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2", + "@algolia/requester-browser-xhr": "5.46.2", + "@algolia/requester-fetch": "5.46.2", + "@algolia/requester-node-http": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-abtesting/node_modules/@algolia/client-common": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.46.2.tgz", + "integrity": "sha512-Hj8gswSJNKZ0oyd0wWissqyasm+wTz1oIsv5ZmLarzOZAp3vFEda8bpDQ8PUhO+DfkbiLyVnAxsPe4cGzWtqkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-abtesting/node_modules/@algolia/requester-browser-xhr": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.46.2.tgz", + "integrity": "sha512-ekotpCwpSp033DIIrsTpYlGUCF6momkgupRV/FA3m62SreTSZUKjgK6VTNyG7TtYfq9YFm/pnh65bATP/ZWJEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-abtesting/node_modules/@algolia/requester-fetch": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.46.2.tgz", + "integrity": "sha512-gKE+ZFi/6y7saTr34wS0SqYFDcjHW4Wminv8PDZEi0/mE99+hSrbKgJWxo2ztb5eqGirQTgIh1AMVacGGWM1iw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-abtesting/node_modules/@algolia/requester-node-http": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.46.2.tgz", + "integrity": "sha512-ciPihkletp7ttweJ8Zt+GukSVLp2ANJHU+9ttiSxsJZThXc4Y2yJ8HGVWesW5jN1zrsZsezN71KrMx/iZsOYpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-analytics": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.46.2.tgz", + "integrity": "sha512-EPBN2Oruw0maWOF4OgGPfioTvd+gmiNwx0HmD9IgmlS+l75DatcBkKOPNJN+0z3wBQWUO5oq602ATxIfmTQ8bA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2", + "@algolia/requester-browser-xhr": "5.46.2", + "@algolia/requester-fetch": "5.46.2", + "@algolia/requester-node-http": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-analytics/node_modules/@algolia/client-common": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.46.2.tgz", + "integrity": "sha512-Hj8gswSJNKZ0oyd0wWissqyasm+wTz1oIsv5ZmLarzOZAp3vFEda8bpDQ8PUhO+DfkbiLyVnAxsPe4cGzWtqkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-analytics/node_modules/@algolia/requester-browser-xhr": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.46.2.tgz", + "integrity": "sha512-ekotpCwpSp033DIIrsTpYlGUCF6momkgupRV/FA3m62SreTSZUKjgK6VTNyG7TtYfq9YFm/pnh65bATP/ZWJEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-analytics/node_modules/@algolia/requester-fetch": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.46.2.tgz", + "integrity": "sha512-gKE+ZFi/6y7saTr34wS0SqYFDcjHW4Wminv8PDZEi0/mE99+hSrbKgJWxo2ztb5eqGirQTgIh1AMVacGGWM1iw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-analytics/node_modules/@algolia/requester-node-http": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.46.2.tgz", + "integrity": "sha512-ciPihkletp7ttweJ8Zt+GukSVLp2ANJHU+9ttiSxsJZThXc4Y2yJ8HGVWesW5jN1zrsZsezN71KrMx/iZsOYpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-common": { + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.53.0.tgz", + "integrity": "sha512-YPN45TXD9Wrse185t/Ta7nktZsqpv97oOjCzp2sblHnCL6rBc9TDeJAg1IGl2UpdwnSD05Zu/5wLB4watOUMyg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-insights": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.46.2.tgz", + "integrity": "sha512-6dBZko2jt8FmQcHCbmNLB0kCV079Mx/DJcySTL3wirgDBUH7xhY1pOuUTLMiGkqM5D8moVZTvTdRKZUJRkrwBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2", + "@algolia/requester-browser-xhr": "5.46.2", + "@algolia/requester-fetch": "5.46.2", + "@algolia/requester-node-http": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-insights/node_modules/@algolia/client-common": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.46.2.tgz", + "integrity": "sha512-Hj8gswSJNKZ0oyd0wWissqyasm+wTz1oIsv5ZmLarzOZAp3vFEda8bpDQ8PUhO+DfkbiLyVnAxsPe4cGzWtqkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-insights/node_modules/@algolia/requester-browser-xhr": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.46.2.tgz", + "integrity": "sha512-ekotpCwpSp033DIIrsTpYlGUCF6momkgupRV/FA3m62SreTSZUKjgK6VTNyG7TtYfq9YFm/pnh65bATP/ZWJEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-insights/node_modules/@algolia/requester-fetch": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.46.2.tgz", + "integrity": "sha512-gKE+ZFi/6y7saTr34wS0SqYFDcjHW4Wminv8PDZEi0/mE99+hSrbKgJWxo2ztb5eqGirQTgIh1AMVacGGWM1iw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-insights/node_modules/@algolia/requester-node-http": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.46.2.tgz", + "integrity": "sha512-ciPihkletp7ttweJ8Zt+GukSVLp2ANJHU+9ttiSxsJZThXc4Y2yJ8HGVWesW5jN1zrsZsezN71KrMx/iZsOYpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-personalization": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.46.2.tgz", + "integrity": "sha512-1waE2Uqh/PHNeDXGn/PM/WrmYOBiUGSVxAWqiJIj73jqPqvfzZgzdakHscIVaDl6Cp+j5dwjsZ5LCgaUr6DtmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2", + "@algolia/requester-browser-xhr": "5.46.2", + "@algolia/requester-fetch": "5.46.2", + "@algolia/requester-node-http": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-personalization/node_modules/@algolia/client-common": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.46.2.tgz", + "integrity": "sha512-Hj8gswSJNKZ0oyd0wWissqyasm+wTz1oIsv5ZmLarzOZAp3vFEda8bpDQ8PUhO+DfkbiLyVnAxsPe4cGzWtqkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-personalization/node_modules/@algolia/requester-browser-xhr": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.46.2.tgz", + "integrity": "sha512-ekotpCwpSp033DIIrsTpYlGUCF6momkgupRV/FA3m62SreTSZUKjgK6VTNyG7TtYfq9YFm/pnh65bATP/ZWJEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-personalization/node_modules/@algolia/requester-fetch": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.46.2.tgz", + "integrity": "sha512-gKE+ZFi/6y7saTr34wS0SqYFDcjHW4Wminv8PDZEi0/mE99+hSrbKgJWxo2ztb5eqGirQTgIh1AMVacGGWM1iw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-personalization/node_modules/@algolia/requester-node-http": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.46.2.tgz", + "integrity": "sha512-ciPihkletp7ttweJ8Zt+GukSVLp2ANJHU+9ttiSxsJZThXc4Y2yJ8HGVWesW5jN1zrsZsezN71KrMx/iZsOYpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-query-suggestions": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.46.2.tgz", + "integrity": "sha512-EgOzTZkyDcNL6DV0V/24+oBJ+hKo0wNgyrOX/mePBM9bc9huHxIY2352sXmoZ648JXXY2x//V1kropF/Spx83w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2", + "@algolia/requester-browser-xhr": "5.46.2", + "@algolia/requester-fetch": "5.46.2", + "@algolia/requester-node-http": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-query-suggestions/node_modules/@algolia/client-common": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.46.2.tgz", + "integrity": "sha512-Hj8gswSJNKZ0oyd0wWissqyasm+wTz1oIsv5ZmLarzOZAp3vFEda8bpDQ8PUhO+DfkbiLyVnAxsPe4cGzWtqkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-query-suggestions/node_modules/@algolia/requester-browser-xhr": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.46.2.tgz", + "integrity": "sha512-ekotpCwpSp033DIIrsTpYlGUCF6momkgupRV/FA3m62SreTSZUKjgK6VTNyG7TtYfq9YFm/pnh65bATP/ZWJEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-query-suggestions/node_modules/@algolia/requester-fetch": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.46.2.tgz", + "integrity": "sha512-gKE+ZFi/6y7saTr34wS0SqYFDcjHW4Wminv8PDZEi0/mE99+hSrbKgJWxo2ztb5eqGirQTgIh1AMVacGGWM1iw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-query-suggestions/node_modules/@algolia/requester-node-http": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.46.2.tgz", + "integrity": "sha512-ciPihkletp7ttweJ8Zt+GukSVLp2ANJHU+9ttiSxsJZThXc4Y2yJ8HGVWesW5jN1zrsZsezN71KrMx/iZsOYpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-search": { + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.53.0.tgz", + "integrity": "sha512-Ds16IyPm/dNJPCU8OzApo2gwGrgWT5BYHhE3NFwZbpCveqyvPDB9sZDDkJ5DsdOGT2aC+R3i0/M1OVXF2qdgPg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@algolia/client-common": "5.53.0", + "@algolia/requester-browser-xhr": "5.53.0", + "@algolia/requester-fetch": "5.53.0", + "@algolia/requester-node-http": "5.53.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/ingestion": { + "version": "1.46.2", + "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.46.2.tgz", + "integrity": "sha512-1Uw2OslTWiOFDtt83y0bGiErJYy5MizadV0nHnOoHFWMoDqWW0kQoMFI65pXqRSkVvit5zjXSLik2xMiyQJDWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2", + "@algolia/requester-browser-xhr": "5.46.2", + "@algolia/requester-fetch": "5.46.2", + "@algolia/requester-node-http": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/ingestion/node_modules/@algolia/client-common": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.46.2.tgz", + "integrity": "sha512-Hj8gswSJNKZ0oyd0wWissqyasm+wTz1oIsv5ZmLarzOZAp3vFEda8bpDQ8PUhO+DfkbiLyVnAxsPe4cGzWtqkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/ingestion/node_modules/@algolia/requester-browser-xhr": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.46.2.tgz", + "integrity": "sha512-ekotpCwpSp033DIIrsTpYlGUCF6momkgupRV/FA3m62SreTSZUKjgK6VTNyG7TtYfq9YFm/pnh65bATP/ZWJEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/ingestion/node_modules/@algolia/requester-fetch": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.46.2.tgz", + "integrity": "sha512-gKE+ZFi/6y7saTr34wS0SqYFDcjHW4Wminv8PDZEi0/mE99+hSrbKgJWxo2ztb5eqGirQTgIh1AMVacGGWM1iw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/ingestion/node_modules/@algolia/requester-node-http": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.46.2.tgz", + "integrity": "sha512-ciPihkletp7ttweJ8Zt+GukSVLp2ANJHU+9ttiSxsJZThXc4Y2yJ8HGVWesW5jN1zrsZsezN71KrMx/iZsOYpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/monitoring": { + "version": "1.46.2", + "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.46.2.tgz", + "integrity": "sha512-xk9f+DPtNcddWN6E7n1hyNNsATBCHIqAvVGG2EAGHJc4AFYL18uM/kMTiOKXE/LKDPyy1JhIerrh9oYb7RBrgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2", + "@algolia/requester-browser-xhr": "5.46.2", + "@algolia/requester-fetch": "5.46.2", + "@algolia/requester-node-http": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/monitoring/node_modules/@algolia/client-common": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.46.2.tgz", + "integrity": "sha512-Hj8gswSJNKZ0oyd0wWissqyasm+wTz1oIsv5ZmLarzOZAp3vFEda8bpDQ8PUhO+DfkbiLyVnAxsPe4cGzWtqkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/monitoring/node_modules/@algolia/requester-browser-xhr": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.46.2.tgz", + "integrity": "sha512-ekotpCwpSp033DIIrsTpYlGUCF6momkgupRV/FA3m62SreTSZUKjgK6VTNyG7TtYfq9YFm/pnh65bATP/ZWJEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/monitoring/node_modules/@algolia/requester-fetch": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.46.2.tgz", + "integrity": "sha512-gKE+ZFi/6y7saTr34wS0SqYFDcjHW4Wminv8PDZEi0/mE99+hSrbKgJWxo2ztb5eqGirQTgIh1AMVacGGWM1iw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/monitoring/node_modules/@algolia/requester-node-http": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.46.2.tgz", + "integrity": "sha512-ciPihkletp7ttweJ8Zt+GukSVLp2ANJHU+9ttiSxsJZThXc4Y2yJ8HGVWesW5jN1zrsZsezN71KrMx/iZsOYpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/recommend": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.46.2.tgz", + "integrity": "sha512-NApbTPj9LxGzNw4dYnZmj2BoXiAc8NmbbH6qBNzQgXklGklt/xldTvu+FACN6ltFsTzoNU6j2mWNlHQTKGC5+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2", + "@algolia/requester-browser-xhr": "5.46.2", + "@algolia/requester-fetch": "5.46.2", + "@algolia/requester-node-http": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/recommend/node_modules/@algolia/client-common": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.46.2.tgz", + "integrity": "sha512-Hj8gswSJNKZ0oyd0wWissqyasm+wTz1oIsv5ZmLarzOZAp3vFEda8bpDQ8PUhO+DfkbiLyVnAxsPe4cGzWtqkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/recommend/node_modules/@algolia/requester-browser-xhr": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.46.2.tgz", + "integrity": "sha512-ekotpCwpSp033DIIrsTpYlGUCF6momkgupRV/FA3m62SreTSZUKjgK6VTNyG7TtYfq9YFm/pnh65bATP/ZWJEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/recommend/node_modules/@algolia/requester-fetch": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.46.2.tgz", + "integrity": "sha512-gKE+ZFi/6y7saTr34wS0SqYFDcjHW4Wminv8PDZEi0/mE99+hSrbKgJWxo2ztb5eqGirQTgIh1AMVacGGWM1iw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/recommend/node_modules/@algolia/requester-node-http": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.46.2.tgz", + "integrity": "sha512-ciPihkletp7ttweJ8Zt+GukSVLp2ANJHU+9ttiSxsJZThXc4Y2yJ8HGVWesW5jN1zrsZsezN71KrMx/iZsOYpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-browser-xhr": { + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.53.0.tgz", + "integrity": "sha512-ke27DqgzCOlt+RbeEdCxtXxMQOnAOi8ujr2wid0DmDKzR95Kw/f9sBsuhBxtjevCqJRJszfRTLY0B1pbO6IhkA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@algolia/client-common": "5.53.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-fetch": { + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.53.0.tgz", + "integrity": "sha512-GngiOqt2Gq4oLno6yXQVj9om+qSO9SWAoduoTOEg79dKZ62brB8OOIvSJG/vDNoanYi6a7Al9uDZwXvi+bcVTg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@algolia/client-common": "5.53.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-node-http": { + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.53.0.tgz", + "integrity": "sha512-6mF9LZMUk0QqWvrnxkxBqhswwz6Xfiwy6/gmTzL5HrlhdVG3ITAqGV2k3XmVThP1h0Ulc3VQwiNCD7/Nr4JNlQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@algolia/client-common": "5.53.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz", + "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.6" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz", + "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@docsearch/css": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.8.2.tgz", + "integrity": "sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@docsearch/js": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-3.8.2.tgz", + "integrity": "sha512-Q5wY66qHn0SwA7Taa0aDbHiJvaFJLOJyHmooQ7y8hlwwQLQ/5WwCcoX0g7ii04Qi2DJlHsd0XXzJ8Ypw9+9YmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@docsearch/react": "3.8.2", + "preact": "^10.0.0" + } + }, + "node_modules/@docsearch/js/node_modules/@docsearch/react": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.8.2.tgz", + "integrity": "sha512-xCRrJQlTt8N9GU0DG4ptwHRkfnSnD/YpdeaXe02iKfqs97TkZJv60yE+1eq/tjPcVnTW8dP5qLP7itifFVV5eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-core": "1.17.7", + "@algolia/autocomplete-preset-algolia": "1.17.7", + "@docsearch/css": "3.8.2", + "algoliasearch": "^5.14.2" + }, + "peerDependencies": { + "@types/react": ">= 16.8.0 < 19.0.0", + "react": ">= 16.8.0 < 19.0.0", + "react-dom": ">= 16.8.0 < 19.0.0", + "search-insights": ">= 1 < 3" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "search-insights": { + "optional": true + } + } + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.4.0.tgz", + "integrity": "sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@emotion/memoize": "^0.9.0" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@exodus/schemasafe": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@exodus/schemasafe/-/schemasafe-1.3.0.tgz", + "integrity": "sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@iconify-json/simple-icons": { + "version": "1.2.66", + "resolved": "https://registry.npmjs.org/@iconify-json/simple-icons/-/simple-icons-1.2.66.tgz", + "integrity": "sha512-D1OnnXwiQXFkVMw5M+Bt8mPsXeMkQyGmMdrmN7lsQlKMUkfLOp6JWhnUJ92po51WXT046aF/zzqSmkKqg08p4Q==", + "dev": true, + "license": "CC0-1.0", + "dependencies": { + "@iconify/types": "*" + } + }, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@nodable/entities": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@nodable/entities/-/entities-2.1.1.tgz", + "integrity": "sha512-Pig3HxDIoMgjdEH8OCf/dkcTmLFjJRjWuq8jSnklu284/TKOPibSRERmOykiwmyXTtv61mP+44f3GMx0tLAyjg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/nodable" + } + ], + "license": "MIT" + }, + "node_modules/@redocly/ajv": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/@redocly/ajv/-/ajv-8.11.2.tgz", + "integrity": "sha512-io1JpnwtIcvojV7QKDUSIuMN/ikdOUd1ReEnUnMKGfDVridQZ31J0MmIuqwuRjWDZfmvr+Q0MqCcfHM2gTivOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js-replace": "^1.0.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@redocly/config": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@redocly/config/-/config-0.22.0.tgz", + "integrity": "sha512-gAy93Ddo01Z3bHuVdPWfCwzgfaYgMdaZPcfL7JZ7hWJoK9V0lXDbigTWkhiPFAaLWzbOJ+kbUQG1+XwIm0KRGQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@redocly/openapi-core": { + "version": "1.34.15", + "resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.34.15.tgz", + "integrity": "sha512-HAwCnNyKcs5XGQqms+9t7OdAPM/5TDstmhF+0i7tdCFato2QKuYIlyWETwkXd8c5zbltr1oB+6y9NTeQLr2d6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@redocly/ajv": "8.11.2", + "@redocly/config": "0.22.0", + "colorette": "1.4.0", + "https-proxy-agent": "7.0.6", + "js-levenshtein": "1.1.6", + "js-yaml": "4.1.1", + "minimatch": "5.1.9", + "pluralize": "8.0.0", + "yaml-ast-parser": "0.0.43" + }, + "engines": { + "node": ">=18.17.0", + "npm": ">=9.5.0" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", + "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", + "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", + "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", + "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", + "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", + "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", + "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", + "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", + "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", + "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", + "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", + "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", + "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", + "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", + "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", + "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", + "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", + "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", + "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", + "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", + "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", + "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", + "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", + "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", + "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@scarf/scarf": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz", + "integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0" + }, + "node_modules/@shikijs/core": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-2.5.0.tgz", + "integrity": "sha512-uu/8RExTKtavlpH7XqnVYBrfBkUc20ngXiX9NSrBhOVZYv/7XQRKUyhtkeflY5QsxC0GbJThCerruZfsUaSldg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/engine-javascript": "2.5.0", + "@shikijs/engine-oniguruma": "2.5.0", + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.4" + } + }, + "node_modules/@shikijs/engine-javascript": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-2.5.0.tgz", + "integrity": "sha512-VjnOpnQf8WuCEZtNUdjjwGUbtAVKuZkVQ/5cHy/tojVVRIRtlWMYVjyWhxOmIq05AlSOv72z7hRNRGVBgQOl0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2", + "oniguruma-to-es": "^3.1.0" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-2.5.0.tgz", + "integrity": "sha512-pGd1wRATzbo/uatrCIILlAdFVKdxImWJGQ5rFiB5VZi2ve5xj3Ax9jny8QvkaV93btQEwR/rSz5ERFpC5mKNIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2" + } + }, + "node_modules/@shikijs/langs": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-2.5.0.tgz", + "integrity": "sha512-Qfrrt5OsNH5R+5tJ/3uYBBZv3SuGmnRPejV9IlIbFH3HTGLDlkqgHymAlzklVmKBjAaVmkPkyikAV/sQ1wSL+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0" + } + }, + "node_modules/@shikijs/themes": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-2.5.0.tgz", + "integrity": "sha512-wGrk+R8tJnO0VMzmUExHR+QdSaPUl/NKs+a4cQQRWyoc3YFbUzuLEi/KWK1hj+8BfHRKm2jNhhJck1dfstJpiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0" + } + }, + "node_modules/@shikijs/transformers": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-2.5.0.tgz", + "integrity": "sha512-SI494W5X60CaUwgi8u4q4m4s3YAFSxln3tzNjOSYqq54wlVgz0/NbbXEb3mdLbqMBztcmS7bVTaEd2w0qMmfeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/core": "2.5.0", + "@shikijs/types": "2.5.0" + } + }, + "node_modules/@shikijs/types": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-2.5.0.tgz", + "integrity": "sha512-ygl5yhxki9ZLNuNpPitBWvcy9fsSKKaRuO4BAlMyagszQidxcpLAr0qiW/q43DtSIDxO6hEbtYLiFZNXO/hdGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", + "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/markdown-it": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.21", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", + "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.1.tgz", + "integrity": "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz", + "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.26.tgz", + "integrity": "sha512-vXyI5GMfuoBCnv5ucIT7jhHKl55Y477yxP6fc4eUswjP8FG3FFVFd41eNDArR+Uk3QKn2Z85NavjaxLxOC19/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@vue/shared": "3.5.26", + "entities": "^7.0.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.26.tgz", + "integrity": "sha512-y1Tcd3eXs834QjswshSilCBnKGeQjQXB6PqFn/1nxcQw4pmG42G8lwz+FZPAZAby6gZeHSt/8LMPfZ4Rb+Bd/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.26", + "@vue/shared": "3.5.26" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.26.tgz", + "integrity": "sha512-egp69qDTSEZcf4bGOSsprUr4xI73wfrY5oRs6GSgXFTiHrWj4Y3X5Ydtip9QMqiCMCPVwLglB9GBxXtTadJ3mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@vue/compiler-core": "3.5.26", + "@vue/compiler-dom": "3.5.26", + "@vue/compiler-ssr": "3.5.26", + "@vue/shared": "3.5.26", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.6", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.26.tgz", + "integrity": "sha512-lZT9/Y0nSIRUPVvapFJEVDbEXruZh2IYHMk2zTtEgJSlP5gVOqeWXH54xDKAaFS4rTnDeDBQUYDtxKyoW9FwDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.26", + "@vue/shared": "3.5.26" + } + }, + "node_modules/@vue/devtools-api": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.9.tgz", + "integrity": "sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^7.7.9" + } + }, + "node_modules/@vue/devtools-kit": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.9.tgz", + "integrity": "sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^7.7.9", + "birpc": "^2.3.0", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.9.tgz", + "integrity": "sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.26.tgz", + "integrity": "sha512-9EnYB1/DIiUYYnzlnUBgwU32NNvLp/nhxLXeWRhHUEeWNTn1ECxX8aGO7RTXeX6PPcxe3LLuNBFoJbV4QZ+CFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.26" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.26.tgz", + "integrity": "sha512-xJWM9KH1kd201w5DvMDOwDHYhrdPTrAatn56oB/LRG4plEQeZRQLw0Bpwih9KYoqmzaxF0OKSn6swzYi84e1/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.26", + "@vue/shared": "3.5.26" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.26.tgz", + "integrity": "sha512-XLLd/+4sPC2ZkN/6+V4O4gjJu6kSDbHAChvsyWgm1oGbdSO3efvGYnm25yCjtFm/K7rrSDvSfPDgN1pHgS4VNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.26", + "@vue/runtime-core": "3.5.26", + "@vue/shared": "3.5.26", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.26.tgz", + "integrity": "sha512-TYKLXmrwWKSodyVuO1WAubucd+1XlLg4set0YoV+Hu8Lo79mp/YMwWV5mC5FgtsDxX3qo1ONrxFaTP1OQgy1uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.26", + "@vue/shared": "3.5.26" + }, + "peerDependencies": { + "vue": "3.5.26" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.26.tgz", + "integrity": "sha512-7Z6/y3uFI5PRoKeorTOSXKcDj0MSasfNNltcslbFrPpcw6aXRUALq4IfJlaTRspiWIUOEZbrpM+iQGmCOiWe4A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vueuse/core": { + "version": "12.8.2", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-12.8.2.tgz", + "integrity": "sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.21", + "@vueuse/metadata": "12.8.2", + "@vueuse/shared": "12.8.2", + "vue": "^3.5.13" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/integrations": { + "version": "12.8.2", + "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-12.8.2.tgz", + "integrity": "sha512-fbGYivgK5uBTRt7p5F3zy6VrETlV9RtZjBqd1/HxGdjdckBgBM4ugP8LHpjolqTj14TXTxSK1ZfgPbHYyGuH7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vueuse/core": "12.8.2", + "@vueuse/shared": "12.8.2", + "vue": "^3.5.13" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "async-validator": "^4", + "axios": "^1", + "change-case": "^5", + "drauu": "^0.4", + "focus-trap": "^7", + "fuse.js": "^7", + "idb-keyval": "^6", + "jwt-decode": "^4", + "nprogress": "^0.2", + "qrcode": "^1.5", + "sortablejs": "^1", + "universal-cookie": "^7" + }, + "peerDependenciesMeta": { + "async-validator": { + "optional": true + }, + "axios": { + "optional": true + }, + "change-case": { + "optional": true + }, + "drauu": { + "optional": true + }, + "focus-trap": { + "optional": true + }, + "fuse.js": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "jwt-decode": { + "optional": true + }, + "nprogress": { + "optional": true + }, + "qrcode": { + "optional": true + }, + "sortablejs": { + "optional": true + }, + "universal-cookie": { + "optional": true + } + } + }, + "node_modules/@vueuse/metadata": { + "version": "12.8.2", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-12.8.2.tgz", + "integrity": "sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "12.8.2", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-12.8.2.tgz", + "integrity": "sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "vue": "^3.5.13" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/algoliasearch": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.46.2.tgz", + "integrity": "sha512-qqAXW9QvKf2tTyhpDA4qXv1IfBwD2eduSW6tUEBFIfCeE9gn9HQ9I5+MaKoenRuHrzk5sQoNh1/iof8mY7uD6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/abtesting": "1.12.2", + "@algolia/client-abtesting": "5.46.2", + "@algolia/client-analytics": "5.46.2", + "@algolia/client-common": "5.46.2", + "@algolia/client-insights": "5.46.2", + "@algolia/client-personalization": "5.46.2", + "@algolia/client-query-suggestions": "5.46.2", + "@algolia/client-search": "5.46.2", + "@algolia/ingestion": "1.46.2", + "@algolia/monitoring": "1.46.2", + "@algolia/recommend": "5.46.2", + "@algolia/requester-browser-xhr": "5.46.2", + "@algolia/requester-fetch": "5.46.2", + "@algolia/requester-node-http": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/algoliasearch/node_modules/@algolia/client-common": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.46.2.tgz", + "integrity": "sha512-Hj8gswSJNKZ0oyd0wWissqyasm+wTz1oIsv5ZmLarzOZAp3vFEda8bpDQ8PUhO+DfkbiLyVnAxsPe4cGzWtqkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/algoliasearch/node_modules/@algolia/client-search": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.46.2.tgz", + "integrity": "sha512-ZsOJqu4HOG5BlvIFnMU0YKjQ9ZI6r3C31dg2jk5kMWPSdhJpYL9xa5hEe7aieE+707dXeMI4ej3diy6mXdZpgA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2", + "@algolia/requester-browser-xhr": "5.46.2", + "@algolia/requester-fetch": "5.46.2", + "@algolia/requester-node-http": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/algoliasearch/node_modules/@algolia/requester-browser-xhr": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.46.2.tgz", + "integrity": "sha512-ekotpCwpSp033DIIrsTpYlGUCF6momkgupRV/FA3m62SreTSZUKjgK6VTNyG7TtYfq9YFm/pnh65bATP/ZWJEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/algoliasearch/node_modules/@algolia/requester-fetch": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.46.2.tgz", + "integrity": "sha512-gKE+ZFi/6y7saTr34wS0SqYFDcjHW4Wminv8PDZEi0/mE99+hSrbKgJWxo2ztb5eqGirQTgIh1AMVacGGWM1iw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/algoliasearch/node_modules/@algolia/requester-node-http": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.46.2.tgz", + "integrity": "sha512-ciPihkletp7ttweJ8Zt+GukSVLp2ANJHU+9ttiSxsJZThXc4Y2yJ8HGVWesW5jN1zrsZsezN71KrMx/iZsOYpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/birpc": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz", + "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/brace-expansion": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", + "dev": true, + "license": "MIT", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", + "dev": true, + "license": "MIT" + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/copy-anything": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-4.0.5.tgz", + "integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-what": "^5.2.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/core-js": { + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.49.0.tgz", + "integrity": "sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", + "dev": true, + "license": "ISC", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/css-to-react-native": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decko": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decko/-/decko-1.2.0.tgz", + "integrity": "sha512-m8FnyHXV1QX+S1cl+KPFDIl6NMkxtKsy6+U/aYyjrOqWMuwAwYWu7ePqrsUHtDR5Y8Yk2pi/KIDSgF+vT4cPOQ==", + "dev": true + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/dompurify": { + "version": "3.4.8", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.8.tgz", + "integrity": "sha512-yb1cEmaOum7wFvOCSQxyfgVlv5D47Rc30iZWoMpbDIWTnJ6grDDQyu2KFJzB2k7u0pMuJcQ1zphH//fFnw2tjQ==", + "dev": true, + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/emoji-regex-xs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex-xs/-/emoji-regex-xs-1.0.0.tgz", + "integrity": "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==", + "dev": true, + "license": "MIT" + }, + "node_modules/entities": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.0.tgz", + "integrity": "sha512-FDWG5cmEYf2Z00IkYRhbFrwIwvdFKH07uV8dvNy0omp/Qb1xcyCWp2UDtcwJF4QZZvk0sLudP6/hAu42TaqVhQ==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es6-promise": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "integrity": "sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==", + "dev": true, + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-xml-builder": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.2.0.tgz", + "integrity": "sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "path-expression-matcher": "^1.5.0", + "xml-naming": "^0.1.0" + } + }, + "node_modules/fast-xml-parser": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.8.0.tgz", + "integrity": "sha512-6bIM7fsJxeo3uXv7OncQYsBAMPJ7V16Slahl/6M98C/i2q+vB1+4a0MtrvYwDFEUrwDSbAmeLDRXsOBwrL7yAg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "@nodable/entities": "^2.1.0", + "fast-xml-builder": "^1.2.0", + "path-expression-matcher": "^1.5.0", + "strnum": "^2.3.0", + "xml-naming": "^0.1.0" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/focus-trap": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.8.0.tgz", + "integrity": "sha512-/yNdlIkpWbM0ptxno3ONTuf+2g318kh2ez3KSeZN5dZ8YC6AAmgeWz+GasYYiBJPFaYcSAPeu4GfhUaChzIJXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tabbable": "^6.4.0" + } + }, + "node_modules/foreach": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.6.tgz", + "integrity": "sha512-k6GAGDyqLe9JaebCsFCoudPPWfihKu8pylYXRlqP1J7ms39iPoTtk2fviNglIeQEwdh0bQeKJ01ZPyuyQvKzwg==", + "dev": true, + "license": "MIT" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/hast-util-to-html": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", + "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/http2-client": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/http2-client/-/http2-client-1.3.5.tgz", + "integrity": "sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA==", + "dev": true, + "license": "MIT" + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-what": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-5.5.0.tgz", + "integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-pointer": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/json-pointer/-/json-pointer-0.6.2.tgz", + "integrity": "sha512-vLWcKbOaXlO+jvRy4qNd+TI1QUPZzfJj1tpJ3vAXDych5XJf93ftpUKe5pKCrzyIIwgBJcOcCVRUfqQP25afBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "foreach": "^2.0.4" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/mark.js": { + "version": "8.11.1", + "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz", + "integrity": "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true, + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", + "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", + "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", + "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/minisearch": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-7.2.0.tgz", + "integrity": "sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg==", + "dev": true, + "license": "MIT" + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "dev": true, + "license": "MIT" + }, + "node_modules/mobx": { + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/mobx/-/mobx-6.16.0.tgz", + "integrity": "sha512-qFIcwox4Mc4xRUVBGm0mt2uXmm4zCnfpwBRVkm59Y7zDei498NmpyKvEDsjCR3OYPbnQCKyhV6mLDs0vt2hBxA==", + "dev": true, + "license": "MIT", + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mobx" + } + }, + "node_modules/mobx-react": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/mobx-react/-/mobx-react-9.2.0.tgz", + "integrity": "sha512-dkGWCx+S0/1mfiuFfHRH8D9cplmwhxOV5CkXMp38u6rQGG2Pv3FWYztS0M7ncR6TyPRQKaTG/pnitInoYE9Vrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mobx-react-lite": "^4.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mobx" + }, + "peerDependencies": { + "mobx": "^6.9.0", + "react": "^16.8.0 || ^17 || ^18 || ^19" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/mobx-react-lite": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/mobx-react-lite/-/mobx-react-lite-4.1.1.tgz", + "integrity": "sha512-iUxiMpsvNraCKXU+yPotsOncNNmyeS2B5DKL+TL6Tar/xm+wwNJAubJmtRSeAoYawdZqwv8Z/+5nPRHeQxTiXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "use-sync-external-store": "^1.4.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mobx" + }, + "peerDependencies": { + "mobx": "^6.9.0", + "react": "^16.8.0 || ^17 || ^18 || ^19" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch-h2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/node-fetch-h2/-/node-fetch-h2-2.3.0.tgz", + "integrity": "sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg==", + "dev": true, + "license": "MIT", + "dependencies": { + "http2-client": "^1.2.5" + }, + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/node-readfiles": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/node-readfiles/-/node-readfiles-0.2.0.tgz", + "integrity": "sha512-SU00ZarexNlE4Rjdm83vglt5Y9yiQ+XI1XpflWlb7q7UTN1JUItm69xMeiQCTxtTfnzt+83T8Cx+vI2ED++VDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es6-promise": "^3.2.1" + } + }, + "node_modules/oas-kit-common": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/oas-kit-common/-/oas-kit-common-1.0.8.tgz", + "integrity": "sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "fast-safe-stringify": "^2.0.7" + } + }, + "node_modules/oas-linter": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/oas-linter/-/oas-linter-3.2.2.tgz", + "integrity": "sha512-KEGjPDVoU5K6swgo9hJVA/qYGlwfbFx+Kg2QB/kd7rzV5N8N5Mg6PlsoCMohVnQmo+pzJap/F610qTodKzecGQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@exodus/schemasafe": "^1.0.0-rc.2", + "should": "^13.2.1", + "yaml": "^1.10.0" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-resolver": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/oas-resolver/-/oas-resolver-2.5.6.tgz", + "integrity": "sha512-Yx5PWQNZomfEhPPOphFbZKi9W93CocQj18NlD2Pa4GWZzdZpSJvYwoiuurRI7m3SpcChrnO08hkuQDL3FGsVFQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "node-fetch-h2": "^2.3.0", + "oas-kit-common": "^1.0.8", + "reftools": "^1.1.9", + "yaml": "^1.10.0", + "yargs": "^17.0.1" + }, + "bin": { + "resolve": "resolve.js" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-schema-walker": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/oas-schema-walker/-/oas-schema-walker-1.1.5.tgz", + "integrity": "sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ==", + "dev": true, + "license": "BSD-3-Clause", + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-validator": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/oas-validator/-/oas-validator-5.0.8.tgz", + "integrity": "sha512-cu20/HE5N5HKqVygs3dt94eYJfBi0TsZvPVXDhbXQHiEityDN+RROTleefoKRKKJ9dFAF2JBkDHgvWj0sjKGmw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "call-me-maybe": "^1.0.1", + "oas-kit-common": "^1.0.8", + "oas-linter": "^3.2.2", + "oas-resolver": "^2.5.6", + "oas-schema-walker": "^1.1.5", + "reftools": "^1.1.9", + "should": "^13.2.1", + "yaml": "^1.10.0" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/oniguruma-to-es": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-3.1.1.tgz", + "integrity": "sha512-bUH8SDvPkH3ho3dvwJwfonjlQ4R80vjyvrU8YpxuROddv55vAEJrTuCuCVUhhsHbtlD9tGGbaNApGQckXhS8iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex-xs": "^1.0.0", + "regex": "^6.0.1", + "regex-recursion": "^6.0.2" + } + }, + "node_modules/openapi-sampler": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/openapi-sampler/-/openapi-sampler-1.7.4.tgz", + "integrity": "sha512-CKS/rd5ucPCuEDbJnjGDXZTsuGWcmv53aCmQx7soZlPEONUGN4af0/dY5+THRFZraSEjeA78nlfzdFswC/N5SA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.7", + "fast-xml-parser": "^5.5.1", + "json-pointer": "0.6.2" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-expression-matcher": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.5.0.tgz", + "integrity": "sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "dev": true, + "license": "MIT" + }, + "node_modules/perfect-scrollbar": { + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/perfect-scrollbar/-/perfect-scrollbar-1.5.6.tgz", + "integrity": "sha512-rixgxw3SxyJbCaSpo1n35A/fwI1r2rdwMKOTCg/AcG+xOEyZcE8UHVjpZMFCVImzsFoCZeJTT+M/rdEIQYO2nw==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/polished": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/polished/-/polished-4.3.1.tgz", + "integrity": "sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.17.8" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/postcss": { + "version": "8.5.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", + "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/preact": { + "version": "10.21.0", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.21.0.tgz", + "integrity": "sha512-aQAIxtzWEwH8ou+OovWVSVNlFImL7xUCwJX3YMqA3U8iKCNC34999fFOnWjYNsylgfPgMexpbk7WYOLtKr/mxg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/prismjs": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", + "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/react": { + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz", + "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.7.tgz", + "integrity": "sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.7" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/react-tabs": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/react-tabs/-/react-tabs-6.1.1.tgz", + "integrity": "sha512-CPiuKoMFf89B7QlbFfdBD9XmUWiE3qudQputMVZB8GQvPJZRX/gqjDaDWOPDwGinEfpJKEuBCkGt83Tt4efeyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "clsx": "^2.0.0", + "prop-types": "^15.5.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/redoc": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/redoc/-/redoc-2.5.3.tgz", + "integrity": "sha512-bBbat+Sx6xKWdyoCGTtA0BWeTEW9Vs4VnEja7q7ZLOk4IM7cHQLrf+kDxWF6dKeKxT8kOBnoy/OsNXCeLttpyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@redocly/openapi-core": "^1.34.15", + "classnames": "^2.3.2", + "decko": "^1.2.0", + "dompurify": "^3.2.4", + "eventemitter3": "^5.0.1", + "json-pointer": "^0.6.2", + "lunr": "^2.3.9", + "mark.js": "^8.11.1", + "marked": "^4.3.0", + "mobx-react": "9.2.0", + "openapi-sampler": "^1.6.2", + "path-browserify": "^1.0.1", + "perfect-scrollbar": "^1.5.5", + "polished": "^4.2.2", + "prismjs": "^1.29.0", + "prop-types": "^15.8.1", + "react-tabs": "^6.0.2", + "slugify": "~1.4.7", + "stickyfill": "^1.1.1", + "swagger2openapi": "^7.0.8", + "url-template": "^2.0.8" + }, + "engines": { + "node": ">=6.9", + "npm": ">=3.0.0" + }, + "peerDependencies": { + "core-js": "^3.1.4", + "mobx": "^6.0.4", + "react": "^16.8.4 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.4 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "styled-components": "^4.1.1 || ^5.1.1 || ^6.0.5" + } + }, + "node_modules/reftools": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/reftools/-/reftools-1.1.9.tgz", + "integrity": "sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w==", + "dev": true, + "license": "BSD-3-Clause", + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", + "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-recursion": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", + "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-utilities": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", + "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", + "dev": true, + "license": "MIT" + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" + }, + "node_modules/rollup": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", + "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.59.0", + "@rollup/rollup-android-arm64": "4.59.0", + "@rollup/rollup-darwin-arm64": "4.59.0", + "@rollup/rollup-darwin-x64": "4.59.0", + "@rollup/rollup-freebsd-arm64": "4.59.0", + "@rollup/rollup-freebsd-x64": "4.59.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", + "@rollup/rollup-linux-arm-musleabihf": "4.59.0", + "@rollup/rollup-linux-arm64-gnu": "4.59.0", + "@rollup/rollup-linux-arm64-musl": "4.59.0", + "@rollup/rollup-linux-loong64-gnu": "4.59.0", + "@rollup/rollup-linux-loong64-musl": "4.59.0", + "@rollup/rollup-linux-ppc64-gnu": "4.59.0", + "@rollup/rollup-linux-ppc64-musl": "4.59.0", + "@rollup/rollup-linux-riscv64-gnu": "4.59.0", + "@rollup/rollup-linux-riscv64-musl": "4.59.0", + "@rollup/rollup-linux-s390x-gnu": "4.59.0", + "@rollup/rollup-linux-x64-gnu": "4.59.0", + "@rollup/rollup-linux-x64-musl": "4.59.0", + "@rollup/rollup-openbsd-x64": "4.59.0", + "@rollup/rollup-openharmony-arm64": "4.59.0", + "@rollup/rollup-win32-arm64-msvc": "4.59.0", + "@rollup/rollup-win32-ia32-msvc": "4.59.0", + "@rollup/rollup-win32-x64-gnu": "4.59.0", + "@rollup/rollup-win32-x64-msvc": "4.59.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/search-insights": { + "version": "2.17.3", + "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz", + "integrity": "sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/shiki": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-2.5.0.tgz", + "integrity": "sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/core": "2.5.0", + "@shikijs/engine-javascript": "2.5.0", + "@shikijs/engine-oniguruma": "2.5.0", + "@shikijs/langs": "2.5.0", + "@shikijs/themes": "2.5.0", + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/should": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", + "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "should-equal": "^2.0.0", + "should-format": "^3.0.3", + "should-type": "^1.4.0", + "should-type-adaptors": "^1.0.1", + "should-util": "^1.0.0" + } + }, + "node_modules/should-equal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", + "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "should-type": "^1.4.0" + } + }, + "node_modules/should-format": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", + "integrity": "sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "should-type": "^1.3.0", + "should-type-adaptors": "^1.0.1" + } + }, + "node_modules/should-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", + "integrity": "sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/should-type-adaptors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", + "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "should-type": "^1.3.0", + "should-util": "^1.0.0" + } + }, + "node_modules/should-util": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", + "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==", + "dev": true, + "license": "MIT" + }, + "node_modules/slugify": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.4.7.tgz", + "integrity": "sha512-tf+h5W1IrjNm/9rKKj0JU2MDMruiopx0jjVA5zCdBtcGjfp0+c5rHw/zADLC3IeKlGHtVbHtpfzvYA0OYT+HKg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/speakingurl": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", + "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stickyfill": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stickyfill/-/stickyfill-1.1.1.tgz", + "integrity": "sha512-GCp7vHAfpao+Qh/3Flh9DXEJ/qSi0KJwJw6zYlZOtRYXWUIpMM6mC2rIep/dK8RQqwW0KxGJIllmjPIBOGN8AA==", + "dev": true + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "dev": true, + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strnum": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.3.0.tgz", + "integrity": "sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "node_modules/styled-components": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.4.2.tgz", + "integrity": "sha512-xZBhBJsMtGqb+aKcwKgaT+BtuFums9VynX2JRvXJGTx5UfZzN12rk5r4nVdhXYvRw+hE7yiYxVrOqJZaK2+Txg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@emotion/is-prop-valid": "1.4.0", + "css-to-react-native": "3.2.0", + "csstype": "3.2.3", + "stylis": "4.3.6" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/styled-components" + }, + "peerDependencies": { + "css-to-react-native": ">= 3.2.0", + "react": ">= 16.8.0", + "react-dom": ">= 16.8.0", + "react-native": ">= 0.68.0" + }, + "peerDependenciesMeta": { + "css-to-react-native": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/stylis": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", + "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/superjson": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.6.tgz", + "integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "copy-anything": "^4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/swagger-ui-dist": { + "version": "5.32.6", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.32.6.tgz", + "integrity": "sha512-75ttZNaYCLoFPnozPZcTUU6mS3wKT8l7WLjU5zJSHFeJa23i5vtnze6IiCl4jDMPeQTXVXIgovq4M11NNfQvSA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@scarf/scarf": "=1.4.0" + } + }, + "node_modules/swagger2openapi": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/swagger2openapi/-/swagger2openapi-7.0.8.tgz", + "integrity": "sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "call-me-maybe": "^1.0.1", + "node-fetch": "^2.6.1", + "node-fetch-h2": "^2.3.0", + "node-readfiles": "^0.2.0", + "oas-kit-common": "^1.0.8", + "oas-resolver": "^2.5.6", + "oas-schema-walker": "^1.1.5", + "oas-validator": "^5.0.8", + "reftools": "^1.1.9", + "yaml": "^1.10.0", + "yargs": "^17.0.1" + }, + "bin": { + "boast": "boast.js", + "oas-validate": "oas-validate.js", + "swagger2openapi": "swagger2openapi.js" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/tabbable": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", + "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/uri-js-replace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uri-js-replace/-/uri-js-replace-1.0.1.tgz", + "integrity": "sha512-W+C9NWNLFOoBI2QWDp4UT9pv65r2w5Cx+3sTYFvtMdDBxkKt1syCqsUdSFAChbEe1uK5TfS04wt/nGwmaeIQ0g==", + "dev": true, + "license": "MIT" + }, + "node_modules/url-template": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", + "integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==", + "dev": true, + "license": "BSD" + }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vite": { + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vitepress": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-1.6.4.tgz", + "integrity": "sha512-+2ym1/+0VVrbhNyRoFFesVvBvHAVMZMK0rw60E3X/5349M1GuVdKeazuksqopEdvkKwKGs21Q729jX81/bkBJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@docsearch/css": "3.8.2", + "@docsearch/js": "3.8.2", + "@iconify-json/simple-icons": "^1.2.21", + "@shikijs/core": "^2.1.0", + "@shikijs/transformers": "^2.1.0", + "@shikijs/types": "^2.1.0", + "@types/markdown-it": "^14.1.2", + "@vitejs/plugin-vue": "^5.2.1", + "@vue/devtools-api": "^7.7.0", + "@vue/shared": "^3.5.13", + "@vueuse/core": "^12.4.0", + "@vueuse/integrations": "^12.4.0", + "focus-trap": "^7.6.4", + "mark.js": "8.11.1", + "minisearch": "^7.1.1", + "shiki": "^2.1.0", + "vite": "^5.4.14", + "vue": "^3.5.13" + }, + "bin": { + "vitepress": "bin/vitepress.js" + }, + "peerDependencies": { + "markdown-it-mathjax3": "^4", + "postcss": "^8" + }, + "peerDependenciesMeta": { + "markdown-it-mathjax3": { + "optional": true + }, + "postcss": { + "optional": true + } + } + }, + "node_modules/vue": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.26.tgz", + "integrity": "sha512-SJ/NTccVyAoNUJmkM9KUqPcYlY+u8OVL1X5EW9RIs3ch5H2uERxyyIUI4MRxVCSOiEcupX9xNGde1tL9ZKpimA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.26", + "@vue/compiler-sfc": "3.5.26", + "@vue/runtime-dom": "3.5.26", + "@vue/server-renderer": "3.5.26", + "@vue/shared": "3.5.26" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/xml-naming": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/xml-naming/-/xml-naming-0.1.0.tgz", + "integrity": "sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yaml": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz", + "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yaml-ast-parser": { + "version": "0.0.43", + "resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz", + "integrity": "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/docs/package.json b/docs/package.json index 2155a55787..c2f741c2ff 100644 --- a/docs/package.json +++ b/docs/package.json @@ -3,10 +3,21 @@ "dev": "vitepress dev --host", "build": "vitepress build", "preview": "vitepress preview", - "set-version": "./scripts/set-version.sh" + "set-version": "./scripts/set-version.sh", + "generate:openapi": "node scripts/generate-openapi.mjs", + "predev": "node scripts/generate-openapi.mjs", + "prebuild": "node scripts/generate-openapi.mjs" }, "devDependencies": { + "redoc": "^2.5.2", + "swagger-ui-dist": "^5.31.0", "vitepress": "^1.6.4" }, - "dependencies": {} + "dependencies": {}, + "overrides": { + "@ungap/structured-clone": "1.3.1" + }, + "resolutions": { + "@ungap/structured-clone": "1.3.1" + } } diff --git a/docs/scripts/generate-openapi.mjs b/docs/scripts/generate-openapi.mjs new file mode 100644 index 0000000000..b86b90d99f --- /dev/null +++ b/docs/scripts/generate-openapi.mjs @@ -0,0 +1,126 @@ +#!/usr/bin/env node +/** + * Dereference backend/schema/swagger.json into docs/src/public/openapi.json + * for static VitePress API reference (Redoc + Swagger UI). + * Uses a small built-in $ref resolver (no extra npm deps required for generation). + */ +import { readFileSync, writeFileSync, mkdirSync } from "node:fs"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const DOCS_ROOT = join(__dirname, ".."); +const REPO_ROOT = process.env.NPM_REPO_ROOT + ? join(process.env.NPM_REPO_ROOT) + : join(DOCS_ROOT, ".."); +const SCHEMA_DIR = join(REPO_ROOT, "backend", "schema"); +const SCHEMA_PATH = join(SCHEMA_DIR, "swagger.json"); +const OUT_PATH = join(DOCS_ROOT, "src", "public", "openapi.json"); +const VERSION_FILE = join(REPO_ROOT, ".version"); + +const loadVersion = () => { + try { + const v = readFileSync(VERSION_FILE, "utf8").trim().replace(/^v/, ""); + if (/^\d+\.\d+\.\d+$/.test(v)) return v; + } catch { + // fall through + } + const pkg = JSON.parse(readFileSync(join(REPO_ROOT, "backend", "package.json"), "utf8")); + return pkg.version || "0.0.0"; +}; + +const readJson = (path) => JSON.parse(readFileSync(path, "utf8")); + +const fileCache = new Map(); + +const loadFileRef = (refPath, baseDir) => { + const resolved = join(baseDir, refPath); + if (!fileCache.has(resolved)) { + const doc = readJson(resolved); + fileCache.set(resolved, doc); + } + return fileCache.get(resolved); +}; + +const resolvePointer = (root, pointer) => { + const parts = pointer.replace(/^#\//, "").split("/"); + let node = root; + for (const part of parts) { + if (node === undefined || node === null) { + throw new Error(`Invalid JSON pointer: ${pointer}`); + } + node = node[part.replace(/~1/g, "/").replace(/~0/g, "~")]; + } + return node; +}; + +const deref = (value, baseDir, document, stack = new Set()) => { + if (value === null || typeof value !== "object") { + return value; + } + + if (Array.isArray(value)) { + return value.map((item) => deref(item, baseDir, document, stack)); + } + + if (typeof value.$ref === "string") { + const ref = value.$ref; + if (stack.has(ref)) { + throw new Error(`Circular $ref: ${ref}`); + } + stack.add(ref); + + let target; + let nextBaseDir = baseDir; + let nextDocument = document; + + if (ref.startsWith("#/")) { + target = resolvePointer(document, ref); + } else if (ref.startsWith("./") || ref.startsWith("../")) { + const hashIndex = ref.indexOf("#"); + const filePart = hashIndex >= 0 ? ref.slice(0, hashIndex) : ref; + const hashPart = hashIndex >= 0 ? ref.slice(hashIndex) : null; + const resolvedFile = join(baseDir, filePart); + nextBaseDir = dirname(resolvedFile); + const fileDoc = loadFileRef(filePart, baseDir); + nextDocument = fileDoc; + target = hashPart ? resolvePointer(fileDoc, hashPart) : fileDoc; + } else { + throw new Error(`Unsupported $ref: ${ref}`); + } + + const resolved = deref(structuredClone(target), nextBaseDir, nextDocument, stack); + stack.delete(ref); + return resolved; + } + + const out = {}; + for (const [key, child] of Object.entries(value)) { + out[key] = deref(child, baseDir, document, stack); + } + return out; +}; + +const main = () => { + const root = readJson(SCHEMA_PATH); + const spec = deref(root, SCHEMA_DIR, root); + + spec.info = spec.info || {}; + spec.info.version = loadVersion(); + spec.servers = [{ url: "/api", description: "NPM API (relative to docs site origin)" }]; + + if (!spec.paths || typeof spec.paths !== "object") { + throw new Error("OpenAPI spec missing paths after dereference"); + } + + mkdirSync(dirname(OUT_PATH), { recursive: true }); + writeFileSync(OUT_PATH, `${JSON.stringify(spec, null, "\t")}\n`, "utf8"); + console.log(`Wrote ${OUT_PATH} (${Object.keys(spec.paths).length} paths, v${spec.info.version})`); +}; + +try { + main(); +} catch (err) { + console.error(err); + process.exit(1); +} diff --git a/docs/src/advanced-config/index.md b/docs/src/advanced-config/index.md index 3ab04ce25b..28aa7340d5 100644 --- a/docs/src/advanced-config/index.md +++ b/docs/src/advanced-config/index.md @@ -4,6 +4,20 @@ outline: deep # Advanced Configuration +## Credential vault and automation + +DNS API tokens are stored encrypted on the **`/data`** volume (`/data/credentials/`). Manage them in the admin UI under **Settings → DNS credentials** (legacy `/credentials` URLs redirect to `/settings?tab=dns-credentials`). Mount the same volume across upgrades. Optionally set `NPM_SECRETS_ENCRYPTION_KEY` (32-byte value, base64-encoded) instead of the auto-generated key under `/data/keys/secrets.json`. + +For REST automation (API keys, async certificate jobs, signed webhooks, external secret stores), see the [Automation API](/advanced/automation-api) guide. Security reporting: [SECURITY.md](https://github.com/NginxProxyManager/nginx-proxy-manager/blob/develop/SECURITY.md). + +To exercise HashiCorp Vault locally during development: + +```bash +docker compose -f docker/docker-compose.dev.yml --profile vault up -d vault-dev +``` + +Vault listens on `http://127.0.0.1:8200` with dev root token `npm-dev-root`. Configure a provider in NPM pointing at `http://vault-dev:8200` from inside the stack network. + ## Running processes as a user/group By default, the services (nginx etc) will run as `root` user inside the docker container. diff --git a/docs/src/advanced/automation-api.md b/docs/src/advanced/automation-api.md new file mode 100644 index 0000000000..3fa6dd7f6b --- /dev/null +++ b/docs/src/advanced/automation-api.md @@ -0,0 +1,180 @@ +--- +outline: deep +--- + +# Automation API + +Nginx Proxy Manager exposes a REST API at `/api` on the admin port (default `81`). + +- **Full reference (Redoc):** [API Reference](/api-reference/) +- **Try it out (Swagger UI):** [API Reference (Swagger)](/api-reference/swagger) — requires `/api` on the same host as the docs site +- **Live schema from a running instance:** `GET /api/schema` + +## Authentication + +### User JWT (existing) + +```bash +curl -s -X POST http://127.0.0.1:81/api/tokens \ + -H 'Content-Type: application/json' \ + -d '{"identity":"admin@example.com","secret":"your-password"}' +``` + +Use `Authorization: Bearer ` on subsequent requests. Tokens default to 1-day expiry; refresh with `GET /api/tokens`. + +### API keys (new) + +Admins can create long-lived keys: + +```bash +curl -s -X POST http://127.0.0.1:81/api/api-keys \ + -H "Authorization: Bearer $TOKEN" \ + -H 'Content-Type: application/json' \ + -d '{"name":"terraform","permissions":{"proxy_hosts":"manage","certificates":"manage"}}' +``` + +The response includes `key` once (`npmak_...`). Use it as: + +`Authorization: Bearer npmak__` + +## Proxy hosts + +| Method | Path | +|--------|------| +| GET | `/api/nginx/proxy-hosts` | +| POST | `/api/nginx/proxy-hosts` | +| GET | `/api/nginx/proxy-hosts/{id}` | +| PUT | `/api/nginx/proxy-hosts/{id}` | +| DELETE | `/api/nginx/proxy-hosts/{id}` | +| POST | `/api/nginx/proxy-hosts/{id}/enable` | +| POST | `/api/nginx/proxy-hosts/{id}/disable` | + +## Certificates + +| Method | Path | +|--------|------| +| GET | `/api/nginx/certificates` | +| POST | `/api/nginx/certificates` | +| PUT | `/api/nginx/certificates/{id}` | +| DELETE | `/api/nginx/certificates/{id}` | +| POST | `/api/nginx/certificates/{id}/renew` | + +Append `?async=true` to **POST** (create) or **renew** to receive `202` with `{ job_id, status }`. Poll `GET /api/jobs/{job_id}`. + +## Admin UI (Settings) + +| Feature | Location | +|---------|----------| +| DNS credentials (internal vault) | **Settings** → **DNS credentials** (`/settings?tab=dns-credentials`; `/credentials` redirects here) | +| External stores (Vault, AWS, Azure, Infisical, HTTP) | **Settings** → **External credential stores** | +| API keys & webhooks | **Settings** → **API keys** / **Webhooks** | + +Users with credentials-only permission can open Settings for the DNS credentials tab without full admin access. + +## DNS credential vault + +Secrets are encrypted on the **`/data` persistent volume** at `/data/credentials/`. Metadata is in the database. + +| Method | Path | +|--------|------| +| GET | `/api/credentials` | +| POST | `/api/credentials` | +| PUT | `/api/credentials/{id}` | +| DELETE | `/api/credentials/{id}` | +| POST | `/api/credentials/{id}/test` | + +Create a certificate referencing a stored credential: + +```json +{ + "provider": "letsencrypt", + "domain_names": ["example.com"], + "meta": { + "dns_challenge": true, + "dns_provider": "cloudflare", + "credential_ref": { "type": "internal", "id": 1 } + } +} +``` + +Set `NPM_SECRETS_ENCRYPTION_KEY` (32-byte base64) before first use in production, or NPM generates `/data/keys/secrets.json` on the data volume. + +## External credential stores (Vault, AWS, Azure, Infisical) + +Configure providers (admin, Settings → External Credential Stores or API): + +| Method | Path | +|--------|------| +| GET | `/api/credential-providers` | +| POST | `/api/credential-providers` | +| PUT | `/api/credential-providers/{id}` | +| DELETE | `/api/credential-providers/{id}` | +| POST | `/api/credential-providers/{id}/test` | +| POST | `/api/credential-providers/{id}/test-resolve` | + +Provider `type`: `vault` (HashiCorp Vault), `aws`, `azure`, `infisical`, `http`. OIDC client secrets (and Infisical Universal Auth secrets) are stored encrypted under `/data/credentials/providers/`. + +### Infisical + +Use **Universal Auth** (Machine Identity client ID + secret). Automation outside the admin UI (for example a separate CI/CD OIDC integration with Infisical) should not reuse the same credentials as the NPM provider entry unless you intend that trust boundary. + +Example provider: + +```json +{ + "name": "Infisical prod", + "type": "infisical", + "oidc_client_id": "", + "oidc_client_secret": "", + "meta": { + "host": "https://vault.example.com", + "workspace_id": "", + "environment_slug": "prod", + "auth_method": "universal" + } +} +``` + +`credential_ref.path` is the Infisical **folder + secret key** (environment comes from the provider’s `environment_slug`, not from this path): + +- `/DNS/cloudflare-api-token` — secret key `cloudflare-api-token` in folder `/DNS` +- `cloudflare-api-token` — same key at project root (`secretPath=/`) + +Alternatively set `path` to the folder (e.g. `/DNS`) and `field` to the secret key. + +Reference in a certificate: + +```json +"meta": { + "dns_challenge": true, + "dns_provider": "cloudflare", + "credential_ref": { + "type": "external", + "provider_id": 1, + "path": "/DNS/cloudflare-api-token" + } +} +``` + +## Webhooks + +Configure endpoints (admin only): + +| Method | Path | +|--------|------| +| GET | `/api/webhooks` | +| POST | `/api/webhooks` | +| DELETE | `/api/webhooks/{id}` | + +Events: `proxy_host.created|updated|deleted|enabled|disabled`, `certificate.created|updated|deleted|renewed|failed`. Verify `X-NPM-Signature: sha256=` over the raw JSON body. Failed deliveries are retried up to three times with backoff. + +## Docker volume + +Mount persistent storage: + +```yaml +volumes: + - ./data:/data +``` + +The credential vault requires `/data` to survive container recreation. diff --git a/docs/src/api-reference/index.md b/docs/src/api-reference/index.md new file mode 100644 index 0000000000..e708a901de --- /dev/null +++ b/docs/src/api-reference/index.md @@ -0,0 +1,15 @@ +--- +outline: deep +--- + +# API Reference (Redoc) + +Full OpenAPI 3.1 reference for the Nginx Proxy Manager REST API (`/api` on the admin port, default `81`). + +- **Guides:** [Automation API](/advanced/automation-api) (auth, async jobs, credentials, webhooks) +- **Try it out:** [Swagger UI](/api-reference/swagger) (calls `/api` on the same host as this docs site; requires the admin API to be reverse-proxied on that host) +- **Live schema from a running instance:** `GET /api/schema` + + + + diff --git a/docs/src/api-reference/swagger.md b/docs/src/api-reference/swagger.md new file mode 100644 index 0000000000..88b8d6b48c --- /dev/null +++ b/docs/src/api-reference/swagger.md @@ -0,0 +1,15 @@ +--- +outline: deep +--- + +# API Reference (Swagger UI) + +Interactive OpenAPI browser with **Try it out**. Requests use server URL **`/api`** relative to this site’s origin. + +For that to work, the NPM admin API must be reachable on the same host (for example reverse-proxy `/api` to port `81`). A sample nginx config is in the repository at `docker/docs-api-proxy.conf.example` ([view on GitHub](https://github.com/NginxProxyManager/nginx-proxy-manager/blob/develop/docker/docs-api-proxy.conf.example)). If you only host static docs without `/api`, use [Redoc](/api-reference/) for reading and the [Automation API](/advanced/automation-api) guide for curl examples. + +Authenticate with **Authorize** using `Bearer ` from `POST /api/tokens` or an API key. + + + + diff --git a/docs/src/public/openapi.json b/docs/src/public/openapi.json new file mode 100644 index 0000000000..55bb8b57b5 --- /dev/null +++ b/docs/src/public/openapi.json @@ -0,0 +1,20598 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Nginx Proxy Manager API", + "version": "2.15.1", + "description": "This is the official API documentation for Nginx Proxy Manager.\n\nMost endpoints require authentication via Bearer Token (JWT). You can generate a token by logging in via the `POST /tokens` endpoint.\n\nFor more information, visit the [Nginx Proxy Manager Documentation](https://nginxproxymanager.com)." + }, + "servers": [ + { + "url": "/api", + "description": "NPM API (relative to docs site origin)" + } + ], + "components": { + "securitySchemes": { + "bearerAuth": { + "type": "http", + "scheme": "bearer", + "bearerFormat": "JWT", + "description": "JWT Bearer Token authentication" + } + } + }, + "tags": [ + { + "name": "public", + "description": "Endpoints that do not require authentication" + }, + { + "name": "audit-log", + "description": "Endpoints related to Audit Logs" + }, + { + "name": "access-lists", + "description": "Endpoints related to Access Lists" + }, + { + "name": "certificates", + "description": "Endpoints related to Certificates" + }, + { + "name": "credentials", + "description": "Endpoints related to stored DNS credentials" + }, + { + "name": "credential-providers", + "description": "External secret store providers (Vault, AWS, Azure, Infisical)" + }, + { + "name": "api-keys", + "description": "Endpoints for automation API keys" + }, + { + "name": "jobs", + "description": "Endpoints for async background jobs" + }, + { + "name": "webhooks", + "description": "Endpoints for outbound webhook configuration" + }, + { + "name": "404-hosts", + "description": "Endpoints related to 404 Hosts" + }, + { + "name": "proxy-hosts", + "description": "Endpoints related to Proxy Hosts" + }, + { + "name": "redirection-hosts", + "description": "Endpoints related to Redirection Hosts" + }, + { + "name": "streams", + "description": "Endpoints related to Streams" + }, + { + "name": "reports", + "description": "Endpoints for viewing reports" + }, + { + "name": "settings", + "description": "Endpoints for managing application settings" + }, + { + "name": "tokens", + "description": "Endpoints for managing authentication tokens" + }, + { + "name": "users", + "description": "Endpoints for managing users" + } + ], + "paths": { + "/": { + "get": { + "operationId": "health", + "summary": "Returns the API health status", + "tags": [ + "public" + ], + "description": "Public health check for the admin API. Returns setup status and semantic version fields without authentication.", + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "status": "OK", + "setup": true, + "version": { + "major": 2, + "minor": 1, + "revision": 0, + "string": "v2.1.0" + } + } + } + }, + "schema": { + "type": "object", + "description": "Health object", + "additionalProperties": false, + "required": [ + "status", + "version" + ], + "properties": { + "status": { + "type": "string", + "description": "Healthy", + "example": "OK" + }, + "setup": { + "type": "boolean", + "description": "Whether the initial setup has been completed", + "example": true + }, + "version": { + "type": "object", + "description": "The version object", + "example": { + "major": 2, + "minor": 0, + "revision": 0, + "string": "v2.0.0" + }, + "additionalProperties": false, + "required": [ + "major", + "minor", + "revision", + "string" + ], + "properties": { + "major": { + "type": "integer", + "minimum": 0, + "example": 2 + }, + "minor": { + "type": "integer", + "minimum": 0, + "example": 10 + }, + "revision": { + "type": "integer", + "minimum": 0, + "example": 1 + }, + "string": { + "type": "string", + "description": "Semantic version string", + "example": "v2.10.1" + } + } + } + } + } + } + } + } + } + } + }, + "/audit-log": { + "get": { + "operationId": "getAuditLogs", + "summary": "Get Audit Logs", + "tags": [ + "audit-log" + ], + "security": [ + { + "bearerAuth": [ + "admin" + ] + } + ], + "description": "Returns paginated audit log entries for administrative review.", + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": [ + { + "id": 7, + "created_on": "2024-10-08T13:09:54.000Z", + "modified_on": "2024-10-08T13:09:54.000Z", + "user_id": 1, + "object_type": "user", + "object_id": 3, + "action": "updated", + "meta": { + "name": "John Doe", + "permissions": { + "user_id": 3, + "visibility": "all", + "access_lists": "manage", + "dead_hosts": "hidden", + "proxy_hosts": "manage", + "redirection_hosts": "view", + "streams": "hidden", + "certificates": "manage", + "id": 3, + "modified_on": "2024-10-08T13:09:54.000Z", + "created_on": "2024-10-08T13:09:51.000Z" + } + } + } + ] + } + }, + "schema": { + "type": "array", + "description": "Audit Log list", + "items": { + "type": "object", + "description": "Audit Log object", + "required": [ + "id", + "created_on", + "modified_on", + "user_id", + "object_type", + "object_id", + "action", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "object_type": { + "type": "string", + "example": "certificate" + }, + "object_id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "action": { + "type": "string", + "example": "created" + }, + "meta": { + "type": "object", + "example": {} + }, + "user": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/audit-log/{id}": { + "get": { + "operationId": "getAuditLog", + "summary": "Get Audit Log Event", + "tags": [ + "audit-log" + ], + "security": [ + { + "bearerAuth": [ + "admin" + ] + } + ], + "description": "Returns a single audit log entry by id.", + "parameters": [ + { + "in": "path", + "name": "id", + "description": "Audit Log Event ID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 1 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "id": 1, + "created_on": "2025-09-15T17:27:45.000Z", + "modified_on": "2025-09-15T17:27:45.000Z", + "user_id": 1, + "object_type": "user", + "object_id": 1, + "action": "created", + "meta": { + "id": 1, + "created_on": "2025-09-15T17:27:45.000Z", + "modified_on": "2025-09-15T17:27:45.000Z", + "is_disabled": false, + "email": "jc@jc21.com", + "name": "Jamie", + "nickname": "Jamie", + "avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm", + "roles": [ + "admin" + ], + "permissions": { + "visibility": "all", + "proxy_hosts": "manage", + "redirection_hosts": "manage", + "dead_hosts": "manage", + "streams": "manage", + "access_lists": "manage", + "certificates": "manage" + } + } + } + } + }, + "schema": { + "type": "object", + "description": "Audit Log object", + "required": [ + "id", + "created_on", + "modified_on", + "user_id", + "object_type", + "object_id", + "action", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "object_type": { + "type": "string", + "example": "certificate" + }, + "object_id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "action": { + "type": "string", + "example": "created" + }, + "meta": { + "type": "object", + "example": {} + }, + "user": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/nginx/access-lists": { + "get": { + "operationId": "getAccessLists", + "summary": "Get all access lists", + "tags": [ + "access-lists" + ], + "security": [ + { + "bearerAuth": [ + "access_lists.view" + ] + } + ], + "description": "Returns all access lists (HTTP authentication and access rules) configured in NPM.", + "parameters": [ + { + "in": "query", + "name": "expand", + "description": "Expansions", + "schema": { + "type": "string", + "enum": [ + "owner", + "items", + "clients", + "proxy_hosts" + ] + } + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "example": { + "id": 1, + "created_on": "2024-10-08T22:15:40.000Z", + "modified_on": "2024-10-08T22:15:40.000Z", + "owner_user_id": 1, + "name": "test1234", + "meta": {}, + "satisfy_any": true, + "pass_auth": false, + "proxy_host_count": 0 + }, + "schema": { + "type": "object", + "description": "Access List object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "name", + "meta", + "satisfy_any", + "pass_auth", + "proxy_host_count" + ], + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "name": { + "type": "string", + "minLength": 1, + "example": "My Access List" + }, + "meta": { + "type": "object", + "example": {} + }, + "satisfy_any": { + "type": "boolean", + "example": true + }, + "pass_auth": { + "type": "boolean", + "example": false + }, + "proxy_host_count": { + "type": "integer", + "minimum": 0, + "example": 3 + } + } + } + } + } + } + } + }, + "post": { + "operationId": "createAccessList", + "summary": "Create a Access List", + "tags": [ + "access-lists" + ], + "security": [ + { + "bearerAuth": [ + "access_lists.manage" + ] + } + ], + "description": "Creates an access list for use on proxy hosts, redirection hosts, or streams.", + "requestBody": { + "description": "Access List Payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string", + "minLength": 1, + "example": "My Access List" + }, + "satisfy_any": { + "type": "boolean", + "example": true + }, + "pass_auth": { + "type": "boolean", + "example": false + }, + "items": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "username": { + "type": "string", + "minLength": 1 + }, + "password": { + "type": "string" + } + }, + "example": { + "username": "admin", + "password": "pass" + } + }, + "example": [ + { + "username": "admin", + "password": "pass" + } + ] + }, + "clients": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "address": { + "oneOf": [ + { + "type": "string", + "pattern": "^([0-9]{1,3}\\.){3}[0-9]{1,3}(/([0-9]|[1-2][0-9]|3[0-2]))?$" + }, + { + "type": "string", + "pattern": "^s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*(/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8]))?$" + }, + { + "type": "string", + "pattern": "^all$" + } + ], + "example": "192.168.0.11" + }, + "directive": { + "type": "string", + "enum": [ + "allow", + "deny" + ], + "example": "allow" + } + }, + "example": { + "directive": "allow", + "address": "192.168.0.0/24" + } + }, + "example": [ + { + "directive": "allow", + "address": "192.168.0.0/24" + } + ] + } + } + }, + "example": { + "name": "My Access List", + "satisfy_any": true, + "pass_auth": false, + "items": [ + { + "username": "admin", + "password": "pass" + } + ], + "clients": [ + { + "directive": "allow", + "address": "192.168.0.0/24" + } + ] + } + } + } + }, + "responses": { + "201": { + "description": "201 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "id": 1, + "created_on": "2024-10-08T22:15:40.000Z", + "modified_on": "2024-10-08T22:15:40.000Z", + "owner_user_id": 1, + "name": "test1234", + "meta": {}, + "satisfy_any": true, + "pass_auth": false, + "proxy_host_count": 0, + "owner": { + "id": 1, + "created_on": "2024-10-07T22:43:55.000Z", + "modified_on": "2024-10-08T12:52:54.000Z", + "is_disabled": false, + "email": "admin@example.com", + "name": "Administrator", + "nickname": "some guy", + "avatar": "//www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?default=mm", + "roles": [ + "admin" + ] + }, + "items": [ + { + "id": 1, + "created_on": "2024-10-08T22:15:40.000Z", + "modified_on": "2024-10-08T22:15:40.000Z", + "access_list_id": 1, + "username": "admin", + "password": "", + "meta": {}, + "hint": "a****" + }, + { + "id": 2, + "created_on": "2024-10-08T22:15:40.000Z", + "modified_on": "2024-10-08T22:15:40.000Z", + "access_list_id": 1, + "username": "asdad", + "password": "", + "meta": {}, + "hint": "a*****" + } + ], + "proxy_hosts": [], + "clients": [ + { + "id": 1, + "created_on": "2024-10-08T22:15:40.000Z", + "modified_on": "2024-10-08T22:15:40.000Z", + "access_list_id": 1, + "address": "127.0.0.1", + "directive": "allow", + "meta": {} + } + ] + } + } + }, + "schema": { + "type": "object", + "description": "Access List object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "name", + "meta", + "satisfy_any", + "pass_auth", + "proxy_host_count" + ], + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "name": { + "type": "string", + "minLength": 1, + "example": "My Access List" + }, + "meta": { + "type": "object", + "example": {} + }, + "satisfy_any": { + "type": "boolean", + "example": true + }, + "pass_auth": { + "type": "boolean", + "example": false + }, + "proxy_host_count": { + "type": "integer", + "minimum": 0, + "example": 3 + } + } + } + } + } + } + } + } + }, + "/nginx/access-lists/{listID}": { + "get": { + "operationId": "getAccessList", + "summary": "Get a access List", + "tags": [ + "access-lists" + ], + "security": [ + { + "bearerAuth": [ + "access_lists.view" + ] + } + ], + "description": "Returns one access list including authorization and access rule entries.", + "parameters": [ + { + "in": "path", + "name": "listID", + "description": "Access List ID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 1 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "id": 1, + "created_on": "2025-10-28T04:06:55.000Z", + "modified_on": "2025-10-29T22:48:20.000Z", + "owner_user_id": 1, + "name": "My Access List", + "meta": {}, + "satisfy_any": false, + "pass_auth": false, + "proxy_host_count": 1 + } + } + }, + "schema": { + "type": "object", + "description": "Access List object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "name", + "meta", + "satisfy_any", + "pass_auth", + "proxy_host_count" + ], + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "name": { + "type": "string", + "minLength": 1, + "example": "My Access List" + }, + "meta": { + "type": "object", + "example": {} + }, + "satisfy_any": { + "type": "boolean", + "example": true + }, + "pass_auth": { + "type": "boolean", + "example": false + }, + "proxy_host_count": { + "type": "integer", + "minimum": 0, + "example": 3 + } + } + } + } + } + } + } + }, + "put": { + "operationId": "updateAccessList", + "summary": "Update a Access List", + "tags": [ + "access-lists" + ], + "security": [ + { + "bearerAuth": [ + "access_lists.manage" + ] + } + ], + "description": "Updates an access list and its nested auth or access items.", + "parameters": [ + { + "in": "path", + "name": "listID", + "description": "Access List ID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 2 + } + ], + "requestBody": { + "description": "Access List Payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "minProperties": 1, + "properties": { + "name": { + "type": "string", + "minLength": 1, + "example": "My Access List" + }, + "satisfy_any": { + "type": "boolean", + "example": true + }, + "pass_auth": { + "type": "boolean", + "example": false + }, + "items": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "username": { + "type": "string", + "minLength": 1 + }, + "password": { + "type": "string" + } + }, + "example": { + "username": "admin", + "password": "pass" + } + }, + "example": [ + { + "username": "admin", + "password": "pass" + } + ] + }, + "clients": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "address": { + "oneOf": [ + { + "type": "string", + "pattern": "^([0-9]{1,3}\\.){3}[0-9]{1,3}(/([0-9]|[1-2][0-9]|3[0-2]))?$" + }, + { + "type": "string", + "pattern": "^s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*(/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8]))?$" + }, + { + "type": "string", + "pattern": "^all$" + } + ], + "example": "192.168.0.11" + }, + "directive": { + "type": "string", + "enum": [ + "allow", + "deny" + ], + "example": "allow" + } + }, + "example": { + "directive": "allow", + "address": "192.168.0.0/24" + } + }, + "example": [ + { + "directive": "allow", + "address": "192.168.0.0/24" + } + ] + } + } + }, + "example": { + "name": "My Access List", + "satisfy_any": true, + "pass_auth": false, + "items": [ + { + "username": "admin2", + "password": "pass2" + } + ], + "clients": [ + { + "directive": "allow", + "address": "192.168.0.0/24" + } + ] + } + } + } + }, + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "id": 1, + "created_on": "2024-10-08T22:15:40.000Z", + "modified_on": "2024-10-08T22:34:34.000Z", + "owner_user_id": 1, + "name": "test123!!", + "meta": {}, + "satisfy_any": true, + "pass_auth": false, + "proxy_host_count": 0, + "owner": { + "id": 1, + "created_on": "2024-10-07T22:43:55.000Z", + "modified_on": "2024-10-08T12:52:54.000Z", + "is_disabled": false, + "email": "admin@example.com", + "name": "Administrator", + "nickname": "some guy", + "avatar": "//www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?default=mm", + "roles": [ + "admin" + ] + }, + "items": [ + { + "id": 1, + "created_on": "2024-10-08T22:15:40.000Z", + "modified_on": "2024-10-08T22:15:40.000Z", + "access_list_id": 1, + "username": "admin", + "password": "", + "meta": {}, + "hint": "a****" + }, + { + "id": 2, + "created_on": "2024-10-08T22:15:40.000Z", + "modified_on": "2024-10-08T22:15:40.000Z", + "access_list_id": 1, + "username": "asdad", + "password": "", + "meta": {}, + "hint": "a*****" + } + ], + "clients": [ + { + "id": 1, + "created_on": "2024-10-08T22:15:40.000Z", + "modified_on": "2024-10-08T22:15:40.000Z", + "access_list_id": 1, + "address": "127.0.0.1", + "directive": "allow", + "meta": {} + } + ], + "proxy_hosts": [] + } + } + }, + "schema": { + "type": "object", + "description": "Access List object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "name", + "meta", + "satisfy_any", + "pass_auth", + "proxy_host_count" + ], + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "name": { + "type": "string", + "minLength": 1, + "example": "My Access List" + }, + "meta": { + "type": "object", + "example": {} + }, + "satisfy_any": { + "type": "boolean", + "example": true + }, + "pass_auth": { + "type": "boolean", + "example": false + }, + "proxy_host_count": { + "type": "integer", + "minimum": 0, + "example": 3 + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "deleteAccessList", + "summary": "Delete a Access List", + "tags": [ + "access-lists" + ], + "security": [ + { + "bearerAuth": [ + "access_lists.manage" + ] + } + ], + "description": "Deletes an access list. Hosts referencing it must be updated separately.", + "parameters": [ + { + "in": "path", + "name": "listID", + "description": "Access List ID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 2 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": true + } + }, + "schema": { + "type": "boolean" + } + } + } + } + } + } + }, + "/nginx/certificates": { + "get": { + "operationId": "getCertificates", + "summary": "Get all certificates", + "tags": [ + "certificates" + ], + "security": [ + { + "bearerAuth": [ + "certificates.view" + ] + } + ], + "description": "Lists SSL certificates known to NPM including managed, custom, and in-progress orders.", + "parameters": [ + { + "in": "query", + "name": "expand", + "description": "Expansions", + "schema": { + "type": "string", + "enum": [ + "owner" + ] + } + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": [ + { + "id": 4, + "created_on": "2024-10-09T05:31:58.000Z", + "modified_on": "2024-10-09T05:32:11.000Z", + "owner_user_id": 1, + "provider": "letsencrypt", + "nice_name": "test.example.com", + "domain_names": [ + "test.example.com" + ], + "expires_on": "2025-01-07T04:34:18.000Z", + "meta": { + "dns_challenge": false + } + } + ] + } + }, + "schema": { + "type": "array", + "description": "Certificates list", + "items": { + "type": "object", + "description": "Certificate object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "provider", + "nice_name", + "domain_names", + "expires_on", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "provider": { + "type": "string", + "pattern": "^(letsencrypt|other)$", + "example": "letsencrypt" + }, + "nice_name": { + "type": "string", + "description": "Nice Name for the custom certificate", + "example": "My Custom Cert" + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "expires_on": { + "description": "Date and time of expiration", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + }, + "meta": { + "type": "object", + "additionalProperties": false, + "properties": { + "certificate": { + "type": "string", + "minLength": 1 + }, + "certificate_key": { + "type": "string", + "minLength": 1 + }, + "dns_challenge": { + "type": "boolean" + }, + "dns_provider_credentials": { + "type": "string" + }, + "credential_ref": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "internal", + "external" + ] + }, + "id": { + "type": "integer", + "minimum": 1 + }, + "provider_id": { + "type": "integer", + "minimum": 1 + }, + "path": { + "type": "string" + }, + "field": { + "type": "string" + } + } + }, + "dns_provider": { + "type": "string" + }, + "letsencrypt_certificate": { + "type": "object" + }, + "propagation_seconds": { + "type": "integer", + "minimum": 0 + }, + "key_type": { + "type": "string", + "enum": [ + "rsa", + "ecdsa" + ], + "default": "rsa" + } + }, + "example": { + "dns_challenge": false + } + } + } + } + } + } + } + } + } + }, + "post": { + "operationId": "createCertificate", + "summary": "Create a Certificate", + "tags": [ + "certificates" + ], + "security": [ + { + "bearerAuth": [ + "certificates.manage" + ] + } + ], + "description": "Requests a new certificate (HTTP, DNS, or custom workflow depending on payload).", + "requestBody": { + "description": "Certificate Payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "required": [ + "provider" + ], + "properties": { + "provider": { + "type": "string", + "pattern": "^(letsencrypt|other)$", + "example": "letsencrypt" + }, + "nice_name": { + "type": "string", + "description": "Nice Name for the custom certificate", + "example": "My Custom Cert" + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "meta": { + "type": "object", + "additionalProperties": false, + "properties": { + "certificate": { + "type": "string", + "minLength": 1 + }, + "certificate_key": { + "type": "string", + "minLength": 1 + }, + "dns_challenge": { + "type": "boolean" + }, + "dns_provider_credentials": { + "type": "string" + }, + "credential_ref": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "internal", + "external" + ] + }, + "id": { + "type": "integer", + "minimum": 1 + }, + "provider_id": { + "type": "integer", + "minimum": 1 + }, + "path": { + "type": "string" + }, + "field": { + "type": "string" + } + } + }, + "dns_provider": { + "type": "string" + }, + "letsencrypt_certificate": { + "type": "object" + }, + "propagation_seconds": { + "type": "integer", + "minimum": 0 + }, + "key_type": { + "type": "string", + "enum": [ + "rsa", + "ecdsa" + ], + "default": "rsa" + } + }, + "example": { + "dns_challenge": false + } + } + } + }, + "example": { + "provider": "letsencrypt", + "domain_names": [ + "test.example.com" + ], + "meta": { + "dns_challenge": false + } + } + } + } + }, + "responses": { + "201": { + "description": "201 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "expires_on": "2025-01-07 04:30:17", + "modified_on": "2024-10-09 05:28:51", + "id": 5, + "created_on": "2024-10-09 05:28:35", + "owner_user_id": 1, + "provider": "letsencrypt", + "nice_name": "test.example.com", + "domain_names": [ + "test.example.com" + ], + "meta": { + "dns_challenge": false, + "letsencrypt_certificate": { + "cn": "test.example.com", + "issuer": "C = US, O = Let's Encrypt, CN = E5", + "dates": { + "from": 1728448218, + "to": 1736224217 + } + } + } + } + } + }, + "schema": { + "type": "object", + "description": "Certificate object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "provider", + "nice_name", + "domain_names", + "expires_on", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "provider": { + "type": "string", + "pattern": "^(letsencrypt|other)$", + "example": "letsencrypt" + }, + "nice_name": { + "type": "string", + "description": "Nice Name for the custom certificate", + "example": "My Custom Cert" + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "expires_on": { + "description": "Date and time of expiration", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + }, + "meta": { + "type": "object", + "additionalProperties": false, + "properties": { + "certificate": { + "type": "string", + "minLength": 1 + }, + "certificate_key": { + "type": "string", + "minLength": 1 + }, + "dns_challenge": { + "type": "boolean" + }, + "dns_provider_credentials": { + "type": "string" + }, + "credential_ref": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "internal", + "external" + ] + }, + "id": { + "type": "integer", + "minimum": 1 + }, + "provider_id": { + "type": "integer", + "minimum": 1 + }, + "path": { + "type": "string" + }, + "field": { + "type": "string" + } + } + }, + "dns_provider": { + "type": "string" + }, + "letsencrypt_certificate": { + "type": "object" + }, + "propagation_seconds": { + "type": "integer", + "minimum": 0 + }, + "key_type": { + "type": "string", + "enum": [ + "rsa", + "ecdsa" + ], + "default": "rsa" + } + }, + "example": { + "dns_challenge": false + } + } + } + } + } + } + }, + "202": { + "description": "Async acceptance when query parameter async=true", + "content": { + "application/json": { + "example": { + "job_id": 1, + "status": "pending" + }, + "schema": { + "type": "object", + "description": "Async certificate request accepted; poll the job endpoint for completion", + "required": [ + "job_id", + "status" + ], + "additionalProperties": false, + "properties": { + "job_id": { + "type": "integer", + "minimum": 1, + "example": 1 + }, + "status": { + "type": "string", + "enum": [ + "pending", + "running", + "completed", + "failed" + ], + "example": "pending" + } + } + } + } + } + }, + "400": { + "description": "400 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "error": { + "code": 400, + "message": "Domains are invalid" + } + } + } + }, + "schema": { + "type": "object", + "description": "Error", + "properties": { + "error": { + "type": "object", + "description": "Error object", + "additionalProperties": false, + "required": [ + "code", + "message" + ], + "properties": { + "code": { + "type": "integer", + "example": 400 + }, + "message": { + "type": "string", + "example": "Bad Request" + } + } + } + } + } + } + } + } + } + } + }, + "/nginx/certificates/dns-providers": { + "get": { + "operationId": "getDNSProviders", + "summary": "Get DNS Providers for Certificates", + "tags": [ + "certificates" + ], + "security": [ + { + "bearerAuth": [ + "certificates.view" + ] + } + ], + "description": "Lists DNS providers supported for ACME DNS challenge certificate issuance.", + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": [ + { + "id": "vultr", + "name": "Vultr", + "credentials": "dns_vultr_key = YOUR_VULTR_API_KEY" + }, + { + "id": "websupport", + "name": "Websupport.sk", + "credentials": "dns_websupport_identifier = \ndns_websupport_secret_key = " + }, + { + "id": "wedos", + "name": "Wedos", + "credentials": "dns_wedos_user = \ndns_wedos_auth = " + }, + { + "id": "zoneedit", + "name": "ZoneEdit", + "credentials": "dns_zoneedit_user = \ndns_zoneedit_token = " + } + ] + } + }, + "schema": { + "type": "array", + "description": "DNS Providers list", + "items": { + "type": "object", + "required": [ + "id", + "name", + "credentials" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for the DNS provider, matching the python package" + }, + "name": { + "type": "string", + "description": "Human-readable name of the DNS provider" + }, + "credentials": { + "type": "string", + "description": "Instructions on how to format the credentials for this DNS provider" + } + } + } + } + } + } + } + } + } + }, + "/nginx/certificates/validate": { + "post": { + "operationId": "validateCertificates", + "summary": "Validates given Custom Certificates", + "tags": [ + "certificates" + ], + "security": [ + { + "bearerAuth": [ + "certificates.manage" + ] + } + ], + "description": "Validates stored certificates and reports expiry or configuration issues.", + "requestBody": { + "description": "Certificate Files", + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "additionalProperties": false, + "required": [ + "certificate", + "certificate_key" + ], + "properties": { + "certificate": { + "type": "string", + "example": "-----BEGIN CERTIFICATE-----\nMIID...-----END CERTIFICATE-----" + }, + "certificate_key": { + "type": "string", + "example": "-----BEGIN CERTIFICATE-----\nMIID...-----END CERTIFICATE-----" + }, + "intermediate_certificate": { + "type": "string", + "example": "-----BEGIN CERTIFICATE-----\nMIID...-----END CERTIFICATE-----" + } + } + }, + "example": { + "certificate": "-----BEGIN CERTIFICATE-----\nMIID...-----END CERTIFICATE-----", + "certificate_key": "-----BEGIN PRIVATE\nMIID...-----END CERTIFICATE-----" + } + } + } + }, + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "certificate": { + "cn": "mkcert", + "issuer": "O = mkcert development CA, OU = jc@jc-Laptop.local (John Doe), CN = mkcert jc@jc-Laptop.local (John Doe)", + "dates": { + "from": 1728458537, + "to": 1799479337 + } + }, + "certificate_key": true + } + } + }, + "schema": { + "type": "object", + "additionalProperties": false, + "required": [ + "certificate", + "certificate_key" + ], + "properties": { + "certificate": { + "type": "object", + "additionalProperties": false, + "required": [ + "cn", + "issuer", + "dates" + ], + "properties": { + "cn": { + "type": "string", + "example": "example.com" + }, + "issuer": { + "type": "string", + "example": "C = US, O = Let's Encrypt, CN = E5" + }, + "dates": { + "type": "object", + "additionalProperties": false, + "required": [ + "from", + "to" + ], + "properties": { + "from": { + "type": "integer" + }, + "to": { + "type": "integer" + } + }, + "example": { + "from": 1728448218, + "to": 1736224217 + } + } + } + }, + "certificate_key": { + "type": "boolean", + "example": true + } + } + } + } + } + }, + "400": { + "description": "400 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "error": { + "code": 400, + "message": "Certificate is not valid" + } + } + } + }, + "schema": { + "type": "object", + "description": "Error", + "properties": { + "error": { + "type": "object", + "description": "Error object", + "additionalProperties": false, + "required": [ + "code", + "message" + ], + "properties": { + "code": { + "type": "integer", + "example": 400 + }, + "message": { + "type": "string", + "example": "Bad Request" + } + } + } + } + } + } + } + } + } + } + }, + "/nginx/certificates/test-http": { + "post": { + "operationId": "testHttpReach", + "summary": "Test HTTP Reachability", + "tags": [ + "certificates" + ], + "security": [ + { + "bearerAuth": [ + "certificates.view" + ] + } + ], + "description": "Tests HTTP reachability for domain validation prior to certificate issuance.", + "requestBody": { + "description": "Test Payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "required": [ + "domains" + ], + "properties": { + "domains": { + "description": "Domain Names separated by a comma", + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + } + } + } + } + } + }, + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "test.example.org": "ok", + "test.example.com": "other:Invalid domain or IP", + "nonexistent.example.com": "404" + } + } + } + } + } + } + } + } + }, + "/nginx/certificates/{certID}": { + "get": { + "operationId": "getCertificate", + "summary": "Get a Certificate", + "tags": [ + "certificates" + ], + "security": [ + { + "bearerAuth": [ + "certificates.view" + ] + } + ], + "description": "Returns one certificate record and metadata by id.", + "parameters": [ + { + "in": "path", + "name": "certID", + "description": "Certificate ID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 1 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "id": 4, + "created_on": "2024-10-09T05:31:58.000Z", + "modified_on": "2024-10-09T05:32:11.000Z", + "owner_user_id": 1, + "provider": "letsencrypt", + "nice_name": "test.example.com", + "domain_names": [ + "test.example.com" + ], + "expires_on": "2025-01-07T04:34:18.000Z", + "meta": { + "dns_challenge": false + } + } + } + }, + "schema": { + "type": "object", + "description": "Certificate object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "provider", + "nice_name", + "domain_names", + "expires_on", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "provider": { + "type": "string", + "pattern": "^(letsencrypt|other)$", + "example": "letsencrypt" + }, + "nice_name": { + "type": "string", + "description": "Nice Name for the custom certificate", + "example": "My Custom Cert" + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "expires_on": { + "description": "Date and time of expiration", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + }, + "meta": { + "type": "object", + "additionalProperties": false, + "properties": { + "certificate": { + "type": "string", + "minLength": 1 + }, + "certificate_key": { + "type": "string", + "minLength": 1 + }, + "dns_challenge": { + "type": "boolean" + }, + "dns_provider_credentials": { + "type": "string" + }, + "credential_ref": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "internal", + "external" + ] + }, + "id": { + "type": "integer", + "minimum": 1 + }, + "provider_id": { + "type": "integer", + "minimum": 1 + }, + "path": { + "type": "string" + }, + "field": { + "type": "string" + } + } + }, + "dns_provider": { + "type": "string" + }, + "letsencrypt_certificate": { + "type": "object" + }, + "propagation_seconds": { + "type": "integer", + "minimum": 0 + }, + "key_type": { + "type": "string", + "enum": [ + "rsa", + "ecdsa" + ], + "default": "rsa" + } + }, + "example": { + "dns_challenge": false + } + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "deleteCertificate", + "summary": "Delete a Certificate", + "tags": [ + "certificates" + ], + "security": [ + { + "bearerAuth": [ + "certificates.manage" + ] + } + ], + "description": "Deletes a certificate record. Does not remove files already deployed to disk until nginx is reloaded.", + "parameters": [ + { + "in": "path", + "name": "certID", + "description": "Certificate ID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 2 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": true + } + }, + "schema": { + "type": "boolean" + } + } + } + } + } + } + }, + "/nginx/certificates/{certID}/download": { + "get": { + "operationId": "downloadCertificate", + "summary": "Downloads a Certificate", + "tags": [ + "certificates" + ], + "security": [ + { + "bearerAuth": [ + "certificates.manage" + ] + } + ], + "description": "Downloads certificate and private key material for a certificate id (requires permission).", + "parameters": [ + { + "in": "path", + "name": "certID", + "description": "Certificate ID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 1 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/zip": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + } + } + } + }, + "/nginx/certificates/{certID}/renew": { + "post": { + "operationId": "renewCertificate", + "summary": "Renews a Certificate", + "tags": [ + "certificates" + ], + "security": [ + { + "bearerAuth": [ + "certificates.manage" + ] + } + ], + "description": "Triggers renewal for an existing managed certificate.", + "parameters": [ + { + "in": "path", + "name": "certID", + "description": "Certificate ID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 1 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "expires_on": "2025-01-07T06:41:58.000Z", + "modified_on": "2024-10-09T07:39:51.000Z", + "id": 4, + "created_on": "2024-10-09T05:31:58.000Z", + "owner_user_id": 1, + "provider": "letsencrypt", + "nice_name": "My Test Cert", + "domain_names": [ + "test.jc21.supernerd.pro" + ], + "meta": { + "dns_challenge": false + } + } + } + }, + "schema": { + "type": "object", + "description": "Certificate object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "provider", + "nice_name", + "domain_names", + "expires_on", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "provider": { + "type": "string", + "pattern": "^(letsencrypt|other)$", + "example": "letsencrypt" + }, + "nice_name": { + "type": "string", + "description": "Nice Name for the custom certificate", + "example": "My Custom Cert" + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "expires_on": { + "description": "Date and time of expiration", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + }, + "meta": { + "type": "object", + "additionalProperties": false, + "properties": { + "certificate": { + "type": "string", + "minLength": 1 + }, + "certificate_key": { + "type": "string", + "minLength": 1 + }, + "dns_challenge": { + "type": "boolean" + }, + "dns_provider_credentials": { + "type": "string" + }, + "credential_ref": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "internal", + "external" + ] + }, + "id": { + "type": "integer", + "minimum": 1 + }, + "provider_id": { + "type": "integer", + "minimum": 1 + }, + "path": { + "type": "string" + }, + "field": { + "type": "string" + } + } + }, + "dns_provider": { + "type": "string" + }, + "letsencrypt_certificate": { + "type": "object" + }, + "propagation_seconds": { + "type": "integer", + "minimum": 0 + }, + "key_type": { + "type": "string", + "enum": [ + "rsa", + "ecdsa" + ], + "default": "rsa" + } + }, + "example": { + "dns_challenge": false + } + } + } + } + } + } + } + } + } + }, + "/nginx/certificates/{certID}/upload": { + "post": { + "operationId": "uploadCertificate", + "summary": "Uploads a custom Certificate", + "tags": [ + "certificates" + ], + "security": [ + { + "bearerAuth": [ + "certificates.manage" + ] + } + ], + "description": "Uploads custom certificate and key files for use on proxy hosts.", + "parameters": [ + { + "in": "path", + "name": "certID", + "description": "Certificate ID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 1 + } + ], + "requestBody": { + "description": "Certificate Files", + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "additionalProperties": false, + "required": [ + "certificate", + "certificate_key" + ], + "properties": { + "certificate": { + "type": "string", + "example": "-----BEGIN CERTIFICATE-----\nMIID...-----END CERTIFICATE-----" + }, + "certificate_key": { + "type": "string", + "example": "-----BEGIN CERTIFICATE-----\nMIID...-----END CERTIFICATE-----" + }, + "intermediate_certificate": { + "type": "string", + "example": "-----BEGIN CERTIFICATE-----\nMIID...-----END CERTIFICATE-----" + } + } + }, + "example": { + "certificate": "-----BEGIN CERTIFICATE-----\nMIID...-----END CERTIFICATE-----", + "certificate_key": "-----BEGIN PRIVATE\nMIID...-----END CERTIFICATE-----" + } + } + } + }, + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "certificate": "-----BEGIN CERTIFICATE-----\nMIIEYDCCAsigAwIBAgIRAPoSC0hvitb26ODMlsH6YbowDQYJKoZIhvcNAQELBQAw\ngZExHjAcBgNVBAoTFW1rY2VydCBkZXZlbG9wbWVudCBDQTEzMDEGA1UECwwqamN1\ncm5vd0BKYW1pZXMtTGFwdG9wLmxvY2FsIChKYW1pZSBDdXJub3cpMTowOAYDVQQD\nDDFta2NlcnQgamN1cm5vd0BKYW1pZXMtTGFwdG9wLmxvY2FsIChKYW1pZSBDdXJu\nb3cpMB4XDTI0MTAwOTA3MjIxN1oXDTI3MDEwOTA3MjIxN1owXjEnMCUGA1UEChMe\nbWtjZXJ0IGRldmVsb3BtZW50IGNlcnRpZmljYXRlMTMwMQYDVQQLDCpqY3Vybm93\nQEphbWllcy1MYXB0b3AubG9jYWwgKEphbWllIEN1cm5vdykwggEiMA0GCSqGSIb3\nDQEBAQUAA4IBDwAwggEKAoIBAQC1n9j9C5Bes1ndqACDckERauxXVNKCnUlUM1bu\nGBx1xc+j2e2Ar23wUJJuWBY18VfT8yqfqVDktO2wrbmvZvLuPmXePOKbIKS+XXh+\n2NG9L5bDG9rwGFCRXnbQj+GWCdMfzx14+CR1IHgeYz6Cv/Si2/LJPCh/CoBfM4hU\nQJON3lxAWrWBpdbZnKYMrxuPBRfW9OuzTbCVXToQoxRAHiOR9081Xn1WeoKr7kVB\nIa5UphlvWXa12w1YmUwJu7YndnJGIavLWeNCVc7ZEo+nS8Wr/4QWicatIWZXpVaE\nOPhRoeplQDxNWg5b/Q26rYoVd7PrCmRs7sVcH79XzGONeH1PAgMBAAGjZTBjMA4G\nA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAfBgNVHSMEGDAWgBSB\n/vfmBUd4W7CvyEMl7YpMVQs8vTAbBgNVHREEFDASghB0ZXN0LmV4YW1wbGUuY29t\nMA0GCSqGSIb3DQEBCwUAA4IBgQASwON/jPAHzcARSenY0ZGY1m5OVTYoQ/JWH0oy\nl8SyFCQFEXt7UHDD/eTtLT0vMyc190nP57P8lTnZGf7hSinZz1B1d6V4cmzxpk0s\nVXZT+irL6bJVJoMBHRpllKAhGULIo33baTrWFKA0oBuWx4AevSWKcLW5j87kEawn\nATCuMQ1I3ifR1mSlB7X8fb+vF+571q0NGuB3a42j6rdtXJ6SmH4+9B4qO0sfHDNt\nIImpLCH/tycDpcYrGSCn1QrekFG1bSEh+Bb9i8rqMDSDsYrTFPZTuOQ3EtjGni9u\nm+rEP3OyJg+md8c+0LVP7/UU4QWWnw3/Wolo5kSCxE8vNTFqi4GhVbdLnUtcIdTV\nXxuR6cKyW87Snj1a0nG76ZLclt/akxDhtzqeV60BO0p8pmiev8frp+E94wFNYCmp\n1cr3CnMEGRaficLSDFC6EBENzlZW2BQT6OMIV+g0NBgSyQe39s2zcdEl5+SzDVuw\nhp8bJUp/QN7pnOVCDbjTQ+HVMXw=\n-----END CERTIFICATE-----\n", + "certificate_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC1n9j9C5Bes1nd\nqACDckERauxXVNKCnUlUM1buGBx1xc+j2e2Ar23wUJJuWBY18VfT8yqfqVDktO2w\nrbmvZvLuPmXePOKbIKS+XXh+2NG9L5bDG9rwGFCRXnbQj+GWCdMfzx14+CR1IHge\nYz6Cv/Si2/LJPCh/CoBfM4hUQJON3lxAWrWBpdbZnKYMrxuPBRfW9OuzTbCVXToQ\noxRAHiOR9081Xn1WeoKr7kVBIa5UphlvWXa12w1YmUwJu7YndnJGIavLWeNCVc7Z\nEo+nS8Wr/4QWicatIWZXpVaEOPhRoeplQDxNWg5b/Q26rYoVd7PrCmRs7sVcH79X\nzGONeH1PAgMBAAECggEAANb3Wtwl07pCjRrMvc7WbC0xYIn82yu8/g2qtjkYUJcU\nia5lQbYN7RGCS85Oc/tkq48xQEG5JQWNH8b918jDEMTrFab0aUEyYcru1q9L8PL6\nYHaNgZSrMrDcHcS8h0QOXNRJT5jeGkiHJaTR0irvB526tqF3knbK9yW22KTfycUe\na0Z9voKn5xRk1DCbHi/nk2EpT7xnjeQeLFaTIRXbS68omkr4YGhwWm5OizoyEGZu\nW0Zum5BkQyMr6kor3wdxOTG97ske2rcyvvHi+ErnwL0xBv0qY0Dhe8DpuXpDezqw\no72yY8h31Fu84i7sAj24YuE5Df8DozItFXQpkgbQ6QKBgQDPrufhvIFm2S/MzBdW\nH8JxY7CJlJPyxOvc1NIl9RczQGAQR90kx52cgIcuIGEG6/wJ/xnGfMmW40F0DnQ+\nN+oLgB9SFxeLkRb7s9Z/8N3uIN8JJFYcerEOiRQeN2BXEEWJ7bUThNtsVrAcKoUh\nELsDmnHW/3V+GKwhd0vpk842+wKBgQDf4PGLG9PTE5tlAoyHFodJRd2RhTJQkwsU\nMDNjLJ+KecLv+Nl+QiJhoflG1ccqtSFlBSCG067CDQ5LV0xm3mLJ7pfJoMgjcq31\nqjEmX4Ls91GuVOPtbwst3yFKjsHaSoKB5fBvWRcKFpBUezM7Qcw2JP3+dQT+bQIq\ncMTkRWDSvQKBgQDOdCQFDjxg/lR7NQOZ1PaZe61aBz5P3pxNqa7ClvMaOsuEQ7w9\nvMYcdtRq8TsjA2JImbSI0TIg8gb2FQxPcYwTJKl+FICOeIwtaSg5hTtJZpnxX5LO\nutTaC0DZjNkTk5RdOdWA8tihyUdGqKoxJY2TVmwGe2rUEDjFB++J4inkEwKBgB6V\ng0nmtkxanFrzOzFlMXwgEEHF+Xaqb9QFNa/xs6XeNnREAapO7JV75Cr6H2hFMFe1\nmJjyqCgYUoCWX3iaHtLJRnEkBtNY4kzyQB6m46LtsnnnXO/dwKA2oDyoPfFNRoDq\nYatEd3JIXNU9s2T/+x7WdOBjKhh72dTkbPFmTPDdAoGAU6rlPBevqOFdObYxdPq8\nEQWu44xqky3Mf5sBpOwtu6rqCYuziLiN7K4sjN5GD5mb1cEU+oS92ZiNcUQ7MFXk\n8yTYZ7U0VcXyAcpYreWwE8thmb0BohJBr+Mp3wLTx32x0HKdO6vpUa0d35LUTUmM\nRrKmPK/msHKK/sVHiL+NFqo=\n-----END PRIVATE KEY-----\n" + } + } + }, + "schema": { + "type": "object", + "additionalProperties": false, + "required": [ + "certificate", + "certificate_key" + ], + "properties": { + "certificate": { + "type": "string", + "minLength": 1, + "example": "-----BEGIN CERTIFICATE-----\nMIID...-----END CERTIFICATE-----" + }, + "certificate_key": { + "type": "string", + "minLength": 1, + "example": "-----BEGIN CERTIFICATE-----\nMIID...-----END CERTIFICATE-----" + }, + "intermediate_certificate": { + "type": "string", + "minLength": 1, + "example": "-----BEGIN CERTIFICATE-----\nMIID...-----END CERTIFICATE-----" + } + } + } + } + } + } + } + } + }, + "/nginx/proxy-hosts": { + "get": { + "operationId": "getProxyHosts", + "summary": "Get all proxy hosts", + "tags": [ + "proxy-hosts" + ], + "security": [ + { + "bearerAuth": [ + "proxy_hosts.view" + ] + } + ], + "description": "Lists reverse proxy hosts (domain to upstream mapping).", + "parameters": [ + { + "in": "query", + "name": "expand", + "description": "Expansions", + "schema": { + "type": "string", + "enum": [ + "access_list", + "owner", + "certificate" + ] + } + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": [ + { + "id": 1, + "created_on": "2025-10-28T01:10:26.000Z", + "modified_on": "2025-10-28T04:07:16.000Z", + "owner_user_id": 1, + "domain_names": [ + "test.jc21com" + ], + "forward_host": "127.0.0.1", + "forward_port": 8081, + "access_list_id": 1, + "certificate_id": 1, + "ssl_forced": false, + "caching_enabled": false, + "block_exploits": false, + "advanced_config": "", + "meta": { + "nginx_online": true, + "nginx_err": null + }, + "allow_websocket_upgrade": false, + "http2_support": false, + "forward_scheme": "http", + "enabled": true, + "locations": [], + "hsts_enabled": false, + "hsts_subdomains": false, + "trust_forwarded_proto": false + } + ] + } + }, + "schema": { + "type": "array", + "description": "Proxy Hosts list", + "items": { + "type": "object", + "description": "Proxy Host object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "domain_names", + "forward_host", + "forward_port", + "access_list_id", + "certificate_id", + "ssl_forced", + "caching_enabled", + "block_exploits", + "advanced_config", + "meta", + "allow_websocket_upgrade", + "http2_support", + "forward_scheme", + "enabled", + "locations", + "hsts_enabled", + "hsts_subdomains", + "trust_forwarded_proto" + ], + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "forward_host": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "127.0.0.1" + }, + "forward_port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "example": 8080 + }, + "access_list_id": { + "description": "Access List ID", + "type": "integer", + "minimum": 0, + "example": 3 + }, + "certificate_id": { + "description": "Certificate ID", + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "example": 5 + }, + { + "type": "string", + "pattern": "^new$", + "example": "new" + } + ], + "example": 5 + }, + "ssl_forced": { + "description": "Is SSL Forced", + "type": "boolean", + "example": true + }, + "caching_enabled": { + "description": "Should we cache assets", + "type": "boolean", + "example": true + }, + "block_exploits": { + "description": "Should we block common exploits", + "type": "boolean", + "example": false + }, + "advanced_config": { + "type": "string", + "example": "" + }, + "meta": { + "type": "object", + "example": { + "nginx_online": true, + "nginx_err": null + } + }, + "allow_websocket_upgrade": { + "description": "Allow Websocket Upgrade for all paths", + "type": "boolean", + "example": true + }, + "http2_support": { + "description": "HTTP2 Protocol Support", + "type": "boolean", + "example": true + }, + "forward_scheme": { + "type": "string", + "enum": [ + "http", + "https" + ], + "example": "http" + }, + "enabled": { + "description": "Is Enabled", + "type": "boolean", + "example": false + }, + "locations": { + "type": "array", + "minItems": 0, + "items": { + "type": "object", + "required": [ + "forward_scheme", + "forward_host", + "forward_port", + "path" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": [ + "integer", + "null" + ] + }, + "path": { + "type": "string", + "minLength": 1 + }, + "forward_scheme": { + "type": "string", + "enum": [ + "http", + "https" + ], + "example": "http" + }, + "forward_host": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "127.0.0.1" + }, + "forward_port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "example": 8080 + }, + "forward_path": { + "type": "string" + }, + "advanced_config": { + "type": "string" + } + } + }, + "example": [ + { + "path": "/app", + "forward_scheme": "http", + "forward_host": "example.com", + "forward_port": 80 + } + ] + }, + "hsts_enabled": { + "description": "Is HSTS Enabled", + "type": "boolean", + "example": true + }, + "hsts_subdomains": { + "description": "Is HSTS applicable to all subdomains", + "type": "boolean", + "example": true + }, + "trust_forwarded_proto": { + "type": "boolean", + "description": "Trust the forwarded headers", + "example": false + }, + "certificate": { + "oneOf": [ + { + "type": "null", + "example": null + }, + { + "type": "object", + "description": "Certificate object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "provider", + "nice_name", + "domain_names", + "expires_on", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "provider": { + "type": "string", + "pattern": "^(letsencrypt|other)$", + "example": "letsencrypt" + }, + "nice_name": { + "type": "string", + "description": "Nice Name for the custom certificate", + "example": "My Custom Cert" + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "expires_on": { + "description": "Date and time of expiration", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + }, + "meta": { + "type": "object", + "additionalProperties": false, + "properties": { + "certificate": { + "type": "string", + "minLength": 1 + }, + "certificate_key": { + "type": "string", + "minLength": 1 + }, + "dns_challenge": { + "type": "boolean" + }, + "dns_provider_credentials": { + "type": "string" + }, + "credential_ref": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "internal", + "external" + ] + }, + "id": { + "type": "integer", + "minimum": 1 + }, + "provider_id": { + "type": "integer", + "minimum": 1 + }, + "path": { + "type": "string" + }, + "field": { + "type": "string" + } + } + }, + "dns_provider": { + "type": "string" + }, + "letsencrypt_certificate": { + "type": "object" + }, + "propagation_seconds": { + "type": "integer", + "minimum": 0 + }, + "key_type": { + "type": "string", + "enum": [ + "rsa", + "ecdsa" + ], + "default": "rsa" + } + }, + "example": { + "dns_challenge": false + } + } + } + } + ], + "example": null + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + }, + "access_list": { + "oneOf": [ + { + "type": "null", + "example": null + }, + { + "type": "object", + "description": "Access List object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "name", + "meta", + "satisfy_any", + "pass_auth", + "proxy_host_count" + ], + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "name": { + "type": "string", + "minLength": 1, + "example": "My Access List" + }, + "meta": { + "type": "object", + "example": {} + }, + "satisfy_any": { + "type": "boolean", + "example": true + }, + "pass_auth": { + "type": "boolean", + "example": false + }, + "proxy_host_count": { + "type": "integer", + "minimum": 0, + "example": 3 + } + } + } + ], + "example": null + } + } + } + } + } + } + } + } + }, + "post": { + "operationId": "createProxyHost", + "summary": "Create a Proxy Host", + "tags": [ + "proxy-hosts" + ], + "security": [ + { + "bearerAuth": [ + "proxy_hosts.manage" + ] + } + ], + "description": "Creates a proxy host with domain names, upstream target, and optional TLS and access settings.", + "requestBody": { + "description": "Proxy Host Payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "required": [ + "domain_names", + "forward_scheme", + "forward_host", + "forward_port" + ], + "properties": { + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "forward_scheme": { + "type": "string", + "enum": [ + "http", + "https" + ], + "example": "http" + }, + "forward_host": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "127.0.0.1" + }, + "forward_port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "example": 8080 + }, + "certificate_id": { + "description": "Certificate ID", + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "example": 5 + }, + { + "type": "string", + "pattern": "^new$", + "example": "new" + } + ], + "example": 5 + }, + "ssl_forced": { + "description": "Is SSL Forced", + "type": "boolean", + "example": true + }, + "hsts_enabled": { + "description": "Is HSTS Enabled", + "type": "boolean", + "example": true + }, + "hsts_subdomains": { + "description": "Is HSTS applicable to all subdomains", + "type": "boolean", + "example": true + }, + "trust_forwarded_proto": { + "type": "boolean", + "description": "Trust the forwarded headers", + "example": false + }, + "http2_support": { + "description": "HTTP2 Protocol Support", + "type": "boolean", + "example": true + }, + "block_exploits": { + "description": "Should we block common exploits", + "type": "boolean", + "example": false + }, + "caching_enabled": { + "description": "Should we cache assets", + "type": "boolean", + "example": true + }, + "allow_websocket_upgrade": { + "description": "Allow Websocket Upgrade for all paths", + "type": "boolean", + "example": true + }, + "access_list_id": { + "description": "Access List ID", + "type": "integer", + "minimum": 0, + "example": 3 + }, + "advanced_config": { + "type": "string", + "example": "" + }, + "enabled": { + "description": "Is Enabled", + "type": "boolean", + "example": false + }, + "meta": { + "type": "object", + "example": { + "nginx_online": true, + "nginx_err": null + } + }, + "locations": { + "type": "array", + "minItems": 0, + "items": { + "type": "object", + "required": [ + "forward_scheme", + "forward_host", + "forward_port", + "path" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": [ + "integer", + "null" + ] + }, + "path": { + "type": "string", + "minLength": 1 + }, + "forward_scheme": { + "type": "string", + "enum": [ + "http", + "https" + ], + "example": "http" + }, + "forward_host": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "127.0.0.1" + }, + "forward_port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "example": 8080 + }, + "forward_path": { + "type": "string" + }, + "advanced_config": { + "type": "string" + } + } + }, + "example": [ + { + "path": "/app", + "forward_scheme": "http", + "forward_host": "example.com", + "forward_port": 80 + } + ] + } + } + }, + "example": { + "domain_names": [ + "test.example.com" + ], + "forward_scheme": "http", + "forward_host": "127.0.0.1", + "forward_port": 8080 + } + } + } + }, + "responses": { + "201": { + "description": "201 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "id": 3, + "created_on": "2025-10-30T01:12:05.000Z", + "modified_on": "2025-10-30T01:12:05.000Z", + "owner_user_id": 1, + "domain_names": [ + "test.example.com" + ], + "forward_host": "127.0.0.1", + "forward_port": 8080, + "access_list_id": 0, + "certificate_id": 0, + "ssl_forced": false, + "caching_enabled": false, + "block_exploits": false, + "advanced_config": "", + "meta": {}, + "allow_websocket_upgrade": false, + "http2_support": false, + "forward_scheme": "http", + "enabled": true, + "locations": [], + "hsts_enabled": false, + "hsts_subdomains": false, + "trust_forwarded_proto": false, + "certificate": null, + "owner": { + "id": 1, + "created_on": "2025-10-28T00:50:24.000Z", + "modified_on": "2025-10-28T00:50:24.000Z", + "is_disabled": false, + "email": "jc@jc21.com", + "name": "jamiec", + "nickname": "jamiec", + "avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm", + "roles": [ + "admin" + ] + }, + "access_list": null + } + } + }, + "schema": { + "type": "object", + "description": "Proxy Host object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "domain_names", + "forward_host", + "forward_port", + "access_list_id", + "certificate_id", + "ssl_forced", + "caching_enabled", + "block_exploits", + "advanced_config", + "meta", + "allow_websocket_upgrade", + "http2_support", + "forward_scheme", + "enabled", + "locations", + "hsts_enabled", + "hsts_subdomains", + "trust_forwarded_proto" + ], + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "forward_host": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "127.0.0.1" + }, + "forward_port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "example": 8080 + }, + "access_list_id": { + "description": "Access List ID", + "type": "integer", + "minimum": 0, + "example": 3 + }, + "certificate_id": { + "description": "Certificate ID", + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "example": 5 + }, + { + "type": "string", + "pattern": "^new$", + "example": "new" + } + ], + "example": 5 + }, + "ssl_forced": { + "description": "Is SSL Forced", + "type": "boolean", + "example": true + }, + "caching_enabled": { + "description": "Should we cache assets", + "type": "boolean", + "example": true + }, + "block_exploits": { + "description": "Should we block common exploits", + "type": "boolean", + "example": false + }, + "advanced_config": { + "type": "string", + "example": "" + }, + "meta": { + "type": "object", + "example": { + "nginx_online": true, + "nginx_err": null + } + }, + "allow_websocket_upgrade": { + "description": "Allow Websocket Upgrade for all paths", + "type": "boolean", + "example": true + }, + "http2_support": { + "description": "HTTP2 Protocol Support", + "type": "boolean", + "example": true + }, + "forward_scheme": { + "type": "string", + "enum": [ + "http", + "https" + ], + "example": "http" + }, + "enabled": { + "description": "Is Enabled", + "type": "boolean", + "example": false + }, + "locations": { + "type": "array", + "minItems": 0, + "items": { + "type": "object", + "required": [ + "forward_scheme", + "forward_host", + "forward_port", + "path" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": [ + "integer", + "null" + ] + }, + "path": { + "type": "string", + "minLength": 1 + }, + "forward_scheme": { + "type": "string", + "enum": [ + "http", + "https" + ], + "example": "http" + }, + "forward_host": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "127.0.0.1" + }, + "forward_port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "example": 8080 + }, + "forward_path": { + "type": "string" + }, + "advanced_config": { + "type": "string" + } + } + }, + "example": [ + { + "path": "/app", + "forward_scheme": "http", + "forward_host": "example.com", + "forward_port": 80 + } + ] + }, + "hsts_enabled": { + "description": "Is HSTS Enabled", + "type": "boolean", + "example": true + }, + "hsts_subdomains": { + "description": "Is HSTS applicable to all subdomains", + "type": "boolean", + "example": true + }, + "trust_forwarded_proto": { + "type": "boolean", + "description": "Trust the forwarded headers", + "example": false + }, + "certificate": { + "oneOf": [ + { + "type": "null", + "example": null + }, + { + "type": "object", + "description": "Certificate object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "provider", + "nice_name", + "domain_names", + "expires_on", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "provider": { + "type": "string", + "pattern": "^(letsencrypt|other)$", + "example": "letsencrypt" + }, + "nice_name": { + "type": "string", + "description": "Nice Name for the custom certificate", + "example": "My Custom Cert" + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "expires_on": { + "description": "Date and time of expiration", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + }, + "meta": { + "type": "object", + "additionalProperties": false, + "properties": { + "certificate": { + "type": "string", + "minLength": 1 + }, + "certificate_key": { + "type": "string", + "minLength": 1 + }, + "dns_challenge": { + "type": "boolean" + }, + "dns_provider_credentials": { + "type": "string" + }, + "credential_ref": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "internal", + "external" + ] + }, + "id": { + "type": "integer", + "minimum": 1 + }, + "provider_id": { + "type": "integer", + "minimum": 1 + }, + "path": { + "type": "string" + }, + "field": { + "type": "string" + } + } + }, + "dns_provider": { + "type": "string" + }, + "letsencrypt_certificate": { + "type": "object" + }, + "propagation_seconds": { + "type": "integer", + "minimum": 0 + }, + "key_type": { + "type": "string", + "enum": [ + "rsa", + "ecdsa" + ], + "default": "rsa" + } + }, + "example": { + "dns_challenge": false + } + } + } + } + ], + "example": null + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + }, + "access_list": { + "oneOf": [ + { + "type": "null", + "example": null + }, + { + "type": "object", + "description": "Access List object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "name", + "meta", + "satisfy_any", + "pass_auth", + "proxy_host_count" + ], + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "name": { + "type": "string", + "minLength": 1, + "example": "My Access List" + }, + "meta": { + "type": "object", + "example": {} + }, + "satisfy_any": { + "type": "boolean", + "example": true + }, + "pass_auth": { + "type": "boolean", + "example": false + }, + "proxy_host_count": { + "type": "integer", + "minimum": 0, + "example": 3 + } + } + } + ], + "example": null + } + } + } + } + } + } + } + } + }, + "/nginx/proxy-hosts/{hostID}": { + "get": { + "operationId": "getProxyHost", + "summary": "Get a Proxy Host", + "tags": [ + "proxy-hosts" + ], + "security": [ + { + "bearerAuth": [ + "proxy_hosts.view" + ] + } + ], + "description": "Returns one proxy host by id.", + "parameters": [ + { + "in": "path", + "name": "hostID", + "description": "The ID of the Proxy Host", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 1 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "id": 3, + "created_on": "2025-10-30T01:12:05.000Z", + "modified_on": "2025-10-30T01:12:05.000Z", + "owner_user_id": 1, + "domain_names": [ + "test.example.com" + ], + "forward_host": "127.0.0.1", + "forward_port": 8080, + "access_list_id": 0, + "certificate_id": 0, + "ssl_forced": false, + "caching_enabled": false, + "block_exploits": false, + "advanced_config": "", + "meta": { + "nginx_online": true, + "nginx_err": null + }, + "allow_websocket_upgrade": false, + "http2_support": false, + "forward_scheme": "http", + "enabled": true, + "locations": [], + "hsts_enabled": false, + "hsts_subdomains": false, + "trust_forwarded_proto": false, + "owner": { + "id": 1, + "created_on": "2025-10-28T00:50:24.000Z", + "modified_on": "2025-10-28T00:50:24.000Z", + "is_disabled": false, + "email": "jc@jc21.com", + "name": "jamiec", + "nickname": "jamiec", + "avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm", + "roles": [ + "admin" + ] + } + } + } + }, + "schema": { + "type": "object", + "description": "Proxy Host object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "domain_names", + "forward_host", + "forward_port", + "access_list_id", + "certificate_id", + "ssl_forced", + "caching_enabled", + "block_exploits", + "advanced_config", + "meta", + "allow_websocket_upgrade", + "http2_support", + "forward_scheme", + "enabled", + "locations", + "hsts_enabled", + "hsts_subdomains", + "trust_forwarded_proto" + ], + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "forward_host": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "127.0.0.1" + }, + "forward_port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "example": 8080 + }, + "access_list_id": { + "description": "Access List ID", + "type": "integer", + "minimum": 0, + "example": 3 + }, + "certificate_id": { + "description": "Certificate ID", + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "example": 5 + }, + { + "type": "string", + "pattern": "^new$", + "example": "new" + } + ], + "example": 5 + }, + "ssl_forced": { + "description": "Is SSL Forced", + "type": "boolean", + "example": true + }, + "caching_enabled": { + "description": "Should we cache assets", + "type": "boolean", + "example": true + }, + "block_exploits": { + "description": "Should we block common exploits", + "type": "boolean", + "example": false + }, + "advanced_config": { + "type": "string", + "example": "" + }, + "meta": { + "type": "object", + "example": { + "nginx_online": true, + "nginx_err": null + } + }, + "allow_websocket_upgrade": { + "description": "Allow Websocket Upgrade for all paths", + "type": "boolean", + "example": true + }, + "http2_support": { + "description": "HTTP2 Protocol Support", + "type": "boolean", + "example": true + }, + "forward_scheme": { + "type": "string", + "enum": [ + "http", + "https" + ], + "example": "http" + }, + "enabled": { + "description": "Is Enabled", + "type": "boolean", + "example": false + }, + "locations": { + "type": "array", + "minItems": 0, + "items": { + "type": "object", + "required": [ + "forward_scheme", + "forward_host", + "forward_port", + "path" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": [ + "integer", + "null" + ] + }, + "path": { + "type": "string", + "minLength": 1 + }, + "forward_scheme": { + "type": "string", + "enum": [ + "http", + "https" + ], + "example": "http" + }, + "forward_host": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "127.0.0.1" + }, + "forward_port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "example": 8080 + }, + "forward_path": { + "type": "string" + }, + "advanced_config": { + "type": "string" + } + } + }, + "example": [ + { + "path": "/app", + "forward_scheme": "http", + "forward_host": "example.com", + "forward_port": 80 + } + ] + }, + "hsts_enabled": { + "description": "Is HSTS Enabled", + "type": "boolean", + "example": true + }, + "hsts_subdomains": { + "description": "Is HSTS applicable to all subdomains", + "type": "boolean", + "example": true + }, + "trust_forwarded_proto": { + "type": "boolean", + "description": "Trust the forwarded headers", + "example": false + }, + "certificate": { + "oneOf": [ + { + "type": "null", + "example": null + }, + { + "type": "object", + "description": "Certificate object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "provider", + "nice_name", + "domain_names", + "expires_on", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "provider": { + "type": "string", + "pattern": "^(letsencrypt|other)$", + "example": "letsencrypt" + }, + "nice_name": { + "type": "string", + "description": "Nice Name for the custom certificate", + "example": "My Custom Cert" + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "expires_on": { + "description": "Date and time of expiration", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + }, + "meta": { + "type": "object", + "additionalProperties": false, + "properties": { + "certificate": { + "type": "string", + "minLength": 1 + }, + "certificate_key": { + "type": "string", + "minLength": 1 + }, + "dns_challenge": { + "type": "boolean" + }, + "dns_provider_credentials": { + "type": "string" + }, + "credential_ref": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "internal", + "external" + ] + }, + "id": { + "type": "integer", + "minimum": 1 + }, + "provider_id": { + "type": "integer", + "minimum": 1 + }, + "path": { + "type": "string" + }, + "field": { + "type": "string" + } + } + }, + "dns_provider": { + "type": "string" + }, + "letsencrypt_certificate": { + "type": "object" + }, + "propagation_seconds": { + "type": "integer", + "minimum": 0 + }, + "key_type": { + "type": "string", + "enum": [ + "rsa", + "ecdsa" + ], + "default": "rsa" + } + }, + "example": { + "dns_challenge": false + } + } + } + } + ], + "example": null + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + }, + "access_list": { + "oneOf": [ + { + "type": "null", + "example": null + }, + { + "type": "object", + "description": "Access List object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "name", + "meta", + "satisfy_any", + "pass_auth", + "proxy_host_count" + ], + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "name": { + "type": "string", + "minLength": 1, + "example": "My Access List" + }, + "meta": { + "type": "object", + "example": {} + }, + "satisfy_any": { + "type": "boolean", + "example": true + }, + "pass_auth": { + "type": "boolean", + "example": false + }, + "proxy_host_count": { + "type": "integer", + "minimum": 0, + "example": 3 + } + } + } + ], + "example": null + } + } + } + } + } + } + } + }, + "put": { + "operationId": "updateProxyHost", + "summary": "Update a Proxy Host", + "tags": [ + "proxy-hosts" + ], + "security": [ + { + "bearerAuth": [ + "proxy_hosts.manage" + ] + } + ], + "description": "Updates proxy host domains, upstream, advanced options, or certificate linkage.", + "parameters": [ + { + "in": "path", + "name": "hostID", + "description": "The ID of the Proxy Host", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 2 + } + ], + "requestBody": { + "description": "Proxy Host Payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "minProperties": 1, + "properties": { + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "forward_scheme": { + "type": "string", + "enum": [ + "http", + "https" + ], + "example": "http" + }, + "forward_host": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "127.0.0.1" + }, + "forward_port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "example": 8080 + }, + "certificate_id": { + "description": "Certificate ID", + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "example": 5 + }, + { + "type": "string", + "pattern": "^new$", + "example": "new" + } + ], + "example": 5 + }, + "ssl_forced": { + "description": "Is SSL Forced", + "type": "boolean", + "example": true + }, + "hsts_enabled": { + "description": "Is HSTS Enabled", + "type": "boolean", + "example": true + }, + "hsts_subdomains": { + "description": "Is HSTS applicable to all subdomains", + "type": "boolean", + "example": true + }, + "trust_forwarded_proto": { + "type": "boolean", + "description": "Trust the forwarded headers", + "example": false + }, + "http2_support": { + "description": "HTTP2 Protocol Support", + "type": "boolean", + "example": true + }, + "block_exploits": { + "description": "Should we block common exploits", + "type": "boolean", + "example": false + }, + "caching_enabled": { + "description": "Should we cache assets", + "type": "boolean", + "example": true + }, + "allow_websocket_upgrade": { + "description": "Allow Websocket Upgrade for all paths", + "type": "boolean", + "example": true + }, + "access_list_id": { + "description": "Access List ID", + "type": "integer", + "minimum": 0, + "example": 3 + }, + "advanced_config": { + "type": "string", + "example": "" + }, + "enabled": { + "description": "Is Enabled", + "type": "boolean", + "example": false + }, + "meta": { + "type": "object", + "example": { + "nginx_online": true, + "nginx_err": null + } + }, + "locations": { + "type": "array", + "minItems": 0, + "items": { + "type": "object", + "required": [ + "forward_scheme", + "forward_host", + "forward_port", + "path" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": [ + "integer", + "null" + ] + }, + "path": { + "type": "string", + "minLength": 1 + }, + "forward_scheme": { + "type": "string", + "enum": [ + "http", + "https" + ], + "example": "http" + }, + "forward_host": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "127.0.0.1" + }, + "forward_port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "example": 8080 + }, + "forward_path": { + "type": "string" + }, + "advanced_config": { + "type": "string" + } + } + }, + "example": [ + { + "path": "/app", + "forward_scheme": "http", + "forward_host": "example.com", + "forward_port": 80 + } + ] + } + } + } + } + } + }, + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "id": 3, + "created_on": "2025-10-30T01:12:05.000Z", + "modified_on": "2025-10-30T01:17:06.000Z", + "owner_user_id": 1, + "domain_names": [ + "test.example.com" + ], + "forward_host": "127.0.0.1", + "forward_port": 8080, + "access_list_id": 0, + "certificate_id": 0, + "ssl_forced": false, + "caching_enabled": false, + "block_exploits": false, + "advanced_config": "", + "meta": { + "nginx_online": true, + "nginx_err": null + }, + "allow_websocket_upgrade": false, + "http2_support": false, + "forward_scheme": "http", + "enabled": true, + "locations": [], + "hsts_enabled": false, + "hsts_subdomains": false, + "trust_forwarded_proto": false, + "owner": { + "id": 1, + "created_on": "2025-10-28T00:50:24.000Z", + "modified_on": "2025-10-28T00:50:24.000Z", + "is_disabled": false, + "email": "jc@jc21.com", + "name": "jamiec", + "nickname": "jamiec", + "avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm", + "roles": [ + "admin" + ] + }, + "certificate": null, + "access_list": null + } + } + }, + "schema": { + "type": "object", + "description": "Proxy Host object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "domain_names", + "forward_host", + "forward_port", + "access_list_id", + "certificate_id", + "ssl_forced", + "caching_enabled", + "block_exploits", + "advanced_config", + "meta", + "allow_websocket_upgrade", + "http2_support", + "forward_scheme", + "enabled", + "locations", + "hsts_enabled", + "hsts_subdomains", + "trust_forwarded_proto" + ], + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "forward_host": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "127.0.0.1" + }, + "forward_port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "example": 8080 + }, + "access_list_id": { + "description": "Access List ID", + "type": "integer", + "minimum": 0, + "example": 3 + }, + "certificate_id": { + "description": "Certificate ID", + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "example": 5 + }, + { + "type": "string", + "pattern": "^new$", + "example": "new" + } + ], + "example": 5 + }, + "ssl_forced": { + "description": "Is SSL Forced", + "type": "boolean", + "example": true + }, + "caching_enabled": { + "description": "Should we cache assets", + "type": "boolean", + "example": true + }, + "block_exploits": { + "description": "Should we block common exploits", + "type": "boolean", + "example": false + }, + "advanced_config": { + "type": "string", + "example": "" + }, + "meta": { + "type": "object", + "example": { + "nginx_online": true, + "nginx_err": null + } + }, + "allow_websocket_upgrade": { + "description": "Allow Websocket Upgrade for all paths", + "type": "boolean", + "example": true + }, + "http2_support": { + "description": "HTTP2 Protocol Support", + "type": "boolean", + "example": true + }, + "forward_scheme": { + "type": "string", + "enum": [ + "http", + "https" + ], + "example": "http" + }, + "enabled": { + "description": "Is Enabled", + "type": "boolean", + "example": false + }, + "locations": { + "type": "array", + "minItems": 0, + "items": { + "type": "object", + "required": [ + "forward_scheme", + "forward_host", + "forward_port", + "path" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": [ + "integer", + "null" + ] + }, + "path": { + "type": "string", + "minLength": 1 + }, + "forward_scheme": { + "type": "string", + "enum": [ + "http", + "https" + ], + "example": "http" + }, + "forward_host": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "127.0.0.1" + }, + "forward_port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "example": 8080 + }, + "forward_path": { + "type": "string" + }, + "advanced_config": { + "type": "string" + } + } + }, + "example": [ + { + "path": "/app", + "forward_scheme": "http", + "forward_host": "example.com", + "forward_port": 80 + } + ] + }, + "hsts_enabled": { + "description": "Is HSTS Enabled", + "type": "boolean", + "example": true + }, + "hsts_subdomains": { + "description": "Is HSTS applicable to all subdomains", + "type": "boolean", + "example": true + }, + "trust_forwarded_proto": { + "type": "boolean", + "description": "Trust the forwarded headers", + "example": false + }, + "certificate": { + "oneOf": [ + { + "type": "null", + "example": null + }, + { + "type": "object", + "description": "Certificate object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "provider", + "nice_name", + "domain_names", + "expires_on", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "provider": { + "type": "string", + "pattern": "^(letsencrypt|other)$", + "example": "letsencrypt" + }, + "nice_name": { + "type": "string", + "description": "Nice Name for the custom certificate", + "example": "My Custom Cert" + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "expires_on": { + "description": "Date and time of expiration", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + }, + "meta": { + "type": "object", + "additionalProperties": false, + "properties": { + "certificate": { + "type": "string", + "minLength": 1 + }, + "certificate_key": { + "type": "string", + "minLength": 1 + }, + "dns_challenge": { + "type": "boolean" + }, + "dns_provider_credentials": { + "type": "string" + }, + "credential_ref": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "internal", + "external" + ] + }, + "id": { + "type": "integer", + "minimum": 1 + }, + "provider_id": { + "type": "integer", + "minimum": 1 + }, + "path": { + "type": "string" + }, + "field": { + "type": "string" + } + } + }, + "dns_provider": { + "type": "string" + }, + "letsencrypt_certificate": { + "type": "object" + }, + "propagation_seconds": { + "type": "integer", + "minimum": 0 + }, + "key_type": { + "type": "string", + "enum": [ + "rsa", + "ecdsa" + ], + "default": "rsa" + } + }, + "example": { + "dns_challenge": false + } + } + } + } + ], + "example": null + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + }, + "access_list": { + "oneOf": [ + { + "type": "null", + "example": null + }, + { + "type": "object", + "description": "Access List object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "name", + "meta", + "satisfy_any", + "pass_auth", + "proxy_host_count" + ], + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "name": { + "type": "string", + "minLength": 1, + "example": "My Access List" + }, + "meta": { + "type": "object", + "example": {} + }, + "satisfy_any": { + "type": "boolean", + "example": true + }, + "pass_auth": { + "type": "boolean", + "example": false + }, + "proxy_host_count": { + "type": "integer", + "minimum": 0, + "example": 3 + } + } + } + ], + "example": null + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "deleteProxyHost", + "summary": "Delete a Proxy Host", + "tags": [ + "proxy-hosts" + ], + "security": [ + { + "bearerAuth": [ + "proxy_hosts.manage" + ] + } + ], + "description": "Deletes a proxy host by id.", + "parameters": [ + { + "in": "path", + "name": "hostID", + "description": "The ID of the Proxy Host", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 2 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": true + } + }, + "schema": { + "type": "boolean" + } + } + } + } + } + } + }, + "/nginx/proxy-hosts/{hostID}/enable": { + "post": { + "operationId": "enableProxyHost", + "summary": "Enable a Proxy Host", + "tags": [ + "proxy-hosts" + ], + "security": [ + { + "bearerAuth": [ + "proxy_hosts.manage" + ] + } + ], + "description": "Enables a proxy host and applies nginx configuration.", + "parameters": [ + { + "in": "path", + "name": "hostID", + "description": "The ID of the Proxy Host", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 2 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": true + } + }, + "schema": { + "type": "boolean" + } + } + } + }, + "400": { + "description": "400 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "error": { + "code": 400, + "message": "Host is already enabled" + } + } + } + }, + "schema": { + "type": "object", + "description": "Error", + "properties": { + "error": { + "type": "object", + "description": "Error object", + "additionalProperties": false, + "required": [ + "code", + "message" + ], + "properties": { + "code": { + "type": "integer", + "example": 400 + }, + "message": { + "type": "string", + "example": "Bad Request" + } + } + } + } + } + } + } + } + } + } + }, + "/nginx/proxy-hosts/{hostID}/disable": { + "post": { + "operationId": "disableProxyHost", + "summary": "Disable a Proxy Host", + "tags": [ + "proxy-hosts" + ], + "security": [ + { + "bearerAuth": [ + "proxy_hosts.manage" + ] + } + ], + "description": "Disables a proxy host in nginx without removing the database record.", + "parameters": [ + { + "in": "path", + "name": "hostID", + "description": "The ID of the Proxy Host", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 2 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": true + } + }, + "schema": { + "type": "boolean" + } + } + } + }, + "400": { + "description": "400 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "error": { + "code": 400, + "message": "Host is already disabled" + } + } + } + }, + "schema": { + "type": "object", + "description": "Error", + "properties": { + "error": { + "type": "object", + "description": "Error object", + "additionalProperties": false, + "required": [ + "code", + "message" + ], + "properties": { + "code": { + "type": "integer", + "example": 400 + }, + "message": { + "type": "string", + "example": "Bad Request" + } + } + } + } + } + } + } + } + } + } + }, + "/nginx/redirection-hosts": { + "get": { + "operationId": "getRedirectionHosts", + "summary": "Get all Redirection hosts", + "tags": [ + "redirection-hosts" + ], + "security": [ + { + "bearerAuth": [ + "redirection_hosts.view" + ] + } + ], + "description": "Lists HTTP redirection hosts (domain-level redirects).", + "parameters": [ + { + "in": "query", + "name": "expand", + "description": "Expansions", + "schema": { + "type": "string", + "enum": [ + "owner", + "certificate" + ] + } + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": [ + { + "id": 1, + "created_on": "2024-10-09T01:13:12.000Z", + "modified_on": "2024-10-09T01:13:13.000Z", + "owner_user_id": 1, + "domain_names": [ + "test.example.com" + ], + "forward_domain_name": "something-else.com", + "preserve_path": false, + "certificate_id": 0, + "ssl_forced": false, + "block_exploits": false, + "advanced_config": "", + "meta": { + "nginx_online": true, + "nginx_err": null + }, + "http2_support": false, + "enabled": true, + "hsts_enabled": false, + "hsts_subdomains": false, + "forward_scheme": "http", + "forward_http_code": 301 + } + ] + } + }, + "schema": { + "type": "array", + "description": "Redirection Hosts list", + "items": { + "type": "object", + "description": "Redirection Host object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "domain_names", + "forward_http_code", + "forward_scheme", + "forward_domain_name", + "preserve_path", + "certificate_id", + "ssl_forced", + "hsts_enabled", + "hsts_subdomains", + "http2_support", + "block_exploits", + "advanced_config", + "enabled", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "forward_http_code": { + "description": "Redirect HTTP Status Code", + "type": "integer", + "minimum": 300, + "maximum": 308, + "example": 302 + }, + "forward_scheme": { + "type": "string", + "enum": [ + "auto", + "http", + "https" + ], + "example": "http" + }, + "forward_domain_name": { + "description": "Domain Name", + "type": "string", + "pattern": "^(?:[^.*]+\\.?)+[^.]$", + "example": "jc21.com" + }, + "preserve_path": { + "description": "Should the path be preserved", + "type": "boolean", + "example": true + }, + "certificate_id": { + "description": "Certificate ID", + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "example": 5 + }, + { + "type": "string", + "pattern": "^new$", + "example": "new" + } + ], + "example": 5 + }, + "ssl_forced": { + "description": "Is SSL Forced", + "type": "boolean", + "example": true + }, + "hsts_enabled": { + "description": "Is HSTS Enabled", + "type": "boolean", + "example": true + }, + "hsts_subdomains": { + "description": "Is HSTS applicable to all subdomains", + "type": "boolean", + "example": true + }, + "http2_support": { + "description": "HTTP2 Protocol Support", + "type": "boolean", + "example": true + }, + "block_exploits": { + "description": "Should we block common exploits", + "type": "boolean", + "example": false + }, + "advanced_config": { + "type": "string", + "example": "" + }, + "enabled": { + "description": "Is Enabled", + "type": "boolean", + "example": false + }, + "meta": { + "type": "object", + "example": { + "nginx_online": true, + "nginx_err": null + } + }, + "certificate": { + "oneOf": [ + { + "type": "null", + "example": null + }, + { + "type": "object", + "description": "Certificate object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "provider", + "nice_name", + "domain_names", + "expires_on", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "provider": { + "type": "string", + "pattern": "^(letsencrypt|other)$", + "example": "letsencrypt" + }, + "nice_name": { + "type": "string", + "description": "Nice Name for the custom certificate", + "example": "My Custom Cert" + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "expires_on": { + "description": "Date and time of expiration", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + }, + "meta": { + "type": "object", + "additionalProperties": false, + "properties": { + "certificate": { + "type": "string", + "minLength": 1 + }, + "certificate_key": { + "type": "string", + "minLength": 1 + }, + "dns_challenge": { + "type": "boolean" + }, + "dns_provider_credentials": { + "type": "string" + }, + "credential_ref": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "internal", + "external" + ] + }, + "id": { + "type": "integer", + "minimum": 1 + }, + "provider_id": { + "type": "integer", + "minimum": 1 + }, + "path": { + "type": "string" + }, + "field": { + "type": "string" + } + } + }, + "dns_provider": { + "type": "string" + }, + "letsencrypt_certificate": { + "type": "object" + }, + "propagation_seconds": { + "type": "integer", + "minimum": 0 + }, + "key_type": { + "type": "string", + "enum": [ + "rsa", + "ecdsa" + ], + "default": "rsa" + } + }, + "example": { + "dns_challenge": false + } + } + } + } + ], + "example": null + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "post": { + "operationId": "createRedirectionHost", + "summary": "Create a Redirection Host", + "tags": [ + "redirection-hosts" + ], + "security": [ + { + "bearerAuth": [ + "redirection_hosts.manage" + ] + } + ], + "description": "Creates a redirection host with source domains and target URL or scheme.", + "requestBody": { + "description": "Redirection Host Payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "required": [ + "domain_names", + "forward_scheme", + "forward_http_code", + "forward_domain_name" + ], + "properties": { + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "forward_http_code": { + "description": "Redirect HTTP Status Code", + "type": "integer", + "minimum": 300, + "maximum": 308, + "example": 302 + }, + "forward_scheme": { + "type": "string", + "enum": [ + "auto", + "http", + "https" + ], + "example": "http" + }, + "forward_domain_name": { + "description": "Domain Name", + "type": "string", + "pattern": "^(?:[^.*]+\\.?)+[^.]$", + "example": "jc21.com" + }, + "preserve_path": { + "description": "Should the path be preserved", + "type": "boolean", + "example": true + }, + "certificate_id": { + "description": "Certificate ID", + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "example": 5 + }, + { + "type": "string", + "pattern": "^new$", + "example": "new" + } + ], + "example": 5 + }, + "ssl_forced": { + "description": "Is SSL Forced", + "type": "boolean", + "example": true + }, + "hsts_enabled": { + "description": "Is HSTS Enabled", + "type": "boolean", + "example": true + }, + "hsts_subdomains": { + "description": "Is HSTS applicable to all subdomains", + "type": "boolean", + "example": true + }, + "http2_support": { + "description": "HTTP2 Protocol Support", + "type": "boolean", + "example": true + }, + "block_exploits": { + "description": "Should we block common exploits", + "type": "boolean", + "example": false + }, + "advanced_config": { + "type": "string", + "example": "" + }, + "meta": { + "type": "object", + "example": { + "nginx_online": true, + "nginx_err": null + } + } + } + }, + "example": { + "domain_names": [ + "test.example.com" + ], + "forward_domain_name": "example.com", + "forward_scheme": "auto", + "forward_http_code": 301, + "preserve_path": false, + "block_exploits": false, + "certificate_id": 0, + "ssl_forced": false, + "http2_support": false, + "hsts_enabled": false, + "hsts_subdomains": false, + "advanced_config": "", + "meta": {} + } + } + } + }, + "responses": { + "201": { + "description": "201 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "id": 2, + "created_on": "2025-10-30T01:27:04.000Z", + "modified_on": "2025-10-30T01:27:04.000Z", + "owner_user_id": 1, + "domain_names": [ + "test.example.com" + ], + "forward_domain_name": "example.com", + "preserve_path": false, + "certificate_id": 0, + "ssl_forced": false, + "block_exploits": false, + "advanced_config": "", + "meta": {}, + "http2_support": false, + "enabled": true, + "hsts_enabled": false, + "hsts_subdomains": false, + "forward_scheme": "auto", + "forward_http_code": 301, + "certificate": null, + "owner": { + "id": 1, + "created_on": "2025-10-28T00:50:24.000Z", + "modified_on": "2025-10-28T00:50:24.000Z", + "is_disabled": false, + "email": "jc@jc21.com", + "name": "jamiec", + "nickname": "jamiec", + "avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm", + "roles": [ + "admin" + ] + } + } + } + }, + "schema": { + "type": "object", + "description": "Redirection Host object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "domain_names", + "forward_http_code", + "forward_scheme", + "forward_domain_name", + "preserve_path", + "certificate_id", + "ssl_forced", + "hsts_enabled", + "hsts_subdomains", + "http2_support", + "block_exploits", + "advanced_config", + "enabled", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "forward_http_code": { + "description": "Redirect HTTP Status Code", + "type": "integer", + "minimum": 300, + "maximum": 308, + "example": 302 + }, + "forward_scheme": { + "type": "string", + "enum": [ + "auto", + "http", + "https" + ], + "example": "http" + }, + "forward_domain_name": { + "description": "Domain Name", + "type": "string", + "pattern": "^(?:[^.*]+\\.?)+[^.]$", + "example": "jc21.com" + }, + "preserve_path": { + "description": "Should the path be preserved", + "type": "boolean", + "example": true + }, + "certificate_id": { + "description": "Certificate ID", + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "example": 5 + }, + { + "type": "string", + "pattern": "^new$", + "example": "new" + } + ], + "example": 5 + }, + "ssl_forced": { + "description": "Is SSL Forced", + "type": "boolean", + "example": true + }, + "hsts_enabled": { + "description": "Is HSTS Enabled", + "type": "boolean", + "example": true + }, + "hsts_subdomains": { + "description": "Is HSTS applicable to all subdomains", + "type": "boolean", + "example": true + }, + "http2_support": { + "description": "HTTP2 Protocol Support", + "type": "boolean", + "example": true + }, + "block_exploits": { + "description": "Should we block common exploits", + "type": "boolean", + "example": false + }, + "advanced_config": { + "type": "string", + "example": "" + }, + "enabled": { + "description": "Is Enabled", + "type": "boolean", + "example": false + }, + "meta": { + "type": "object", + "example": { + "nginx_online": true, + "nginx_err": null + } + }, + "certificate": { + "oneOf": [ + { + "type": "null", + "example": null + }, + { + "type": "object", + "description": "Certificate object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "provider", + "nice_name", + "domain_names", + "expires_on", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "provider": { + "type": "string", + "pattern": "^(letsencrypt|other)$", + "example": "letsencrypt" + }, + "nice_name": { + "type": "string", + "description": "Nice Name for the custom certificate", + "example": "My Custom Cert" + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "expires_on": { + "description": "Date and time of expiration", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + }, + "meta": { + "type": "object", + "additionalProperties": false, + "properties": { + "certificate": { + "type": "string", + "minLength": 1 + }, + "certificate_key": { + "type": "string", + "minLength": 1 + }, + "dns_challenge": { + "type": "boolean" + }, + "dns_provider_credentials": { + "type": "string" + }, + "credential_ref": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "internal", + "external" + ] + }, + "id": { + "type": "integer", + "minimum": 1 + }, + "provider_id": { + "type": "integer", + "minimum": 1 + }, + "path": { + "type": "string" + }, + "field": { + "type": "string" + } + } + }, + "dns_provider": { + "type": "string" + }, + "letsencrypt_certificate": { + "type": "object" + }, + "propagation_seconds": { + "type": "integer", + "minimum": 0 + }, + "key_type": { + "type": "string", + "enum": [ + "rsa", + "ecdsa" + ], + "default": "rsa" + } + }, + "example": { + "dns_challenge": false + } + } + } + } + ], + "example": null + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/nginx/redirection-hosts/{hostID}": { + "get": { + "operationId": "getRedirectionHost", + "summary": "Get a Redirection Host", + "tags": [ + "redirection-hosts" + ], + "security": [ + { + "bearerAuth": [ + "redirection_hosts.view" + ] + } + ], + "description": "Returns one redirection host by id.", + "parameters": [ + { + "in": "path", + "name": "hostID", + "description": "The ID of the Redirection Host", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 1 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "id": 1, + "created_on": "2024-10-09T01:13:12.000Z", + "modified_on": "2024-10-09T01:13:13.000Z", + "owner_user_id": 1, + "domain_names": [ + "test.example.com" + ], + "forward_domain_name": "something-else.com", + "preserve_path": false, + "certificate_id": 0, + "ssl_forced": false, + "block_exploits": false, + "advanced_config": "", + "meta": { + "nginx_online": true, + "nginx_err": null + }, + "http2_support": false, + "enabled": true, + "hsts_enabled": false, + "hsts_subdomains": false, + "forward_scheme": "http", + "forward_http_code": 301 + } + } + }, + "schema": { + "type": "object", + "description": "Redirection Host object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "domain_names", + "forward_http_code", + "forward_scheme", + "forward_domain_name", + "preserve_path", + "certificate_id", + "ssl_forced", + "hsts_enabled", + "hsts_subdomains", + "http2_support", + "block_exploits", + "advanced_config", + "enabled", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "forward_http_code": { + "description": "Redirect HTTP Status Code", + "type": "integer", + "minimum": 300, + "maximum": 308, + "example": 302 + }, + "forward_scheme": { + "type": "string", + "enum": [ + "auto", + "http", + "https" + ], + "example": "http" + }, + "forward_domain_name": { + "description": "Domain Name", + "type": "string", + "pattern": "^(?:[^.*]+\\.?)+[^.]$", + "example": "jc21.com" + }, + "preserve_path": { + "description": "Should the path be preserved", + "type": "boolean", + "example": true + }, + "certificate_id": { + "description": "Certificate ID", + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "example": 5 + }, + { + "type": "string", + "pattern": "^new$", + "example": "new" + } + ], + "example": 5 + }, + "ssl_forced": { + "description": "Is SSL Forced", + "type": "boolean", + "example": true + }, + "hsts_enabled": { + "description": "Is HSTS Enabled", + "type": "boolean", + "example": true + }, + "hsts_subdomains": { + "description": "Is HSTS applicable to all subdomains", + "type": "boolean", + "example": true + }, + "http2_support": { + "description": "HTTP2 Protocol Support", + "type": "boolean", + "example": true + }, + "block_exploits": { + "description": "Should we block common exploits", + "type": "boolean", + "example": false + }, + "advanced_config": { + "type": "string", + "example": "" + }, + "enabled": { + "description": "Is Enabled", + "type": "boolean", + "example": false + }, + "meta": { + "type": "object", + "example": { + "nginx_online": true, + "nginx_err": null + } + }, + "certificate": { + "oneOf": [ + { + "type": "null", + "example": null + }, + { + "type": "object", + "description": "Certificate object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "provider", + "nice_name", + "domain_names", + "expires_on", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "provider": { + "type": "string", + "pattern": "^(letsencrypt|other)$", + "example": "letsencrypt" + }, + "nice_name": { + "type": "string", + "description": "Nice Name for the custom certificate", + "example": "My Custom Cert" + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "expires_on": { + "description": "Date and time of expiration", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + }, + "meta": { + "type": "object", + "additionalProperties": false, + "properties": { + "certificate": { + "type": "string", + "minLength": 1 + }, + "certificate_key": { + "type": "string", + "minLength": 1 + }, + "dns_challenge": { + "type": "boolean" + }, + "dns_provider_credentials": { + "type": "string" + }, + "credential_ref": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "internal", + "external" + ] + }, + "id": { + "type": "integer", + "minimum": 1 + }, + "provider_id": { + "type": "integer", + "minimum": 1 + }, + "path": { + "type": "string" + }, + "field": { + "type": "string" + } + } + }, + "dns_provider": { + "type": "string" + }, + "letsencrypt_certificate": { + "type": "object" + }, + "propagation_seconds": { + "type": "integer", + "minimum": 0 + }, + "key_type": { + "type": "string", + "enum": [ + "rsa", + "ecdsa" + ], + "default": "rsa" + } + }, + "example": { + "dns_challenge": false + } + } + } + } + ], + "example": null + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + } + } + } + } + } + } + } + }, + "put": { + "operationId": "updateRedirectionHost", + "summary": "Update a Redirection Host", + "tags": [ + "redirection-hosts" + ], + "security": [ + { + "bearerAuth": [ + "redirection_hosts.manage" + ] + } + ], + "description": "Updates redirection host matching rules and destination.", + "parameters": [ + { + "in": "path", + "name": "hostID", + "description": "The ID of the Redirection Host", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 2 + } + ], + "requestBody": { + "description": "Redirection Host Payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "minProperties": 1, + "properties": { + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "forward_http_code": { + "description": "Redirect HTTP Status Code", + "type": "integer", + "minimum": 300, + "maximum": 308, + "example": 302 + }, + "forward_scheme": { + "type": "string", + "enum": [ + "auto", + "http", + "https" + ], + "example": "http" + }, + "forward_domain_name": { + "description": "Domain Name", + "type": "string", + "pattern": "^(?:[^.*]+\\.?)+[^.]$", + "example": "jc21.com" + }, + "preserve_path": { + "description": "Should the path be preserved", + "type": "boolean", + "example": true + }, + "certificate_id": { + "description": "Certificate ID", + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "example": 5 + }, + { + "type": "string", + "pattern": "^new$", + "example": "new" + } + ], + "example": 5 + }, + "ssl_forced": { + "description": "Is SSL Forced", + "type": "boolean", + "example": true + }, + "hsts_enabled": { + "description": "Is HSTS Enabled", + "type": "boolean", + "example": true + }, + "hsts_subdomains": { + "description": "Is HSTS applicable to all subdomains", + "type": "boolean", + "example": true + }, + "http2_support": { + "description": "HTTP2 Protocol Support", + "type": "boolean", + "example": true + }, + "block_exploits": { + "description": "Should we block common exploits", + "type": "boolean", + "example": false + }, + "advanced_config": { + "type": "string", + "example": "" + }, + "meta": { + "type": "object", + "example": { + "nginx_online": true, + "nginx_err": null + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "id": 1, + "created_on": "2024-10-09T01:13:12.000Z", + "modified_on": "2024-10-09T01:18:11.000Z", + "owner_user_id": 1, + "domain_names": [ + "test.example.com" + ], + "forward_domain_name": "something-else.com", + "preserve_path": false, + "certificate_id": 0, + "ssl_forced": false, + "block_exploits": false, + "advanced_config": "", + "meta": { + "nginx_online": true, + "nginx_err": null + }, + "http2_support": false, + "enabled": true, + "hsts_enabled": false, + "hsts_subdomains": false, + "forward_scheme": "http", + "forward_http_code": 301, + "owner": { + "id": 1, + "created_on": "2024-10-09T00:59:56.000Z", + "modified_on": "2024-10-09T00:59:56.000Z", + "is_disabled": false, + "email": "admin@example.com", + "name": "Administrator", + "nickname": "Admin", + "avatar": "", + "roles": [ + "admin" + ] + }, + "certificate": null + } + } + }, + "schema": { + "type": "object", + "description": "Redirection Host object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "domain_names", + "forward_http_code", + "forward_scheme", + "forward_domain_name", + "preserve_path", + "certificate_id", + "ssl_forced", + "hsts_enabled", + "hsts_subdomains", + "http2_support", + "block_exploits", + "advanced_config", + "enabled", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "forward_http_code": { + "description": "Redirect HTTP Status Code", + "type": "integer", + "minimum": 300, + "maximum": 308, + "example": 302 + }, + "forward_scheme": { + "type": "string", + "enum": [ + "auto", + "http", + "https" + ], + "example": "http" + }, + "forward_domain_name": { + "description": "Domain Name", + "type": "string", + "pattern": "^(?:[^.*]+\\.?)+[^.]$", + "example": "jc21.com" + }, + "preserve_path": { + "description": "Should the path be preserved", + "type": "boolean", + "example": true + }, + "certificate_id": { + "description": "Certificate ID", + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "example": 5 + }, + { + "type": "string", + "pattern": "^new$", + "example": "new" + } + ], + "example": 5 + }, + "ssl_forced": { + "description": "Is SSL Forced", + "type": "boolean", + "example": true + }, + "hsts_enabled": { + "description": "Is HSTS Enabled", + "type": "boolean", + "example": true + }, + "hsts_subdomains": { + "description": "Is HSTS applicable to all subdomains", + "type": "boolean", + "example": true + }, + "http2_support": { + "description": "HTTP2 Protocol Support", + "type": "boolean", + "example": true + }, + "block_exploits": { + "description": "Should we block common exploits", + "type": "boolean", + "example": false + }, + "advanced_config": { + "type": "string", + "example": "" + }, + "enabled": { + "description": "Is Enabled", + "type": "boolean", + "example": false + }, + "meta": { + "type": "object", + "example": { + "nginx_online": true, + "nginx_err": null + } + }, + "certificate": { + "oneOf": [ + { + "type": "null", + "example": null + }, + { + "type": "object", + "description": "Certificate object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "provider", + "nice_name", + "domain_names", + "expires_on", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "provider": { + "type": "string", + "pattern": "^(letsencrypt|other)$", + "example": "letsencrypt" + }, + "nice_name": { + "type": "string", + "description": "Nice Name for the custom certificate", + "example": "My Custom Cert" + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "expires_on": { + "description": "Date and time of expiration", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + }, + "meta": { + "type": "object", + "additionalProperties": false, + "properties": { + "certificate": { + "type": "string", + "minLength": 1 + }, + "certificate_key": { + "type": "string", + "minLength": 1 + }, + "dns_challenge": { + "type": "boolean" + }, + "dns_provider_credentials": { + "type": "string" + }, + "credential_ref": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "internal", + "external" + ] + }, + "id": { + "type": "integer", + "minimum": 1 + }, + "provider_id": { + "type": "integer", + "minimum": 1 + }, + "path": { + "type": "string" + }, + "field": { + "type": "string" + } + } + }, + "dns_provider": { + "type": "string" + }, + "letsencrypt_certificate": { + "type": "object" + }, + "propagation_seconds": { + "type": "integer", + "minimum": 0 + }, + "key_type": { + "type": "string", + "enum": [ + "rsa", + "ecdsa" + ], + "default": "rsa" + } + }, + "example": { + "dns_challenge": false + } + } + } + } + ], + "example": null + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "deleteRedirectionHost", + "summary": "Delete a Redirection Host", + "tags": [ + "redirection-hosts" + ], + "security": [ + { + "bearerAuth": [ + "redirection_hosts.manage" + ] + } + ], + "description": "Deletes a redirection host by id.", + "parameters": [ + { + "in": "path", + "name": "hostID", + "description": "The ID of the Redirection Host", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 2 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": true + } + }, + "schema": { + "type": "boolean" + } + } + } + } + } + } + }, + "/nginx/redirection-hosts/{hostID}/enable": { + "post": { + "operationId": "enableRedirectionHost", + "summary": "Enable a Redirection Host", + "tags": [ + "redirection-hosts" + ], + "security": [ + { + "bearerAuth": [ + "redirection_hosts.manage" + ] + } + ], + "description": "Enables a redirection host in nginx.", + "parameters": [ + { + "in": "path", + "name": "hostID", + "description": "The ID of the Redirection Host", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 2 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": true + } + }, + "schema": { + "type": "boolean" + } + } + } + }, + "400": { + "description": "400 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "error": { + "code": 400, + "message": "Host is already enabled" + } + } + } + }, + "schema": { + "type": "object", + "description": "Error", + "properties": { + "error": { + "type": "object", + "description": "Error object", + "additionalProperties": false, + "required": [ + "code", + "message" + ], + "properties": { + "code": { + "type": "integer", + "example": 400 + }, + "message": { + "type": "string", + "example": "Bad Request" + } + } + } + } + } + } + } + } + } + } + }, + "/nginx/redirection-hosts/{hostID}/disable": { + "post": { + "operationId": "disableRedirectionHost", + "summary": "Disable a Redirection Host", + "tags": [ + "redirection-hosts" + ], + "security": [ + { + "bearerAuth": [ + "redirection_hosts.manage" + ] + } + ], + "description": "Disables a redirection host without deleting configuration.", + "parameters": [ + { + "in": "path", + "name": "hostID", + "description": "The ID of the Redirection Host", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 2 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": true + } + }, + "schema": { + "type": "boolean" + } + } + } + }, + "400": { + "description": "400 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "error": { + "code": 400, + "message": "Host is already disabled" + } + } + } + }, + "schema": { + "type": "object", + "description": "Error", + "properties": { + "error": { + "type": "object", + "description": "Error object", + "additionalProperties": false, + "required": [ + "code", + "message" + ], + "properties": { + "code": { + "type": "integer", + "example": 400 + }, + "message": { + "type": "string", + "example": "Bad Request" + } + } + } + } + } + } + } + } + } + } + }, + "/nginx/dead-hosts": { + "get": { + "operationId": "getDeadHosts", + "summary": "Get all 404 hosts", + "tags": [ + "404-hosts" + ], + "security": [ + { + "bearerAuth": [ + "dead_hosts.view" + ] + } + ], + "description": "Lists 404 / catch-all hosts (dead hosts) configured in NPM.", + "parameters": [ + { + "in": "query", + "name": "expand", + "description": "Expansions", + "schema": { + "type": "string", + "enum": [ + "owner", + "certificate" + ] + } + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": [ + { + "id": 1, + "created_on": "2024-10-09T01:38:52.000Z", + "modified_on": "2024-10-09T01:38:52.000Z", + "owner_user_id": 1, + "domain_names": [ + "test.example.com" + ], + "certificate_id": 0, + "ssl_forced": false, + "advanced_config": "", + "meta": { + "nginx_online": true, + "nginx_err": null + }, + "http2_support": false, + "enabled": true, + "hsts_enabled": false, + "hsts_subdomains": false + } + ] + } + }, + "schema": { + "type": "array", + "description": "404 Hosts list", + "items": { + "type": "object", + "description": "404 Host object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "domain_names", + "certificate_id", + "ssl_forced", + "hsts_enabled", + "hsts_subdomains", + "http2_support", + "advanced_config", + "enabled", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "certificate_id": { + "description": "Certificate ID", + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "example": 5 + }, + { + "type": "string", + "pattern": "^new$", + "example": "new" + } + ], + "example": 5 + }, + "ssl_forced": { + "description": "Is SSL Forced", + "type": "boolean", + "example": true + }, + "hsts_enabled": { + "description": "Is HSTS Enabled", + "type": "boolean", + "example": true + }, + "hsts_subdomains": { + "description": "Is HSTS applicable to all subdomains", + "type": "boolean", + "example": true + }, + "http2_support": { + "description": "HTTP2 Protocol Support", + "type": "boolean", + "example": true + }, + "advanced_config": { + "type": "string", + "example": "" + }, + "enabled": { + "description": "Is Enabled", + "type": "boolean", + "example": false + }, + "meta": { + "type": "object", + "example": {} + }, + "certificate": { + "oneOf": [ + { + "type": "null", + "example": null + }, + { + "type": "object", + "description": "Certificate object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "provider", + "nice_name", + "domain_names", + "expires_on", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "provider": { + "type": "string", + "pattern": "^(letsencrypt|other)$", + "example": "letsencrypt" + }, + "nice_name": { + "type": "string", + "description": "Nice Name for the custom certificate", + "example": "My Custom Cert" + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "expires_on": { + "description": "Date and time of expiration", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + }, + "meta": { + "type": "object", + "additionalProperties": false, + "properties": { + "certificate": { + "type": "string", + "minLength": 1 + }, + "certificate_key": { + "type": "string", + "minLength": 1 + }, + "dns_challenge": { + "type": "boolean" + }, + "dns_provider_credentials": { + "type": "string" + }, + "credential_ref": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "internal", + "external" + ] + }, + "id": { + "type": "integer", + "minimum": 1 + }, + "provider_id": { + "type": "integer", + "minimum": 1 + }, + "path": { + "type": "string" + }, + "field": { + "type": "string" + } + } + }, + "dns_provider": { + "type": "string" + }, + "letsencrypt_certificate": { + "type": "object" + }, + "propagation_seconds": { + "type": "integer", + "minimum": 0 + }, + "key_type": { + "type": "string", + "enum": [ + "rsa", + "ecdsa" + ], + "default": "rsa" + } + }, + "example": { + "dns_challenge": false + } + } + } + } + ], + "example": null + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "post": { + "operationId": "create404Host", + "summary": "Create a 404 Host", + "tags": [ + "404-hosts" + ], + "security": [ + { + "bearerAuth": [ + "dead_hosts.manage" + ] + } + ], + "description": "Creates a 404 host that serves a default site when no other host matches.", + "requestBody": { + "description": "404 Host Payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "required": [ + "domain_names" + ], + "properties": { + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "certificate_id": { + "description": "Certificate ID", + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "example": 5 + }, + { + "type": "string", + "pattern": "^new$", + "example": "new" + } + ], + "example": 5 + }, + "ssl_forced": { + "description": "Is SSL Forced", + "type": "boolean", + "example": true + }, + "hsts_enabled": { + "description": "Is HSTS Enabled", + "type": "boolean", + "example": true + }, + "hsts_subdomains": { + "description": "Is HSTS applicable to all subdomains", + "type": "boolean", + "example": true + }, + "http2_support": { + "description": "HTTP2 Protocol Support", + "type": "boolean", + "example": true + }, + "advanced_config": { + "type": "string", + "example": "" + }, + "meta": { + "type": "object", + "example": {} + } + } + }, + "example": { + "domain_names": [ + "test.example.com" + ], + "certificate_id": 0, + "ssl_forced": false, + "advanced_config": "", + "http2_support": false, + "hsts_enabled": false, + "hsts_subdomains": false, + "meta": {} + } + } + } + }, + "responses": { + "201": { + "description": "201 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "id": 1, + "created_on": "2024-10-09T01:38:52.000Z", + "modified_on": "2024-10-09T01:38:52.000Z", + "owner_user_id": 1, + "domain_names": [ + "test.example.com" + ], + "certificate_id": 0, + "ssl_forced": false, + "advanced_config": "", + "meta": {}, + "http2_support": false, + "enabled": true, + "hsts_enabled": false, + "hsts_subdomains": false, + "certificate": null, + "owner": { + "id": 1, + "created_on": "2024-10-09T00:59:56.000Z", + "modified_on": "2024-10-09T00:59:56.000Z", + "is_disabled": false, + "email": "admin@example.com", + "name": "Administrator", + "nickname": "Admin", + "avatar": "", + "roles": [ + "admin" + ] + } + } + } + }, + "schema": { + "type": "object", + "description": "404 Host object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "domain_names", + "certificate_id", + "ssl_forced", + "hsts_enabled", + "hsts_subdomains", + "http2_support", + "advanced_config", + "enabled", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "certificate_id": { + "description": "Certificate ID", + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "example": 5 + }, + { + "type": "string", + "pattern": "^new$", + "example": "new" + } + ], + "example": 5 + }, + "ssl_forced": { + "description": "Is SSL Forced", + "type": "boolean", + "example": true + }, + "hsts_enabled": { + "description": "Is HSTS Enabled", + "type": "boolean", + "example": true + }, + "hsts_subdomains": { + "description": "Is HSTS applicable to all subdomains", + "type": "boolean", + "example": true + }, + "http2_support": { + "description": "HTTP2 Protocol Support", + "type": "boolean", + "example": true + }, + "advanced_config": { + "type": "string", + "example": "" + }, + "enabled": { + "description": "Is Enabled", + "type": "boolean", + "example": false + }, + "meta": { + "type": "object", + "example": {} + }, + "certificate": { + "oneOf": [ + { + "type": "null", + "example": null + }, + { + "type": "object", + "description": "Certificate object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "provider", + "nice_name", + "domain_names", + "expires_on", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "provider": { + "type": "string", + "pattern": "^(letsencrypt|other)$", + "example": "letsencrypt" + }, + "nice_name": { + "type": "string", + "description": "Nice Name for the custom certificate", + "example": "My Custom Cert" + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "expires_on": { + "description": "Date and time of expiration", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + }, + "meta": { + "type": "object", + "additionalProperties": false, + "properties": { + "certificate": { + "type": "string", + "minLength": 1 + }, + "certificate_key": { + "type": "string", + "minLength": 1 + }, + "dns_challenge": { + "type": "boolean" + }, + "dns_provider_credentials": { + "type": "string" + }, + "credential_ref": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "internal", + "external" + ] + }, + "id": { + "type": "integer", + "minimum": 1 + }, + "provider_id": { + "type": "integer", + "minimum": 1 + }, + "path": { + "type": "string" + }, + "field": { + "type": "string" + } + } + }, + "dns_provider": { + "type": "string" + }, + "letsencrypt_certificate": { + "type": "object" + }, + "propagation_seconds": { + "type": "integer", + "minimum": 0 + }, + "key_type": { + "type": "string", + "enum": [ + "rsa", + "ecdsa" + ], + "default": "rsa" + } + }, + "example": { + "dns_challenge": false + } + } + } + } + ], + "example": null + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/nginx/dead-hosts/{hostID}": { + "get": { + "operationId": "getDeadHost", + "summary": "Get a 404 Host", + "tags": [ + "404-hosts" + ], + "security": [ + { + "bearerAuth": [ + "dead_hosts.view" + ] + } + ], + "description": "Returns one 404 host configuration by id.", + "parameters": [ + { + "in": "path", + "name": "hostID", + "description": "The ID of the 404 Host", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 1 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "id": 1, + "created_on": "2024-10-09T01:38:52.000Z", + "modified_on": "2024-10-09T01:38:52.000Z", + "owner_user_id": 1, + "domain_names": [ + "test.example.com" + ], + "certificate_id": 0, + "ssl_forced": false, + "advanced_config": "", + "meta": { + "nginx_online": true, + "nginx_err": null + }, + "http2_support": false, + "enabled": true, + "hsts_enabled": false, + "hsts_subdomains": false + } + } + }, + "schema": { + "type": "object", + "description": "404 Host object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "domain_names", + "certificate_id", + "ssl_forced", + "hsts_enabled", + "hsts_subdomains", + "http2_support", + "advanced_config", + "enabled", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "certificate_id": { + "description": "Certificate ID", + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "example": 5 + }, + { + "type": "string", + "pattern": "^new$", + "example": "new" + } + ], + "example": 5 + }, + "ssl_forced": { + "description": "Is SSL Forced", + "type": "boolean", + "example": true + }, + "hsts_enabled": { + "description": "Is HSTS Enabled", + "type": "boolean", + "example": true + }, + "hsts_subdomains": { + "description": "Is HSTS applicable to all subdomains", + "type": "boolean", + "example": true + }, + "http2_support": { + "description": "HTTP2 Protocol Support", + "type": "boolean", + "example": true + }, + "advanced_config": { + "type": "string", + "example": "" + }, + "enabled": { + "description": "Is Enabled", + "type": "boolean", + "example": false + }, + "meta": { + "type": "object", + "example": {} + }, + "certificate": { + "oneOf": [ + { + "type": "null", + "example": null + }, + { + "type": "object", + "description": "Certificate object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "provider", + "nice_name", + "domain_names", + "expires_on", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "provider": { + "type": "string", + "pattern": "^(letsencrypt|other)$", + "example": "letsencrypt" + }, + "nice_name": { + "type": "string", + "description": "Nice Name for the custom certificate", + "example": "My Custom Cert" + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "expires_on": { + "description": "Date and time of expiration", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + }, + "meta": { + "type": "object", + "additionalProperties": false, + "properties": { + "certificate": { + "type": "string", + "minLength": 1 + }, + "certificate_key": { + "type": "string", + "minLength": 1 + }, + "dns_challenge": { + "type": "boolean" + }, + "dns_provider_credentials": { + "type": "string" + }, + "credential_ref": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "internal", + "external" + ] + }, + "id": { + "type": "integer", + "minimum": 1 + }, + "provider_id": { + "type": "integer", + "minimum": 1 + }, + "path": { + "type": "string" + }, + "field": { + "type": "string" + } + } + }, + "dns_provider": { + "type": "string" + }, + "letsencrypt_certificate": { + "type": "object" + }, + "propagation_seconds": { + "type": "integer", + "minimum": 0 + }, + "key_type": { + "type": "string", + "enum": [ + "rsa", + "ecdsa" + ], + "default": "rsa" + } + }, + "example": { + "dns_challenge": false + } + } + } + } + ], + "example": null + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + } + } + } + } + } + } + } + }, + "put": { + "operationId": "updateDeadHost", + "summary": "Update a 404 Host", + "tags": [ + "404-hosts" + ], + "security": [ + { + "bearerAuth": [ + "dead_hosts.manage" + ] + } + ], + "description": "Updates a 404 host domain names, forwarding, or enabled state.", + "parameters": [ + { + "in": "path", + "name": "hostID", + "description": "The ID of the 404 Host", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 2 + } + ], + "requestBody": { + "description": "404 Host Payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "minProperties": 1, + "properties": { + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "certificate_id": { + "description": "Certificate ID", + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "example": 5 + }, + { + "type": "string", + "pattern": "^new$", + "example": "new" + } + ], + "example": 5 + }, + "ssl_forced": { + "description": "Is SSL Forced", + "type": "boolean", + "example": true + }, + "hsts_enabled": { + "description": "Is HSTS Enabled", + "type": "boolean", + "example": true + }, + "hsts_subdomains": { + "description": "Is HSTS applicable to all subdomains", + "type": "boolean", + "example": true + }, + "http2_support": { + "description": "HTTP2 Protocol Support", + "type": "boolean", + "example": true + }, + "advanced_config": { + "type": "string", + "example": "" + }, + "meta": { + "type": "object", + "example": {} + } + } + } + } + } + }, + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "id": 1, + "created_on": "2024-10-09T01:38:52.000Z", + "modified_on": "2024-10-09T01:46:06.000Z", + "owner_user_id": 1, + "domain_names": [ + "test.example.com" + ], + "certificate_id": 0, + "ssl_forced": false, + "advanced_config": "", + "meta": { + "nginx_online": true, + "nginx_err": null + }, + "http2_support": false, + "enabled": true, + "hsts_enabled": false, + "hsts_subdomains": false, + "owner": { + "id": 1, + "created_on": "2024-10-09T00:59:56.000Z", + "modified_on": "2024-10-09T00:59:56.000Z", + "is_disabled": false, + "email": "admin@example.com", + "name": "Administrator", + "nickname": "Admin", + "avatar": "", + "roles": [ + "admin" + ] + }, + "certificate": null + } + } + }, + "schema": { + "type": "object", + "description": "404 Host object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "domain_names", + "certificate_id", + "ssl_forced", + "hsts_enabled", + "hsts_subdomains", + "http2_support", + "advanced_config", + "enabled", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "certificate_id": { + "description": "Certificate ID", + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "example": 5 + }, + { + "type": "string", + "pattern": "^new$", + "example": "new" + } + ], + "example": 5 + }, + "ssl_forced": { + "description": "Is SSL Forced", + "type": "boolean", + "example": true + }, + "hsts_enabled": { + "description": "Is HSTS Enabled", + "type": "boolean", + "example": true + }, + "hsts_subdomains": { + "description": "Is HSTS applicable to all subdomains", + "type": "boolean", + "example": true + }, + "http2_support": { + "description": "HTTP2 Protocol Support", + "type": "boolean", + "example": true + }, + "advanced_config": { + "type": "string", + "example": "" + }, + "enabled": { + "description": "Is Enabled", + "type": "boolean", + "example": false + }, + "meta": { + "type": "object", + "example": {} + }, + "certificate": { + "oneOf": [ + { + "type": "null", + "example": null + }, + { + "type": "object", + "description": "Certificate object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "provider", + "nice_name", + "domain_names", + "expires_on", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "provider": { + "type": "string", + "pattern": "^(letsencrypt|other)$", + "example": "letsencrypt" + }, + "nice_name": { + "type": "string", + "description": "Nice Name for the custom certificate", + "example": "My Custom Cert" + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "expires_on": { + "description": "Date and time of expiration", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + }, + "meta": { + "type": "object", + "additionalProperties": false, + "properties": { + "certificate": { + "type": "string", + "minLength": 1 + }, + "certificate_key": { + "type": "string", + "minLength": 1 + }, + "dns_challenge": { + "type": "boolean" + }, + "dns_provider_credentials": { + "type": "string" + }, + "credential_ref": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "internal", + "external" + ] + }, + "id": { + "type": "integer", + "minimum": 1 + }, + "provider_id": { + "type": "integer", + "minimum": 1 + }, + "path": { + "type": "string" + }, + "field": { + "type": "string" + } + } + }, + "dns_provider": { + "type": "string" + }, + "letsencrypt_certificate": { + "type": "object" + }, + "propagation_seconds": { + "type": "integer", + "minimum": 0 + }, + "key_type": { + "type": "string", + "enum": [ + "rsa", + "ecdsa" + ], + "default": "rsa" + } + }, + "example": { + "dns_challenge": false + } + } + } + } + ], + "example": null + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "deleteDeadHost", + "summary": "Delete a 404 Host", + "tags": [ + "404-hosts" + ], + "security": [ + { + "bearerAuth": [ + "dead_hosts.manage" + ] + } + ], + "description": "Deletes a 404 host by id.", + "parameters": [ + { + "in": "path", + "name": "hostID", + "description": "The ID of the 404 Host", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 2 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": true + } + }, + "schema": { + "type": "boolean" + } + } + } + } + } + } + }, + "/nginx/dead-hosts/{hostID}/enable": { + "post": { + "operationId": "enableDeadHost", + "summary": "Enable a 404 Host", + "tags": [ + "404-hosts" + ], + "security": [ + { + "bearerAuth": [ + "dead_hosts.manage" + ] + } + ], + "description": "Enables a previously disabled 404 host and reloads nginx when required.", + "parameters": [ + { + "in": "path", + "name": "hostID", + "description": "The ID of the 404 Host", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 2 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": true + } + }, + "schema": { + "type": "boolean" + } + } + } + }, + "400": { + "description": "400 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "error": { + "code": 400, + "message": "Host is already enabled" + } + } + } + }, + "schema": { + "type": "object", + "description": "Error", + "properties": { + "error": { + "type": "object", + "description": "Error object", + "additionalProperties": false, + "required": [ + "code", + "message" + ], + "properties": { + "code": { + "type": "integer", + "example": 400 + }, + "message": { + "type": "string", + "example": "Bad Request" + } + } + } + } + } + } + } + } + } + } + }, + "/nginx/dead-hosts/{hostID}/disable": { + "post": { + "operationId": "disableDeadHost", + "summary": "Disable a 404 Host", + "tags": [ + "404-hosts" + ], + "security": [ + { + "bearerAuth": [ + "dead_hosts.manage" + ] + } + ], + "description": "Disables a 404 host without deleting its configuration.", + "parameters": [ + { + "in": "path", + "name": "hostID", + "description": "The ID of the 404 Host", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 2 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": true + } + }, + "schema": { + "type": "boolean" + } + } + } + }, + "400": { + "description": "400 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "error": { + "code": 400, + "message": "Host is already disabled" + } + } + } + }, + "schema": { + "type": "object", + "description": "Error", + "properties": { + "error": { + "type": "object", + "description": "Error object", + "additionalProperties": false, + "required": [ + "code", + "message" + ], + "properties": { + "code": { + "type": "integer", + "example": 400 + }, + "message": { + "type": "string", + "example": "Bad Request" + } + } + } + } + } + } + } + } + } + } + }, + "/nginx/streams": { + "get": { + "operationId": "getStreams", + "summary": "Get all streams", + "tags": [ + "streams" + ], + "security": [ + { + "bearerAuth": [ + "streams.view" + ] + } + ], + "description": "Lists TCP/UDP stream proxies configured in NPM.", + "parameters": [ + { + "in": "query", + "name": "expand", + "description": "Expansions", + "schema": { + "type": "string", + "enum": [ + "owner", + "certificate" + ] + } + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": [ + { + "id": 1, + "created_on": "2024-10-09T02:33:45.000Z", + "modified_on": "2024-10-09T02:33:45.000Z", + "owner_user_id": 1, + "incoming_port": 9090, + "forwarding_host": "router.internal", + "forwarding_port": 80, + "tcp_forwarding": true, + "udp_forwarding": false, + "meta": { + "nginx_online": true, + "nginx_err": null + }, + "enabled": true, + "certificate_id": 0 + } + ] + } + }, + "schema": { + "type": "array", + "description": "Streams list", + "items": { + "type": "object", + "description": "Stream object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "incoming_port", + "forwarding_host", + "forwarding_port", + "tcp_forwarding", + "udp_forwarding", + "enabled", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "incoming_port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "example": 9090 + }, + "forwarding_host": { + "anyOf": [ + { + "description": "Domain Name", + "type": "string", + "pattern": "^(?:[^.*]+\\.?)+[^.]$", + "example": "example.com" + }, + { + "type": "string", + "format": "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$" + }, + { + "type": "string", + "format": "ipv6" + } + ], + "example": "example.com" + }, + "forwarding_port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "example": 80 + }, + "tcp_forwarding": { + "type": "boolean", + "example": true + }, + "udp_forwarding": { + "type": "boolean", + "example": false + }, + "enabled": { + "description": "Is Enabled", + "type": "boolean", + "example": false + }, + "certificate_id": { + "description": "Certificate ID", + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "example": 5 + }, + { + "type": "string", + "pattern": "^new$", + "example": "new" + } + ], + "example": 5 + }, + "meta": { + "type": "object", + "example": {} + }, + "certificate": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "object", + "description": "Certificate object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "provider", + "nice_name", + "domain_names", + "expires_on", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "provider": { + "type": "string", + "pattern": "^(letsencrypt|other)$", + "example": "letsencrypt" + }, + "nice_name": { + "type": "string", + "description": "Nice Name for the custom certificate", + "example": "My Custom Cert" + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "expires_on": { + "description": "Date and time of expiration", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + }, + "meta": { + "type": "object", + "additionalProperties": false, + "properties": { + "certificate": { + "type": "string", + "minLength": 1 + }, + "certificate_key": { + "type": "string", + "minLength": 1 + }, + "dns_challenge": { + "type": "boolean" + }, + "dns_provider_credentials": { + "type": "string" + }, + "credential_ref": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "internal", + "external" + ] + }, + "id": { + "type": "integer", + "minimum": 1 + }, + "provider_id": { + "type": "integer", + "minimum": 1 + }, + "path": { + "type": "string" + }, + "field": { + "type": "string" + } + } + }, + "dns_provider": { + "type": "string" + }, + "letsencrypt_certificate": { + "type": "object" + }, + "propagation_seconds": { + "type": "integer", + "minimum": 0 + }, + "key_type": { + "type": "string", + "enum": [ + "rsa", + "ecdsa" + ], + "default": "rsa" + } + }, + "example": { + "dns_challenge": false + } + } + } + } + ], + "example": null + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "post": { + "operationId": "createStream", + "summary": "Create a Stream", + "tags": [ + "streams" + ], + "security": [ + { + "bearerAuth": [ + "streams.manage" + ] + } + ], + "description": "Creates a layer-4 stream forwarding entry.", + "requestBody": { + "description": "Stream Payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "required": [ + "incoming_port", + "forwarding_host", + "forwarding_port" + ], + "properties": { + "incoming_port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "example": 9090 + }, + "forwarding_host": { + "anyOf": [ + { + "description": "Domain Name", + "type": "string", + "pattern": "^(?:[^.*]+\\.?)+[^.]$", + "example": "example.com" + }, + { + "type": "string", + "format": "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$" + }, + { + "type": "string", + "format": "ipv6" + } + ], + "example": "example.com" + }, + "forwarding_port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "example": 80 + }, + "tcp_forwarding": { + "type": "boolean", + "example": true + }, + "udp_forwarding": { + "type": "boolean", + "example": false + }, + "certificate_id": { + "description": "Certificate ID", + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "example": 5 + }, + { + "type": "string", + "pattern": "^new$", + "example": "new" + } + ], + "example": 5 + }, + "meta": { + "type": "object", + "example": {} + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + } + } + }, + "example": { + "incoming_port": 8888, + "forwarding_host": "127.0.0.1", + "forwarding_port": 8080, + "tcp_forwarding": true, + "udp_forwarding": false, + "certificate_id": 0, + "meta": {} + } + } + } + }, + "responses": { + "201": { + "description": "201 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "id": 1, + "created_on": "2024-10-09T02:33:45.000Z", + "modified_on": "2024-10-09T02:33:45.000Z", + "owner_user_id": 1, + "incoming_port": 9090, + "forwarding_host": "router.internal", + "forwarding_port": 80, + "tcp_forwarding": true, + "udp_forwarding": false, + "meta": { + "nginx_online": true, + "nginx_err": null + }, + "enabled": true, + "owner": { + "id": 1, + "created_on": "2024-10-09T02:33:16.000Z", + "modified_on": "2024-10-09T02:33:16.000Z", + "is_disabled": false, + "email": "admin@example.com", + "name": "Administrator", + "nickname": "Admin", + "avatar": "", + "roles": [ + "admin" + ] + }, + "certificate_id": 0 + } + } + }, + "schema": { + "type": "object", + "description": "Stream object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "incoming_port", + "forwarding_host", + "forwarding_port", + "tcp_forwarding", + "udp_forwarding", + "enabled", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "incoming_port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "example": 9090 + }, + "forwarding_host": { + "anyOf": [ + { + "description": "Domain Name", + "type": "string", + "pattern": "^(?:[^.*]+\\.?)+[^.]$", + "example": "example.com" + }, + { + "type": "string", + "format": "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$" + }, + { + "type": "string", + "format": "ipv6" + } + ], + "example": "example.com" + }, + "forwarding_port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "example": 80 + }, + "tcp_forwarding": { + "type": "boolean", + "example": true + }, + "udp_forwarding": { + "type": "boolean", + "example": false + }, + "enabled": { + "description": "Is Enabled", + "type": "boolean", + "example": false + }, + "certificate_id": { + "description": "Certificate ID", + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "example": 5 + }, + { + "type": "string", + "pattern": "^new$", + "example": "new" + } + ], + "example": 5 + }, + "meta": { + "type": "object", + "example": {} + }, + "certificate": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "object", + "description": "Certificate object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "provider", + "nice_name", + "domain_names", + "expires_on", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "provider": { + "type": "string", + "pattern": "^(letsencrypt|other)$", + "example": "letsencrypt" + }, + "nice_name": { + "type": "string", + "description": "Nice Name for the custom certificate", + "example": "My Custom Cert" + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "expires_on": { + "description": "Date and time of expiration", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + }, + "meta": { + "type": "object", + "additionalProperties": false, + "properties": { + "certificate": { + "type": "string", + "minLength": 1 + }, + "certificate_key": { + "type": "string", + "minLength": 1 + }, + "dns_challenge": { + "type": "boolean" + }, + "dns_provider_credentials": { + "type": "string" + }, + "credential_ref": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "internal", + "external" + ] + }, + "id": { + "type": "integer", + "minimum": 1 + }, + "provider_id": { + "type": "integer", + "minimum": 1 + }, + "path": { + "type": "string" + }, + "field": { + "type": "string" + } + } + }, + "dns_provider": { + "type": "string" + }, + "letsencrypt_certificate": { + "type": "object" + }, + "propagation_seconds": { + "type": "integer", + "minimum": 0 + }, + "key_type": { + "type": "string", + "enum": [ + "rsa", + "ecdsa" + ], + "default": "rsa" + } + }, + "example": { + "dns_challenge": false + } + } + } + } + ], + "example": null + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/nginx/streams/{streamID}": { + "get": { + "operationId": "getStream", + "summary": "Get a Stream", + "tags": [ + "streams" + ], + "security": [ + { + "bearerAuth": [ + "streams.view" + ] + } + ], + "description": "Returns one stream definition by id.", + "parameters": [ + { + "in": "path", + "name": "streamID", + "description": "The ID of the Stream", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 2 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "id": 1, + "created_on": "2024-10-09T02:33:45.000Z", + "modified_on": "2024-10-09T02:33:45.000Z", + "owner_user_id": 1, + "incoming_port": 9090, + "forwarding_host": "router.internal", + "forwarding_port": 80, + "tcp_forwarding": true, + "udp_forwarding": false, + "meta": { + "nginx_online": true, + "nginx_err": null + }, + "enabled": true, + "certificate_id": 0 + } + } + }, + "schema": { + "type": "object", + "description": "Stream object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "incoming_port", + "forwarding_host", + "forwarding_port", + "tcp_forwarding", + "udp_forwarding", + "enabled", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "incoming_port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "example": 9090 + }, + "forwarding_host": { + "anyOf": [ + { + "description": "Domain Name", + "type": "string", + "pattern": "^(?:[^.*]+\\.?)+[^.]$", + "example": "example.com" + }, + { + "type": "string", + "format": "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$" + }, + { + "type": "string", + "format": "ipv6" + } + ], + "example": "example.com" + }, + "forwarding_port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "example": 80 + }, + "tcp_forwarding": { + "type": "boolean", + "example": true + }, + "udp_forwarding": { + "type": "boolean", + "example": false + }, + "enabled": { + "description": "Is Enabled", + "type": "boolean", + "example": false + }, + "certificate_id": { + "description": "Certificate ID", + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "example": 5 + }, + { + "type": "string", + "pattern": "^new$", + "example": "new" + } + ], + "example": 5 + }, + "meta": { + "type": "object", + "example": {} + }, + "certificate": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "object", + "description": "Certificate object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "provider", + "nice_name", + "domain_names", + "expires_on", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "provider": { + "type": "string", + "pattern": "^(letsencrypt|other)$", + "example": "letsencrypt" + }, + "nice_name": { + "type": "string", + "description": "Nice Name for the custom certificate", + "example": "My Custom Cert" + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "expires_on": { + "description": "Date and time of expiration", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + }, + "meta": { + "type": "object", + "additionalProperties": false, + "properties": { + "certificate": { + "type": "string", + "minLength": 1 + }, + "certificate_key": { + "type": "string", + "minLength": 1 + }, + "dns_challenge": { + "type": "boolean" + }, + "dns_provider_credentials": { + "type": "string" + }, + "credential_ref": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "internal", + "external" + ] + }, + "id": { + "type": "integer", + "minimum": 1 + }, + "provider_id": { + "type": "integer", + "minimum": 1 + }, + "path": { + "type": "string" + }, + "field": { + "type": "string" + } + } + }, + "dns_provider": { + "type": "string" + }, + "letsencrypt_certificate": { + "type": "object" + }, + "propagation_seconds": { + "type": "integer", + "minimum": 0 + }, + "key_type": { + "type": "string", + "enum": [ + "rsa", + "ecdsa" + ], + "default": "rsa" + } + }, + "example": { + "dns_challenge": false + } + } + } + } + ], + "example": null + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + } + } + } + } + } + } + } + }, + "put": { + "operationId": "updateStream", + "summary": "Update a Stream", + "tags": [ + "streams" + ], + "security": [ + { + "bearerAuth": [ + "streams.manage" + ] + } + ], + "description": "Updates stream listen ports, upstream, or protocol options.", + "parameters": [ + { + "in": "path", + "name": "streamID", + "description": "The ID of the Stream", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 2 + } + ], + "requestBody": { + "description": "Stream Payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "minProperties": 1, + "properties": { + "incoming_port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "example": 9090 + }, + "forwarding_host": { + "anyOf": [ + { + "description": "Domain Name", + "type": "string", + "pattern": "^(?:[^.*]+\\.?)+[^.]$", + "example": "example.com" + }, + { + "type": "string", + "format": "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$" + }, + { + "type": "string", + "format": "ipv6" + } + ], + "example": "example.com" + }, + "forwarding_port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "example": 80 + }, + "tcp_forwarding": { + "type": "boolean", + "example": true + }, + "udp_forwarding": { + "type": "boolean", + "example": false + }, + "certificate_id": { + "description": "Certificate ID", + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "example": 5 + }, + { + "type": "string", + "pattern": "^new$", + "example": "new" + } + ], + "example": 5 + }, + "meta": { + "type": "object", + "example": {} + } + } + } + } + } + }, + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "id": 1, + "created_on": "2024-10-09T02:33:45.000Z", + "modified_on": "2024-10-09T02:33:45.000Z", + "owner_user_id": 1, + "incoming_port": 9090, + "forwarding_host": "router.internal", + "forwarding_port": 80, + "tcp_forwarding": true, + "udp_forwarding": false, + "meta": { + "nginx_online": true, + "nginx_err": null + }, + "enabled": true, + "owner": { + "id": 1, + "created_on": "2024-10-09T02:33:16.000Z", + "modified_on": "2024-10-09T02:33:16.000Z", + "is_disabled": false, + "email": "admin@example.com", + "name": "Administrator", + "nickname": "Admin", + "avatar": "", + "roles": [ + "admin" + ] + }, + "certificate_id": 0 + } + } + }, + "schema": { + "type": "object", + "description": "Stream object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "incoming_port", + "forwarding_host", + "forwarding_port", + "tcp_forwarding", + "udp_forwarding", + "enabled", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "incoming_port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "example": 9090 + }, + "forwarding_host": { + "anyOf": [ + { + "description": "Domain Name", + "type": "string", + "pattern": "^(?:[^.*]+\\.?)+[^.]$", + "example": "example.com" + }, + { + "type": "string", + "format": "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$" + }, + { + "type": "string", + "format": "ipv6" + } + ], + "example": "example.com" + }, + "forwarding_port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "example": 80 + }, + "tcp_forwarding": { + "type": "boolean", + "example": true + }, + "udp_forwarding": { + "type": "boolean", + "example": false + }, + "enabled": { + "description": "Is Enabled", + "type": "boolean", + "example": false + }, + "certificate_id": { + "description": "Certificate ID", + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "example": 5 + }, + { + "type": "string", + "pattern": "^new$", + "example": "new" + } + ], + "example": 5 + }, + "meta": { + "type": "object", + "example": {} + }, + "certificate": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "object", + "description": "Certificate object", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "provider", + "nice_name", + "domain_names", + "expires_on", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "provider": { + "type": "string", + "pattern": "^(letsencrypt|other)$", + "example": "letsencrypt" + }, + "nice_name": { + "type": "string", + "description": "Nice Name for the custom certificate", + "example": "My Custom Cert" + }, + "domain_names": { + "description": "Domain Names separated by a comma", + "type": "array", + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + }, + "example": [ + "example.com", + "www.example.com" + ] + }, + "expires_on": { + "description": "Date and time of expiration", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + }, + "meta": { + "type": "object", + "additionalProperties": false, + "properties": { + "certificate": { + "type": "string", + "minLength": 1 + }, + "certificate_key": { + "type": "string", + "minLength": 1 + }, + "dns_challenge": { + "type": "boolean" + }, + "dns_provider_credentials": { + "type": "string" + }, + "credential_ref": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "internal", + "external" + ] + }, + "id": { + "type": "integer", + "minimum": 1 + }, + "provider_id": { + "type": "integer", + "minimum": 1 + }, + "path": { + "type": "string" + }, + "field": { + "type": "string" + } + } + }, + "dns_provider": { + "type": "string" + }, + "letsencrypt_certificate": { + "type": "object" + }, + "propagation_seconds": { + "type": "integer", + "minimum": 0 + }, + "key_type": { + "type": "string", + "enum": [ + "rsa", + "ecdsa" + ], + "default": "rsa" + } + }, + "example": { + "dns_challenge": false + } + } + } + } + ], + "example": null + }, + "owner": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "deleteStream", + "summary": "Delete a Stream", + "tags": [ + "streams" + ], + "security": [ + { + "bearerAuth": [ + "streams.manage" + ] + } + ], + "description": "Deletes a stream by id.", + "parameters": [ + { + "in": "path", + "name": "streamID", + "description": "The ID of the Stream", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 2 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": true + } + }, + "schema": { + "type": "boolean" + } + } + } + } + } + } + }, + "/nginx/streams/{streamID}/enable": { + "post": { + "operationId": "enableStream", + "summary": "Enable a Stream", + "tags": [ + "streams" + ], + "security": [ + { + "bearerAuth": [ + "streams.manage" + ] + } + ], + "description": "Enables a stream and reloads nginx configuration.", + "parameters": [ + { + "in": "path", + "name": "streamID", + "description": "The ID of the Stream", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 2 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": true + } + }, + "schema": { + "type": "boolean" + } + } + } + }, + "400": { + "description": "400 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "error": { + "code": 400, + "message": "Host is already enabled" + } + } + } + }, + "schema": { + "type": "object", + "description": "Error", + "properties": { + "error": { + "type": "object", + "description": "Error object", + "additionalProperties": false, + "required": [ + "code", + "message" + ], + "properties": { + "code": { + "type": "integer", + "example": 400 + }, + "message": { + "type": "string", + "example": "Bad Request" + } + } + } + } + } + } + } + } + } + } + }, + "/nginx/streams/{streamID}/disable": { + "post": { + "operationId": "disableStream", + "summary": "Disable a Stream", + "tags": [ + "streams" + ], + "security": [ + { + "bearerAuth": [ + "streams.manage" + ] + } + ], + "description": "Disables a stream in nginx without deleting the record.", + "parameters": [ + { + "in": "path", + "name": "streamID", + "description": "The ID of the Stream", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 2 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": true + } + }, + "schema": { + "type": "boolean" + } + } + } + }, + "400": { + "description": "400 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "error": { + "code": 400, + "message": "Host is already disabled" + } + } + } + }, + "schema": { + "type": "object", + "description": "Error", + "properties": { + "error": { + "type": "object", + "description": "Error object", + "additionalProperties": false, + "required": [ + "code", + "message" + ], + "properties": { + "code": { + "type": "integer", + "example": 400 + }, + "message": { + "type": "string", + "example": "Bad Request" + } + } + } + } + } + } + } + } + } + } + }, + "/reports/hosts": { + "get": { + "operationId": "reportsHosts", + "summary": "Report on Host Statistics", + "tags": [ + "reports" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "description": "Returns reporting data about configured hosts for dashboards and diagnostics.", + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "proxy": 20, + "redirection": 1, + "stream": 0, + "dead": 1 + } + } + }, + "schema": { + "type": "object", + "properties": { + "proxy": { + "type": "integer", + "description": "Proxy Hosts Count", + "example": 20 + }, + "redirection": { + "type": "integer", + "description": "Redirection Hosts Count", + "example": 2 + }, + "stream": { + "type": "integer", + "description": "Streams Count", + "example": 0 + }, + "dead": { + "type": "integer", + "description": "404 Hosts Count", + "example": 3 + } + } + } + } + } + } + } + } + }, + "/schema": { + "get": { + "operationId": "schema", + "summary": "Returns this swagger API schema", + "tags": [ + "public" + ], + "description": "Returns the fully dereferenced OpenAPI document for this running instance. Used by dev Swagger on port 3082 and for live schema inspection.", + "responses": { + "200": { + "description": "200 response" + } + } + } + }, + "/settings": { + "get": { + "operationId": "getSettings", + "summary": "Get all settings", + "tags": [ + "settings" + ], + "security": [ + { + "bearerAuth": [ + "admin" + ] + } + ], + "description": "Lists application settings keys and values visible to the authenticated administrator.", + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": [ + { + "id": "default-site", + "name": "Default Site", + "description": "What to show when Nginx is hit with an unknown Host", + "value": "congratulations", + "meta": {} + } + ] + } + }, + "schema": { + "type": "array", + "description": "Setting list", + "items": { + "type": "object", + "description": "Setting object", + "required": [ + "id", + "name", + "description", + "value", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "description": "Setting ID", + "minLength": 1, + "example": "default-site" + }, + "name": { + "type": "string", + "description": "Setting Display Name", + "minLength": 1, + "example": "Default Site" + }, + "description": { + "type": "string", + "description": "Meaningful description", + "minLength": 1, + "example": "What to show when Nginx is hit with an unknown Host" + }, + "value": { + "description": "Value in almost any form", + "example": "congratulations", + "anyOf": [ + { + "type": "string", + "minLength": 1 + }, + { + "type": "integer" + }, + { + "type": "object" + }, + { + "type": "number" + }, + { + "type": "array" + } + ] + }, + "meta": { + "description": "Extra metadata", + "example": { + "redirect": "http://example.com", + "html": "

404

" + }, + "type": "object" + } + } + } + } + } + } + } + } + } + }, + "/settings/{settingID}": { + "get": { + "operationId": "getSetting", + "summary": "Get a setting", + "tags": [ + "settings" + ], + "security": [ + { + "bearerAuth": [ + "admin" + ] + } + ], + "description": "Returns one setting by id or key identifier.", + "parameters": [ + { + "in": "path", + "name": "settingID", + "schema": { + "type": "string", + "minLength": 1 + }, + "required": true, + "description": "Setting ID", + "example": "default-site" + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "id": "default-site", + "name": "Default Site", + "description": "What to show when Nginx is hit with an unknown Host", + "value": "congratulations", + "meta": {} + } + } + }, + "schema": { + "type": "object", + "description": "Setting object", + "required": [ + "id", + "name", + "description", + "value", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "description": "Setting ID", + "minLength": 1, + "example": "default-site" + }, + "name": { + "type": "string", + "description": "Setting Display Name", + "minLength": 1, + "example": "Default Site" + }, + "description": { + "type": "string", + "description": "Meaningful description", + "minLength": 1, + "example": "What to show when Nginx is hit with an unknown Host" + }, + "value": { + "description": "Value in almost any form", + "example": "congratulations", + "anyOf": [ + { + "type": "string", + "minLength": 1 + }, + { + "type": "integer" + }, + { + "type": "object" + }, + { + "type": "number" + }, + { + "type": "array" + } + ] + }, + "meta": { + "description": "Extra metadata", + "example": { + "redirect": "http://example.com", + "html": "

404

" + }, + "type": "object" + } + } + } + } + } + } + } + }, + "put": { + "operationId": "updateSetting", + "summary": "Update a setting", + "tags": [ + "settings" + ], + "security": [ + { + "bearerAuth": [ + "admin" + ] + } + ], + "description": "Updates a single application setting value.", + "parameters": [ + { + "in": "path", + "name": "settingID", + "schema": { + "type": "string", + "minLength": 1, + "enum": [ + "default-site" + ] + }, + "required": true, + "description": "Setting ID", + "example": "default-site" + } + ], + "requestBody": { + "description": "Setting Payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "minProperties": 1, + "properties": { + "value": { + "type": "string", + "minLength": 1, + "enum": [ + "congratulations", + "404", + "444", + "redirect", + "html" + ], + "example": "html" + }, + "meta": { + "type": "object", + "additionalProperties": false, + "properties": { + "redirect": { + "type": "string" + }, + "html": { + "type": "string" + } + }, + "example": { + "html": "

hello world

" + } + } + } + }, + "example": { + "value": "congratulations", + "meta": {} + } + } + } + }, + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "id": "default-site", + "name": "Default Site", + "description": "What to show when Nginx is hit with an unknown Host", + "value": "congratulations", + "meta": {} + } + } + }, + "schema": { + "type": "object", + "description": "Setting object", + "required": [ + "id", + "name", + "description", + "value", + "meta" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "description": "Setting ID", + "minLength": 1, + "example": "default-site" + }, + "name": { + "type": "string", + "description": "Setting Display Name", + "minLength": 1, + "example": "Default Site" + }, + "description": { + "type": "string", + "description": "Meaningful description", + "minLength": 1, + "example": "What to show when Nginx is hit with an unknown Host" + }, + "value": { + "description": "Value in almost any form", + "example": "congratulations", + "anyOf": [ + { + "type": "string", + "minLength": 1 + }, + { + "type": "integer" + }, + { + "type": "object" + }, + { + "type": "number" + }, + { + "type": "array" + } + ] + }, + "meta": { + "description": "Extra metadata", + "example": { + "redirect": "http://example.com", + "html": "

404

" + }, + "type": "object" + } + } + } + } + } + } + } + } + }, + "/tokens": { + "get": { + "operationId": "refreshToken", + "summary": "Refresh your access token", + "tags": [ + "tokens" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "description": "Refreshes an existing JWT using a valid refresh token cookie or body field.", + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "expires": "2025-02-04T20:40:46.340Z", + "token": "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.ey...xaHKYr3Kk6MvkUjcC4" + } + } + }, + "schema": { + "type": "object", + "description": "Token object", + "required": [ + "expires", + "token" + ], + "additionalProperties": false, + "properties": { + "expires": { + "description": "Token Expiry ISO Time String", + "example": "2025-02-04T20:40:46.340Z", + "type": "string" + }, + "token": { + "description": "JWT Token", + "example": "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.ey...xaHKYr3Kk6MvkUjcC4", + "type": "string" + } + } + } + } + } + } + } + }, + "post": { + "operationId": "requestToken", + "summary": "Request a new access token from credentials", + "tags": [ + "tokens" + ], + "description": "Authenticates with email and password and returns JWT access and refresh tokens.", + "requestBody": { + "description": "Credentials Payload", + "required": true, + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "identity": { + "minLength": 1, + "type": "string", + "example": "me@example.com" + }, + "scope": { + "minLength": 1, + "type": "string", + "enum": [ + "user" + ], + "example": "user" + }, + "secret": { + "minLength": 1, + "type": "string", + "example": "bigredhorsebanana" + } + }, + "required": [ + "identity", + "secret" + ], + "type": "object" + }, + "example": { + "identity": "me@example.com", + "secret": "bigredhorsebanana" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "expires": "2025-02-04T20:40:46.340Z", + "token": "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.ey...xaHKYr3Kk6MvkUjcC4" + } + } + }, + "schema": { + "oneOf": [ + { + "type": "object", + "description": "Token object", + "required": [ + "expires", + "token" + ], + "additionalProperties": false, + "properties": { + "expires": { + "description": "Token Expiry ISO Time String", + "example": "2025-02-04T20:40:46.340Z", + "type": "string" + }, + "token": { + "description": "JWT Token", + "example": "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.ey...xaHKYr3Kk6MvkUjcC4", + "type": "string" + } + } + }, + { + "type": "object", + "description": "Token object", + "required": [ + "requires_2fa", + "challenge_token" + ], + "additionalProperties": false, + "properties": { + "requires_2fa": { + "description": "Whether this token request requires two-factor authentication", + "example": true, + "type": "boolean" + }, + "challenge_token": { + "description": "Challenge Token used in subsequent 2FA verification", + "example": "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.ey...xaHKYr3Kk6MvkUjcC4", + "type": "string" + } + } + } + ] + } + } + }, + "description": "200 response" + } + } + } + }, + "/tokens/2fa": { + "post": { + "operationId": "loginWith2FA", + "summary": "Verify 2FA code and get full token", + "tags": [ + "tokens" + ], + "description": "Completes login when two-factor authentication is required for the account.", + "requestBody": { + "description": "2fa Challenge Payload", + "required": true, + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "challenge_token": { + "minLength": 1, + "type": "string", + "example": "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.ey...xaHKYr3Kk6MvkUjcC4" + }, + "code": { + "minLength": 6, + "maxLength": 8, + "type": "string", + "example": "012345" + } + }, + "required": [ + "challenge_token", + "code" + ], + "type": "object" + }, + "example": { + "challenge_token": "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.ey...xaHKYr3Kk6MvkUjcC4", + "code": "012345" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "expires": "2025-02-04T20:40:46.340Z", + "token": "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.ey...xaHKYr3Kk6MvkUjcC4" + } + } + }, + "schema": { + "type": "object", + "description": "Token object", + "required": [ + "expires", + "token" + ], + "additionalProperties": false, + "properties": { + "expires": { + "description": "Token Expiry ISO Time String", + "example": "2025-02-04T20:40:46.340Z", + "type": "string" + }, + "token": { + "description": "JWT Token", + "example": "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.ey...xaHKYr3Kk6MvkUjcC4", + "type": "string" + } + } + } + } + }, + "description": "200 response" + } + } + } + }, + "/version/check": { + "get": { + "operationId": "checkVersion", + "summary": "Returns any new version data from github", + "tags": [ + "public" + ], + "description": "Checks whether a newer upstream release is available compared to the running version.", + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "current": "v2.12.0", + "latest": "v2.13.4", + "update_available": true + } + } + }, + "schema": { + "type": "object", + "description": "Check Version object", + "additionalProperties": false, + "required": [ + "current", + "latest", + "update_available" + ], + "properties": { + "current": { + "type": [ + "string", + "null" + ], + "description": "Current version string", + "example": "v2.10.1" + }, + "latest": { + "type": [ + "string", + "null" + ], + "description": "Latest version string", + "example": "v2.13.4" + }, + "update_available": { + "type": "boolean", + "description": "Whether there's an update available", + "example": true + } + } + } + } + } + } + } + } + }, + "/users": { + "get": { + "operationId": "getUsers", + "summary": "Get all users", + "tags": [ + "users" + ], + "security": [ + { + "bearerAuth": [ + "admin" + ] + } + ], + "description": "Lists administrator accounts and role assignments.", + "parameters": [ + { + "in": "query", + "name": "expand", + "description": "Expansions", + "schema": { + "type": "string", + "enum": [ + "permissions" + ] + } + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": [ + { + "id": 1, + "created_on": "2020-01-30T09:36:08.000Z", + "modified_on": "2020-01-30T09:41:04.000Z", + "is_disabled": false, + "email": "jc@jc21.com", + "name": "Jamie Curnow", + "nickname": "James", + "avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm", + "roles": [ + "admin" + ] + } + ] + }, + "withPermissions": { + "value": [ + { + "id": 1, + "created_on": "2020-01-30T09:36:08.000Z", + "modified_on": "2020-01-30T09:41:04.000Z", + "is_disabled": false, + "email": "jc@jc21.com", + "name": "Jamie Curnow", + "nickname": "James", + "avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm", + "roles": [ + "admin" + ], + "permissions": { + "visibility": "all", + "proxy_hosts": "manage", + "redirection_hosts": "manage", + "dead_hosts": "manage", + "streams": "manage", + "access_lists": "manage", + "certificates": "manage", + "credentials": "manage" + } + } + ] + } + }, + "schema": { + "type": "array", + "description": "User list", + "items": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + } + } + } + } + } + } + }, + "post": { + "operationId": "createUser", + "summary": "Create a User", + "tags": [ + "users" + ], + "security": [ + { + "bearerAuth": [ + "admin" + ] + } + ], + "description": "Creates a new administrator user with roles and permissions.", + "requestBody": { + "description": "User Payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "nickname", + "email" + ], + "properties": { + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "auth": { + "type": "object", + "description": "Auth Credentials", + "example": { + "type": "password", + "secret": "bigredhorsebanana" + } + } + } + } + } + } + }, + "responses": { + "201": { + "description": "201 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "id": 2, + "created_on": "2020-01-30T09:41:04.000Z", + "modified_on": "2020-01-30T09:41:04.000Z", + "is_disabled": false, + "email": "jc@jc21.com", + "name": "Jamie Curnow", + "nickname": "James", + "avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm", + "roles": [ + "admin" + ], + "permissions": { + "id": 3, + "created_on": "2020-01-30T09:41:04.000Z", + "modified_on": "2020-01-30T09:41:04.000Z", + "user_id": 2, + "visibility": "user", + "proxy_hosts": "manage", + "redirection_hosts": "manage", + "dead_hosts": "manage", + "streams": "manage", + "access_lists": "manage", + "certificates": "manage", + "credentials": "manage" + } + } + } + }, + "schema": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + } + } + } + } + } + } + }, + "/users/{userID}": { + "get": { + "operationId": "getUser", + "summary": "Get a user", + "tags": [ + "users" + ], + "security": [ + { + "bearerAuth": [ + "admin" + ] + } + ], + "description": "Returns one user record by id.", + "parameters": [ + { + "in": "path", + "name": "userID", + "schema": { + "oneOf": [ + { + "type": "string", + "pattern": "^me$" + }, + { + "type": "integer", + "minimum": 1 + } + ] + }, + "required": true, + "description": "User ID or 'me' for yourself", + "example": 1 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "id": 1, + "created_on": "2020-01-30T09:36:08.000Z", + "modified_on": "2020-01-30T09:41:04.000Z", + "is_disabled": false, + "email": "jc@jc21.com", + "name": "Jamie Curnow", + "nickname": "James", + "avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm", + "roles": [ + "admin" + ] + } + } + }, + "schema": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + } + } + } + } + } + }, + "put": { + "operationId": "updateUser", + "summary": "Update a User", + "tags": [ + "users" + ], + "security": [ + { + "bearerAuth": [ + "admin" + ] + } + ], + "description": "Updates user profile fields such as name or email.", + "parameters": [ + { + "in": "path", + "name": "userID", + "schema": { + "oneOf": [ + { + "type": "string", + "pattern": "^me$" + }, + { + "type": "integer", + "minimum": 1 + } + ] + }, + "required": true, + "description": "User ID or 'me' for yourself", + "example": 2 + } + ], + "requestBody": { + "description": "User Payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "minProperties": 1, + "properties": { + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + } + } + } + } + } + }, + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "id": 2, + "created_on": "2020-01-30T09:36:08.000Z", + "modified_on": "2020-01-30T09:41:04.000Z", + "is_disabled": false, + "email": "jc@jc21.com", + "name": "Jamie Curnow", + "nickname": "James", + "avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm", + "roles": [ + "admin" + ] + } + } + }, + "schema": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "deleteUser", + "summary": "Delete a User", + "tags": [ + "users" + ], + "security": [ + { + "bearerAuth": [ + "admin" + ] + } + ], + "description": "Deletes a user account by id.", + "parameters": [ + { + "in": "path", + "name": "userID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "User ID", + "example": 2 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": true + } + }, + "schema": { + "type": "boolean" + } + } + } + } + } + } + }, + "/users/{userID}/2fa": { + "post": { + "operationId": "setupUser2fa", + "summary": "Start 2FA setup, returns QR code URL", + "tags": [ + "users" + ], + "description": "Starts TOTP enrollment and returns QR code / secret material for the user.", + "parameters": [ + { + "in": "path", + "name": "userID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "User ID", + "example": 2 + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "secret": "JZYCEBIEEJYUGPQM", + "otpauth_url": "otpauth://totp/Nginx%20Proxy%20Manager:jc%40jc21.com?secret=JZYCEBIEEJYUGPQM&period=30&digits=6&algorithm=SHA1&issuer=Nginx%20Proxy%20Manager" + } + } + }, + "schema": { + "type": "object", + "required": [ + "secret", + "otpauth_url" + ], + "additionalProperties": false, + "properties": { + "secret": { + "description": "TOTP Secret", + "example": "JZYCEBIEEJYUGPQM", + "type": "string" + }, + "otpauth_url": { + "description": "OTP Auth URL for QR Code generation", + "example": "otpauth://totp/Nginx%20Proxy%20Manager:jc%40jc21.com?secret=JZYCEBIEEJYUGPQM&period=30&digits=6&algorithm=SHA1&issuer=Nginx%20Proxy%20Manager", + "type": "string" + } + } + } + } + }, + "description": "200 response" + } + } + }, + "get": { + "operationId": "getUser2faStatus", + "summary": "Get user 2fa Status", + "tags": [ + "users" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "description": "Returns whether two-factor authentication is enabled for the user.", + "parameters": [ + { + "in": "path", + "name": "userID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "User ID", + "example": 2 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "enabled": false, + "backup_codes_remaining": 0 + } + } + }, + "schema": { + "type": "object", + "additionalProperties": false, + "required": [ + "enabled", + "backup_codes_remaining" + ], + "properties": { + "enabled": { + "type": "boolean", + "description": "Is 2FA enabled for this user", + "example": true + }, + "backup_codes_remaining": { + "type": "integer", + "description": "Number of remaining backup codes for this user", + "example": 5 + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "disableUser2fa", + "summary": "Disable 2fa for user", + "tags": [ + "users" + ], + "description": "Disables two-factor authentication for a user (requires administrative permission).", + "parameters": [ + { + "in": "path", + "name": "userID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "User ID", + "example": 2 + }, + { + "in": "query", + "name": "code", + "schema": { + "type": "string", + "minLength": 6, + "maxLength": 6, + "example": "012345" + }, + "required": true, + "description": "2fa Code", + "example": "012345" + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "examples": { + "default": { + "value": true + } + }, + "schema": { + "type": "boolean" + } + } + }, + "description": "200 response" + } + } + } + }, + "/users/{userID}/2fa/enable": { + "post": { + "operationId": "enableUser2fa", + "summary": "Verify code and enable 2FA", + "tags": [ + "users" + ], + "description": "Confirms TOTP enrollment with a verification code and enables 2FA.", + "parameters": [ + { + "in": "path", + "name": "userID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "User ID", + "example": 2 + } + ], + "requestBody": { + "description": "Verification Payload", + "required": true, + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "code": { + "minLength": 6, + "maxLength": 8, + "type": "string", + "example": "123456" + } + }, + "required": [ + "code" + ], + "type": "object" + }, + "example": { + "code": "123456" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "backup_codes": [ + "6CD7CB06", + "495302F3", + "D8037852", + "A6FFC956", + "BC1A1851", + "A05E644F", + "A406D2E8", + "0AE3C522" + ] + } + } + }, + "schema": { + "type": "object", + "required": [ + "backup_codes" + ], + "additionalProperties": false, + "properties": { + "backup_codes": { + "description": "Backup codes", + "example": [ + "6CD7CB06", + "495302F3", + "D8037852", + "A6FFC956", + "BC1A1851", + "A05E644F", + "A406D2E8", + "0AE3C522" + ], + "type": "array", + "items": { + "type": "string", + "example": "6CD7CB06" + } + } + } + } + } + }, + "description": "200 response" + } + } + } + }, + "/users/{userID}/2fa/backup-codes": { + "post": { + "operationId": "regenUser2faCodes", + "summary": "Regenerate 2FA backup codes", + "tags": [ + "users" + ], + "description": "Regenerates one-time backup codes after verifying an existing TOTP code.", + "parameters": [ + { + "in": "path", + "name": "userID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "User ID", + "example": 2 + } + ], + "requestBody": { + "description": "Verification Payload", + "required": true, + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "code": { + "minLength": 6, + "maxLength": 8, + "type": "string", + "example": "123456" + } + }, + "required": [ + "code" + ], + "type": "object" + }, + "example": { + "code": "123456" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "backup_codes": [ + "6CD7CB06", + "495302F3", + "D8037852", + "A6FFC956", + "BC1A1851", + "A05E644F", + "A406D2E8", + "0AE3C522" + ] + } + } + }, + "schema": { + "type": "object", + "required": [ + "backup_codes" + ], + "additionalProperties": false, + "properties": { + "backup_codes": { + "description": "Backup codes", + "example": [ + "6CD7CB06", + "495302F3", + "D8037852", + "A6FFC956", + "BC1A1851", + "A05E644F", + "A406D2E8", + "0AE3C522" + ], + "type": "array", + "items": { + "type": "string", + "example": "6CD7CB06" + } + } + } + } + } + }, + "description": "200 response" + } + } + } + }, + "/users/{userID}/auth": { + "put": { + "operationId": "updateUserAuth", + "summary": "Update a User's Authentication", + "tags": [ + "users" + ], + "security": [ + { + "bearerAuth": [ + "admin" + ] + } + ], + "description": "Updates password or authentication-related fields for a user.", + "parameters": [ + { + "in": "path", + "name": "userID", + "schema": { + "oneOf": [ + { + "type": "string", + "pattern": "^me$" + }, + { + "type": "integer", + "minimum": 1 + } + ] + }, + "required": true, + "description": "User ID or 'me' for yourself", + "example": 2 + } + ], + "requestBody": { + "description": "Auth Payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "type", + "secret" + ], + "properties": { + "type": { + "type": "string", + "pattern": "^password$", + "example": "password" + }, + "current": { + "type": "string", + "minLength": 1, + "maxLength": 64, + "example": "changeme" + }, + "secret": { + "type": "string", + "minLength": 8, + "maxLength": 64, + "example": "mySuperN3wP@ssword!" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": true + } + }, + "schema": { + "type": "boolean" + } + } + } + } + } + } + }, + "/users/{userID}/permissions": { + "put": { + "operationId": "updateUserPermissions", + "summary": "Update a User's Permissions", + "tags": [ + "users" + ], + "security": [ + { + "bearerAuth": [ + "admin" + ] + } + ], + "description": "Updates fine-grained permissions and roles assigned to a user.", + "parameters": [ + { + "in": "path", + "name": "userID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "User ID", + "example": 2 + } + ], + "requestBody": { + "description": "Permissions Payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "minProperties": 1, + "properties": { + "visibility": { + "type": "string", + "description": "Visibility Type", + "enum": [ + "all", + "user" + ], + "example": "all" + }, + "access_lists": { + "type": "string", + "description": "Access Lists Permissions", + "enum": [ + "hidden", + "view", + "manage" + ], + "example": "view" + }, + "dead_hosts": { + "type": "string", + "description": "404 Hosts Permissions", + "enum": [ + "hidden", + "view", + "manage" + ], + "example": "manage" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts Permissions", + "enum": [ + "hidden", + "view", + "manage" + ], + "example": "hidden" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Permissions", + "enum": [ + "hidden", + "view", + "manage" + ], + "example": "view" + }, + "streams": { + "type": "string", + "description": "Streams Permissions", + "enum": [ + "hidden", + "view", + "manage" + ], + "example": "manage" + }, + "certificates": { + "type": "string", + "description": "Certificates Permissions", + "enum": [ + "hidden", + "view", + "manage" + ], + "example": "hidden" + }, + "credentials": { + "type": "string", + "description": "Stored DNS Credentials Permissions", + "enum": [ + "hidden", + "view", + "manage" + ], + "example": "manage" + } + } + }, + "example": { + "visibility": "all", + "access_lists": "view", + "certificates": "hidden", + "dead_hosts": "hidden", + "proxy_hosts": "manage", + "redirection_hosts": "hidden", + "streams": "hidden" + } + } + } + }, + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": true + } + }, + "schema": { + "type": "boolean" + } + } + } + } + } + } + }, + "/users/{userID}/login": { + "post": { + "operationId": "loginAsUser", + "summary": "Login as this user", + "tags": [ + "users" + ], + "security": [ + { + "bearerAuth": [ + "admin" + ] + } + ], + "description": "Issues a session token for the target user (administrative impersonation).", + "parameters": [ + { + "in": "path", + "name": "userID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "User ID", + "example": 2 + } + ], + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": { + "token": "eyJhbGciOiJSUzI1NiIsInR...16OjT8B3NLyXg", + "expires": "2020-01-31T10:56:23.239Z", + "user": { + "id": 1, + "created_on": "2020-01-30T10:43:44.000Z", + "modified_on": "2020-01-30T10:43:44.000Z", + "is_disabled": false, + "email": "user2@example.com", + "name": "John Doe", + "nickname": "Jonny", + "avatar": "//www.gravatar.com/avatar/3c8d73f45fd8763f827b964c76e6032a?default=mm", + "roles": [] + } + } + } + }, + "schema": { + "type": "object", + "description": "Login object", + "required": [ + "expires", + "token", + "user" + ], + "additionalProperties": false, + "properties": { + "token": { + "description": "JWT Token", + "type": "string", + "example": "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.ey...xaHKYr3Kk6MvkUjcC4" + }, + "expires": { + "description": "Token Expiry Timestamp", + "type": "string", + "example": "2020-01-30T10:43:44.000Z" + }, + "user": { + "type": "object", + "description": "User object", + "required": [ + "id", + "created_on", + "modified_on", + "is_disabled", + "email", + "name", + "nickname", + "avatar", + "roles" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "description": "User ID", + "minimum": 1, + "example": 1 + }, + "created_on": { + "type": "string", + "description": "Created Date", + "example": "2020-01-30T09:36:08.000Z" + }, + "modified_on": { + "type": "string", + "description": "Modified Date", + "example": "2020-01-30T09:41:04.000Z" + }, + "is_disabled": { + "type": "boolean", + "description": "Is user Disabled", + "example": true + }, + "email": { + "type": "string", + "description": "Email", + "minLength": 3, + "example": "jc@jc21.com" + }, + "name": { + "type": "string", + "description": "Name", + "minLength": 1, + "example": "Jamie Curnow" + }, + "nickname": { + "type": "string", + "description": "Nickname", + "example": "James" + }, + "avatar": { + "type": "string", + "description": "Gravatar URL based on email, without scheme", + "example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm" + }, + "roles": { + "description": "Roles applied", + "example": [ + "admin" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "type": "object", + "description": "Permissions if expanded in request", + "required": [ + "visibility", + "proxy_hosts", + "redirection_hosts", + "dead_hosts", + "streams", + "access_lists", + "certificates", + "credentials" + ], + "properties": { + "visibility": { + "type": "string", + "description": "Visibility level", + "example": "all", + "pattern": "^(all|user)$" + }, + "proxy_hosts": { + "type": "string", + "description": "Proxy Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "redirection_hosts": { + "type": "string", + "description": "Redirection Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "dead_hosts": { + "type": "string", + "description": "Dead Hosts access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "streams": { + "type": "string", + "description": "Streams access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + }, + "access_lists": { + "type": "string", + "description": "Access Lists access level", + "example": "hidden", + "pattern": "^(manage|view|hidden)$" + }, + "certificates": { + "type": "string", + "description": "Certificates access level", + "example": "view", + "pattern": "^(manage|view|hidden)$" + }, + "credentials": { + "type": "string", + "description": "Stored DNS credentials access level", + "example": "manage", + "pattern": "^(manage|view|hidden)$" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/credentials": { + "get": { + "operationId": "listCredentials", + "summary": "List stored DNS credentials", + "tags": [ + "credentials" + ], + "security": [ + { + "bearerAuth": [ + "credentials.view" + ] + } + ], + "description": "Lists DNS credentials stored in the encrypted NPM vault on the data volume.", + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "description": "Stored DNS credential list", + "items": { + "type": "object", + "description": "Credential metadata (secret stored on persistent volume)", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "name", + "dns_provider" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "Cloudflare Production" + }, + "dns_provider": { + "type": "string", + "minLength": 1, + "example": "cloudflare" + }, + "last_used_at": { + "type": [ + "string", + "null" + ], + "example": "2026-06-03T12:00:00.000Z" + } + } + } + } + } + } + } + } + }, + "post": { + "operationId": "createCredential", + "summary": "Create a stored DNS credential", + "tags": [ + "credentials" + ], + "security": [ + { + "bearerAuth": [ + "credentials.manage" + ] + } + ], + "description": "Creates a named DNS credential (certbot provider INI) in the internal vault for certificate issuance.", + "requestBody": { + "description": "DNS credential payload", + "required": true, + "content": { + "application/json": { + "example": { + "name": "Cypress test credential", + "dns_provider": "acmedns", + "credentials": "dns_acmedns_api_url = http://127.0.0.1:80/" + }, + "schema": { + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "dns_provider", + "credentials" + ], + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "Cypress test credential" + }, + "dns_provider": { + "type": "string", + "minLength": 1, + "example": "acmedns" + }, + "credentials": { + "type": "string", + "minLength": 1, + "description": "Certbot DNS plugin credentials file content (INI format)", + "example": "dns_acmedns_api_url = http://127.0.0.1:80/" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "type": "object", + "description": "Credential metadata (secret stored on persistent volume)", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "name", + "dns_provider" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "Cloudflare Production" + }, + "dns_provider": { + "type": "string", + "minLength": 1, + "example": "cloudflare" + }, + "last_used_at": { + "type": [ + "string", + "null" + ], + "example": "2026-06-03T12:00:00.000Z" + } + } + } + } + } + } + } + } + }, + "/credentials/migrate-legacy": { + "post": { + "operationId": "migrateLegacyCredentials", + "summary": "Migrate plaintext DNS credentials from certificates into the vault", + "tags": [ + "credentials" + ], + "security": [ + { + "bearerAuth": [ + "credentials.manage" + ] + } + ], + "description": "Moves inline DNS provider credentials from certificates into the vault. Supports dry-run preview before apply.", + "requestBody": { + "description": "Migration options", + "content": { + "application/json": { + "example": { + "dry_run": true + }, + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "dry_run": { + "type": "boolean", + "example": true + } + } + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "example": { + "dry_run": true, + "count": 0, + "results": [] + }, + "schema": { + "type": "object", + "required": [ + "dry_run", + "count", + "results" + ], + "properties": { + "dry_run": { + "type": "boolean", + "example": true + }, + "count": { + "type": "integer", + "example": 0 + }, + "results": { + "type": "array", + "example": [], + "items": { + "type": "object", + "required": [ + "certificate_id", + "status" + ], + "properties": { + "certificate_id": { + "type": "integer", + "minimum": 1 + }, + "domain_names": { + "type": "array", + "items": { + "type": "string" + } + }, + "dns_provider": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "skipped", + "migrated", + "would_migrate" + ] + }, + "credential_id": { + "type": "integer", + "minimum": 1 + } + } + } + } + } + } + } + } + } + } + } + }, + "/credentials/{credentialID}": { + "get": { + "operationId": "getCredential", + "summary": "Get a stored DNS credential", + "tags": [ + "credentials" + ], + "security": [ + { + "bearerAuth": [ + "credentials.view" + ] + } + ], + "description": "Returns metadata for one stored DNS credential. Secret payload is not exposed.", + "parameters": [ + { + "in": "path", + "name": "credentialID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "Credential ID", + "example": 1 + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "description": "Credential metadata (secret stored on persistent volume)", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "name", + "dns_provider" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "Cloudflare Production" + }, + "dns_provider": { + "type": "string", + "minLength": 1, + "example": "cloudflare" + }, + "last_used_at": { + "type": [ + "string", + "null" + ], + "example": "2026-06-03T12:00:00.000Z" + } + } + } + } + } + } + } + }, + "put": { + "operationId": "updateCredential", + "summary": "Update a stored DNS credential", + "tags": [ + "credentials" + ], + "security": [ + { + "bearerAuth": [ + "credentials.manage" + ] + } + ], + "description": "Updates a stored DNS credential name or encrypted provider configuration.", + "parameters": [ + { + "in": "path", + "name": "credentialID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "Credential ID", + "example": 1 + } + ], + "requestBody": { + "description": "Credential update payload", + "required": true, + "content": { + "application/json": { + "example": { + "name": "Updated credential name" + }, + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "Updated credential name" + }, + "dns_provider": { + "type": "string", + "minLength": 1, + "example": "acmedns" + }, + "credentials": { + "type": "string", + "minLength": 1, + "example": "dns_acmedns_api_url = http://127.0.0.1:80/" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "description": "Credential metadata (secret stored on persistent volume)", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "name", + "dns_provider" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "Cloudflare Production" + }, + "dns_provider": { + "type": "string", + "minLength": 1, + "example": "cloudflare" + }, + "last_used_at": { + "type": [ + "string", + "null" + ], + "example": "2026-06-03T12:00:00.000Z" + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "deleteCredential", + "summary": "Delete a stored DNS credential", + "tags": [ + "credentials" + ], + "security": [ + { + "bearerAuth": [ + "credentials.manage" + ] + } + ], + "description": "Deletes a stored DNS credential from the vault.", + "parameters": [ + { + "in": "path", + "name": "credentialID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "Credential ID", + "example": 1 + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "boolean" + } + } + } + } + } + } + }, + "/credentials/{credentialID}/test": { + "post": { + "operationId": "testCredential", + "summary": "Verify a stored credential can be read from the vault", + "tags": [ + "credentials" + ], + "security": [ + { + "bearerAuth": [ + "credentials.view" + ] + } + ], + "description": "Validates that a stored credential can be decrypted and parsed for the configured DNS provider.", + "parameters": [ + { + "in": "path", + "name": "credentialID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "Credential ID", + "example": 1 + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "example": { + "ok": true, + "dns_provider": "acmedns", + "plugin_name": "ACME DNS" + }, + "schema": { + "type": "object", + "properties": { + "ok": { + "type": "boolean", + "example": true + }, + "dns_provider": { + "type": "string", + "example": "acmedns" + }, + "plugin_name": { + "type": "string", + "example": "ACME DNS" + } + } + } + } + } + } + } + } + }, + "/credential-providers": { + "get": { + "operationId": "listCredentialProviders", + "summary": "List credential providers", + "tags": [ + "credential-providers" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "description": "Lists external credential store providers (Vault, AWS, Azure, Infisical, HTTP). Client secrets are not included in responses.", + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "example": [], + "schema": { + "type": "array", + "description": "Credential provider list", + "items": { + "type": "object", + "description": "External credential store provider configuration", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "name", + "type", + "meta", + "has_oidc_secret" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "Cypress vault stub" + }, + "type": { + "type": "string", + "enum": [ + "vault", + "aws", + "azure", + "infisical", + "http" + ], + "example": "vault" + }, + "oidc_issuer": { + "type": [ + "string", + "null" + ], + "example": "https://issuer.example/oauth2" + }, + "oidc_client_id": { + "type": [ + "string", + "null" + ], + "example": "npm-test" + }, + "oidc_audience": { + "type": [ + "string", + "null" + ], + "example": null + }, + "oidc_scope": { + "type": [ + "string", + "null" + ], + "example": null + }, + "meta": { + "type": "object", + "description": "Provider-specific configuration", + "example": { + "address": "http://127.0.0.1:65535", + "mount": "secret", + "role": "npm" + } + }, + "has_oidc_secret": { + "type": "boolean", + "description": "Whether an OIDC client secret is stored for this provider", + "example": true + } + } + } + } + } + } + } + } + }, + "post": { + "operationId": "createCredentialProvider", + "summary": "Create credential provider", + "tags": [ + "credential-providers" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "description": "Registers an external credential store provider. OIDC or Universal Auth credentials are stored encrypted under the data volume.", + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "example": { + "id": 1, + "created_on": "2026-06-05T06:20:47.000Z", + "modified_on": "2026-06-05T06:20:47.000Z", + "owner_user_id": 1, + "name": "Cypress vault stub", + "type": "vault", + "oidc_issuer": "https://issuer.example/oauth2", + "oidc_client_id": "npm-test", + "oidc_audience": null, + "oidc_scope": null, + "meta": { + "address": "http://127.0.0.1:65535", + "mount": "secret", + "role": "npm" + }, + "has_oidc_secret": true + }, + "schema": { + "type": "object", + "description": "External credential store provider configuration", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "name", + "type", + "meta", + "has_oidc_secret" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "Cypress vault stub" + }, + "type": { + "type": "string", + "enum": [ + "vault", + "aws", + "azure", + "infisical", + "http" + ], + "example": "vault" + }, + "oidc_issuer": { + "type": [ + "string", + "null" + ], + "example": "https://issuer.example/oauth2" + }, + "oidc_client_id": { + "type": [ + "string", + "null" + ], + "example": "npm-test" + }, + "oidc_audience": { + "type": [ + "string", + "null" + ], + "example": null + }, + "oidc_scope": { + "type": [ + "string", + "null" + ], + "example": null + }, + "meta": { + "type": "object", + "description": "Provider-specific configuration", + "example": { + "address": "http://127.0.0.1:65535", + "mount": "secret", + "role": "npm" + } + }, + "has_oidc_secret": { + "type": "boolean", + "description": "Whether an OIDC client secret is stored for this provider", + "example": true + } + } + } + } + } + } + } + } + }, + "/credential-providers/{providerID}": { + "get": { + "operationId": "getCredentialProvider", + "summary": "Get credential provider", + "tags": [ + "credential-providers" + ], + "description": "Returns one credential provider configuration by id without secret material.", + "parameters": [ + { + "in": "path", + "name": "providerID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "Credential provider ID", + "example": 1 + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "example": { + "id": 1, + "created_on": "2026-06-05T06:20:47.000Z", + "modified_on": "2026-06-05T06:20:47.000Z", + "owner_user_id": 1, + "name": "Cypress vault stub", + "type": "vault", + "oidc_issuer": "https://issuer.example/oauth2", + "oidc_client_id": "npm-test", + "oidc_audience": null, + "oidc_scope": null, + "meta": {}, + "has_oidc_secret": true + }, + "schema": { + "type": "object", + "description": "External credential store provider configuration", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "name", + "type", + "meta", + "has_oidc_secret" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "Cypress vault stub" + }, + "type": { + "type": "string", + "enum": [ + "vault", + "aws", + "azure", + "infisical", + "http" + ], + "example": "vault" + }, + "oidc_issuer": { + "type": [ + "string", + "null" + ], + "example": "https://issuer.example/oauth2" + }, + "oidc_client_id": { + "type": [ + "string", + "null" + ], + "example": "npm-test" + }, + "oidc_audience": { + "type": [ + "string", + "null" + ], + "example": null + }, + "oidc_scope": { + "type": [ + "string", + "null" + ], + "example": null + }, + "meta": { + "type": "object", + "description": "Provider-specific configuration", + "example": { + "address": "http://127.0.0.1:65535", + "mount": "secret", + "role": "npm" + } + }, + "has_oidc_secret": { + "type": "boolean", + "description": "Whether an OIDC client secret is stored for this provider", + "example": true + } + } + } + } + } + } + } + }, + "put": { + "operationId": "updateCredentialProvider", + "summary": "Update credential provider", + "tags": [ + "credential-providers" + ], + "description": "Updates provider settings. Omit secret fields to keep existing encrypted values.", + "parameters": [ + { + "in": "path", + "name": "providerID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "Credential provider ID", + "example": 1 + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "delete": { + "operationId": "deleteCredentialProvider", + "summary": "Delete credential provider", + "tags": [ + "credential-providers" + ], + "description": "Soft-deletes a credential provider. Existing certificate references may fail resolution until updated.", + "parameters": [ + { + "in": "path", + "name": "providerID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "Credential provider ID", + "example": 1 + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/credential-providers/{providerID}/test": { + "post": { + "operationId": "testCredentialProvider", + "summary": "Test provider authentication", + "tags": [ + "credential-providers" + ], + "description": "Verifies that the provider can obtain an access token (OIDC client credentials or Infisical Universal Auth).", + "parameters": [ + { + "in": "path", + "name": "providerID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "Credential provider ID", + "example": 1 + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "example": { + "ok": true, + "type": "vault", + "name": "Cypress vault stub" + }, + "schema": { + "type": "object", + "description": "Credential provider connectivity test result", + "required": [ + "ok" + ], + "additionalProperties": false, + "properties": { + "ok": { + "type": "boolean", + "example": true + }, + "type": { + "type": "string", + "example": "vault" + }, + "name": { + "type": "string", + "example": "Cypress vault stub" + } + } + } + } + } + } + } + } + }, + "/credential-providers/{providerID}/test-resolve": { + "post": { + "operationId": "testCredentialProviderResolve", + "summary": "Test secret resolution", + "tags": [ + "credential-providers" + ], + "description": "Tests resolving a secret path through the provider without returning secret contents (response includes byte length only).", + "parameters": [ + { + "in": "path", + "name": "providerID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "Credential provider ID", + "example": 1 + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api-keys": { + "get": { + "operationId": "listApiKeys", + "summary": "List API keys", + "tags": [ + "api-keys" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "description": "Lists automation API keys. Secrets are never returned; each entry indicates whether a key is still configured.", + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "example": [], + "schema": { + "type": "array", + "description": "API key list", + "items": { + "type": "object", + "description": "Automation API key metadata (secret hash is never returned)", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "name", + "permissions" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "Cypress automation key" + }, + "permissions": { + "type": "object", + "description": "Scoped permissions granted to this API key", + "additionalProperties": { + "type": "string" + }, + "example": { + "proxy_hosts": "manage", + "certificates": "manage", + "credentials": "manage" + } + }, + "expires_on": { + "type": [ + "string", + "null" + ], + "example": null + }, + "last_used_at": { + "type": [ + "string", + "null" + ], + "example": null + }, + "is_revoked": { + "type": "integer", + "enum": [ + 0, + 1 + ], + "example": 0 + }, + "key": { + "type": "string", + "description": "Raw API key; returned only on create", + "pattern": "^npmak_", + "example": "npmak_a1b2c3d4_base64urlsecret" + } + } + } + } + } + } + } + } + }, + "post": { + "operationId": "createApiKey", + "summary": "Create an API key", + "tags": [ + "api-keys" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "description": "Creates a long-lived API key for automation. The raw key is returned once in the response and cannot be retrieved again.", + "requestBody": { + "description": "API key configuration", + "required": true, + "content": { + "application/json": { + "example": { + "name": "Cypress automation key", + "permissions": { + "proxy_hosts": "manage" + } + }, + "schema": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string", + "example": "Cypress automation key" + }, + "permissions": { + "type": "object", + "example": { + "proxy_hosts": "manage" + } + }, + "expires_on": { + "type": [ + "string", + "null" + ], + "example": null + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "example": { + "id": 1, + "created_on": "2026-06-05T06:20:47.000Z", + "modified_on": "2026-06-05T06:20:47.000Z", + "owner_user_id": 1, + "name": "Cypress automation key", + "permissions": { + "proxy_hosts": "manage" + }, + "expires_on": null, + "last_used_at": null, + "is_revoked": 0, + "key": "npmak_a1b2c3d4_base64urlsecret" + }, + "schema": { + "type": "object", + "description": "Automation API key metadata (secret hash is never returned)", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "name", + "permissions" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "Cypress automation key" + }, + "permissions": { + "type": "object", + "description": "Scoped permissions granted to this API key", + "additionalProperties": { + "type": "string" + }, + "example": { + "proxy_hosts": "manage", + "certificates": "manage", + "credentials": "manage" + } + }, + "expires_on": { + "type": [ + "string", + "null" + ], + "example": null + }, + "last_used_at": { + "type": [ + "string", + "null" + ], + "example": null + }, + "is_revoked": { + "type": "integer", + "enum": [ + 0, + 1 + ], + "example": 0 + }, + "key": { + "type": "string", + "description": "Raw API key; returned only on create", + "pattern": "^npmak_", + "example": "npmak_a1b2c3d4_base64urlsecret" + } + } + } + } + } + } + } + } + }, + "/api-keys/{apiKeyID}": { + "delete": { + "operationId": "deleteApiKey", + "summary": "Revoke an API key", + "tags": [ + "api-keys" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "description": "Revokes an API key by id. Revoked keys fail authentication immediately.", + "parameters": [ + { + "in": "path", + "name": "apiKeyID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "API key ID", + "example": 1 + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/jobs": { + "get": { + "operationId": "listJobs", + "summary": "List recent async jobs", + "tags": [ + "jobs" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "description": "Lists recent asynchronous automation jobs (certificate issuance, migrations, etc.).", + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "example": [], + "schema": { + "type": "array", + "description": "Background job list", + "items": { + "type": "object", + "description": "Asynchronous background job", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "type", + "status", + "payload" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "type": { + "type": "string", + "minLength": 1, + "maxLength": 64, + "example": "certificate.create" + }, + "status": { + "type": "string", + "enum": [ + "pending", + "running", + "completed", + "failed" + ], + "example": "pending" + }, + "payload": { + "type": "object", + "description": "Job input payload", + "example": {} + }, + "result": { + "type": [ + "object", + "null" + ], + "description": "Job result when completed", + "example": null + }, + "error": { + "type": [ + "string", + "null" + ], + "description": "Error message when failed", + "example": null + }, + "finished_on": { + "type": [ + "string", + "null" + ], + "description": "Completion timestamp", + "example": null + } + } + } + } + } + } + } + } + } + }, + "/jobs/{jobID}": { + "get": { + "operationId": "getJob", + "summary": "Get async job status", + "tags": [ + "jobs" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "description": "Returns status and result metadata for one background job by id.", + "parameters": [ + { + "in": "path", + "name": "jobID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "Job ID", + "example": 1 + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "example": { + "id": 1, + "created_on": "2026-06-05T06:20:47.000Z", + "modified_on": "2026-06-05T06:20:47.000Z", + "owner_user_id": 1, + "type": "certificate.create", + "status": "pending", + "payload": {}, + "result": null, + "error": null, + "finished_on": null + }, + "schema": { + "type": "object", + "description": "Asynchronous background job", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "type", + "status", + "payload" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "type": { + "type": "string", + "minLength": 1, + "maxLength": 64, + "example": "certificate.create" + }, + "status": { + "type": "string", + "enum": [ + "pending", + "running", + "completed", + "failed" + ], + "example": "pending" + }, + "payload": { + "type": "object", + "description": "Job input payload", + "example": {} + }, + "result": { + "type": [ + "object", + "null" + ], + "description": "Job result when completed", + "example": null + }, + "error": { + "type": [ + "string", + "null" + ], + "description": "Error message when failed", + "example": null + }, + "finished_on": { + "type": [ + "string", + "null" + ], + "description": "Completion timestamp", + "example": null + } + } + } + } + } + } + } + } + }, + "/webhooks": { + "get": { + "operationId": "listWebhooks", + "summary": "List webhook endpoints", + "tags": [ + "webhooks" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "description": "Lists outbound webhook endpoints configured for automation events.", + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "example": [], + "schema": { + "type": "array", + "description": "Webhook endpoint list", + "items": { + "type": "object", + "description": "Outbound webhook endpoint configuration", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "name", + "url", + "events", + "is_enabled" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "Cypress webhook" + }, + "url": { + "type": "string", + "minLength": 1, + "maxLength": 2048, + "example": "http://127.0.0.1:65535/npm-webhook-test" + }, + "events": { + "type": "array", + "minItems": 1, + "items": { + "type": "string" + }, + "example": [ + "certificate.created" + ] + }, + "is_enabled": { + "description": "Whether the endpoint receives events", + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "integer", + "enum": [ + 0, + 1 + ] + } + ], + "example": 1 + }, + "secret": { + "type": "string", + "description": "HMAC signing secret; returned only on create when generated by the server", + "minLength": 1, + "example": "ff387bfac72d5913371afd9d8c651e61369f2ba886b2d72a9402f441913aa279" + } + } + } + } + } + } + } + } + }, + "post": { + "operationId": "createWebhook", + "summary": "Create a webhook endpoint", + "tags": [ + "webhooks" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "description": "Creates a webhook endpoint with optional HMAC signing secret.", + "requestBody": { + "description": "Webhook endpoint configuration", + "required": true, + "content": { + "application/json": { + "example": { + "name": "Cypress webhook", + "url": "http://127.0.0.1:65535/npm-webhook-test", + "events": [ + "certificate.created" + ] + }, + "schema": { + "type": "object", + "required": [ + "name", + "url", + "events" + ], + "properties": { + "name": { + "type": "string", + "example": "Cypress webhook" + }, + "url": { + "type": "string", + "example": "http://127.0.0.1:65535/npm-webhook-test" + }, + "events": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "certificate.created" + ] + }, + "secret": { + "type": "string", + "example": "custom-signing-secret" + }, + "is_enabled": { + "type": "boolean", + "example": true + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "example": { + "id": 1, + "created_on": "2026-06-05T06:20:47.000Z", + "modified_on": "2026-06-05T06:20:47.000Z", + "owner_user_id": 1, + "name": "Cypress webhook", + "url": "http://127.0.0.1:65535/npm-webhook-test", + "events": [ + "certificate.created" + ], + "is_enabled": 1, + "secret": "ff387bfac72d5913371afd9d8c651e61369f2ba886b2d72a9402f441913aa279" + }, + "schema": { + "type": "object", + "description": "Outbound webhook endpoint configuration", + "required": [ + "id", + "created_on", + "modified_on", + "owner_user_id", + "name", + "url", + "events", + "is_enabled" + ], + "additionalProperties": false, + "properties": { + "id": { + "description": "Unique identifier", + "readOnly": true, + "type": "integer", + "minimum": 1, + "example": 11 + }, + "created_on": { + "description": "Date and time of creation", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "modified_on": { + "description": "Date and time of last update", + "readOnly": true, + "type": "string", + "example": "2025-10-28T04:17:54.000Z" + }, + "owner_user_id": { + "description": "User ID", + "type": "integer", + "minimum": 1, + "example": 2 + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "Cypress webhook" + }, + "url": { + "type": "string", + "minLength": 1, + "maxLength": 2048, + "example": "http://127.0.0.1:65535/npm-webhook-test" + }, + "events": { + "type": "array", + "minItems": 1, + "items": { + "type": "string" + }, + "example": [ + "certificate.created" + ] + }, + "is_enabled": { + "description": "Whether the endpoint receives events", + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "integer", + "enum": [ + 0, + 1 + ] + } + ], + "example": 1 + }, + "secret": { + "type": "string", + "description": "HMAC signing secret; returned only on create when generated by the server", + "minLength": 1, + "example": "ff387bfac72d5913371afd9d8c651e61369f2ba886b2d72a9402f441913aa279" + } + } + } + } + } + } + } + } + }, + "/webhooks/{webhookID}": { + "delete": { + "operationId": "deleteWebhook", + "summary": "Delete a webhook endpoint", + "tags": [ + "webhooks" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "description": "Deletes a webhook configuration by id.", + "parameters": [ + { + "in": "path", + "name": "webhookID", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "description": "Webhook endpoint ID", + "example": 1 + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + } + } +} diff --git a/docs/yarn.lock b/docs/yarn.lock deleted file mode 100644 index c756948271..0000000000 --- a/docs/yarn.lock +++ /dev/null @@ -1,1213 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@algolia/abtesting@1.12.2": - version "1.12.2" - resolved "https://registry.yarnpkg.com/@algolia/abtesting/-/abtesting-1.12.2.tgz#1cba5e3c654d02c6d435822a0a0070a5c435daa6" - integrity sha512-oWknd6wpfNrmRcH0vzed3UPX0i17o4kYLM5OMITyMVM2xLgaRbIafoxL0e8mcrNNb0iORCJA0evnNDKRYth5WQ== - dependencies: - "@algolia/client-common" "5.46.2" - "@algolia/requester-browser-xhr" "5.46.2" - "@algolia/requester-fetch" "5.46.2" - "@algolia/requester-node-http" "5.46.2" - -"@algolia/autocomplete-core@1.17.7": - version "1.17.7" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.17.7.tgz#2c410baa94a47c5c5f56ed712bb4a00ebe24088b" - integrity sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q== - dependencies: - "@algolia/autocomplete-plugin-algolia-insights" "1.17.7" - "@algolia/autocomplete-shared" "1.17.7" - -"@algolia/autocomplete-plugin-algolia-insights@1.17.7": - version "1.17.7" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.17.7.tgz#7d2b105f84e7dd8f0370aa4c4ab3b704e6760d82" - integrity sha512-Jca5Ude6yUOuyzjnz57og7Et3aXjbwCSDf/8onLHSQgw1qW3ALl9mrMWaXb5FmPVkV3EtkD2F/+NkT6VHyPu9A== - dependencies: - "@algolia/autocomplete-shared" "1.17.7" - -"@algolia/autocomplete-preset-algolia@1.17.7": - version "1.17.7" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.17.7.tgz#c9badc0d73d62db5bf565d839d94ec0034680ae9" - integrity sha512-ggOQ950+nwbWROq2MOCIL71RE0DdQZsceqrg32UqnhDz8FlO9rL8ONHNsI2R1MH0tkgVIDKI/D0sMiUchsFdWA== - dependencies: - "@algolia/autocomplete-shared" "1.17.7" - -"@algolia/autocomplete-shared@1.17.7": - version "1.17.7" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.17.7.tgz#105e84ad9d1a31d3fb86ba20dc890eefe1a313a0" - integrity sha512-o/1Vurr42U/qskRSuhBH+VKxMvkkUVTLU6WZQr+L5lGZZLYWyhdzWjW0iGXY7EkwRTjBqvN2EsR81yCTGV/kmg== - -"@algolia/client-abtesting@5.46.2": - version "5.46.2" - resolved "https://registry.yarnpkg.com/@algolia/client-abtesting/-/client-abtesting-5.46.2.tgz#264a72f0e9d2fe0d0dc5c3d2d16bbb9cfe2ce9e8" - integrity sha512-oRSUHbylGIuxrlzdPA8FPJuwrLLRavOhAmFGgdAvMcX47XsyM+IOGa9tc7/K5SPvBqn4nhppOCEz7BrzOPWc4A== - dependencies: - "@algolia/client-common" "5.46.2" - "@algolia/requester-browser-xhr" "5.46.2" - "@algolia/requester-fetch" "5.46.2" - "@algolia/requester-node-http" "5.46.2" - -"@algolia/client-analytics@5.46.2": - version "5.46.2" - resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-5.46.2.tgz#3f00a237508aa0c46c9c02dea9c855e0a78e241f" - integrity sha512-EPBN2Oruw0maWOF4OgGPfioTvd+gmiNwx0HmD9IgmlS+l75DatcBkKOPNJN+0z3wBQWUO5oq602ATxIfmTQ8bA== - dependencies: - "@algolia/client-common" "5.46.2" - "@algolia/requester-browser-xhr" "5.46.2" - "@algolia/requester-fetch" "5.46.2" - "@algolia/requester-node-http" "5.46.2" - -"@algolia/client-common@5.46.2": - version "5.46.2" - resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-5.46.2.tgz#7f282fd8f721b0d96958445df2170f4c7dce6aac" - integrity sha512-Hj8gswSJNKZ0oyd0wWissqyasm+wTz1oIsv5ZmLarzOZAp3vFEda8bpDQ8PUhO+DfkbiLyVnAxsPe4cGzWtqkg== - -"@algolia/client-insights@5.46.2": - version "5.46.2" - resolved "https://registry.yarnpkg.com/@algolia/client-insights/-/client-insights-5.46.2.tgz#194b7b529ee8a4ffd5d70037745082996c3b9aa0" - integrity sha512-6dBZko2jt8FmQcHCbmNLB0kCV079Mx/DJcySTL3wirgDBUH7xhY1pOuUTLMiGkqM5D8moVZTvTdRKZUJRkrwBA== - dependencies: - "@algolia/client-common" "5.46.2" - "@algolia/requester-browser-xhr" "5.46.2" - "@algolia/requester-fetch" "5.46.2" - "@algolia/requester-node-http" "5.46.2" - -"@algolia/client-personalization@5.46.2": - version "5.46.2" - resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-5.46.2.tgz#d604da7f0a3df1b3e2a9fe338d368e48fb781f8e" - integrity sha512-1waE2Uqh/PHNeDXGn/PM/WrmYOBiUGSVxAWqiJIj73jqPqvfzZgzdakHscIVaDl6Cp+j5dwjsZ5LCgaUr6DtmA== - dependencies: - "@algolia/client-common" "5.46.2" - "@algolia/requester-browser-xhr" "5.46.2" - "@algolia/requester-fetch" "5.46.2" - "@algolia/requester-node-http" "5.46.2" - -"@algolia/client-query-suggestions@5.46.2": - version "5.46.2" - resolved "https://registry.yarnpkg.com/@algolia/client-query-suggestions/-/client-query-suggestions-5.46.2.tgz#f13bc5897bfbdc19509d430a26e9bbe2402e00c9" - integrity sha512-EgOzTZkyDcNL6DV0V/24+oBJ+hKo0wNgyrOX/mePBM9bc9huHxIY2352sXmoZ648JXXY2x//V1kropF/Spx83w== - dependencies: - "@algolia/client-common" "5.46.2" - "@algolia/requester-browser-xhr" "5.46.2" - "@algolia/requester-fetch" "5.46.2" - "@algolia/requester-node-http" "5.46.2" - -"@algolia/client-search@5.46.2": - version "5.46.2" - resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-5.46.2.tgz#771367916aaa3fb7a19d5944f8375504b0568ba6" - integrity sha512-ZsOJqu4HOG5BlvIFnMU0YKjQ9ZI6r3C31dg2jk5kMWPSdhJpYL9xa5hEe7aieE+707dXeMI4ej3diy6mXdZpgA== - dependencies: - "@algolia/client-common" "5.46.2" - "@algolia/requester-browser-xhr" "5.46.2" - "@algolia/requester-fetch" "5.46.2" - "@algolia/requester-node-http" "5.46.2" - -"@algolia/ingestion@1.46.2": - version "1.46.2" - resolved "https://registry.yarnpkg.com/@algolia/ingestion/-/ingestion-1.46.2.tgz#2a5d8a592d9f864dfb438722506382af56f8554f" - integrity sha512-1Uw2OslTWiOFDtt83y0bGiErJYy5MizadV0nHnOoHFWMoDqWW0kQoMFI65pXqRSkVvit5zjXSLik2xMiyQJDWQ== - dependencies: - "@algolia/client-common" "5.46.2" - "@algolia/requester-browser-xhr" "5.46.2" - "@algolia/requester-fetch" "5.46.2" - "@algolia/requester-node-http" "5.46.2" - -"@algolia/monitoring@1.46.2": - version "1.46.2" - resolved "https://registry.yarnpkg.com/@algolia/monitoring/-/monitoring-1.46.2.tgz#bd199368a49cb799cf12cfe76c49de6dd3021148" - integrity sha512-xk9f+DPtNcddWN6E7n1hyNNsATBCHIqAvVGG2EAGHJc4AFYL18uM/kMTiOKXE/LKDPyy1JhIerrh9oYb7RBrgw== - dependencies: - "@algolia/client-common" "5.46.2" - "@algolia/requester-browser-xhr" "5.46.2" - "@algolia/requester-fetch" "5.46.2" - "@algolia/requester-node-http" "5.46.2" - -"@algolia/recommend@5.46.2": - version "5.46.2" - resolved "https://registry.yarnpkg.com/@algolia/recommend/-/recommend-5.46.2.tgz#e74bade1254046ed9be8ccd37f2a116ab9799508" - integrity sha512-NApbTPj9LxGzNw4dYnZmj2BoXiAc8NmbbH6qBNzQgXklGklt/xldTvu+FACN6ltFsTzoNU6j2mWNlHQTKGC5+Q== - dependencies: - "@algolia/client-common" "5.46.2" - "@algolia/requester-browser-xhr" "5.46.2" - "@algolia/requester-fetch" "5.46.2" - "@algolia/requester-node-http" "5.46.2" - -"@algolia/requester-browser-xhr@5.46.2": - version "5.46.2" - resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.46.2.tgz#7662480143405e815e1eed99136b4b2acd838ee7" - integrity sha512-ekotpCwpSp033DIIrsTpYlGUCF6momkgupRV/FA3m62SreTSZUKjgK6VTNyG7TtYfq9YFm/pnh65bATP/ZWJEg== - dependencies: - "@algolia/client-common" "5.46.2" - -"@algolia/requester-fetch@5.46.2": - version "5.46.2" - resolved "https://registry.yarnpkg.com/@algolia/requester-fetch/-/requester-fetch-5.46.2.tgz#dee07f0131b75f30d083bafd6fb878afe7402eb9" - integrity sha512-gKE+ZFi/6y7saTr34wS0SqYFDcjHW4Wminv8PDZEi0/mE99+hSrbKgJWxo2ztb5eqGirQTgIh1AMVacGGWM1iw== - dependencies: - "@algolia/client-common" "5.46.2" - -"@algolia/requester-node-http@5.46.2": - version "5.46.2" - resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-5.46.2.tgz#7869d67cb2926bbdbfbfed2b4757e547c2e227eb" - integrity sha512-ciPihkletp7ttweJ8Zt+GukSVLp2ANJHU+9ttiSxsJZThXc4Y2yJ8HGVWesW5jN1zrsZsezN71KrMx/iZsOYpg== - dependencies: - "@algolia/client-common" "5.46.2" - -"@babel/helper-string-parser@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" - integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== - -"@babel/helper-validator-identifier@^7.28.5": - version "7.28.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz#010b6938fab7cb7df74aa2bbc06aa503b8fe5fb4" - integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q== - -"@babel/parser@^7.28.5": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.6.tgz#f01a8885b7fa1e56dd8a155130226cd698ef13fd" - integrity sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ== - dependencies: - "@babel/types" "^7.28.6" - -"@babel/types@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.6.tgz#c3e9377f1b155005bcc4c46020e7e394e13089df" - integrity sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg== - dependencies: - "@babel/helper-string-parser" "^7.27.1" - "@babel/helper-validator-identifier" "^7.28.5" - -"@docsearch/css@3.8.2": - version "3.8.2" - resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.8.2.tgz#7973ceb6892c30f154ba254cd05c562257a44977" - integrity sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ== - -"@docsearch/js@3.8.2": - version "3.8.2" - resolved "https://registry.yarnpkg.com/@docsearch/js/-/js-3.8.2.tgz#bdcfc9837700eb38453b88e211ab5cc5a3813cc6" - integrity sha512-Q5wY66qHn0SwA7Taa0aDbHiJvaFJLOJyHmooQ7y8hlwwQLQ/5WwCcoX0g7ii04Qi2DJlHsd0XXzJ8Ypw9+9YmQ== - dependencies: - "@docsearch/react" "3.8.2" - preact "^10.0.0" - -"@docsearch/react@3.8.2": - version "3.8.2" - resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-3.8.2.tgz#7b11d39b61c976c0aa9fbde66e6b73b30f3acd42" - integrity sha512-xCRrJQlTt8N9GU0DG4ptwHRkfnSnD/YpdeaXe02iKfqs97TkZJv60yE+1eq/tjPcVnTW8dP5qLP7itifFVV5eg== - dependencies: - "@algolia/autocomplete-core" "1.17.7" - "@algolia/autocomplete-preset-algolia" "1.17.7" - "@docsearch/css" "3.8.2" - algoliasearch "^5.14.2" - -"@esbuild/aix-ppc64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" - integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== - -"@esbuild/android-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052" - integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== - -"@esbuild/android-arm@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28" - integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== - -"@esbuild/android-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e" - integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== - -"@esbuild/darwin-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a" - integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== - -"@esbuild/darwin-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22" - integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== - -"@esbuild/freebsd-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e" - integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== - -"@esbuild/freebsd-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261" - integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== - -"@esbuild/linux-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b" - integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== - -"@esbuild/linux-arm@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9" - integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== - -"@esbuild/linux-ia32@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2" - integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== - -"@esbuild/linux-loong64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df" - integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== - -"@esbuild/linux-mips64el@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe" - integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== - -"@esbuild/linux-ppc64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4" - integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== - -"@esbuild/linux-riscv64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc" - integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== - -"@esbuild/linux-s390x@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de" - integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== - -"@esbuild/linux-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0" - integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== - -"@esbuild/netbsd-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047" - integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== - -"@esbuild/openbsd-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70" - integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== - -"@esbuild/sunos-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b" - integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== - -"@esbuild/win32-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d" - integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== - -"@esbuild/win32-ia32@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b" - integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== - -"@esbuild/win32-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c" - integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== - -"@iconify-json/simple-icons@^1.2.21": - version "1.2.66" - resolved "https://registry.yarnpkg.com/@iconify-json/simple-icons/-/simple-icons-1.2.66.tgz#d0576ca65f69616b49491129e17132316cf3f309" - integrity sha512-D1OnnXwiQXFkVMw5M+Bt8mPsXeMkQyGmMdrmN7lsQlKMUkfLOp6JWhnUJ92po51WXT046aF/zzqSmkKqg08p4Q== - dependencies: - "@iconify/types" "*" - -"@iconify/types@*": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@iconify/types/-/types-2.0.0.tgz#ab0e9ea681d6c8a1214f30cd741fe3a20cc57f57" - integrity sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg== - -"@jridgewell/sourcemap-codec@^1.5.5": - version "1.5.5" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" - integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== - -"@rollup/rollup-android-arm-eabi@4.59.0": - version "4.59.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz#a6742c74c7d9d6d604ef8a48f99326b4ecda3d82" - integrity sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg== - -"@rollup/rollup-android-arm64@4.59.0": - version "4.59.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz#97247be098de4df0c11971089fd2edf80a5da8cf" - integrity sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q== - -"@rollup/rollup-darwin-arm64@4.59.0": - version "4.59.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz#674852cf14cf11b8056e0b1a2f4e872b523576cf" - integrity sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg== - -"@rollup/rollup-darwin-x64@4.59.0": - version "4.59.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz#36dfd7ed0aaf4d9d89d9ef983af72632455b0246" - integrity sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w== - -"@rollup/rollup-freebsd-arm64@4.59.0": - version "4.59.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz#2f87c2074b4220260fdb52a9996246edfc633c22" - integrity sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA== - -"@rollup/rollup-freebsd-x64@4.59.0": - version "4.59.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz#9b5a26522a38a95dc06616d1939d4d9a76937803" - integrity sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg== - -"@rollup/rollup-linux-arm-gnueabihf@4.59.0": - version "4.59.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz#86aa4859385a8734235b5e40a48e52d770758c3a" - integrity sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw== - -"@rollup/rollup-linux-arm-musleabihf@4.59.0": - version "4.59.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz#cbe70e56e6ece8dac83eb773b624fc9e5a460976" - integrity sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA== - -"@rollup/rollup-linux-arm64-gnu@4.59.0": - version "4.59.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz#d14992a2e653bc3263d284bc6579b7a2890e1c45" - integrity sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA== - -"@rollup/rollup-linux-arm64-musl@4.59.0": - version "4.59.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz#2fdd1ddc434ea90aeaa0851d2044789b4d07f6da" - integrity sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA== - -"@rollup/rollup-linux-loong64-gnu@4.59.0": - version "4.59.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz#8a181e6f89f969f21666a743cd411416c80099e7" - integrity sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg== - -"@rollup/rollup-linux-loong64-musl@4.59.0": - version "4.59.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz#904125af2babc395f8061daa27b5af1f4e3f2f78" - integrity sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q== - -"@rollup/rollup-linux-ppc64-gnu@4.59.0": - version "4.59.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz#a57970ac6864c9a3447411a658224bdcf948be22" - integrity sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA== - -"@rollup/rollup-linux-ppc64-musl@4.59.0": - version "4.59.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz#bb84de5b26870567a4267666e08891e80bb56a63" - integrity sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA== - -"@rollup/rollup-linux-riscv64-gnu@4.59.0": - version "4.59.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz#72d00d2c7fb375ce3564e759db33f17a35bffab9" - integrity sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg== - -"@rollup/rollup-linux-riscv64-musl@4.59.0": - version "4.59.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz#4c166ef58e718f9245bd31873384ba15a5c1a883" - integrity sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg== - -"@rollup/rollup-linux-s390x-gnu@4.59.0": - version "4.59.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz#bb5025cde9a61db478c2ca7215808ad3bce73a09" - integrity sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w== - -"@rollup/rollup-linux-x64-gnu@4.59.0": - version "4.59.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz#9b66b1f9cd95c6624c788f021c756269ffed1552" - integrity sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg== - -"@rollup/rollup-linux-x64-musl@4.59.0": - version "4.59.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz#b007ca255dc7166017d57d7d2451963f0bd23fd9" - integrity sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg== - -"@rollup/rollup-openbsd-x64@4.59.0": - version "4.59.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz#e8b357b2d1aa2c8d76a98f5f0d889eabe93f4ef9" - integrity sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ== - -"@rollup/rollup-openharmony-arm64@4.59.0": - version "4.59.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz#96c2e3f4aacd3d921981329831ff8dde492204dc" - integrity sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA== - -"@rollup/rollup-win32-arm64-msvc@4.59.0": - version "4.59.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz#2d865149d706d938df8b4b8f117e69a77646d581" - integrity sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A== - -"@rollup/rollup-win32-ia32-msvc@4.59.0": - version "4.59.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz#abe1593be0fa92325e9971c8da429c5e05b92c36" - integrity sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA== - -"@rollup/rollup-win32-x64-gnu@4.59.0": - version "4.59.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz#c4af3e9518c9a5cd4b1c163dc81d0ad4d82e7eab" - integrity sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA== - -"@rollup/rollup-win32-x64-msvc@4.59.0": - version "4.59.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz#4584a8a87b29188a4c1fe987a9fcf701e256d86c" - integrity sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA== - -"@shikijs/core@2.5.0", "@shikijs/core@^2.1.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@shikijs/core/-/core-2.5.0.tgz#e14d33961dfa3141393d4a76fc8923d0d1c4b62f" - integrity sha512-uu/8RExTKtavlpH7XqnVYBrfBkUc20ngXiX9NSrBhOVZYv/7XQRKUyhtkeflY5QsxC0GbJThCerruZfsUaSldg== - dependencies: - "@shikijs/engine-javascript" "2.5.0" - "@shikijs/engine-oniguruma" "2.5.0" - "@shikijs/types" "2.5.0" - "@shikijs/vscode-textmate" "^10.0.2" - "@types/hast" "^3.0.4" - hast-util-to-html "^9.0.4" - -"@shikijs/engine-javascript@2.5.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@shikijs/engine-javascript/-/engine-javascript-2.5.0.tgz#e045c6ecfbda6c99137547b0a482e0b87f1053fc" - integrity sha512-VjnOpnQf8WuCEZtNUdjjwGUbtAVKuZkVQ/5cHy/tojVVRIRtlWMYVjyWhxOmIq05AlSOv72z7hRNRGVBgQOl0w== - dependencies: - "@shikijs/types" "2.5.0" - "@shikijs/vscode-textmate" "^10.0.2" - oniguruma-to-es "^3.1.0" - -"@shikijs/engine-oniguruma@2.5.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@shikijs/engine-oniguruma/-/engine-oniguruma-2.5.0.tgz#230de5693cc1da6c9d59c7ad83593c2027274817" - integrity sha512-pGd1wRATzbo/uatrCIILlAdFVKdxImWJGQ5rFiB5VZi2ve5xj3Ax9jny8QvkaV93btQEwR/rSz5ERFpC5mKNIw== - dependencies: - "@shikijs/types" "2.5.0" - "@shikijs/vscode-textmate" "^10.0.2" - -"@shikijs/langs@2.5.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@shikijs/langs/-/langs-2.5.0.tgz#97ab50c495922cc1ca06e192985b28dc73de5d50" - integrity sha512-Qfrrt5OsNH5R+5tJ/3uYBBZv3SuGmnRPejV9IlIbFH3HTGLDlkqgHymAlzklVmKBjAaVmkPkyikAV/sQ1wSL+w== - dependencies: - "@shikijs/types" "2.5.0" - -"@shikijs/themes@2.5.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@shikijs/themes/-/themes-2.5.0.tgz#8c6aecf73f5455681c8bec15797cf678162896cb" - integrity sha512-wGrk+R8tJnO0VMzmUExHR+QdSaPUl/NKs+a4cQQRWyoc3YFbUzuLEi/KWK1hj+8BfHRKm2jNhhJck1dfstJpiw== - dependencies: - "@shikijs/types" "2.5.0" - -"@shikijs/transformers@^2.1.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@shikijs/transformers/-/transformers-2.5.0.tgz#190c84786ff06c417580ab79177338a947168c55" - integrity sha512-SI494W5X60CaUwgi8u4q4m4s3YAFSxln3tzNjOSYqq54wlVgz0/NbbXEb3mdLbqMBztcmS7bVTaEd2w0qMmfeg== - dependencies: - "@shikijs/core" "2.5.0" - "@shikijs/types" "2.5.0" - -"@shikijs/types@2.5.0", "@shikijs/types@^2.1.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@shikijs/types/-/types-2.5.0.tgz#e949c7384802703a48b9d6425dd41673c164df69" - integrity sha512-ygl5yhxki9ZLNuNpPitBWvcy9fsSKKaRuO4BAlMyagszQidxcpLAr0qiW/q43DtSIDxO6hEbtYLiFZNXO/hdGw== - dependencies: - "@shikijs/vscode-textmate" "^10.0.2" - "@types/hast" "^3.0.4" - -"@shikijs/vscode-textmate@^10.0.2": - version "10.0.2" - resolved "https://registry.yarnpkg.com/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz#a90ab31d0cc1dfb54c66a69e515bf624fa7b2224" - integrity sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg== - -"@types/estree@1.0.8": - version "1.0.8" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" - integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== - -"@types/hast@^3.0.0", "@types/hast@^3.0.4": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@types/hast/-/hast-3.0.4.tgz#1d6b39993b82cea6ad783945b0508c25903e15aa" - integrity sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ== - dependencies: - "@types/unist" "*" - -"@types/linkify-it@^5": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@types/linkify-it/-/linkify-it-5.0.0.tgz#21413001973106cda1c3a9b91eedd4ccd5469d76" - integrity sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q== - -"@types/markdown-it@^14.1.2": - version "14.1.2" - resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-14.1.2.tgz#57f2532a0800067d9b934f3521429a2e8bfb4c61" - integrity sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog== - dependencies: - "@types/linkify-it" "^5" - "@types/mdurl" "^2" - -"@types/mdast@^4.0.0": - version "4.0.4" - resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-4.0.4.tgz#7ccf72edd2f1aa7dd3437e180c64373585804dd6" - integrity sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA== - dependencies: - "@types/unist" "*" - -"@types/mdurl@^2": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-2.0.0.tgz#d43878b5b20222682163ae6f897b20447233bdfd" - integrity sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg== - -"@types/unist@*", "@types/unist@^3.0.0": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/unist/-/unist-3.0.3.tgz#acaab0f919ce69cce629c2d4ed2eb4adc1b6c20c" - integrity sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q== - -"@types/web-bluetooth@^0.0.21": - version "0.0.21" - resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz#525433c784aed9b457aaa0ee3d92aeb71f346b63" - integrity sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA== - -"@ungap/structured-clone@^1.0.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" - integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== - -"@vitejs/plugin-vue@^5.2.1": - version "5.2.4" - resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz#9e8a512eb174bfc2a333ba959bbf9de428d89ad8" - integrity sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA== - -"@vue/compiler-core@3.5.26": - version "3.5.26" - resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.5.26.tgz#1a91ea90980528bedff7b1c292690bfb30612485" - integrity sha512-vXyI5GMfuoBCnv5ucIT7jhHKl55Y477yxP6fc4eUswjP8FG3FFVFd41eNDArR+Uk3QKn2Z85NavjaxLxOC19/w== - dependencies: - "@babel/parser" "^7.28.5" - "@vue/shared" "3.5.26" - entities "^7.0.0" - estree-walker "^2.0.2" - source-map-js "^1.2.1" - -"@vue/compiler-dom@3.5.26": - version "3.5.26" - resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.5.26.tgz#66c36b6ed8bdf43236d7188ea332bc9d078eb286" - integrity sha512-y1Tcd3eXs834QjswshSilCBnKGeQjQXB6PqFn/1nxcQw4pmG42G8lwz+FZPAZAby6gZeHSt/8LMPfZ4Rb+Bd/A== - dependencies: - "@vue/compiler-core" "3.5.26" - "@vue/shared" "3.5.26" - -"@vue/compiler-sfc@3.5.26": - version "3.5.26" - resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.5.26.tgz#fb1c6c4bf9a9e22bb169e039e19437cb6995917a" - integrity sha512-egp69qDTSEZcf4bGOSsprUr4xI73wfrY5oRs6GSgXFTiHrWj4Y3X5Ydtip9QMqiCMCPVwLglB9GBxXtTadJ3mA== - dependencies: - "@babel/parser" "^7.28.5" - "@vue/compiler-core" "3.5.26" - "@vue/compiler-dom" "3.5.26" - "@vue/compiler-ssr" "3.5.26" - "@vue/shared" "3.5.26" - estree-walker "^2.0.2" - magic-string "^0.30.21" - postcss "^8.5.6" - source-map-js "^1.2.1" - -"@vue/compiler-ssr@3.5.26": - version "3.5.26" - resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.5.26.tgz#f6e94bccbb5339180779036ddfb614f998a197ea" - integrity sha512-lZT9/Y0nSIRUPVvapFJEVDbEXruZh2IYHMk2zTtEgJSlP5gVOqeWXH54xDKAaFS4rTnDeDBQUYDtxKyoW9FwDw== - dependencies: - "@vue/compiler-dom" "3.5.26" - "@vue/shared" "3.5.26" - -"@vue/devtools-api@^7.7.0": - version "7.7.9" - resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-7.7.9.tgz#999dbea50da6b00cf59a1336f11fdc2b43d9e063" - integrity sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g== - dependencies: - "@vue/devtools-kit" "^7.7.9" - -"@vue/devtools-kit@^7.7.9": - version "7.7.9" - resolved "https://registry.yarnpkg.com/@vue/devtools-kit/-/devtools-kit-7.7.9.tgz#bc218a815616e8987df7ab3e10fc1fb3b8706c58" - integrity sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA== - dependencies: - "@vue/devtools-shared" "^7.7.9" - birpc "^2.3.0" - hookable "^5.5.3" - mitt "^3.0.1" - perfect-debounce "^1.0.0" - speakingurl "^14.0.1" - superjson "^2.2.2" - -"@vue/devtools-shared@^7.7.9": - version "7.7.9" - resolved "https://registry.yarnpkg.com/@vue/devtools-shared/-/devtools-shared-7.7.9.tgz#fa4c096b744927081a7dda5fcf05f34b1ae6ca14" - integrity sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA== - dependencies: - rfdc "^1.4.1" - -"@vue/reactivity@3.5.26": - version "3.5.26" - resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.5.26.tgz#59a1edf566dc80133c1c26c93711c877e8602c48" - integrity sha512-9EnYB1/DIiUYYnzlnUBgwU32NNvLp/nhxLXeWRhHUEeWNTn1ECxX8aGO7RTXeX6PPcxe3LLuNBFoJbV4QZ+CFQ== - dependencies: - "@vue/shared" "3.5.26" - -"@vue/runtime-core@3.5.26": - version "3.5.26" - resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.5.26.tgz#3f2c040bcf8018c03a1ab5adb0d788c13c986f0e" - integrity sha512-xJWM9KH1kd201w5DvMDOwDHYhrdPTrAatn56oB/LRG4plEQeZRQLw0Bpwih9KYoqmzaxF0OKSn6swzYi84e1/Q== - dependencies: - "@vue/reactivity" "3.5.26" - "@vue/shared" "3.5.26" - -"@vue/runtime-dom@3.5.26": - version "3.5.26" - resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.5.26.tgz#5954848614883948ecc1f631a67b32cc32f81936" - integrity sha512-XLLd/+4sPC2ZkN/6+V4O4gjJu6kSDbHAChvsyWgm1oGbdSO3efvGYnm25yCjtFm/K7rrSDvSfPDgN1pHgS4VNQ== - dependencies: - "@vue/reactivity" "3.5.26" - "@vue/runtime-core" "3.5.26" - "@vue/shared" "3.5.26" - csstype "^3.2.3" - -"@vue/server-renderer@3.5.26": - version "3.5.26" - resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.5.26.tgz#269055497fcc75b3984063f866f17c748b565ef4" - integrity sha512-TYKLXmrwWKSodyVuO1WAubucd+1XlLg4set0YoV+Hu8Lo79mp/YMwWV5mC5FgtsDxX3qo1ONrxFaTP1OQgy1uA== - dependencies: - "@vue/compiler-ssr" "3.5.26" - "@vue/shared" "3.5.26" - -"@vue/shared@3.5.26", "@vue/shared@^3.5.13": - version "3.5.26" - resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.5.26.tgz#1e02ef2d64aced818cd31d81ce5175711dc90a9f" - integrity sha512-7Z6/y3uFI5PRoKeorTOSXKcDj0MSasfNNltcslbFrPpcw6aXRUALq4IfJlaTRspiWIUOEZbrpM+iQGmCOiWe4A== - -"@vueuse/core@12.8.2", "@vueuse/core@^12.4.0": - version "12.8.2" - resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-12.8.2.tgz#007c6dd29a7d1f6933e916e7a2f8ef3c3f968eaa" - integrity sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ== - dependencies: - "@types/web-bluetooth" "^0.0.21" - "@vueuse/metadata" "12.8.2" - "@vueuse/shared" "12.8.2" - vue "^3.5.13" - -"@vueuse/integrations@^12.4.0": - version "12.8.2" - resolved "https://registry.yarnpkg.com/@vueuse/integrations/-/integrations-12.8.2.tgz#d04f33d86fe985c9a27c98addcfde9f30f2db1df" - integrity sha512-fbGYivgK5uBTRt7p5F3zy6VrETlV9RtZjBqd1/HxGdjdckBgBM4ugP8LHpjolqTj14TXTxSK1ZfgPbHYyGuH7g== - dependencies: - "@vueuse/core" "12.8.2" - "@vueuse/shared" "12.8.2" - vue "^3.5.13" - -"@vueuse/metadata@12.8.2": - version "12.8.2" - resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-12.8.2.tgz#6cb3a4e97cdcf528329eebc1bda73cd7f64318d3" - integrity sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A== - -"@vueuse/shared@12.8.2": - version "12.8.2" - resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-12.8.2.tgz#b9e4611d0603629c8e151f982459da394e22f930" - integrity sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w== - dependencies: - vue "^3.5.13" - -algoliasearch@^5.14.2: - version "5.46.2" - resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-5.46.2.tgz#3afba0e53f3293e39cfde9b2ef27c583d44bf2a5" - integrity sha512-qqAXW9QvKf2tTyhpDA4qXv1IfBwD2eduSW6tUEBFIfCeE9gn9HQ9I5+MaKoenRuHrzk5sQoNh1/iof8mY7uD6Q== - dependencies: - "@algolia/abtesting" "1.12.2" - "@algolia/client-abtesting" "5.46.2" - "@algolia/client-analytics" "5.46.2" - "@algolia/client-common" "5.46.2" - "@algolia/client-insights" "5.46.2" - "@algolia/client-personalization" "5.46.2" - "@algolia/client-query-suggestions" "5.46.2" - "@algolia/client-search" "5.46.2" - "@algolia/ingestion" "1.46.2" - "@algolia/monitoring" "1.46.2" - "@algolia/recommend" "5.46.2" - "@algolia/requester-browser-xhr" "5.46.2" - "@algolia/requester-fetch" "5.46.2" - "@algolia/requester-node-http" "5.46.2" - -birpc@^2.3.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/birpc/-/birpc-2.9.0.tgz#b59550897e4cd96a223e2a6c1475b572236ed145" - integrity sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw== - -ccount@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/ccount/-/ccount-2.0.1.tgz#17a3bf82302e0870d6da43a01311a8bc02a3ecf5" - integrity sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg== - -character-entities-html4@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-2.1.0.tgz#1f1adb940c971a4b22ba39ddca6b618dc6e56b2b" - integrity sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA== - -character-entities-legacy@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz#76bc83a90738901d7bc223a9e93759fdd560125b" - integrity sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ== - -comma-separated-tokens@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz#4e89c9458acb61bc8fef19f4529973b2392839ee" - integrity sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg== - -copy-anything@^4: - version "4.0.5" - resolved "https://registry.yarnpkg.com/copy-anything/-/copy-anything-4.0.5.tgz#16cabafd1ea4bb327a540b750f2b4df522825aea" - integrity sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA== - dependencies: - is-what "^5.2.0" - -csstype@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.2.3.tgz#ec48c0f3e993e50648c86da559e2610995cf989a" - integrity sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ== - -dequal@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" - integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== - -devlop@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/devlop/-/devlop-1.1.0.tgz#4db7c2ca4dc6e0e834c30be70c94bbc976dc7018" - integrity sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA== - dependencies: - dequal "^2.0.0" - -emoji-regex-xs@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex-xs/-/emoji-regex-xs-1.0.0.tgz#e8af22e5d9dbd7f7f22d280af3d19d2aab5b0724" - integrity sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg== - -entities@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-7.0.0.tgz#2ae4e443f3f17d152d3f5b0f79b932c1e59deb7a" - integrity sha512-FDWG5cmEYf2Z00IkYRhbFrwIwvdFKH07uV8dvNy0omp/Qb1xcyCWp2UDtcwJF4QZZvk0sLudP6/hAu42TaqVhQ== - -esbuild@^0.21.3: - version "0.21.5" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d" - integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw== - optionalDependencies: - "@esbuild/aix-ppc64" "0.21.5" - "@esbuild/android-arm" "0.21.5" - "@esbuild/android-arm64" "0.21.5" - "@esbuild/android-x64" "0.21.5" - "@esbuild/darwin-arm64" "0.21.5" - "@esbuild/darwin-x64" "0.21.5" - "@esbuild/freebsd-arm64" "0.21.5" - "@esbuild/freebsd-x64" "0.21.5" - "@esbuild/linux-arm" "0.21.5" - "@esbuild/linux-arm64" "0.21.5" - "@esbuild/linux-ia32" "0.21.5" - "@esbuild/linux-loong64" "0.21.5" - "@esbuild/linux-mips64el" "0.21.5" - "@esbuild/linux-ppc64" "0.21.5" - "@esbuild/linux-riscv64" "0.21.5" - "@esbuild/linux-s390x" "0.21.5" - "@esbuild/linux-x64" "0.21.5" - "@esbuild/netbsd-x64" "0.21.5" - "@esbuild/openbsd-x64" "0.21.5" - "@esbuild/sunos-x64" "0.21.5" - "@esbuild/win32-arm64" "0.21.5" - "@esbuild/win32-ia32" "0.21.5" - "@esbuild/win32-x64" "0.21.5" - -estree-walker@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" - integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== - -focus-trap@^7.6.4: - version "7.8.0" - resolved "https://registry.yarnpkg.com/focus-trap/-/focus-trap-7.8.0.tgz#b1d9463fa42b93ad7a5223d750493a6c09b672a8" - integrity sha512-/yNdlIkpWbM0ptxno3ONTuf+2g318kh2ez3KSeZN5dZ8YC6AAmgeWz+GasYYiBJPFaYcSAPeu4GfhUaChzIJXA== - dependencies: - tabbable "^6.4.0" - -fsevents@~2.3.2, fsevents@~2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - -hast-util-to-html@^9.0.4: - version "9.0.5" - resolved "https://registry.yarnpkg.com/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz#ccc673a55bb8e85775b08ac28380f72d47167005" - integrity sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw== - dependencies: - "@types/hast" "^3.0.0" - "@types/unist" "^3.0.0" - ccount "^2.0.0" - comma-separated-tokens "^2.0.0" - hast-util-whitespace "^3.0.0" - html-void-elements "^3.0.0" - mdast-util-to-hast "^13.0.0" - property-information "^7.0.0" - space-separated-tokens "^2.0.0" - stringify-entities "^4.0.0" - zwitch "^2.0.4" - -hast-util-whitespace@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz#7778ed9d3c92dd9e8c5c8f648a49c21fc51cb621" - integrity sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw== - dependencies: - "@types/hast" "^3.0.0" - -hookable@^5.5.3: - version "5.5.3" - resolved "https://registry.yarnpkg.com/hookable/-/hookable-5.5.3.tgz#6cfc358984a1ef991e2518cb9ed4a778bbd3215d" - integrity sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ== - -html-void-elements@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-3.0.0.tgz#fc9dbd84af9e747249034d4d62602def6517f1d7" - integrity sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg== - -is-what@^5.2.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/is-what/-/is-what-5.5.0.tgz#a3031815757cfe1f03fed990bf6355a2d3f628c4" - integrity sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw== - -magic-string@^0.30.21: - version "0.30.21" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.21.tgz#56763ec09a0fa8091df27879fd94d19078c00d91" - integrity sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ== - dependencies: - "@jridgewell/sourcemap-codec" "^1.5.5" - -mark.js@8.11.1: - version "8.11.1" - resolved "https://registry.yarnpkg.com/mark.js/-/mark.js-8.11.1.tgz#180f1f9ebef8b0e638e4166ad52db879beb2ffc5" - integrity sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ== - -mdast-util-to-hast@^13.0.0: - version "13.2.1" - resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz#d7ff84ca499a57e2c060ae67548ad950e689a053" - integrity sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA== - dependencies: - "@types/hast" "^3.0.0" - "@types/mdast" "^4.0.0" - "@ungap/structured-clone" "^1.0.0" - devlop "^1.0.0" - micromark-util-sanitize-uri "^2.0.0" - trim-lines "^3.0.0" - unist-util-position "^5.0.0" - unist-util-visit "^5.0.0" - vfile "^6.0.0" - -micromark-util-character@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-2.1.0.tgz#31320ace16b4644316f6bf057531689c71e2aee1" - integrity sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ== - dependencies: - micromark-util-symbol "^2.0.0" - micromark-util-types "^2.0.0" - -micromark-util-encode@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz#0921ac7953dc3f1fd281e3d1932decfdb9382ab1" - integrity sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA== - -micromark-util-sanitize-uri@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz#ec8fbf0258e9e6d8f13d9e4770f9be64342673de" - integrity sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw== - dependencies: - micromark-util-character "^2.0.0" - micromark-util-encode "^2.0.0" - micromark-util-symbol "^2.0.0" - -micromark-util-symbol@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz#12225c8f95edf8b17254e47080ce0862d5db8044" - integrity sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw== - -micromark-util-types@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-2.0.0.tgz#63b4b7ffeb35d3ecf50d1ca20e68fc7caa36d95e" - integrity sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w== - -minisearch@^7.1.1: - version "7.2.0" - resolved "https://registry.yarnpkg.com/minisearch/-/minisearch-7.2.0.tgz#3dc30e41e9464b3836553b6d969b656614f8f359" - integrity sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg== - -mitt@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.1.tgz#ea36cf0cc30403601ae074c8f77b7092cdab36d1" - integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw== - -nanoid@^3.3.11: - version "3.3.11" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" - integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== - -oniguruma-to-es@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/oniguruma-to-es/-/oniguruma-to-es-3.1.1.tgz#480e4bac4d3bc9439ac0d2124f0725e7a0d76d17" - integrity sha512-bUH8SDvPkH3ho3dvwJwfonjlQ4R80vjyvrU8YpxuROddv55vAEJrTuCuCVUhhsHbtlD9tGGbaNApGQckXhS8iQ== - dependencies: - emoji-regex-xs "^1.0.0" - regex "^6.0.1" - regex-recursion "^6.0.2" - -perfect-debounce@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/perfect-debounce/-/perfect-debounce-1.0.0.tgz#9c2e8bc30b169cc984a58b7d5b28049839591d2a" - integrity sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA== - -picocolors@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" - integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== - -postcss@^8.4.43, postcss@^8.5.6: - version "8.5.14" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.14.tgz#a66c2d7808fadf69ebb5b84a03f8bafd76c4919c" - integrity sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg== - dependencies: - nanoid "^3.3.11" - picocolors "^1.1.1" - source-map-js "^1.2.1" - -preact@^10.0.0: - version "10.21.0" - resolved "https://registry.yarnpkg.com/preact/-/preact-10.21.0.tgz#5b0335c873a1724deb66e517830db4fd310c24f6" - integrity sha512-aQAIxtzWEwH8ou+OovWVSVNlFImL7xUCwJX3YMqA3U8iKCNC34999fFOnWjYNsylgfPgMexpbk7WYOLtKr/mxg== - -property-information@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/property-information/-/property-information-7.1.0.tgz#b622e8646e02b580205415586b40804d3e8bfd5d" - integrity sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ== - -regex-recursion@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/regex-recursion/-/regex-recursion-6.0.2.tgz#a0b1977a74c87f073377b938dbedfab2ea582b33" - integrity sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg== - dependencies: - regex-utilities "^2.3.0" - -regex-utilities@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/regex-utilities/-/regex-utilities-2.3.0.tgz#87163512a15dce2908cf079c8960d5158ff43280" - integrity sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng== - -regex@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/regex/-/regex-6.1.0.tgz#d7ce98f8ee32da7497c13f6601fca2bc4a6a7803" - integrity sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg== - dependencies: - regex-utilities "^2.3.0" - -rfdc@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca" - integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== - -rollup@^4.20.0: - version "4.59.0" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.59.0.tgz#cf74edac17c1486f562d728a4d923a694abdf06f" - integrity sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg== - dependencies: - "@types/estree" "1.0.8" - optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.59.0" - "@rollup/rollup-android-arm64" "4.59.0" - "@rollup/rollup-darwin-arm64" "4.59.0" - "@rollup/rollup-darwin-x64" "4.59.0" - "@rollup/rollup-freebsd-arm64" "4.59.0" - "@rollup/rollup-freebsd-x64" "4.59.0" - "@rollup/rollup-linux-arm-gnueabihf" "4.59.0" - "@rollup/rollup-linux-arm-musleabihf" "4.59.0" - "@rollup/rollup-linux-arm64-gnu" "4.59.0" - "@rollup/rollup-linux-arm64-musl" "4.59.0" - "@rollup/rollup-linux-loong64-gnu" "4.59.0" - "@rollup/rollup-linux-loong64-musl" "4.59.0" - "@rollup/rollup-linux-ppc64-gnu" "4.59.0" - "@rollup/rollup-linux-ppc64-musl" "4.59.0" - "@rollup/rollup-linux-riscv64-gnu" "4.59.0" - "@rollup/rollup-linux-riscv64-musl" "4.59.0" - "@rollup/rollup-linux-s390x-gnu" "4.59.0" - "@rollup/rollup-linux-x64-gnu" "4.59.0" - "@rollup/rollup-linux-x64-musl" "4.59.0" - "@rollup/rollup-openbsd-x64" "4.59.0" - "@rollup/rollup-openharmony-arm64" "4.59.0" - "@rollup/rollup-win32-arm64-msvc" "4.59.0" - "@rollup/rollup-win32-ia32-msvc" "4.59.0" - "@rollup/rollup-win32-x64-gnu" "4.59.0" - "@rollup/rollup-win32-x64-msvc" "4.59.0" - fsevents "~2.3.2" - -shiki@^2.1.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/shiki/-/shiki-2.5.0.tgz#09d01ebf3b0b06580431ce3ddc023320442cf223" - integrity sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ== - dependencies: - "@shikijs/core" "2.5.0" - "@shikijs/engine-javascript" "2.5.0" - "@shikijs/engine-oniguruma" "2.5.0" - "@shikijs/langs" "2.5.0" - "@shikijs/themes" "2.5.0" - "@shikijs/types" "2.5.0" - "@shikijs/vscode-textmate" "^10.0.2" - "@types/hast" "^3.0.4" - -source-map-js@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" - integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== - -space-separated-tokens@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz#1ecd9d2350a3844572c3f4a312bceb018348859f" - integrity sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q== - -speakingurl@^14.0.1: - version "14.0.1" - resolved "https://registry.yarnpkg.com/speakingurl/-/speakingurl-14.0.1.tgz#f37ec8ddc4ab98e9600c1c9ec324a8c48d772a53" - integrity sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ== - -stringify-entities@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-4.0.4.tgz#b3b79ef5f277cc4ac73caeb0236c5ba939b3a4f3" - integrity sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg== - dependencies: - character-entities-html4 "^2.0.0" - character-entities-legacy "^3.0.0" - -superjson@^2.2.2: - version "2.2.6" - resolved "https://registry.yarnpkg.com/superjson/-/superjson-2.2.6.tgz#a223a3a988172a5f9656e2063fe5f733af40d099" - integrity sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA== - dependencies: - copy-anything "^4" - -tabbable@^6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-6.4.0.tgz#36eb7a06d80b3924a22095daf45740dea3bf5581" - integrity sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg== - -trim-lines@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-3.0.1.tgz#d802e332a07df861c48802c04321017b1bd87338" - integrity sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg== - -unist-util-is@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-6.0.0.tgz#b775956486aff107a9ded971d996c173374be424" - integrity sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw== - dependencies: - "@types/unist" "^3.0.0" - -unist-util-position@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-5.0.0.tgz#678f20ab5ca1207a97d7ea8a388373c9cf896be4" - integrity sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA== - dependencies: - "@types/unist" "^3.0.0" - -unist-util-stringify-position@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz#449c6e21a880e0855bf5aabadeb3a740314abac2" - integrity sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ== - dependencies: - "@types/unist" "^3.0.0" - -unist-util-visit-parents@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz#4d5f85755c3b8f0dc69e21eca5d6d82d22162815" - integrity sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw== - dependencies: - "@types/unist" "^3.0.0" - unist-util-is "^6.0.0" - -unist-util-visit@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-5.0.0.tgz#a7de1f31f72ffd3519ea71814cccf5fd6a9217d6" - integrity sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg== - dependencies: - "@types/unist" "^3.0.0" - unist-util-is "^6.0.0" - unist-util-visit-parents "^6.0.0" - -vfile-message@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-4.0.2.tgz#c883c9f677c72c166362fd635f21fc165a7d1181" - integrity sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw== - dependencies: - "@types/unist" "^3.0.0" - unist-util-stringify-position "^4.0.0" - -vfile@^6.0.0: - version "6.0.3" - resolved "https://registry.yarnpkg.com/vfile/-/vfile-6.0.3.tgz#3652ab1c496531852bf55a6bac57af981ebc38ab" - integrity sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q== - dependencies: - "@types/unist" "^3.0.0" - vfile-message "^4.0.0" - -vite@^5.4.14: - version "5.4.21" - resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.21.tgz#84a4f7c5d860b071676d39ba513c0d598fdc7027" - integrity sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw== - dependencies: - esbuild "^0.21.3" - postcss "^8.4.43" - rollup "^4.20.0" - optionalDependencies: - fsevents "~2.3.3" - -vitepress@^1.6.4: - version "1.6.4" - resolved "https://registry.yarnpkg.com/vitepress/-/vitepress-1.6.4.tgz#1b6c68fede541a3f401a66263dce0c985e2d8d92" - integrity sha512-+2ym1/+0VVrbhNyRoFFesVvBvHAVMZMK0rw60E3X/5349M1GuVdKeazuksqopEdvkKwKGs21Q729jX81/bkBJg== - dependencies: - "@docsearch/css" "3.8.2" - "@docsearch/js" "3.8.2" - "@iconify-json/simple-icons" "^1.2.21" - "@shikijs/core" "^2.1.0" - "@shikijs/transformers" "^2.1.0" - "@shikijs/types" "^2.1.0" - "@types/markdown-it" "^14.1.2" - "@vitejs/plugin-vue" "^5.2.1" - "@vue/devtools-api" "^7.7.0" - "@vue/shared" "^3.5.13" - "@vueuse/core" "^12.4.0" - "@vueuse/integrations" "^12.4.0" - focus-trap "^7.6.4" - mark.js "8.11.1" - minisearch "^7.1.1" - shiki "^2.1.0" - vite "^5.4.14" - vue "^3.5.13" - -vue@^3.5.13: - version "3.5.26" - resolved "https://registry.yarnpkg.com/vue/-/vue-3.5.26.tgz#03a0b17311e0e593d34b9358fa249b85e3a6d9fb" - integrity sha512-SJ/NTccVyAoNUJmkM9KUqPcYlY+u8OVL1X5EW9RIs3ch5H2uERxyyIUI4MRxVCSOiEcupX9xNGde1tL9ZKpimA== - dependencies: - "@vue/compiler-dom" "3.5.26" - "@vue/compiler-sfc" "3.5.26" - "@vue/runtime-dom" "3.5.26" - "@vue/server-renderer" "3.5.26" - "@vue/shared" "3.5.26" - -zwitch@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.4.tgz#c827d4b0acb76fc3e685a4c6ec2902d51070e9d7" - integrity sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A== diff --git a/frontend/check-locales.cjs b/frontend/check-locales.cjs index deb418a3ec..ad8a5f7e04 100755 --- a/frontend/check-locales.cjs +++ b/frontend/check-locales.cjs @@ -59,7 +59,7 @@ try { // get all translations used in frontend code const tmpobj = tmp.fileSync({ postfix: ".json" }); -spawnSync("yarn", ["locale-extract", "--out-file", tmpobj.name]); +spawnSync("npm", ["run", "locale-extract", "--", "--out-file", tmpobj.name], { stdio: "inherit", shell: true }); const allLocalesInProject = require(tmpobj.name); diff --git a/frontend/package-lock.json b/frontend/package-lock.json new file mode 100644 index 0000000000..06f76862cf --- /dev/null +++ b/frontend/package-lock.json @@ -0,0 +1,5710 @@ +{ + "name": "nginx-proxy-manager", + "version": "2.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "nginx-proxy-manager", + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "@tabler/core": "^1.4.0", + "@tabler/icons-react": "^3.44.0", + "@tanstack/react-query": "^5.101.0", + "@tanstack/react-table": "^8.21.3", + "@uiw/react-textarea-code-editor": "^3.1.1", + "classnames": "^2.5.1", + "country-flag-icons": "^1.6.17", + "date-fns": "^4.4.0", + "ez-modal-react": "^1.0.5", + "formik": "^2.4.9", + "generate-password-browser": "^1.1.0", + "humps": "^2.0.1", + "query-string": "^9.4.0", + "react": "^19.2.7", + "react-bootstrap": "^2.10.10", + "react-dom": "^19.2.7", + "react-intl": "^10.1.11", + "react-markdown": "^10.1.0", + "react-router-dom": "^7.16.0", + "react-select": "^5.10.2", + "react-toastify": "^11.1.0", + "rehype-sanitize": "^6.0.0", + "rooks": "^9.8.0" + }, + "devDependencies": { + "@biomejs/biome": "^2.4.15", + "@formatjs/cli": "^6.16.6", + "@tanstack/react-query-devtools": "^5.100.14", + "@testing-library/dom": "^10.4.1", + "@testing-library/jest-dom": "^6.9.1", + "@testing-library/react": "^16.3.2", + "@types/country-flag-icons": "^1.2.2", + "@types/humps": "^2.0.6", + "@types/node": "^25.9.1", + "@types/react": "^19.2.16", + "@types/react-dom": "^19.2.3", + "@types/react-table": "^7.7.20", + "@vitejs/plugin-react": "^6.0.2", + "happy-dom": "^20.9.0", + "postcss": "^8.5.15", + "postcss-simple-vars": "^7.0.1", + "sass": "^1.100.0", + "tmp": "^0.2.7", + "typescript": "6.0.3", + "vite": "^8.0.16", + "vite-plugin-checker": "^0.14.1", + "vitest": "^4.1.8" + } + }, + "node_modules/@adobe/css-tools": { + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.4.tgz", + "integrity": "sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@biomejs/biome": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.4.15.tgz", + "integrity": "sha512-j5VH3a/h/HXTKBM50MDMxRCzkeLv9S2XJcW2WgnZT1+xyisi+0bISrXR82gCX+8S9lvK0skEvHJRN+3Ktr2hlw==", + "dev": true, + "license": "MIT OR Apache-2.0", + "bin": { + "biome": "bin/biome" + }, + "engines": { + "node": ">=14.21.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/biome" + }, + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "2.4.15", + "@biomejs/cli-darwin-x64": "2.4.15", + "@biomejs/cli-linux-arm64": "2.4.15", + "@biomejs/cli-linux-arm64-musl": "2.4.15", + "@biomejs/cli-linux-x64": "2.4.15", + "@biomejs/cli-linux-x64-musl": "2.4.15", + "@biomejs/cli-win32-arm64": "2.4.15", + "@biomejs/cli-win32-x64": "2.4.15" + } + }, + "node_modules/@biomejs/cli-darwin-arm64": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.4.15.tgz", + "integrity": "sha512-rF3PPqLq1yoST79zaQbDjVJwsuIeci/O+9bgNmC5QpgOqz6aqYuzA4abyAGx+mgyiDXn4A049xAN8gijbuR1Qg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-darwin-x64": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.4.15.tgz", + "integrity": "sha512-/5KHXYMfSJs1fNXiX30xFtI8JcCFV6zaVVLxOa0M2sfqBKHkpQhRTv94yxQWxeTY2lzo2OuTlNvPC+hDQt2wcQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.4.15.tgz", + "integrity": "sha512-owaAMZD/T4LrD0ELNCk0Km3qrRHuM0X6EAyVE1FSqGY0rbLoiDLrO4Us2tllm6cAeB2Ioa9C2C08NZPdr8+0Ug==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64-musl": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.4.15.tgz", + "integrity": "sha512-ZPcxznxm0pogHBLZhYntyR3sR+MrZjqJIKEr7ZqVen0Rl+P/4upVmfYXjftizi9RoqZntg33fv/1fbdhbYXpEQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.4.15.tgz", + "integrity": "sha512-0jj7THz12GbUOLmMibktK6DZjqz2zV64KFxyBtcFTKPiiOIY0a7vns1elpO1dERvxpsZ5ik0oFfz0oGwFde1+g==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64-musl": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.4.15.tgz", + "integrity": "sha512-CNq/9W38SYSH023lfcQ4KKU8K0YX8T//FZUhcgtMMRABDojx5XsMV7jlweAvGSl389wJQB29Qo6Zb/a+jdvt+w==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-arm64": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.4.15.tgz", + "integrity": "sha512-ouhkYdlhp/1GghEJPdWwD/Vi3gQ1nFxuSpMolWsbq3Lsq3QUR4jl6UdhhscdCugKU5vOEuMiJhvKj66O0OCq+w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.4.15.tgz", + "integrity": "sha512-zBrGq5mx5wwpnow4+2BxUvleDM+GNd4sLbPaMapsSLQLD0NGRCquqPBTgN+7XkUteHvj7M+BstuI8tmnV7+HgQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emotion/babel-plugin": { + "version": "11.13.5", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", + "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.3.3", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/cache": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", + "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", + "license": "MIT" + }, + "node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", + "license": "MIT" + }, + "node_modules/@emotion/react": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", + "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/cache": "^11.14.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz", + "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==", + "license": "MIT", + "dependencies": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.10.0", + "@emotion/utils": "^1.4.2", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", + "license": "MIT" + }, + "node_modules/@emotion/unitless": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", + "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==", + "license": "MIT" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz", + "integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", + "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==", + "license": "MIT" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", + "license": "MIT" + }, + "node_modules/@floating-ui/core": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.4.tgz", + "integrity": "sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.5.tgz", + "integrity": "sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.4", + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", + "license": "MIT" + }, + "node_modules/@formatjs/cli": { + "version": "6.16.6", + "resolved": "https://registry.npmjs.org/@formatjs/cli/-/cli-6.16.6.tgz", + "integrity": "sha512-82l9wmeqvClrtI/8VQOcFVZQwZWYEiMI505hywngF+xr7ti94OQXg0gi3piYaQarfiIac2GSMibLQ2aQM5mJaA==", + "dev": true, + "license": "MIT", + "bin": { + "formatjs": "bin/formatjs" + }, + "engines": { + "node": ">= 20.12.0" + }, + "optionalDependencies": { + "@formatjs/cli-native-darwin-arm64": "1.1.1", + "@formatjs/cli-native-linux-arm64": "1.2.1", + "@formatjs/cli-native-linux-x64": "1.1.1", + "@formatjs/cli-native-win32-x64": "1.1.2" + }, + "peerDependencies": { + "@glimmer/syntax": "^0.84.3 || ^0.95.0", + "@vue/compiler-core": "^3.5.0", + "content-tag": "^4.1.0", + "vue": "^3.5.0" + }, + "peerDependenciesMeta": { + "@glimmer/env": { + "optional": true + }, + "@glimmer/reference": { + "optional": true + }, + "@glimmer/syntax": { + "optional": true + }, + "@glimmer/validator": { + "optional": true + }, + "@vue/compiler-core": { + "optional": true + }, + "content-tag": { + "optional": true + }, + "vue": { + "optional": true + } + } + }, + "node_modules/@formatjs/cli-native-darwin-arm64": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@formatjs/cli-native-darwin-arm64/-/cli-native-darwin-arm64-1.1.1.tgz", + "integrity": "sha512-G2IfmxwDN1kUMIbM9ec5HfJTNR89X11+U3bt4lewfrRqoHOc9bQAkkVHLsY8gNVLjyQIXch58Ewd+AAHkg6cag==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@formatjs/cli-native-linux-arm64": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@formatjs/cli-native-linux-arm64/-/cli-native-linux-arm64-1.2.1.tgz", + "integrity": "sha512-dbafLt5p1wQi16QnTFuz6s5j5c8HcyRSw+gUp5xEtaQ9Ua2YKRu+YqlgsERg+ArTWN+ZTHIGu+0YymTvfTropA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@formatjs/cli-native-linux-x64": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@formatjs/cli-native-linux-x64/-/cli-native-linux-x64-1.1.1.tgz", + "integrity": "sha512-zi6eOPAc03fszPyiGCkmzBxjIxynDFflie9zgbyZIQgKV7MhXEmUmpGYeaTTDX903OFCJJ3ZvpajSTdZ7C7yeQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@formatjs/cli-native-win32-x64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@formatjs/cli-native-win32-x64/-/cli-native-win32-x64-1.1.2.tgz", + "integrity": "sha512-2TKatQRlDbVc+eJE4b9n0/+bsDg+DpS0kmHw7OYI1zGXhus4YqRPtlJnraazRmPlXtRNgvY/UYCPgBvX7DbYhw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@formatjs/fast-memoize": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-3.1.5.tgz", + "integrity": "sha512-KLi3fan6WnCHmigd9pmEEN8Hid0v4wiFBW576M/d07KMWYecf1CvyMI3n34vCmHT4AoVqG2n702kiHbXjzZX2A==", + "license": "MIT" + }, + "node_modules/@formatjs/icu-messageformat-parser": { + "version": "3.5.10", + "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-3.5.10.tgz", + "integrity": "sha512-XeJihYLy1lCe19xfK1KWKG/betBOK2rB0luL8lSkjfvJj0zP+LTJvkC+RKd0jsFI8mWxN71LrarHSrEXE8xxOQ==", + "license": "MIT", + "dependencies": { + "@formatjs/icu-skeleton-parser": "2.1.9" + } + }, + "node_modules/@formatjs/icu-skeleton-parser": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-2.1.9.tgz", + "integrity": "sha512-rsxswgHMfU1zUgB2byc08fesf83wLGjFnzLCEtuf00mx2doiqc6pYrf67raI37XqdRcGUviQepk2UKGqpng74Q==", + "license": "MIT" + }, + "node_modules/@formatjs/intl": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@formatjs/intl/-/intl-4.1.12.tgz", + "integrity": "sha512-r288ut+p+CUQZSg+0gAT+D0i6xgrnoxE0B4HTbPY2zei/AtYmFhlu87BKjgCf1CweH4pZIbr152JFjxO8jVb1A==", + "license": "MIT", + "dependencies": { + "@formatjs/fast-memoize": "3.1.5", + "@formatjs/icu-messageformat-parser": "3.5.10", + "intl-messageformat": "11.2.7" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@js-temporal/polyfill": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@js-temporal/polyfill/-/polyfill-0.5.1.tgz", + "integrity": "sha512-hloP58zRVCRSpgDxmqCWJNlizAlUgJFqG2ypq79DCvyv9tHjRYMDOcPFjzfl/A1/YxDvRCZz8wvZvmapQnKwFQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "jsbi": "^4.3.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", + "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.133.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.133.0.tgz", + "integrity": "sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz", + "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.3", + "is-glob": "^4.0.3", + "node-addon-api": "^7.0.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.6", + "@parcel/watcher-darwin-arm64": "2.5.6", + "@parcel/watcher-darwin-x64": "2.5.6", + "@parcel/watcher-freebsd-x64": "2.5.6", + "@parcel/watcher-linux-arm-glibc": "2.5.6", + "@parcel/watcher-linux-arm-musl": "2.5.6", + "@parcel/watcher-linux-arm64-glibc": "2.5.6", + "@parcel/watcher-linux-arm64-musl": "2.5.6", + "@parcel/watcher-linux-x64-glibc": "2.5.6", + "@parcel/watcher-linux-x64-musl": "2.5.6", + "@parcel/watcher-win32-arm64": "2.5.6", + "@parcel/watcher-win32-ia32": "2.5.6", + "@parcel/watcher-win32-x64": "2.5.6" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", + "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", + "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", + "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", + "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", + "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", + "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz", + "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", + "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", + "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", + "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", + "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", + "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz", + "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@react-aria/ssr": { + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.10.tgz", + "integrity": "sha512-hvTm77Pf+pMBhuBm760Li0BVIO38jv1IBws1xFm1NoL26PU+fe+FMW5+VZWyANR6nYL65joaJKZqOdTQMkO9IQ==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@restart/hooks": { + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.16.tgz", + "integrity": "sha512-f7aCv7c+nU/3mF7NWLtVVr0Ra80RqsO89hO72r+Y/nvQr5+q0UFGkocElTH6MJApvReVh6JHUFYn2cw1WdHF3w==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.3" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@restart/ui": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.9.4.tgz", + "integrity": "sha512-N4C7haUc3vn4LTwVUPlkJN8Ach/+yIMvRuTVIhjilNHqegY60SGLrzud6errOMNJwSnmYFnt1J0H/k8FE3A4KA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.0", + "@popperjs/core": "^2.11.8", + "@react-aria/ssr": "^3.5.0", + "@restart/hooks": "^0.5.0", + "@types/warning": "^3.0.3", + "dequal": "^2.0.3", + "dom-helpers": "^5.2.0", + "uncontrollable": "^8.0.4", + "warning": "^4.0.3" + }, + "peerDependencies": { + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + } + }, + "node_modules/@restart/ui/node_modules/@restart/hooks": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.5.1.tgz", + "integrity": "sha512-EMoH04NHS1pbn07iLTjIjgttuqb7qu4+/EyhAx27MHpoENcB2ZdSsLTNxmKD+WEPnZigo62Qc8zjGnNxoSE/5Q==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.3" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@restart/ui/node_modules/uncontrollable": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.4.tgz", + "integrity": "sha512-ulRWYWHvscPFc0QQXvyJjY6LIXU56f0h8pQFvhxiKk5V1fcI8gp9Ht9leVAhrVjzqMw0BgjspBINx9r6oyJUvQ==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.14.0" + } + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.3.tgz", + "integrity": "sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.3.tgz", + "integrity": "sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.3.tgz", + "integrity": "sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.3.tgz", + "integrity": "sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.3.tgz", + "integrity": "sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.3.tgz", + "integrity": "sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.3.tgz", + "integrity": "sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.3.tgz", + "integrity": "sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.3.tgz", + "integrity": "sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.3.tgz", + "integrity": "sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.3.tgz", + "integrity": "sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.3.tgz", + "integrity": "sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.3.tgz", + "integrity": "sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.3.tgz", + "integrity": "sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.3.tgz", + "integrity": "sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@swc/helpers": { + "version": "0.5.18", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.18.tgz", + "integrity": "sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@tabler/core": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@tabler/core/-/core-1.4.0.tgz", + "integrity": "sha512-5BigzOlbOH9N0Is4u0rYNRCiwtnUXWO57K9zwuscygcicAa8UV9MGaS4zTgQsZEtZ9tsNANhN/YD8gCBGKYCiw==", + "license": "MIT", + "dependencies": { + "@popperjs/core": "^2.11.8", + "bootstrap": "5.3.7" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/codecalm" + } + }, + "node_modules/@tabler/icons": { + "version": "3.44.0", + "resolved": "https://registry.npmjs.org/@tabler/icons/-/icons-3.44.0.tgz", + "integrity": "sha512-Wn0AOZG9sg0L+bjfMqq4eNhC6pQjIrk94LvvWYNYkY8KH8wC3YILRzQlrnVJc4FUeMxH/AK97QsYCX35H3LndA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/codecalm" + } + }, + "node_modules/@tabler/icons-react": { + "version": "3.44.0", + "resolved": "https://registry.npmjs.org/@tabler/icons-react/-/icons-react-3.44.0.tgz", + "integrity": "sha512-8+rvzBbVm/1Z3sG3x7GUNAaxIKxwgz8xaMhRs23nrCnMTKRFAhEC+82zAIFeAA0seXdrAGX5HFCkaLpGK2rVHg==", + "license": "MIT", + "dependencies": { + "@tabler/icons": "3.44.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/codecalm" + }, + "peerDependencies": { + "react": ">= 16" + } + }, + "node_modules/@tanstack/query-core": { + "version": "5.101.0", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.101.0.tgz", + "integrity": "sha512-cQetA74EB+seWySv1TTKr828TnP0u39m6LykwDXIo84SNortpDkp30TMEjkqtYCNP9c40uT/iwl6MLiufEt0Ow==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/query-devtools": { + "version": "5.100.14", + "resolved": "https://registry.npmjs.org/@tanstack/query-devtools/-/query-devtools-5.100.14.tgz", + "integrity": "sha512-g96SmSSQecYTYcyuAMRXr895GplJv01UGt7qttQWPOUyZ5EGz5tbRc589bMc2m5BsPFD6O0PCEAHdbDYNP6UBw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.101.0", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.101.0.tgz", + "integrity": "sha512-rLlJXSpkqfizLWgkR5+eLeIk0MvTx/meEIR7LRjxic+qxiQP8zVjq7BqQkiCMNLQBlLfuOLqqr6KO5GtrDlmSg==", + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "5.101.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18 || ^19" + } + }, + "node_modules/@tanstack/react-query-devtools": { + "version": "5.100.14", + "resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-5.100.14.tgz", + "integrity": "sha512-JkP5VDgKOw3t/QSA1OABRHEqx8BuNs5MfvZRooNqdvN57SzTuGq3fKR1a2IH5rqa5HDLUm+FOXUEnB9ueHiLzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tanstack/query-devtools": "5.100.14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "@tanstack/react-query": "^5.100.14", + "react": "^18 || ^19" + } + }, + "node_modules/@tanstack/react-table": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.21.3.tgz", + "integrity": "sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==", + "license": "MIT", + "dependencies": { + "@tanstack/table-core": "8.21.3" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/@tanstack/table-core": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.21.3.tgz", + "integrity": "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@testing-library/dom": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", + "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "picocolors": "1.1.1", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/jest-dom": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.9.1.tgz", + "integrity": "sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@adobe/css-tools": "^4.4.0", + "aria-query": "^5.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "picocolors": "^1.1.1", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@testing-library/react": { + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.2.tgz", + "integrity": "sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@testing-library/dom": "^10.0.0", + "@types/react": "^18.0.0 || ^19.0.0", + "@types/react-dom": "^18.0.0 || ^19.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", + "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/country-flag-icons": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/country-flag-icons/-/country-flag-icons-1.2.2.tgz", + "integrity": "sha512-CefEn/J336TBDp7NX8JqzlDtCBOsm8M3r1Li0gEOt0HOMHF1XemNyrx9lSHjsafcb1yYWybU0N8ZAXuyCaND0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "license": "MIT" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.7.tgz", + "integrity": "sha512-PQTyIulDkIDro8P+IHbKCsw7U2xxBYflVzW/FgWdCAePD9xGSidgA76/GeJ6lBKoblyhf9pBY763gbrN+1dI8g==", + "license": "MIT", + "dependencies": { + "hoist-non-react-statics": "^3.3.0" + }, + "peerDependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/humps": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/humps/-/humps-2.0.6.tgz", + "integrity": "sha512-Fagm1/a/1J9gDKzGdtlPmmTN5eSw/aaTzHtj740oSfo+MODsSY2WglxMmhTdOglC8nxqUhGGQ+5HfVtBvxo3Kg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "25.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.1.tgz", + "integrity": "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": ">=7.24.0 <7.24.7" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "license": "MIT" + }, + "node_modules/@types/prismjs": { + "version": "1.26.6", + "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.6.tgz", + "integrity": "sha512-vqlvI7qlMvcCBbVe0AKAb4f97//Hy0EBTaiW8AalRnG/xAN5zOiWWyrNqNXeq8+KAuvRewjCVY1+IPxk4RdNYw==", + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.2.16", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.16.tgz", + "integrity": "sha512-esJiCAnl0kfpNdE69f3So4WJUXy95dLZydX0KwK46riIHDzHM7O9Vtf9xCHW0PXIqvgqNrswl522kA/5yx+F4w==", + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@types/react-table": { + "version": "7.7.20", + "resolved": "https://registry.npmjs.org/@types/react-table/-/react-table-7.7.20.tgz", + "integrity": "sha512-ahMp4pmjVlnExxNwxyaDrFgmKxSbPwU23sGQw2gJK4EhCvnvmib2s/O/+y1dfV57dXOwpr2plfyBol+vEHbi2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.12", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", + "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/@types/warning": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.3.tgz", + "integrity": "sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q==", + "license": "MIT" + }, + "node_modules/@types/whatwg-mimetype": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-mimetype/-/whatwg-mimetype-3.0.2.tgz", + "integrity": "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@uiw/react-textarea-code-editor": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@uiw/react-textarea-code-editor/-/react-textarea-code-editor-3.1.1.tgz", + "integrity": "sha512-AERRbp/d85vWR+UPgsB5hEgerNXuyszdmhWl2fV2H2jN63jgOobwEnjIpb76Vwy8SaGa/AdehaoJX2XZgNXtJA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.6", + "rehype": "~13.0.0", + "rehype-prism-plus": "2.0.0" + }, + "funding": { + "url": "https://jaywcjlove.github.io/#/sponsor" + }, + "peerDependencies": { + "@babel/runtime": ">=7.10.0", + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.1.tgz", + "integrity": "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==", + "license": "ISC" + }, + "node_modules/@vitejs/plugin-react": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.2.tgz", + "integrity": "sha512-DlSMqo4WhThw4vB8Mpn0Woe9J+Jfq1geJ61AKW0QEgLzGMNwtIMdxbDUzLxcun8W7NbJO0e2Jg/Nxm3cCSVzzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "^1.0.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", + "babel-plugin-react-compiler": "^1.0.0", + "vite": "^8.0.0" + }, + "peerDependenciesMeta": { + "@rolldown/plugin-babel": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + } + } + }, + "node_modules/@vitest/expect": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.8.tgz", + "integrity": "sha512-h3nDO677RDLEGlBxyQ5CW8RlMThSKSRLUePLOx09gNIWRL40edgA1GCZSZgf1W55MFAG6/Sw14KeaAnqv0NKdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.8", + "@vitest/utils": "4.1.8", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.8.tgz", + "integrity": "sha512-LEiN/xe4OSIbKe9HQIp5OC24agGD9J5CnmMgsLohVVoOPWL9a2sBoR6VBx43jQZb7Kr1l4RCuyCJzcAa0+dojw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.1.8", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.8.tgz", + "integrity": "sha512-9GasEBxpZ1VYIpqHf/0+YGg121uSNwCKOJqIrTwWP/TB7DmFCiaBpNl3aPZzoLWfWkuqhbH8vJIVobZkvdo2cA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.8.tgz", + "integrity": "sha512-EmVxeBAfMJvycdjd6Hm+RbFBbA9fKvo0Kx37hNpBYoYeavH3RNsBXWDooR1mgD52dCrxIIuP7UotpfiwOikvcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.1.8", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.8.tgz", + "integrity": "sha512-acfZboRmAIf05DEKcBQy33VXojFJjtUdLyo7oOmV9kebb2xdU01UknNiPuPZoJZQyO7DF0gZdTGTpeAzET9QPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.8", + "@vitest/utils": "4.1.8", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.8.tgz", + "integrity": "sha512-6EevtBp6OZOPF7bmz36HrGMeP3txgVSrgebWxHOafDXGkhIzfXK14f8KF6MuFfgXXUeHxmpD3BQxkV00/3s5mA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.8.tgz", + "integrity": "sha512-uOJamYALNhfJ6iolExyQM40yIQwDqYnkKtQ5VCiSe17E33H0aQ/u+1GlRuz4LZBk6Mm3sg90G9hEbmEt37C1Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.8", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bootstrap": { + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.7.tgz", + "integrity": "sha512-7KgiD8UHjfcPBHEpDNg+zGz8L3LqR3GVwqZiBRFX04a1BCArZOz1r2kjly2HQ0WokqTO0v1nF+QAt8dsW4lKlw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "license": "MIT", + "peerDependencies": { + "@popperjs/core": "^2.11.8" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "license": "MIT" + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "license": "MIT" + }, + "node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cosmiconfig/node_modules/yaml": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz", + "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/country-flag-icons": { + "version": "1.6.17", + "resolved": "https://registry.npmjs.org/country-flag-icons/-/country-flag-icons-1.6.17.tgz", + "integrity": "sha512-Nmik0289ZVZSI3c7mJR/amg6DyY7Z59b0sTFSKayeX72mHfPzCPJygwJs2pYgQULzuAyWeCUgwAJ+Dq8OR+JFw==", + "license": "MIT" + }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true, + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/date-fns": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.4.0.tgz", + "integrity": "sha512-+1UMbeh68lH1SegH83CGWwpb6OHHbpSgr3+s5Eww5M4CAgswBpoWS0AjTOfEJ33HiYKz1hdj/KTFprzXHmq/6w==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz", + "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/decode-uri-component": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.4.1.tgz", + "integrity": "sha512-+8VxcR21HhTy8nOt6jf20w0c9CADrw1O8d+VZ/YzzCt4bJ3uBjw+D1q2osAB8RnpwwaeYBxy0HyKQxD5JBMuuQ==", + "license": "MIT", + "engines": { + "node": ">=14.16" + } + }, + "node_modules/deepmerge": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", + "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true, + "license": "MIT" + }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-module-lexer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/ez-modal-react": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/ez-modal-react/-/ez-modal-react-1.0.5.tgz", + "integrity": "sha512-/A8yLK54tpmWCMkW8Pwqc2xxspmimGOOw/m+1Y+tNtUIheuDHhLynHP1Q0utciJEGDAK849aQcd+6DrJ88hggQ==", + "license": "MIT", + "peerDependencies": { + "react": ">16.8.0", + "react-dom": ">16.8.0", + "typescript": ">4.0.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/filter-obj": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-5.1.0.tgz", + "integrity": "sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "license": "MIT" + }, + "node_modules/formik": { + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/formik/-/formik-2.4.9.tgz", + "integrity": "sha512-5nI94BMnlFDdQRBY4Sz39WkhxajZJ57Fzs8wVbtsQlm5ScKIR1QLYqv/ultBnobObtlUyxpxoLodpixrsf36Og==", + "funding": [ + { + "type": "individual", + "url": "https://opencollective.com/formik" + } + ], + "license": "Apache-2.0", + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.1", + "deepmerge": "^2.1.1", + "hoist-non-react-statics": "^3.3.0", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "react-fast-compare": "^2.0.1", + "tiny-warning": "^1.0.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generate-password-browser": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/generate-password-browser/-/generate-password-browser-1.1.0.tgz", + "integrity": "sha512-qsQve0rVbCqGqAfKgZwjxKUfI1d1nyd22dz+kE8gn1iw1LxGkR+Slsl79XXfm2wxuK27IkopTs5KXcOEQnhg0w==", + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3", + "randombytes": "^2.0.5" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/happy-dom": { + "version": "20.9.0", + "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-20.9.0.tgz", + "integrity": "sha512-GZZ9mKe8r646NUAf/zemnGbjYh4Bt8/MqASJY+pSm5ZDtc3YQox+4gsLI7yi1hba6o+eCsGxpHn5+iEVn31/FQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": ">=20.0.0", + "@types/whatwg-mimetype": "^3.0.2", + "@types/ws": "^8.18.1", + "entities": "^7.0.1", + "whatwg-mimetype": "^3.0.0", + "ws": "^8.18.3" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hast-util-from-html": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz", + "integrity": "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "devlop": "^1.1.0", + "hast-util-from-parse5": "^8.0.0", + "parse5": "^7.0.0", + "vfile": "^6.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-parse5": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", + "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "hastscript": "^9.0.0", + "property-information": "^7.0.0", + "vfile": "^6.0.0", + "vfile-location": "^5.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-sanitize": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-5.0.2.tgz", + "integrity": "sha512-3yTWghByc50aGS7JlGhk61SPenfE/p1oaFeNwkOOyrscaOkMGrcW9+Cy/QAIOBpZxP1yqDIzFMR0+Np0i0+usg==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "unist-util-position": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-html": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", + "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", + "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-string": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.1.tgz", + "integrity": "sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hastscript": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz", + "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^4.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/html-url-attributes": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz", + "integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/humps": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/humps/-/humps-2.0.1.tgz", + "integrity": "sha512-E0eIbrFWUhwfXJmsbdjRQFQPrl5pTEoKlz163j1mTqqUnU9PgR4AgB8AIITzuB3vLBdxZXyZ9TDIrwB2OASz4g==", + "license": "MIT" + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/immutable": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.5.tgz", + "integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==", + "dev": true, + "license": "MIT" + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/inline-style-parser": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", + "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", + "license": "MIT" + }, + "node_modules/intl-messageformat": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-11.2.7.tgz", + "integrity": "sha512-+q6Ktg119nULZEpZ8YTuGOst9MyEzFtjD63FTGBlN1mLz0Z/MOUYDIvnpVKwq17eezIEh+cfJIebfJoCetpiNw==", + "license": "BSD-3-Clause", + "dependencies": { + "@formatjs/fast-memoize": "3.1.5", + "@formatjs/icu-messageformat-parser": "3.5.10" + } + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/jsbi": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-4.3.2.tgz", + "integrity": "sha512-9fqMSQbhJykSeii05nxKl4m6Eqn2P6rOlYiS+C5Dr/HPIU/7yZxu5qzbs40tgaFORiw2Amd0mirjxatXYMkIew==", + "license": "Apache-2.0", + "optional": true + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT" + }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz", + "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==", + "license": "MIT" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "license": "MIT" + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, + "license": "MIT", + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", + "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", + "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==", + "license": "MIT" + }, + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/npm-run-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", + "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0", + "unicorn-magic": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-numeric-range": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz", + "integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==", + "license": "ISC" + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-simple-vars": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-simple-vars/-/postcss-simple-vars-7.0.1.tgz", + "integrity": "sha512-5GLLXaS8qmzHMOjVxqkk1TZPf1jMqesiI7qLhnlyERalG0sMbHIbJqrcnrpmZdKCLglHnRHoEBB61RtGTsj++A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.1" + } + }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true, + "license": "MIT" + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types-extra": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz", + "integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==", + "license": "MIT", + "dependencies": { + "react-is": "^16.3.2", + "warning": "^4.0.0" + }, + "peerDependencies": { + "react": ">=0.14.0" + } + }, + "node_modules/proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, + "node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/query-string": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-9.4.0.tgz", + "integrity": "sha512-ivvWyHqU9K1Log4hJFhqVIIMoEi0nzmlRhvk2pPcTuQH/Y0K5iTTMxEx7R0PRHD2Z1hMVbWnjfsEWbIKIK+3IA==", + "license": "MIT", + "dependencies": { + "decode-uri-component": "^0.4.1", + "filter-obj": "^5.1.0", + "split-on-first": "^3.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/raf": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", + "license": "MIT", + "dependencies": { + "performance-now": "^2.1.0" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/react": { + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz", + "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-bootstrap": { + "version": "2.10.10", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.10.10.tgz", + "integrity": "sha512-gMckKUqn8aK/vCnfwoBpBVFUGT9SVQxwsYrp9yDHt0arXMamxALerliKBxr1TPbntirK/HGrUAHYbAeQTa9GHQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7", + "@restart/hooks": "^0.4.9", + "@restart/ui": "^1.9.4", + "@types/prop-types": "^15.7.12", + "@types/react-transition-group": "^4.4.6", + "classnames": "^2.3.2", + "dom-helpers": "^5.2.1", + "invariant": "^2.2.4", + "prop-types": "^15.8.1", + "prop-types-extra": "^1.1.0", + "react-transition-group": "^4.4.5", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" + }, + "peerDependencies": { + "@types/react": ">=16.14.8", + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-dom": { + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.7.tgz", + "integrity": "sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.7" + } + }, + "node_modules/react-fast-compare": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz", + "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==", + "license": "MIT" + }, + "node_modules/react-intl": { + "version": "10.1.11", + "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-10.1.11.tgz", + "integrity": "sha512-9VCaWKumbrP91QvS50IYRlbZsD4KdSLwcfEeF9CQLmnqK9qCvFCfyof694I9lqHJL2/TUxBwLCA+whjF129oAg==", + "license": "BSD-3-Clause", + "dependencies": { + "@formatjs/icu-messageformat-parser": "3.5.10", + "@formatjs/intl": "4.1.12", + "intl-messageformat": "11.2.7" + }, + "peerDependencies": { + "@types/react": "19", + "react": "19" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==", + "license": "MIT" + }, + "node_modules/react-markdown": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz", + "integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "html-url-attributes": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "unified": "^11.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=18", + "react": ">=18" + } + }, + "node_modules/react-router": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.16.0.tgz", + "integrity": "sha512-wArC8lVyJb3+jM9OpDyW6hLCizACWkvQR/sSGqSs+o5uEXEtGlqdZ4v8hENR3Jad6i+LRkK93q/+bQAcvl6V1A==", + "license": "MIT", + "dependencies": { + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router-dom": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.16.0.tgz", + "integrity": "sha512-kMUAbimWB5FVbF4Bce4bJsiKJWLIUHq/mEG8+CFDnCSgltptBiG5nguducmsJeGKytlCvQud9Qhzpn49iduTlA==", + "license": "MIT", + "dependencies": { + "react-router": "7.16.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/react-select": { + "version": "5.10.2", + "resolved": "https://registry.npmjs.org/react-select/-/react-select-5.10.2.tgz", + "integrity": "sha512-Z33nHdEFWq9tfnfVXaiM12rbJmk+QjFEztWLtmXqQhz6Al4UZZ9xc0wiatmGtUOCCnHN0WizL3tCMYRENX4rVQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.0", + "@emotion/cache": "^11.4.0", + "@emotion/react": "^11.8.1", + "@floating-ui/dom": "^1.0.1", + "@types/react-transition-group": "^4.4.0", + "memoize-one": "^6.0.0", + "prop-types": "^15.6.0", + "react-transition-group": "^4.3.0", + "use-isomorphic-layout-effect": "^1.2.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/react-toastify": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-11.1.0.tgz", + "integrity": "sha512-e9h23x3phN0wbFeB6yovmWp7lobzV4CaCH0LO8nVP6H7Y+3GbcLpIzMm9dJhcp1RXbpyfvjgpfXqO80QAmn7sg==", + "license": "MIT", + "dependencies": { + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": "^18 || ^19", + "react-dom": "^18 || ^19" + } + }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, + "node_modules/readdirp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/refractor": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/refractor/-/refractor-4.9.0.tgz", + "integrity": "sha512-nEG1SPXFoGGx+dcjftjv8cAjEusIh6ED1xhf5DG3C0x/k+rmZ2duKnc3QLpt6qeHv5fPb8uwN3VWN2BT7fr3Og==", + "license": "MIT", + "dependencies": { + "@types/hast": "^2.0.0", + "@types/prismjs": "^1.0.0", + "hastscript": "^7.0.0", + "parse-entities": "^4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/@types/hast": { + "version": "2.3.10", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz", + "integrity": "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2" + } + }, + "node_modules/refractor/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" + }, + "node_modules/refractor/node_modules/hast-util-parse-selector": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz", + "integrity": "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/refractor/node_modules/hastscript": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.2.0.tgz", + "integrity": "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^3.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/refractor/node_modules/property-information": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/rehype": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/rehype/-/rehype-13.0.2.tgz", + "integrity": "sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "rehype-parse": "^9.0.0", + "rehype-stringify": "^10.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-parse": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz", + "integrity": "sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-from-html": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-prism-plus": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/rehype-prism-plus/-/rehype-prism-plus-2.0.0.tgz", + "integrity": "sha512-FeM/9V2N7EvDZVdR2dqhAzlw5YI49m9Tgn7ZrYJeYHIahM6gcXpH0K1y2gNnKanZCydOMluJvX2cB9z3lhY8XQ==", + "license": "MIT", + "dependencies": { + "hast-util-to-string": "^3.0.0", + "parse-numeric-range": "^1.3.0", + "refractor": "^4.8.0", + "rehype-parse": "^9.0.0", + "unist-util-filter": "^5.0.0", + "unist-util-visit": "^5.0.0" + } + }, + "node_modules/rehype-sanitize": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/rehype-sanitize/-/rehype-sanitize-6.0.0.tgz", + "integrity": "sha512-CsnhKNsyI8Tub6L4sm5ZFsme4puGfc6pYylvXo1AeqaGbjOYyzNv3qZPwvs0oMJ39eryyeOdmxwUIo94IpEhqg==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-sanitize": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-stringify": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.1.tgz", + "integrity": "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-to-html": "^9.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", + "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/rolldown": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.3.tgz", + "integrity": "sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.133.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.3", + "@rolldown/binding-darwin-arm64": "1.0.3", + "@rolldown/binding-darwin-x64": "1.0.3", + "@rolldown/binding-freebsd-x64": "1.0.3", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.3", + "@rolldown/binding-linux-arm64-gnu": "1.0.3", + "@rolldown/binding-linux-arm64-musl": "1.0.3", + "@rolldown/binding-linux-ppc64-gnu": "1.0.3", + "@rolldown/binding-linux-s390x-gnu": "1.0.3", + "@rolldown/binding-linux-x64-gnu": "1.0.3", + "@rolldown/binding-linux-x64-musl": "1.0.3", + "@rolldown/binding-openharmony-arm64": "1.0.3", + "@rolldown/binding-wasm32-wasi": "1.0.3", + "@rolldown/binding-win32-arm64-msvc": "1.0.3", + "@rolldown/binding-win32-x64-msvc": "1.0.3" + } + }, + "node_modules/rooks": { + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/rooks/-/rooks-9.8.0.tgz", + "integrity": "sha512-S6FqnmERx5zgl8ZUEcnyTe1jgjwE5xeFCgOV4bzgQHKp26P7YA7uPnzzOgacojtoX6E7pQTcewSGqN83wVyz+g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "lodash.debounce": "^4.0.8", + "raf": "^3.4.1", + "use-sync-external-store": "^1.6.0" + }, + "engines": { + "node": ">=v10.24.1" + }, + "optionalDependencies": { + "@js-temporal/polyfill": "^0.5.1" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/sass": { + "version": "1.100.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.100.0.tgz", + "integrity": "sha512-B5j0rYMlinhhOo9tjQebMVVn0TfyXAF+wB3b2ggZUuJ/is/Y+7+JGjirAMxHZ9Z3hIP98NPfamlAkBHa1lAaXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^5.0.0", + "immutable": "^5.1.5", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=20.19.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "license": "MIT" + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/split-on-first": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-3.0.0.tgz", + "integrity": "sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.1.0.tgz", + "integrity": "sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/style-to-js": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", + "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==", + "license": "MIT", + "dependencies": { + "style-to-object": "1.0.14" + } + }, + "node_modules/style-to-object": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", + "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.2.7" + } + }, + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", + "license": "MIT" + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", + "license": "MIT" + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyrainbow": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", + "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tmp": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", + "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/typescript": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uncontrollable": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz", + "integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.6.3", + "@types/react": ">=16.9.11", + "invariant": "^2.2.4", + "react-lifecycles-compat": "^3.0.4" + }, + "peerDependencies": { + "react": ">=15.0.0" + } + }, + "node_modules/undici-types": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", + "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", + "dev": true, + "license": "MIT" + }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-filter": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/unist-util-filter/-/unist-util-filter-5.0.1.tgz", + "integrity": "sha512-pHx7D4Zt6+TsfwylH9+lYhBhzyhEnCXs/lbq/Hstxno5z4gVdyc2WEW0asfjGKPyG4pEKrnBv5hdkO6+aRnQJw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/use-isomorphic-layout-effect": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.1.tgz", + "integrity": "sha512-tpZZ+EX0gaghDAiFR37hj5MgY6ZN55kLiPkJsKxBMZ6GZdOSPJXiOzPM984oPYZ5AnehYx5WQp1+ME8I/P/pRA==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", + "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vite": { + "version": "8.0.16", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.16.tgz", + "integrity": "sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lightningcss": "^1.32.0", + "picomatch": "^4.0.4", + "postcss": "^8.5.15", + "rolldown": "1.0.3", + "tinyglobby": "^0.2.17" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.1.18", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-plugin-checker": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/vite-plugin-checker/-/vite-plugin-checker-0.14.1.tgz", + "integrity": "sha512-Mv8oQc9XYBYf+XkP/riqqQCt8lBP6Iad75PZPho1lHRrpxQI0BwX2gwE10enn4f6Hgc+PvR1F7N38KARcaJtzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "chokidar": "^5.0.0", + "npm-run-path": "^6.0.0", + "picocolors": "^1.1.1", + "picomatch": "^4.0.4", + "proper-lockfile": "^4.1.2", + "tiny-invariant": "^1.3.3" + }, + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@biomejs/biome": ">=2.4.12", + "eslint": ">=9.39.4", + "meow": "^13.2.0 || ^14.0.0", + "optionator": "^0.9.4", + "oxlint": ">=1", + "stylelint": ">=16.26.1", + "typescript": "*", + "vite": ">=5.4.21", + "vue-tsc": "~2.2.10 || ^3.0.0" + }, + "peerDependenciesMeta": { + "@biomejs/biome": { + "optional": true + }, + "eslint": { + "optional": true + }, + "meow": { + "optional": true + }, + "optionator": { + "optional": true + }, + "oxlint": { + "optional": true + }, + "stylelint": { + "optional": true + }, + "typescript": { + "optional": true + }, + "vue-tsc": { + "optional": true + } + } + }, + "node_modules/vitest": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.8.tgz", + "integrity": "sha512-flY6ScbCIt9HThs+C5HS7jvGOB560DJtk/Z15IQROTA6zEy49Nh8T/dofWTQL+n3vswqn87sbJNiuqw1SDp5Ig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.1.8", + "@vitest/mocker": "4.1.8", + "@vitest/pretty-format": "4.1.8", + "@vitest/runner": "4.1.8", + "@vitest/snapshot": "4.1.8", + "@vitest/spy": "4.1.8", + "@vitest/utils": "4.1.8", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.8", + "@vitest/browser-preview": "4.1.8", + "@vitest/browser-webdriverio": "4.1.8", + "@vitest/coverage-istanbul": "4.1.8", + "@vitest/coverage-v8": "4.1.8", + "@vitest/ui": "4.1.8", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/coverage-istanbul": { + "optional": true + }, + "@vitest/coverage-v8": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "vite": { + "optional": false + } + } + }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/web-namespaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ws": { + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/frontend/package.json b/frontend/package.json index a592fda5c8..837abf429d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -34,6 +34,7 @@ "react-dom": "^19.2.7", "react-intl": "^10.1.11", "react-markdown": "^10.1.0", + "rehype-sanitize": "^6.0.0", "react-router-dom": "^7.16.0", "react-select": "^5.10.2", "react-toastify": "^11.1.0", diff --git a/frontend/src/Router.tsx b/frontend/src/Router.tsx index 6aa8f0894f..86048b03ca 100644 --- a/frontend/src/Router.tsx +++ b/frontend/src/Router.tsx @@ -1,5 +1,5 @@ import { lazy, Suspense } from "react"; -import { BrowserRouter, Route, Routes } from "react-router-dom"; +import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom"; import { ErrorNotFound, LoadingPage, @@ -25,6 +25,7 @@ const ProxyHosts = lazy(() => import("src/pages/Nginx/ProxyHosts")); const RedirectionHosts = lazy(() => import("src/pages/Nginx/RedirectionHosts")); const DeadHosts = lazy(() => import("src/pages/Nginx/DeadHosts")); const Streams = lazy(() => import("src/pages/Nginx/Streams")); +const Documentation = lazy(() => import("src/pages/Documentation")); function Router() { const health = useHealth(); @@ -62,6 +63,10 @@ function Router() { } /> } /> + } + /> } /> } /> } /> @@ -70,6 +75,7 @@ function Router() { } /> } /> } /> + } /> } /> diff --git a/frontend/src/api/backend/createApiKey.ts b/frontend/src/api/backend/createApiKey.ts new file mode 100644 index 0000000000..5a4edd58a4 --- /dev/null +++ b/frontend/src/api/backend/createApiKey.ts @@ -0,0 +1,10 @@ +import * as api from "./base"; +import type { ApiKey } from "./getApiKeys"; + +export async function createApiKey(data: { + name: string; + permissions?: Record; + expiresOn?: string | null; +}): Promise { + return await api.post({ url: "/api-keys", data }); +} diff --git a/frontend/src/api/backend/createCredential.ts b/frontend/src/api/backend/createCredential.ts new file mode 100644 index 0000000000..9ac622be92 --- /dev/null +++ b/frontend/src/api/backend/createCredential.ts @@ -0,0 +1,10 @@ +import * as api from "./base"; +import type { StoredCredential } from "./getCredentials"; + +export async function createCredential(data: { + name: string; + dnsProvider: string; + credentials: string; +}): Promise { + return await api.post({ url: "/credentials", data }); +} diff --git a/frontend/src/api/backend/createCredentialProvider.ts b/frontend/src/api/backend/createCredentialProvider.ts new file mode 100644 index 0000000000..9b1dcecd78 --- /dev/null +++ b/frontend/src/api/backend/createCredentialProvider.ts @@ -0,0 +1,6 @@ +import * as api from "./base"; +import type { CredentialProvider } from "./getCredentialProviders"; + +export async function createCredentialProvider(data: Record): Promise { + return await api.post({ url: "/credential-providers", data }); +} diff --git a/frontend/src/api/backend/createWebhook.ts b/frontend/src/api/backend/createWebhook.ts new file mode 100644 index 0000000000..fb5ba5ade7 --- /dev/null +++ b/frontend/src/api/backend/createWebhook.ts @@ -0,0 +1,12 @@ +import * as api from "./base"; +import type { WebhookEndpoint } from "./getWebhooks"; + +export async function createWebhook(data: { + name: string; + url: string; + events: string[]; + secret?: string; + isEnabled?: boolean; +}): Promise { + return await api.post({ url: "/webhooks", data }); +} diff --git a/frontend/src/api/backend/deleteApiKey.ts b/frontend/src/api/backend/deleteApiKey.ts new file mode 100644 index 0000000000..b1b018a7f8 --- /dev/null +++ b/frontend/src/api/backend/deleteApiKey.ts @@ -0,0 +1,5 @@ +import * as api from "./base"; + +export async function deleteApiKey(id: number): Promise { + return await api.del({ url: `/api-keys/${id}` }); +} diff --git a/frontend/src/api/backend/deleteCredential.ts b/frontend/src/api/backend/deleteCredential.ts new file mode 100644 index 0000000000..4ca78f8c2e --- /dev/null +++ b/frontend/src/api/backend/deleteCredential.ts @@ -0,0 +1,5 @@ +import * as api from "./base"; + +export async function deleteCredential(id: number): Promise { + return await api.del({ url: `/credentials/${id}` }); +} diff --git a/frontend/src/api/backend/deleteCredentialProvider.ts b/frontend/src/api/backend/deleteCredentialProvider.ts new file mode 100644 index 0000000000..e2a24c1693 --- /dev/null +++ b/frontend/src/api/backend/deleteCredentialProvider.ts @@ -0,0 +1,5 @@ +import * as api from "./base"; + +export async function deleteCredentialProvider(id: number): Promise { + return await api.del({ url: `/credential-providers/${id}` }); +} diff --git a/frontend/src/api/backend/deleteWebhook.ts b/frontend/src/api/backend/deleteWebhook.ts new file mode 100644 index 0000000000..65f3e26039 --- /dev/null +++ b/frontend/src/api/backend/deleteWebhook.ts @@ -0,0 +1,5 @@ +import * as api from "./base"; + +export async function deleteWebhook(id: number): Promise { + return await api.del({ url: `/webhooks/${id}` }); +} diff --git a/frontend/src/api/backend/getApiKeys.ts b/frontend/src/api/backend/getApiKeys.ts new file mode 100644 index 0000000000..1d94a111e9 --- /dev/null +++ b/frontend/src/api/backend/getApiKeys.ts @@ -0,0 +1,15 @@ +import * as api from "./base"; + +export interface ApiKey { + id: number; + name: string; + keyPrefix: string; + permissions: Record; + expiresOn?: string | null; + lastUsedAt?: string | null; + createdOn: string; +} + +export async function getApiKeys(): Promise { + return await api.get({ url: "/api-keys" }); +} diff --git a/frontend/src/api/backend/getCredentialProviders.ts b/frontend/src/api/backend/getCredentialProviders.ts new file mode 100644 index 0000000000..5cb09295e2 --- /dev/null +++ b/frontend/src/api/backend/getCredentialProviders.ts @@ -0,0 +1,17 @@ +import * as api from "./base"; + +export interface CredentialProvider { + id: number; + name: string; + type: string; + oidcIssuer?: string; + oidcClientId?: string; + oidcAudience?: string; + oidcScope?: string; + meta: Record; + hasOidcSecret?: boolean; +} + +export async function getCredentialProviders(): Promise { + return await api.get({ url: "/credential-providers" }); +} diff --git a/frontend/src/api/backend/getCredentials.ts b/frontend/src/api/backend/getCredentials.ts new file mode 100644 index 0000000000..9c09ad6585 --- /dev/null +++ b/frontend/src/api/backend/getCredentials.ts @@ -0,0 +1,14 @@ +import * as api from "./base"; + +export interface StoredCredential { + id: number; + name: string; + dnsProvider: string; + createdOn: string; + modifiedOn: string; + lastUsedAt?: string | null; +} + +export async function getCredentials(): Promise { + return await api.get({ url: "/credentials" }); +} diff --git a/frontend/src/api/backend/getWebhooks.ts b/frontend/src/api/backend/getWebhooks.ts new file mode 100644 index 0000000000..188049ec43 --- /dev/null +++ b/frontend/src/api/backend/getWebhooks.ts @@ -0,0 +1,13 @@ +import * as api from "./base"; + +export interface WebhookEndpoint { + id: number; + name: string; + url: string; + events: string[]; + isEnabled: boolean; +} + +export async function getWebhooks(): Promise { + return await api.get({ url: "/webhooks" }); +} diff --git a/frontend/src/api/backend/index.ts b/frontend/src/api/backend/index.ts index 40cb4142fc..000ae7ac38 100644 --- a/frontend/src/api/backend/index.ts +++ b/frontend/src/api/backend/index.ts @@ -1,5 +1,9 @@ export * from "./checkVersion"; +export * from "./createApiKey"; export * from "./createAccessList"; +export * from "./createCredential"; +export * from "./createCredentialProvider"; +export * from "./createWebhook"; export * from "./createCertificate"; export * from "./createDeadHost"; export * from "./createProxyHost"; @@ -7,6 +11,10 @@ export * from "./createRedirectionHost"; export * from "./createStream"; export * from "./createUser"; export * from "./deleteAccessList"; +export * from "./deleteApiKey"; +export * from "./deleteCredential"; +export * from "./deleteCredentialProvider"; +export * from "./deleteWebhook"; export * from "./deleteCertificate"; export * from "./deleteDeadHost"; export * from "./deleteProxyHost"; @@ -16,6 +24,10 @@ export * from "./deleteUser"; export * from "./downloadCertificate"; export * from "./expansions"; export * from "./getAccessList"; +export * from "./getApiKeys"; +export * from "./getCredentialProviders"; +export * from "./getCredentials"; +export * from "./getWebhooks"; export * from "./getAccessLists"; export * from "./getAuditLog"; export * from "./getAuditLogs"; @@ -39,11 +51,15 @@ export * from "./getUser"; export * from "./getUsers"; export * from "./helpers"; export * from "./loginAsUser"; +export * from "./migrateLegacyCredentials"; export * from "./models"; export * from "./refreshToken"; export * from "./renewCertificate"; export * from "./responseTypes"; export * from "./setPermissions"; +export * from "./testCredentialProvider"; +export * from "./updateCredential"; +export * from "./updateCredentialProvider"; export * from "./testHttpCertificate"; export * from "./toggleDeadHost"; export * from "./toggleProxyHost"; diff --git a/frontend/src/api/backend/migrateLegacyCredentials.ts b/frontend/src/api/backend/migrateLegacyCredentials.ts new file mode 100644 index 0000000000..6ef292ce3d --- /dev/null +++ b/frontend/src/api/backend/migrateLegacyCredentials.ts @@ -0,0 +1,5 @@ +import * as api from "./base"; + +export async function migrateLegacyCredentials(dryRun = false) { + return await api.post({ url: "/credentials/migrate-legacy", data: { dryRun } }); +} diff --git a/frontend/src/api/backend/models.ts b/frontend/src/api/backend/models.ts index 2ae0b08348..eb438bbeff 100644 --- a/frontend/src/api/backend/models.ts +++ b/frontend/src/api/backend/models.ts @@ -2,6 +2,8 @@ export interface AppVersion { major: number; minor: number; revision: number; + /** Semantic version label from API (e.g. v3.0.0). */ + string?: string; } export interface UserPermissions { @@ -16,6 +18,7 @@ export interface UserPermissions { streams: string; accessLists: string; certificates: string; + credentials: string; } export interface User { diff --git a/frontend/src/api/backend/testCredentialProvider.ts b/frontend/src/api/backend/testCredentialProvider.ts new file mode 100644 index 0000000000..7a3dd3987a --- /dev/null +++ b/frontend/src/api/backend/testCredentialProvider.ts @@ -0,0 +1,9 @@ +import * as api from "./base"; + +export async function testCredentialProvider(id: number) { + return await api.post({ url: `/credential-providers/${id}/test` }); +} + +export async function testCredentialProviderResolve(id: number, path: string, field?: string) { + return await api.post({ url: `/credential-providers/${id}/test-resolve`, data: { path, field } }); +} diff --git a/frontend/src/api/backend/updateCredential.ts b/frontend/src/api/backend/updateCredential.ts new file mode 100644 index 0000000000..e5be234c58 --- /dev/null +++ b/frontend/src/api/backend/updateCredential.ts @@ -0,0 +1,9 @@ +import * as api from "./base"; +import type { StoredCredential } from "./getCredentials"; + +export async function updateCredential( + id: number, + data: Partial<{ name: string; dnsProvider: string; credentials: string }>, +): Promise { + return await api.put({ url: `/credentials/${id}`, data }); +} diff --git a/frontend/src/api/backend/updateCredentialProvider.ts b/frontend/src/api/backend/updateCredentialProvider.ts new file mode 100644 index 0000000000..251b77cfa0 --- /dev/null +++ b/frontend/src/api/backend/updateCredentialProvider.ts @@ -0,0 +1,9 @@ +import * as api from "./base"; +import type { CredentialProvider } from "./getCredentialProviders"; + +export async function updateCredentialProvider( + id: number, + data: Record, +): Promise { + return await api.put({ url: `/credential-providers/${id}`, data }); +} diff --git a/frontend/src/components/Form/DNSProviderFields.tsx b/frontend/src/components/Form/DNSProviderFields.tsx index 182654811a..3808c37778 100644 --- a/frontend/src/components/Form/DNSProviderFields.tsx +++ b/frontend/src/components/Form/DNSProviderFields.tsx @@ -4,7 +4,7 @@ import { Field, useFormikContext } from "formik"; import { useState } from "react"; import Select, { type ActionMeta } from "react-select"; import type { DNSProvider } from "src/api/backend"; -import { useDnsProviders } from "src/hooks"; +import { useCredentialProviders, useCredentials, useDnsProviders } from "src/hooks"; import { intl, T } from "src/locale"; import styles from "./DNSProviderFields.module.css"; @@ -20,13 +20,18 @@ interface Props { export function DNSProviderFields({ showBoundaryBox = false }: Props) { const { values, setFieldValue } = useFormikContext(); const { data: dnsProviders, isLoading } = useDnsProviders(); + const { data: storedCredentials } = useCredentials(); + const { data: externalProviders } = useCredentialProviders(); const [dnsProviderId, setDnsProviderId] = useState(null); + const [credentialSource, setCredentialSource] = useState<"manual" | "internal" | "external">("manual"); const v: any = values || {}; const handleChange = (newValue: any, _actionMeta: ActionMeta) => { setFieldValue("meta.dnsProvider", newValue?.value); setFieldValue("meta.dnsProviderCredentials", newValue?.credentials); + setFieldValue("meta.credentialRef", undefined); + setCredentialSource("manual"); setDnsProviderId(newValue?.value); }; @@ -69,6 +74,116 @@ export function DNSProviderFields({ showBoundaryBox = false }: Props) { {dnsProviderId ? ( <> +
+ + +
+ + {credentialSource === "internal" && storedCredentials?.length ? ( +
+ + +
+ ) : null} + + {credentialSource === "external" && externalProviders?.length ? ( +
+
+ + +
+
+ + { + setFieldValue("meta.credentialRef", { + type: "external", + providerId: v.meta?.credentialRef?.providerId, + path: e.target.value, + }); + }} + /> +
+
+ ) : null} + + {credentialSource === "manual" ? ( {({ field }: any) => (
@@ -105,6 +220,7 @@ export function DNSProviderFields({ showBoundaryBox = false }: Props) {
)}
+ ) : null} {({ field }: any) => (
diff --git a/frontend/src/components/Form/FormLabelWithHelp.tsx b/frontend/src/components/Form/FormLabelWithHelp.tsx new file mode 100644 index 0000000000..ee286cd683 --- /dev/null +++ b/frontend/src/components/Form/FormLabelWithHelp.tsx @@ -0,0 +1,23 @@ +import { IconHelp } from "@tabler/icons-react"; +import type { ReactNode } from "react"; +import OverlayTrigger from "react-bootstrap/OverlayTrigger"; +import Tooltip from "react-bootstrap/Tooltip"; + +type Props = { + label: ReactNode; + help: string; + htmlFor?: string; +}; + +export function FormLabelWithHelp({ label, help, htmlFor }: Props) { + return ( + + ); +} diff --git a/frontend/src/components/Form/index.ts b/frontend/src/components/Form/index.ts index f218b2e330..f12fad0ddc 100644 --- a/frontend/src/components/Form/index.ts +++ b/frontend/src/components/Form/index.ts @@ -1,3 +1,4 @@ +export * from "./FormLabelWithHelp"; export * from "./AccessClientFields"; export * from "./AccessField"; export * from "./BasicAuthFields"; diff --git a/frontend/src/components/SiteFooter.tsx b/frontend/src/components/SiteFooter.tsx index df903a6099..e15d84b183 100644 --- a/frontend/src/components/SiteFooter.tsx +++ b/frontend/src/components/SiteFooter.tsx @@ -10,7 +10,7 @@ export function SiteFooter() { return ""; } const v = health.data.version; - return `v${v.major}.${v.minor}.${v.revision}`; + return v.string ?? `v${v.major}.${v.minor}.${v.revision}`; }; return ( @@ -19,6 +19,11 @@ export function SiteFooter() {
+
+ + + {({ field, form }: any) => getPermissionButtons(field, form)} + +
)} diff --git a/frontend/src/modals/index.ts b/frontend/src/modals/index.ts index a06a0c0d71..49811a75ec 100644 --- a/frontend/src/modals/index.ts +++ b/frontend/src/modals/index.ts @@ -1,5 +1,6 @@ export * from "./AccessListModal"; export * from "./ChangePasswordModal"; +export * from "./CredentialModal"; export * from "./CustomCertificateModal"; export * from "./DeadHostModal"; export * from "./DeleteConfirmModal"; diff --git a/frontend/src/modules/AuthStore.ts b/frontend/src/modules/AuthStore.ts index 9978aaa2f6..5423777c6e 100644 --- a/frontend/src/modules/AuthStore.ts +++ b/frontend/src/modules/AuthStore.ts @@ -1,7 +1,9 @@ import { getUnixTime, parseISO } from "date-fns"; import type { TokenResponse } from "src/api/backend"; -export const TOKEN_KEY = "authentications"; +/** localStorage key for the auth session stack (not a credential). */ +export const AUTH_SESSION_STORAGE_KEY = "npm_auth_sessions"; +export const TOKEN_KEY = AUTH_SESSION_STORAGE_KEY; export class AuthStore { // Get all tokens from stack diff --git a/frontend/src/modules/Permissions.ts b/frontend/src/modules/Permissions.ts index 2d784213e4..ebc5309e20 100644 --- a/frontend/src/modules/Permissions.ts +++ b/frontend/src/modules/Permissions.ts @@ -8,6 +8,7 @@ export const DEAD_HOSTS = "deadHosts"; export const STREAMS = "streams"; export const CERTIFICATES = "certificates"; export const ACCESS_LISTS = "accessLists"; +export const CREDENTIALS = "credentials"; export const MANAGE = "manage"; export const VIEW = "view"; @@ -24,7 +25,8 @@ export type Section = | typeof DEAD_HOSTS | typeof STREAMS | typeof CERTIFICATES - | typeof ACCESS_LISTS; + | typeof ACCESS_LISTS + | typeof CREDENTIALS; export type Permission = typeof MANAGE | typeof VIEW; diff --git a/frontend/src/pages/Credentials/Table.tsx b/frontend/src/pages/Credentials/Table.tsx new file mode 100644 index 0000000000..71fe39659e --- /dev/null +++ b/frontend/src/pages/Credentials/Table.tsx @@ -0,0 +1,96 @@ +import { IconDotsVertical, IconEdit, IconTrash } from "@tabler/icons-react"; +import { createColumnHelper, getCoreRowModel, useReactTable } from "@tanstack/react-table"; +import { useMemo } from "react"; +import type { StoredCredential } from "src/api/backend/getCredentials"; +import { EmptyData, HasPermission, ValueWithDateFormatter } from "src/components"; +import { TableLayout } from "src/components/Table/TableLayout"; +import { intl, T } from "src/locale"; +import { CREDENTIALS, MANAGE } from "src/modules/Permissions"; + +interface Props { + data: StoredCredential[]; + isFiltered?: boolean; + isFetching?: boolean; + onEdit: (item: StoredCredential) => void; + onDelete: (id: number) => void; + onNew: () => void; +} + +export default function Table({ data, isFetching, isFiltered, onEdit, onDelete, onNew }: Props) { + const columns = useMemo(() => { + const columnHelper = createColumnHelper(); + return [ + columnHelper.accessor("name", { + header: intl.formatMessage({ id: "column.name" }), + cell: (info) => ( + + ), + }), + columnHelper.accessor("dnsProvider", { + header: intl.formatMessage({ id: "certificates.dns.provider" }), + }), + columnHelper.accessor("lastUsedAt", { + header: "Last used", + cell: (info) => info.getValue() || "—", + }), + columnHelper.display({ + id: "actions", + cell: (info) => ( + + +
+ + ), + }), + ]; + }, [onDelete, onEdit]); + + const tableInstance = useReactTable({ + data, + columns, + getCoreRowModel: getCoreRowModel(), + rowCount: data.length, + meta: { + isFetching, + }, + }); + + return ( + + } + /> + ); +} diff --git a/frontend/src/pages/Documentation/Documentation.module.css b/frontend/src/pages/Documentation/Documentation.module.css new file mode 100644 index 0000000000..93e065d799 --- /dev/null +++ b/frontend/src/pages/Documentation/Documentation.module.css @@ -0,0 +1,4 @@ +.documentationIframe { + min-height: calc(100vh - 180px); + height: calc(100vh - 180px); +} diff --git a/frontend/src/pages/Documentation/index.tsx b/frontend/src/pages/Documentation/index.tsx new file mode 100644 index 0000000000..75fd478bb3 --- /dev/null +++ b/frontend/src/pages/Documentation/index.tsx @@ -0,0 +1,51 @@ +import { IconExternalLink } from "@tabler/icons-react"; +import { useSearchParams } from "react-router-dom"; +import { DOCS_BASE, HELP_SECTION_DOC_PATHS } from "src/config/docs"; +import { T } from "src/locale"; +import styles from "./Documentation.module.css"; + +export default function Documentation() { + const [searchParams] = useSearchParams(); + const section = searchParams.get("section"); + const docPath = + section && section in HELP_SECTION_DOC_PATHS + ? HELP_SECTION_DOC_PATHS[section] + : "/guide/"; + const iframeSrc = `${DOCS_BASE}${docPath}`; + + return ( +
+
+
+
+
+
+

+ +

+
+ +
+
+
+