From 8d5ecf8f68ea2c0bf31149a9832248334a6f5446 Mon Sep 17 00:00:00 2001 From: florida117 <77394159+florida117@users.noreply.github.com> Date: Tue, 3 Feb 2026 08:19:16 +0000 Subject: [PATCH 01/12] Add WebAuthn/Passkey authentication support Implements passwordless passkey login alongside the existing email/password flow. Passkeys provide phishing-resistant, multi-factor authentication (device + biometric) and bypass TOTP 2FA when used. Closes #3363 Co-Authored-By: Claude Opus 4.5 --- backend/internal/token.js | 34 + backend/internal/webauthn.js | 396 +++++++ .../20260203120000_webauthn_credentials.js | 51 + backend/models/webauthn_credential.js | 67 ++ backend/package.json | 1 + backend/routes/tokens.js | 46 + backend/routes/users.js | 145 +++ .../paths/tokens/passkey/options/post.json | 44 + .../paths/tokens/passkey/verify/post.json | 41 + .../paths/users/userID/passkeys/get.json | 36 + .../userID/passkeys/passkeyID/delete.json | 32 + .../users/userID/passkeys/passkeyID/put.json | 59 + .../passkeys/register/options/post.json | 30 + .../userID/passkeys/register/verify/post.json | 61 + backend/schema/swagger.json | 33 + backend/yarn.lock | 1046 ++++++++++------- frontend/package.json | 1 + frontend/src/api/backend/index.ts | 1 + frontend/src/api/backend/passkeys.ts | 80 ++ frontend/src/api/backend/responseTypes.ts | 23 + frontend/src/components/SiteHeader.tsx | 15 +- frontend/src/context/AuthContext.tsx | 12 + frontend/src/locale/src/en.json | 42 + frontend/src/modals/PasskeyModal.tsx | 312 +++++ frontend/src/modals/index.ts | 1 + frontend/src/pages/Login/index.tsx | 32 +- frontend/yarn.lock | 210 ++-- 27 files changed, 2287 insertions(+), 564 deletions(-) create mode 100644 backend/internal/webauthn.js create mode 100644 backend/migrations/20260203120000_webauthn_credentials.js create mode 100644 backend/models/webauthn_credential.js create mode 100644 backend/schema/paths/tokens/passkey/options/post.json create mode 100644 backend/schema/paths/tokens/passkey/verify/post.json create mode 100644 backend/schema/paths/users/userID/passkeys/get.json create mode 100644 backend/schema/paths/users/userID/passkeys/passkeyID/delete.json create mode 100644 backend/schema/paths/users/userID/passkeys/passkeyID/put.json create mode 100644 backend/schema/paths/users/userID/passkeys/register/options/post.json create mode 100644 backend/schema/paths/users/userID/passkeys/register/verify/post.json create mode 100644 frontend/src/api/backend/passkeys.ts create mode 100644 frontend/src/modals/PasskeyModal.tsx diff --git a/backend/internal/token.js b/backend/internal/token.js index 126283e2dd..665409b641 100644 --- a/backend/internal/token.js +++ b/backend/internal/token.js @@ -5,6 +5,7 @@ import authModel from "../models/auth.js"; import TokenModel from "../models/token.js"; import userModel from "../models/user.js"; import twoFactor from "./2fa.js"; +import webauthn from "./webauthn.js"; const ERROR_MESSAGE_INVALID_AUTH = "Invalid email or password"; const ERROR_MESSAGE_INVALID_AUTH_I18N = "error.invalid-auth"; @@ -210,6 +211,39 @@ export default { }; }, + /** + * Verify passkey authentication and return full token + * @param {string} challengeToken + * @param {Object} credential + * @param {string} [expiry] + * @returns {Promise} + */ + getTokenFromPasskey: async (challengeToken, credential, expiry, req) => { + const Token = TokenModel(); + const tokenExpiry = expiry || "1d"; + + const userId = await webauthn.verifyAuthentication(challengeToken, credential, req); + + const expiryDate = parseDatePeriod(tokenExpiry); + if (expiryDate === null) { + throw new errs.AuthError(`Invalid expiry time: ${tokenExpiry}`); + } + + const signed = await Token.create({ + iss: "api", + attrs: { + id: userId, + }, + scope: ["user"], + expiresIn: tokenExpiry, + }); + + return { + token: signed.token, + expires: expiryDate.toISOString(), + }; + }, + /** * @param {Object} user * @returns {Promise} diff --git a/backend/internal/webauthn.js b/backend/internal/webauthn.js new file mode 100644 index 0000000000..e91ef3b6ac --- /dev/null +++ b/backend/internal/webauthn.js @@ -0,0 +1,396 @@ +import { + generateRegistrationOptions, + verifyRegistrationResponse, + generateAuthenticationOptions, + verifyAuthenticationResponse, +} from "@simplewebauthn/server"; +import errs from "../lib/error.js"; +import TokenModel from "../models/token.js"; +import userModel from "../models/user.js"; +import webauthnCredentialModel from "../models/webauthn_credential.js"; + +/** + * Derive WebAuthn relying party settings from the request. + * Environment variables override auto-detection if set. + * + * @param {Object} req Express request object + * @returns {{ rpID: string, rpName: string, origin: string }} + */ +const getRP = (req) => { + const rpID = process.env.WEBAUTHN_RP_ID || req.hostname; + const rpName = process.env.WEBAUTHN_RP_NAME || "Nginx Proxy Manager"; + const origin = process.env.WEBAUTHN_ORIGIN + || `${req.protocol}://${req.get("host")}`; + return { rpID, rpName, origin }; +}; + +const internalWebauthn = { + /** + * Generate registration options for a user + * + * @param {Access} access + * @param {number} userId + * @param {Object} req Express request object + * @returns {Promise<{options: Object, challenge_token: string}>} + */ + generateRegOptions: async (access, userId, req) => { + await access.can("users:password", userId); + + const user = await userModel + .query() + .where("id", userId) + .andWhere("is_deleted", 0) + .first(); + + if (!user) { + throw new errs.ItemNotFoundError("User not found"); + } + + const existingCreds = await webauthnCredentialModel + .query() + .where("user_id", userId) + .andWhere("is_deleted", 0); + + const { rpID, rpName } = getRP(req); + + const options = await generateRegistrationOptions({ + rpName, + rpID, + userName: user.email, + userDisplayName: user.name || user.nickname || user.email, + excludeCredentials: existingCreds.map((cred) => ({ + id: cred.credential_id, + transports: cred.transports || [], + })), + authenticatorSelection: { + residentKey: "preferred", + userVerification: "preferred", + }, + }); + + const Token = TokenModel(); + const challengeToken = await Token.create({ + iss: "api", + attrs: { + challenge: options.challenge, + userId: userId, + }, + scope: ["webauthn-reg-challenge"], + expiresIn: "5m", + }); + + return { + options, + challenge_token: challengeToken.token, + }; + }, + + /** + * Verify registration response and store credential + * + * @param {Access} access + * @param {number} userId + * @param {string} challengeToken + * @param {Object} credential + * @param {string} friendlyName + * @param {Object} req Express request object + * @returns {Promise} + */ + verifyRegistration: async (access, userId, challengeToken, credential, friendlyName, req) => { + await access.can("users:password", userId); + + const Token = TokenModel(); + let tokenData; + try { + tokenData = await Token.load(challengeToken); + } catch { + throw new errs.AuthError("Invalid or expired challenge token"); + } + + if (!tokenData.scope || tokenData.scope[0] !== "webauthn-reg-challenge") { + throw new errs.AuthError("Invalid challenge token"); + } + + if (tokenData.attrs?.userId !== userId) { + throw new errs.AuthError("Challenge token does not match user"); + } + + const expectedChallenge = tokenData.attrs?.challenge; + if (!expectedChallenge) { + throw new errs.AuthError("Invalid challenge token"); + } + + const { rpID, origin } = getRP(req); + + let verification; + try { + verification = await verifyRegistrationResponse({ + response: credential, + expectedChallenge, + expectedOrigin: origin, + expectedRPID: rpID, + }); + } catch (err) { + throw new errs.AuthError(`Registration verification failed: ${err.message}`); + } + + if (!verification.verified || !verification.registrationInfo) { + throw new errs.AuthError("Registration verification failed"); + } + + const { credential: regCredential, credentialDeviceType, credentialBackedUp } = verification.registrationInfo; + + const record = await webauthnCredentialModel.query().insertAndFetch({ + user_id: userId, + credential_id: regCredential.id, + public_key: Buffer.from(regCredential.publicKey).toString("base64url"), + counter: regCredential.counter, + transports: credential.response?.transports || [], + device_type: credentialDeviceType, + backed_up: credentialBackedUp ? 1 : 0, + friendly_name: friendlyName || "", + }); + + return { + id: record.id, + friendly_name: record.friendly_name, + created_on: record.created_on, + device_type: record.device_type, + backed_up: record.backed_up, + }; + }, + + /** + * Generate authentication options + * + * @param {string|null} email Optional email to filter credentials + * @param {Object} req Express request object + * @returns {Promise<{options: Object, challenge_token: string}>} + */ + generateAuthOptions: async (email, req) => { + const { rpID } = getRP(req); + + let allowCredentials; + if (email) { + const user = await userModel + .query() + .where("email", email.toLowerCase().trim()) + .andWhere("is_deleted", 0) + .andWhere("is_disabled", 0) + .first(); + + if (!user) { + throw new errs.AuthError("Invalid credentials"); + } + + const creds = await webauthnCredentialModel + .query() + .where("user_id", user.id) + .andWhere("is_deleted", 0); + + if (creds.length === 0) { + throw new errs.AuthError("No passkeys registered for this account"); + } + + allowCredentials = creds.map((cred) => ({ + id: cred.credential_id, + transports: cred.transports || [], + })); + } + + const options = await generateAuthenticationOptions({ + rpID, + userVerification: "preferred", + ...(allowCredentials ? { allowCredentials } : {}), + }); + + const Token = TokenModel(); + const challengeToken = await Token.create({ + iss: "api", + attrs: { + challenge: options.challenge, + }, + scope: ["webauthn-auth-challenge"], + expiresIn: "5m", + }); + + return { + options, + challenge_token: challengeToken.token, + }; + }, + + /** + * Verify authentication response + * + * @param {string} challengeToken + * @param {Object} credential + * @param {Object} req Express request object + * @returns {Promise} userId + */ + verifyAuthentication: async (challengeToken, credential, req) => { + const Token = TokenModel(); + let tokenData; + try { + tokenData = await Token.load(challengeToken); + } catch { + throw new errs.AuthError("Invalid or expired challenge token"); + } + + if (!tokenData.scope || tokenData.scope[0] !== "webauthn-auth-challenge") { + throw new errs.AuthError("Invalid challenge token"); + } + + const expectedChallenge = tokenData.attrs?.challenge; + if (!expectedChallenge) { + throw new errs.AuthError("Invalid challenge token"); + } + + // Look up credential by ID + const dbCredential = await webauthnCredentialModel + .query() + .where("credential_id", credential.id) + .andWhere("is_deleted", 0) + .first(); + + if (!dbCredential) { + throw new errs.AuthError("Passkey not recognized"); + } + + // Verify the user is active + const user = await userModel + .query() + .where("id", dbCredential.user_id) + .andWhere("is_deleted", 0) + .andWhere("is_disabled", 0) + .first(); + + if (!user) { + throw new errs.AuthError("User account is not available"); + } + + const { rpID, origin } = getRP(req); + + let verification; + try { + verification = await verifyAuthenticationResponse({ + response: credential, + expectedChallenge, + expectedOrigin: origin, + expectedRPID: rpID, + credential: { + id: dbCredential.credential_id, + publicKey: Buffer.from(dbCredential.public_key, "base64url"), + counter: dbCredential.counter, + transports: dbCredential.transports || [], + }, + }); + } catch (err) { + throw new errs.AuthError(`Passkey verification failed: ${err.message}`); + } + + if (!verification.verified) { + throw new errs.AuthError("Passkey verification failed"); + } + + // Update counter + await webauthnCredentialModel + .query() + .findById(dbCredential.id) + .patch({ counter: verification.authenticationInfo.newCounter }); + + return user.id; + }, + + /** + * List passkeys for a user + * + * @param {Access} access + * @param {number} userId + * @returns {Promise} + */ + list: async (access, userId) => { + await access.can("users:password", userId); + + const creds = await webauthnCredentialModel + .query() + .where("user_id", userId) + .andWhere("is_deleted", 0) + .orderBy("created_on", "desc"); + + return creds.map((cred) => ({ + id: cred.id, + friendly_name: cred.friendly_name, + created_on: cred.created_on, + device_type: cred.device_type, + backed_up: cred.backed_up, + })); + }, + + /** + * Rename a passkey + * + * @param {Access} access + * @param {number} userId + * @param {number} credentialId + * @param {string} friendlyName + * @returns {Promise} + */ + rename: async (access, userId, credentialId, friendlyName) => { + await access.can("users:password", userId); + + const cred = await webauthnCredentialModel + .query() + .where("id", credentialId) + .andWhere("user_id", userId) + .andWhere("is_deleted", 0) + .first(); + + if (!cred) { + throw new errs.ItemNotFoundError("Passkey not found"); + } + + await webauthnCredentialModel + .query() + .findById(credentialId) + .patch({ friendly_name: friendlyName }); + + return { + id: cred.id, + friendly_name: friendlyName, + created_on: cred.created_on, + device_type: cred.device_type, + backed_up: cred.backed_up, + }; + }, + + /** + * Soft-delete a passkey + * + * @param {Access} access + * @param {number} userId + * @param {number} credentialId + * @returns {Promise} + */ + remove: async (access, userId, credentialId) => { + await access.can("users:password", userId); + + const cred = await webauthnCredentialModel + .query() + .where("id", credentialId) + .andWhere("user_id", userId) + .andWhere("is_deleted", 0) + .first(); + + if (!cred) { + throw new errs.ItemNotFoundError("Passkey not found"); + } + + await webauthnCredentialModel + .query() + .findById(credentialId) + .patch({ is_deleted: 1 }); + }, +}; + +export default internalWebauthn; diff --git a/backend/migrations/20260203120000_webauthn_credentials.js b/backend/migrations/20260203120000_webauthn_credentials.js new file mode 100644 index 0000000000..9b775f7e05 --- /dev/null +++ b/backend/migrations/20260203120000_webauthn_credentials.js @@ -0,0 +1,51 @@ +import { migrate as logger } from "../logger.js"; + +const migrateName = "webauthn-credentials"; + +/** + * Migrate + * + * @see http://knexjs.org/#Schema + * + * @param {Object} knex + * @returns {Promise} + */ +const up = (knex) => { + logger.info(`[${migrateName}] Migrating Up...`); + + return knex.schema + .createTable("webauthn_credential", (table) => { + table.increments().primary(); + table.dateTime("created_on").notNull(); + table.dateTime("modified_on").notNull(); + table.integer("user_id").notNull().unsigned(); + table.string("credential_id", 512).notNull(); + table.text("public_key").notNull(); + table.bigInteger("counter").notNull().unsigned().defaultTo(0); + table.json("transports").notNull(); + table.string("device_type", 30).notNull().defaultTo("singleDevice"); + table.integer("backed_up").notNull().unsigned().defaultTo(0); + table.string("friendly_name", 255).notNull().defaultTo(""); + table.integer("is_deleted").notNull().unsigned().defaultTo(0); + table.unique("credential_id"); + table.index("user_id"); + }) + .then(() => { + logger.info(`[${migrateName}] webauthn_credential Table created`); + }); +}; + +/** + * Undo Migrate + * + * @param {Object} knex + * @returns {Promise} + */ +const down = (knex) => { + logger.info(`[${migrateName}] Migrating Down...`); + return knex.schema.dropTableIfExists("webauthn_credential").then(() => { + logger.info(`[${migrateName}] webauthn_credential Table dropped`); + }); +}; + +export { up, down }; diff --git a/backend/models/webauthn_credential.js b/backend/models/webauthn_credential.js new file mode 100644 index 0000000000..28524ec62e --- /dev/null +++ b/backend/models/webauthn_credential.js @@ -0,0 +1,67 @@ +// Objection Docs: +// http://vincit.github.io/objection.js/ + +import { Model } from "objection"; +import db from "../db.js"; +import { convertBoolFieldsToInt, convertIntFieldsToBool } from "../lib/helpers.js"; +import now from "./now_helper.js"; +import User from "./user.js"; + +Model.knex(db()); + +const boolFields = ["is_deleted", "backed_up"]; + +class WebauthnCredential extends Model { + $beforeInsert() { + this.created_on = now(); + this.modified_on = now(); + + if (typeof this.transports === "undefined") { + this.transports = []; + } + } + + $beforeUpdate() { + this.modified_on = now(); + } + + $parseDatabaseJson(json) { + const thisJson = super.$parseDatabaseJson(json); + return convertIntFieldsToBool(thisJson, boolFields); + } + + $formatDatabaseJson(json) { + const thisJson = convertBoolFieldsToInt(json, boolFields); + return super.$formatDatabaseJson(thisJson); + } + + static get name() { + return "WebauthnCredential"; + } + + static get tableName() { + return "webauthn_credential"; + } + + static get jsonAttributes() { + return ["transports"]; + } + + static get relationMappings() { + return { + user: { + relation: Model.BelongsToOneRelation, + modelClass: User, + join: { + from: "webauthn_credential.user_id", + to: "user.id", + }, + filter: { + is_deleted: 0, + }, + }, + }; + } +} + +export default WebauthnCredential; diff --git a/backend/package.json b/backend/package.json index 93ddfdd68b..8850c7c3b3 100644 --- a/backend/package.json +++ b/backend/package.json @@ -13,6 +13,7 @@ }, "dependencies": { "@apidevtools/json-schema-ref-parser": "^14.1.1", + "@simplewebauthn/server": "^13.2.2", "ajv": "^8.17.1", "archiver": "^7.0.1", "batchflow": "^0.4.0", diff --git a/backend/routes/tokens.js b/backend/routes/tokens.js index 8a6a1bc0fb..13c0949a7c 100644 --- a/backend/routes/tokens.js +++ b/backend/routes/tokens.js @@ -1,5 +1,6 @@ import express from "express"; import internalToken from "../internal/token.js"; +import internalWebauthn from "../internal/webauthn.js"; import jwtdecode from "../lib/express/jwt-decode.js"; import apiValidator from "../lib/validator/api.js"; import { debug, express as logger } from "../logger.js"; @@ -75,4 +76,49 @@ router } }); +router + .route("/passkey/options") + .options((_, res) => { + res.sendStatus(204); + }) + + /** + * POST /tokens/passkey/options + * + * Generate passkey authentication options + */ + .post(async (req, res, next) => { + try { + const data = await apiValidator(getValidationSchema("/tokens/passkey/options", "post"), req.body); + const result = await internalWebauthn.generateAuthOptions(data.email || null, req); + res.status(200).send(result); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }); + +router + .route("/passkey/verify") + .options((_, res) => { + res.sendStatus(204); + }) + + /** + * POST /tokens/passkey/verify + * + * Verify passkey authentication and get full token + */ + .post(async (req, res, next) => { + try { + const data = await apiValidator(getValidationSchema("/tokens/passkey/verify", "post"), req.body); + const credential = JSON.parse(data.credential); + const result = await internalToken.getTokenFromPasskey(data.challenge_token, credential, undefined, req); + res.status(200).send(result); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }); + export default router; diff --git a/backend/routes/users.js b/backend/routes/users.js index 7c3da8c1d1..e0358ba2bb 100644 --- a/backend/routes/users.js +++ b/backend/routes/users.js @@ -1,6 +1,7 @@ import express from "express"; import internal2FA from "../internal/2fa.js"; import internalUser from "../internal/user.js"; +import internalWebauthn from "../internal/webauthn.js"; import Access from "../lib/access.js"; import { isCI } from "../lib/config.js"; import errs from "../lib/error.js"; @@ -452,4 +453,148 @@ router } }); +/** + * User passkeys + * + * /api/users/123/passkeys + */ +router + .route("/:user_id/passkeys") + .options((_, res) => { + res.sendStatus(204); + }) + .all(jwtdecode()) + .all(userIdFromMe) + + /** + * GET /api/users/123/passkeys + * + * List user's registered passkeys + */ + .get(async (req, res, next) => { + try { + const result = await internalWebauthn.list(res.locals.access, req.params.user_id); + res.status(200).send(result); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }); + +/** + * User passkey registration options + * + * /api/users/123/passkeys/register/options + */ +router + .route("/:user_id/passkeys/register/options") + .options((_, res) => { + res.sendStatus(204); + }) + .all(jwtdecode()) + .all(userIdFromMe) + + /** + * POST /api/users/123/passkeys/register/options + * + * Generate passkey registration options + */ + .post(async (req, res, next) => { + try { + const result = await internalWebauthn.generateRegOptions(res.locals.access, req.params.user_id, req); + res.status(200).send(result); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }); + +/** + * User passkey registration verify + * + * /api/users/123/passkeys/register/verify + */ +router + .route("/:user_id/passkeys/register/verify") + .options((_, res) => { + res.sendStatus(204); + }) + .all(jwtdecode()) + .all(userIdFromMe) + + /** + * POST /api/users/123/passkeys/register/verify + * + * Verify passkey registration + */ + .post(async (req, res, next) => { + try { + const credential = JSON.parse(req.body.credential); + const result = await internalWebauthn.verifyRegistration( + res.locals.access, + req.params.user_id, + req.body.challenge_token, + credential, + req.body.friendly_name || "", + req, + ); + res.status(201).send(result); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }); + +/** + * Specific user passkey + * + * /api/users/123/passkeys/456 + */ +router + .route("/:user_id/passkeys/:passkey_id") + .options((_, res) => { + res.sendStatus(204); + }) + .all(jwtdecode()) + .all(userIdFromMe) + + /** + * PUT /api/users/123/passkeys/456 + * + * Rename a passkey + */ + .put(async (req, res, next) => { + try { + const result = await internalWebauthn.rename( + res.locals.access, + req.params.user_id, + Number.parseInt(req.params.passkey_id, 10), + req.body.friendly_name, + ); + res.status(200).send(result); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } + }) + + /** + * DELETE /api/users/123/passkeys/456 + * + * Delete a passkey + */ + .delete(async (req, res, next) => { + try { + await internalWebauthn.remove( + res.locals.access, + req.params.user_id, + Number.parseInt(req.params.passkey_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/paths/tokens/passkey/options/post.json b/backend/schema/paths/tokens/passkey/options/post.json new file mode 100644 index 0000000000..2a618bcf25 --- /dev/null +++ b/backend/schema/paths/tokens/passkey/options/post.json @@ -0,0 +1,44 @@ +{ + "operationId": "requestPasskeyAuthOptions", + "summary": "Generate passkey authentication options", + "tags": ["tokens"], + "requestBody": { + "description": "Optional email to filter credentials", + "required": false, + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "email": { + "type": "string", + "format": "email", + "example": "me@example.com" + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "options": { + "type": "object" + }, + "challenge_token": { + "type": "string" + } + } + } + } + }, + "description": "200 response" + } + } +} diff --git a/backend/schema/paths/tokens/passkey/verify/post.json b/backend/schema/paths/tokens/passkey/verify/post.json new file mode 100644 index 0000000000..e6bf6f1538 --- /dev/null +++ b/backend/schema/paths/tokens/passkey/verify/post.json @@ -0,0 +1,41 @@ +{ + "operationId": "verifyPasskeyAuth", + "summary": "Verify passkey authentication and get full token", + "tags": ["tokens"], + "requestBody": { + "description": "Passkey authentication response", + "required": true, + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "challenge_token": { + "minLength": 1, + "type": "string" + }, + "credential": { + "minLength": 1, + "type": "string", + "description": "JSON-stringified WebAuthn credential response" + } + }, + "required": ["challenge_token", "credential"], + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "../../../../components/token-object.json" + } + } + }, + "description": "200 response" + } + } +} diff --git a/backend/schema/paths/users/userID/passkeys/get.json b/backend/schema/paths/users/userID/passkeys/get.json new file mode 100644 index 0000000000..c8b1312982 --- /dev/null +++ b/backend/schema/paths/users/userID/passkeys/get.json @@ -0,0 +1,36 @@ +{ + "operationId": "listPasskeys", + "summary": "List user's registered passkeys", + "tags": ["users"], + "security": [{ "BearerAuth": [] }], + "parameters": [ + { + "in": "path", + "name": "userID", + "schema": { "type": "integer", "minimum": 1 }, + "required": true + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { "type": "integer" }, + "friendly_name": { "type": "string" }, + "created_on": { "type": "string" }, + "device_type": { "type": "string" }, + "backed_up": { "type": "boolean" } + } + } + } + } + }, + "description": "200 response" + } + } +} diff --git a/backend/schema/paths/users/userID/passkeys/passkeyID/delete.json b/backend/schema/paths/users/userID/passkeys/passkeyID/delete.json new file mode 100644 index 0000000000..981772d930 --- /dev/null +++ b/backend/schema/paths/users/userID/passkeys/passkeyID/delete.json @@ -0,0 +1,32 @@ +{ + "operationId": "deletePasskey", + "summary": "Delete a passkey", + "tags": ["users"], + "security": [{ "BearerAuth": [] }], + "parameters": [ + { + "in": "path", + "name": "userID", + "schema": { "type": "integer", "minimum": 1 }, + "required": true + }, + { + "in": "path", + "name": "passkeyID", + "schema": { "type": "integer", "minimum": 1 }, + "required": true + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "boolean" + } + } + }, + "description": "200 response" + } + } +} diff --git a/backend/schema/paths/users/userID/passkeys/passkeyID/put.json b/backend/schema/paths/users/userID/passkeys/passkeyID/put.json new file mode 100644 index 0000000000..f693317ab3 --- /dev/null +++ b/backend/schema/paths/users/userID/passkeys/passkeyID/put.json @@ -0,0 +1,59 @@ +{ + "operationId": "renamePasskey", + "summary": "Rename a passkey", + "tags": ["users"], + "security": [{ "BearerAuth": [] }], + "parameters": [ + { + "in": "path", + "name": "userID", + "schema": { "type": "integer", "minimum": 1 }, + "required": true + }, + { + "in": "path", + "name": "passkeyID", + "schema": { "type": "integer", "minimum": 1 }, + "required": true + } + ], + "requestBody": { + "description": "Passkey rename payload", + "required": true, + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "friendly_name": { + "minLength": 1, + "maxLength": 255, + "type": "string" + } + }, + "required": ["friendly_name"], + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { "type": "integer" }, + "friendly_name": { "type": "string" }, + "created_on": { "type": "string" }, + "device_type": { "type": "string" }, + "backed_up": { "type": "boolean" } + } + } + } + }, + "description": "200 response" + } + } +} diff --git a/backend/schema/paths/users/userID/passkeys/register/options/post.json b/backend/schema/paths/users/userID/passkeys/register/options/post.json new file mode 100644 index 0000000000..955c47f3e6 --- /dev/null +++ b/backend/schema/paths/users/userID/passkeys/register/options/post.json @@ -0,0 +1,30 @@ +{ + "operationId": "getPasskeyRegOptions", + "summary": "Generate passkey registration options", + "tags": ["users"], + "security": [{ "BearerAuth": [] }], + "parameters": [ + { + "in": "path", + "name": "userID", + "schema": { "type": "integer", "minimum": 1 }, + "required": true + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "options": { "type": "object" }, + "challenge_token": { "type": "string" } + } + } + } + }, + "description": "200 response" + } + } +} diff --git a/backend/schema/paths/users/userID/passkeys/register/verify/post.json b/backend/schema/paths/users/userID/passkeys/register/verify/post.json new file mode 100644 index 0000000000..8da4eb52a2 --- /dev/null +++ b/backend/schema/paths/users/userID/passkeys/register/verify/post.json @@ -0,0 +1,61 @@ +{ + "operationId": "verifyPasskeyRegistration", + "summary": "Verify passkey registration and store credential", + "tags": ["users"], + "security": [{ "BearerAuth": [] }], + "parameters": [ + { + "in": "path", + "name": "userID", + "schema": { "type": "integer", "minimum": 1 }, + "required": true + } + ], + "requestBody": { + "description": "Passkey registration response", + "required": true, + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "challenge_token": { + "minLength": 1, + "type": "string" + }, + "credential": { + "minLength": 1, + "type": "string", + "description": "JSON-stringified WebAuthn credential response" + }, + "friendly_name": { + "type": "string", + "maxLength": 255 + } + }, + "required": ["challenge_token", "credential"], + "type": "object" + } + } + } + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { "type": "integer" }, + "friendly_name": { "type": "string" }, + "created_on": { "type": "string" }, + "device_type": { "type": "string" }, + "backed_up": { "type": "boolean" } + } + } + } + }, + "description": "201 response" + } + } +} diff --git a/backend/schema/swagger.json b/backend/schema/swagger.json index 4222f19ddd..f5c65cac0c 100644 --- a/backend/schema/swagger.json +++ b/backend/schema/swagger.json @@ -298,6 +298,16 @@ "$ref": "./paths/tokens/2fa/post.json" } }, + "/tokens/passkey/options": { + "post": { + "$ref": "./paths/tokens/passkey/options/post.json" + } + }, + "/tokens/passkey/verify": { + "post": { + "$ref": "./paths/tokens/passkey/verify/post.json" + } + }, "/version/check": { "get": { "$ref": "./paths/version/check/get.json" @@ -343,6 +353,29 @@ "$ref": "./paths/users/userID/2fa/backup-codes/post.json" } }, + "/users/{userID}/passkeys": { + "get": { + "$ref": "./paths/users/userID/passkeys/get.json" + } + }, + "/users/{userID}/passkeys/register/options": { + "post": { + "$ref": "./paths/users/userID/passkeys/register/options/post.json" + } + }, + "/users/{userID}/passkeys/register/verify": { + "post": { + "$ref": "./paths/users/userID/passkeys/register/verify/post.json" + } + }, + "/users/{userID}/passkeys/{passkeyID}": { + "put": { + "$ref": "./paths/users/userID/passkeys/passkeyID/put.json" + }, + "delete": { + "$ref": "./paths/users/userID/passkeys/passkeyID/delete.json" + } + }, "/users/{userID}/auth": { "put": { "$ref": "./paths/users/userID/auth/put.json" diff --git a/backend/yarn.lock b/backend/yarn.lock index a8688084c3..cd9a1a3bd3 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -4,7 +4,7 @@ "@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" + resolved "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-14.0.1.tgz" integrity sha512-Oc96zvmxx1fqoSEdUmfmvvb59/KDOnUoJ7s2t7bISyAn0XEz57LCCw8k2Y4Pf3mwKaZLMciESALORLgfe2frCw== dependencies: "@types/json-schema" "^7.0.15" @@ -12,7 +12,7 @@ "@apidevtools/json-schema-ref-parser@^14.1.1": version "14.1.1" - resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-14.1.1.tgz#0bae59809b7848c7a89dc6bb2f3bb980b7c290b1" + resolved "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-14.1.1.tgz" integrity sha512-uGF1YGOzzD50L7HLNWclXmsEhQflw8/zZHIz0/AzkJrKL5r9PceUipZxR/cp/8veTk4TVfdDJLyIwXLjaP5ePg== dependencies: "@types/json-schema" "^7.0.15" @@ -20,17 +20,17 @@ "@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" + resolved "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz" 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" + resolved "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz" 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" + resolved "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-12.1.0.tgz" integrity sha512-e5mJoswsnAX0jG+J09xHFYQXb/bUc5S3pLpMxUuRUA2H8T2kni3yEoyz2R3Dltw5f4A6j6rPNMpWTK+iVDFlng== dependencies: "@apidevtools/json-schema-ref-parser" "14.0.1" @@ -42,7 +42,7 @@ "@biomejs/biome@^2.3.12": version "2.3.12" - resolved "https://registry.yarnpkg.com/@biomejs/biome/-/biome-2.3.12.tgz#7cf21b69734ac6a310bcd014d3a0b3b1dc5a1758" + resolved "https://registry.npmjs.org/@biomejs/biome/-/biome-2.3.12.tgz" integrity sha512-AR7h4aSlAvXj7TAajW/V12BOw2EiS0AqZWV5dGozf4nlLoUF/ifvD0+YgKSskT0ylA6dY1A8AwgP8kZ6yaCQnA== optionalDependencies: "@biomejs/cli-darwin-arm64" "2.3.12" @@ -56,7 +56,7 @@ "@biomejs/cli-darwin-arm64@2.3.12": version "2.3.12" - resolved "https://registry.yarnpkg.com/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.3.12.tgz#ff0029420b0fc307ad0345a4190fe14ca4fd2676" + resolved "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.3.12.tgz" integrity sha512-cO6fn+KiMBemva6EARDLQBxeyvLzgidaFRJi8G7OeRqz54kWK0E+uSjgFaiHlc3DZYoa0+1UFE8mDxozpc9ieg== "@biomejs/cli-darwin-x64@2.3.12": @@ -96,12 +96,17 @@ "@gar/promisify@^1.0.1": version "1.1.3" - resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" + resolved "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz" integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== +"@hexagon/base64@^1.1.27": + version "1.1.28" + resolved "https://registry.npmjs.org/@hexagon/base64/-/base64-1.1.28.tgz" + integrity sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw== + "@isaacs/cliui@^8.0.2": version "8.0.2" - resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + resolved "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz" integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== dependencies: string-width "^5.1.2" @@ -111,6 +116,11 @@ wrap-ansi "^8.1.0" wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" +"@levischuck/tiny-cbor@^0.2.2": + version "0.2.11" + resolved "https://registry.npmjs.org/@levischuck/tiny-cbor/-/tiny-cbor-0.2.11.tgz" + integrity sha512-llBRm4dT4Z89aRsm6u2oEZ8tfwL/2l6BwpZ7JcyieouniDECM5AqNgr/y08zalEIvW3RSK4upYyybDcmjXqAow== + "@noble/hashes@^2.0.1": version "2.0.1" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-2.0.1.tgz#fc1a928061d1232b0a52bb754393c37a5216c89e" @@ -118,7 +128,7 @@ "@npmcli/fs@^1.0.0": version "1.1.1" - resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-1.1.1.tgz#72f719fe935e687c56a4faecf3c03d06ba593257" + resolved "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz" integrity sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ== dependencies: "@gar/promisify" "^1.0.1" @@ -126,7 +136,7 @@ "@npmcli/move-file@^1.0.1": version "1.1.2" - resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.1.2.tgz#1a82c3e372f7cae9253eb66d72543d6b8685c674" + resolved "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz" integrity sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg== dependencies: mkdirp "^1.0.4" @@ -177,9 +187,141 @@ dependencies: "@otplib/core" "13.2.1" +"@peculiar/asn1-android@^2.3.10": + version "2.6.0" + resolved "https://registry.npmjs.org/@peculiar/asn1-android/-/asn1-android-2.6.0.tgz" + integrity sha512-cBRCKtYPF7vJGN76/yG8VbxRcHLPF3HnkoHhKOZeHpoVtbMYfY9ROKtH3DtYUY9m8uI1Mh47PRhHf2hSK3xcSQ== + dependencies: + "@peculiar/asn1-schema" "^2.6.0" + asn1js "^3.0.6" + tslib "^2.8.1" + +"@peculiar/asn1-cms@^2.6.0": + version "2.6.0" + resolved "https://registry.npmjs.org/@peculiar/asn1-cms/-/asn1-cms-2.6.0.tgz" + integrity sha512-2uZqP+ggSncESeUF/9Su8rWqGclEfEiz1SyU02WX5fUONFfkjzS2Z/F1Li0ofSmf4JqYXIOdCAZqIXAIBAT1OA== + dependencies: + "@peculiar/asn1-schema" "^2.6.0" + "@peculiar/asn1-x509" "^2.6.0" + "@peculiar/asn1-x509-attr" "^2.6.0" + asn1js "^3.0.6" + tslib "^2.8.1" + +"@peculiar/asn1-csr@^2.6.0": + version "2.6.0" + resolved "https://registry.npmjs.org/@peculiar/asn1-csr/-/asn1-csr-2.6.0.tgz" + integrity sha512-BeWIu5VpTIhfRysfEp73SGbwjjoLL/JWXhJ/9mo4vXnz3tRGm+NGm3KNcRzQ9VMVqwYS2RHlolz21svzRXIHPQ== + dependencies: + "@peculiar/asn1-schema" "^2.6.0" + "@peculiar/asn1-x509" "^2.6.0" + asn1js "^3.0.6" + tslib "^2.8.1" + +"@peculiar/asn1-ecc@^2.3.8", "@peculiar/asn1-ecc@^2.6.0": + version "2.6.0" + resolved "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.6.0.tgz" + integrity sha512-FF3LMGq6SfAOwUG2sKpPXblibn6XnEIKa+SryvUl5Pik+WR9rmRA3OCiwz8R3lVXnYnyRkSZsSLdml8H3UiOcw== + dependencies: + "@peculiar/asn1-schema" "^2.6.0" + "@peculiar/asn1-x509" "^2.6.0" + asn1js "^3.0.6" + tslib "^2.8.1" + +"@peculiar/asn1-pfx@^2.6.0": + version "2.6.0" + resolved "https://registry.npmjs.org/@peculiar/asn1-pfx/-/asn1-pfx-2.6.0.tgz" + integrity sha512-rtUvtf+tyKGgokHHmZzeUojRZJYPxoD/jaN1+VAB4kKR7tXrnDCA/RAWXAIhMJJC+7W27IIRGe9djvxKgsldCQ== + dependencies: + "@peculiar/asn1-cms" "^2.6.0" + "@peculiar/asn1-pkcs8" "^2.6.0" + "@peculiar/asn1-rsa" "^2.6.0" + "@peculiar/asn1-schema" "^2.6.0" + asn1js "^3.0.6" + tslib "^2.8.1" + +"@peculiar/asn1-pkcs8@^2.6.0": + version "2.6.0" + resolved "https://registry.npmjs.org/@peculiar/asn1-pkcs8/-/asn1-pkcs8-2.6.0.tgz" + integrity sha512-KyQ4D8G/NrS7Fw3XCJrngxmjwO/3htnA0lL9gDICvEQ+GJ+EPFqldcJQTwPIdvx98Tua+WjkdKHSC0/Km7T+lA== + dependencies: + "@peculiar/asn1-schema" "^2.6.0" + "@peculiar/asn1-x509" "^2.6.0" + asn1js "^3.0.6" + tslib "^2.8.1" + +"@peculiar/asn1-pkcs9@^2.6.0": + version "2.6.0" + resolved "https://registry.npmjs.org/@peculiar/asn1-pkcs9/-/asn1-pkcs9-2.6.0.tgz" + integrity sha512-b78OQ6OciW0aqZxdzliXGYHASeCvvw5caqidbpQRYW2mBtXIX2WhofNXTEe7NyxTb0P6J62kAAWLwn0HuMF1Fw== + dependencies: + "@peculiar/asn1-cms" "^2.6.0" + "@peculiar/asn1-pfx" "^2.6.0" + "@peculiar/asn1-pkcs8" "^2.6.0" + "@peculiar/asn1-schema" "^2.6.0" + "@peculiar/asn1-x509" "^2.6.0" + "@peculiar/asn1-x509-attr" "^2.6.0" + asn1js "^3.0.6" + tslib "^2.8.1" + +"@peculiar/asn1-rsa@^2.3.8", "@peculiar/asn1-rsa@^2.6.0": + version "2.6.0" + resolved "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.6.0.tgz" + integrity sha512-Nu4C19tsrTsCp9fDrH+sdcOKoVfdfoQQ7S3VqjJU6vedR7tY3RLkQ5oguOIB3zFW33USDUuYZnPEQYySlgha4w== + dependencies: + "@peculiar/asn1-schema" "^2.6.0" + "@peculiar/asn1-x509" "^2.6.0" + asn1js "^3.0.6" + tslib "^2.8.1" + +"@peculiar/asn1-schema@^2.3.8", "@peculiar/asn1-schema@^2.6.0": + version "2.6.0" + resolved "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.6.0.tgz" + integrity sha512-xNLYLBFTBKkCzEZIw842BxytQQATQv+lDTCEMZ8C196iJcJJMBUZxrhSTxLaohMyKK8QlzRNTRkUmanucnDSqg== + dependencies: + asn1js "^3.0.6" + pvtsutils "^1.3.6" + tslib "^2.8.1" + +"@peculiar/asn1-x509-attr@^2.6.0": + version "2.6.0" + resolved "https://registry.npmjs.org/@peculiar/asn1-x509-attr/-/asn1-x509-attr-2.6.0.tgz" + integrity sha512-MuIAXFX3/dc8gmoZBkwJWxUWOSvG4MMDntXhrOZpJVMkYX+MYc/rUAU2uJOved9iJEoiUx7//3D8oG83a78UJA== + dependencies: + "@peculiar/asn1-schema" "^2.6.0" + "@peculiar/asn1-x509" "^2.6.0" + asn1js "^3.0.6" + tslib "^2.8.1" + +"@peculiar/asn1-x509@^2.3.8", "@peculiar/asn1-x509@^2.6.0": + version "2.6.0" + resolved "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.6.0.tgz" + integrity sha512-uzYbPEpoQiBoTq0/+jZtpM6Gq6zADBx+JNFP3yqRgziWBxQ/Dt/HcuvRfm9zJTPdRcBqPNdaRHTVwpyiq6iNMA== + dependencies: + "@peculiar/asn1-schema" "^2.6.0" + asn1js "^3.0.6" + pvtsutils "^1.3.6" + tslib "^2.8.1" + +"@peculiar/x509@^1.13.0": + version "1.14.3" + resolved "https://registry.npmjs.org/@peculiar/x509/-/x509-1.14.3.tgz" + integrity sha512-C2Xj8FZ0uHWeCXXqX5B4/gVFQmtSkiuOolzAgutjTfseNOHT3pUjljDZsTSxXFGgio54bCzVFqmEOUrIVk8RDA== + dependencies: + "@peculiar/asn1-cms" "^2.6.0" + "@peculiar/asn1-csr" "^2.6.0" + "@peculiar/asn1-ecc" "^2.6.0" + "@peculiar/asn1-pkcs9" "^2.6.0" + "@peculiar/asn1-rsa" "^2.6.0" + "@peculiar/asn1-schema" "^2.6.0" + "@peculiar/asn1-x509" "^2.6.0" + pvtsutils "^1.3.6" + reflect-metadata "^0.2.2" + tslib "^2.8.1" + tsyringe "^4.10.0" + "@pkgjs/parseargs@^0.11.0": version "0.11.0" - resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + resolved "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz" integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== "@scure/base@^2.0.0": @@ -187,36 +329,50 @@ resolved "https://registry.yarnpkg.com/@scure/base/-/base-2.0.0.tgz#ba6371fddf92c2727e88ad6ab485db6e624f9a98" integrity sha512-3E1kpuZginKkek01ovG8krQ0Z44E3DHPjc5S2rjJw9lZn3KSQOs8S7wqikF/AH7iRanHypj85uGyxk0XAyC37w== +"@simplewebauthn/server@^13.2.2": + version "13.2.2" + resolved "https://registry.npmjs.org/@simplewebauthn/server/-/server-13.2.2.tgz" + integrity sha512-HcWLW28yTMGXpwE9VLx9J+N2KEUaELadLrkPEEI9tpI5la70xNEVEsu/C+m3u7uoq4FulLqZQhgBCzR9IZhFpA== + dependencies: + "@hexagon/base64" "^1.1.27" + "@levischuck/tiny-cbor" "^0.2.2" + "@peculiar/asn1-android" "^2.3.10" + "@peculiar/asn1-ecc" "^2.3.8" + "@peculiar/asn1-rsa" "^2.3.8" + "@peculiar/asn1-schema" "^2.3.8" + "@peculiar/asn1-x509" "^2.3.8" + "@peculiar/x509" "^1.13.0" + "@tootallnate/once@1": version "1.1.2" - resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" + resolved "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz" integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== "@tootallnate/quickjs-emscripten@^0.23.0": version "0.23.0" - resolved "https://registry.yarnpkg.com/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz#db4ecfd499a9765ab24002c3b696d02e6d32a12c" + resolved "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz" integrity sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA== "@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" + resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== abbrev@1: version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + resolved "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== abort-controller@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + resolved "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz" 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" + resolved "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz" integrity sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng== dependencies: mime-types "^3.0.0" @@ -224,26 +380,26 @@ accepts@^2.0.0: agent-base@6, agent-base@^6.0.2: version "6.0.2" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz" integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== dependencies: debug "4" agent-base@^7.1.0, agent-base@^7.1.2: version "7.1.4" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.4.tgz#e3cd76d4c548ee895d3c3fd8dc1f6c5b9032e7a8" + resolved "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz" integrity sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ== agentkeepalive@^4.1.3: version "4.6.0" - resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.6.0.tgz#35f73e94b3f40bf65f105219c623ad19c136ea6a" + resolved "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz" integrity sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ== dependencies: humanize-ms "^1.2.1" aggregate-error@^3.0.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + resolved "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz" integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== dependencies: clean-stack "^2.0.0" @@ -251,19 +407,19 @@ aggregate-error@^3.0.0: 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" + resolved "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz" 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" + resolved "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz" integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== dependencies: ajv "^8.0.0" ajv@^8.0.0, ajv@^8.17.1: version "8.17.1" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" + resolved "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz" integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== dependencies: fast-deep-equal "^3.1.3" @@ -273,36 +429,36 @@ ajv@^8.0.0, ajv@^8.17.1: ansi-regex@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== ansi-regex@^6.0.1: version "6.2.2" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.2.2.tgz#60216eea464d864597ce2832000738a0589650c1" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz" integrity sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg== ansi-styles@^3.2.1: version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" 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" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" ansi-styles@^6.1.0: version "6.2.3" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.3.tgz#c044d5dcc521a076413472597a1acb1f103c4041" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz" integrity sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg== anymatch@~3.1.2: version "3.1.3" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== dependencies: normalize-path "^3.0.0" @@ -310,12 +466,12 @@ anymatch@~3.1.2: "aproba@^1.0.3 || ^2.0.0": version "2.1.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.1.0.tgz#75500a190313d95c64e871e7e4284c6ac219f0b1" + resolved "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz" integrity sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew== archiver-utils@^5.0.0, archiver-utils@^5.0.2: version "5.0.2" - resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-5.0.2.tgz#63bc719d951803efc72cf961a56ef810760dd14d" + resolved "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.2.tgz" integrity sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA== dependencies: glob "^10.0.0" @@ -328,7 +484,7 @@ archiver-utils@^5.0.0, archiver-utils@^5.0.2: archiver@^7.0.1: version "7.0.1" - resolved "https://registry.yarnpkg.com/archiver/-/archiver-7.0.1.tgz#c9d91c350362040b8927379c7aa69c0655122f61" + resolved "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz" integrity sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ== dependencies: archiver-utils "^5.0.2" @@ -341,7 +497,7 @@ archiver@^7.0.1: are-we-there-yet@^3.0.0: version "3.0.1" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz#679df222b278c64f2cdba1175cdc00b0d96164bd" + resolved "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz" integrity sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg== dependencies: delegates "^1.0.0" @@ -349,66 +505,75 @@ are-we-there-yet@^3.0.0: argparse@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" 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" + resolved "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz" integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== dependencies: safer-buffer "~2.1.0" +asn1js@^3.0.6: + version "3.0.7" + resolved "https://registry.npmjs.org/asn1js/-/asn1js-3.0.7.tgz" + integrity sha512-uLvq6KJu04qoQM6gvBfKFjlh6Gl0vOKQuR5cJMDHQkmwfMOQeN3F3SHCv9SNYSL+CRoHvOGFfllDlVz03GQjvQ== + dependencies: + pvtsutils "^1.3.6" + pvutils "^1.1.3" + tslib "^2.8.1" + ast-types@^0.13.4: version "0.13.4" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.4.tgz#ee0d77b343263965ecc3fb62da16e7222b2b6782" + resolved "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz" 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" + resolved "https://registry.npmjs.org/async/-/async-3.2.6.tgz" 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" + resolved "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz" integrity sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g== b4a@^1.6.4: version "1.7.3" - resolved "https://registry.yarnpkg.com/b4a/-/b4a-1.7.3.tgz#24cf7ccda28f5465b66aec2bac69e32809bf112f" + resolved "https://registry.npmjs.org/b4a/-/b4a-1.7.3.tgz" integrity sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q== balanced-match@^1.0.0: version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== bare-events@^2.7.0: version "2.8.2" - resolved "https://registry.yarnpkg.com/bare-events/-/bare-events-2.8.2.tgz#7b3e10bd8e1fc80daf38bb516921678f566ab89f" + resolved "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz" 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" + resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== basic-ftp@^5.0.2: version "5.0.5" - resolved "https://registry.yarnpkg.com/basic-ftp/-/basic-ftp-5.0.5.tgz#14a474f5fffecca1f4f406f1c26b18f800225ac0" + resolved "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz" integrity sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg== batchflow@^0.4.0: version "0.4.0" - resolved "https://registry.yarnpkg.com/batchflow/-/batchflow-0.4.0.tgz#7d419df79b6b7587b06f9ea34f96ccef6f74e5b5" + resolved "https://registry.npmjs.org/batchflow/-/batchflow-0.4.0.tgz" integrity sha512-XwQQoCGPUjdLWzmpAvRNZc91wnBYuKLmj52d9LLZ1Ww06ow5RBqBt8kUmU9/3ZvPq88j7Elh3V4cEhgNKXbIlQ== bcrypt@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/bcrypt/-/bcrypt-6.0.0.tgz#86643fddde9bcd0ad91400b063003fa4b0312835" + resolved "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz" integrity sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg== dependencies: node-addon-api "^8.3.0" @@ -416,19 +581,19 @@ bcrypt@^6.0.0: binary-extensions@^2.0.0: version "2.3.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz" 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" + resolved "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz" 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" + resolved "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz" integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== dependencies: buffer "^5.5.0" @@ -437,12 +602,12 @@ bl@^4.0.3: blueimp-md5@^2.16.0: version "2.19.0" - resolved "https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.19.0.tgz#b53feea5498dcb53dc6ec4b823adb84b729c4af0" + resolved "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz" 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" + resolved "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz" integrity sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA== dependencies: bytes "^3.1.2" @@ -457,7 +622,7 @@ body-parser@^2.2.1, body-parser@^2.2.2: brace-expansion@^1.1.7: version "1.1.12" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz" integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== dependencies: balanced-match "^1.0.0" @@ -465,31 +630,31 @@ brace-expansion@^1.1.7: brace-expansion@^2.0.1: version "2.0.2" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz" integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== dependencies: balanced-match "^1.0.0" braces@~3.0.2: version "3.0.3" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz" 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" + resolved "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz" 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" + resolved "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz" integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== buffer@^5.5.0: version "5.7.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== dependencies: base64-js "^1.3.1" @@ -497,7 +662,7 @@ buffer@^5.5.0: buffer@^6.0.3: version "6.0.3" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + resolved "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz" integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== dependencies: base64-js "^1.3.1" @@ -505,19 +670,19 @@ buffer@^6.0.3: busboy@^1.6.0: version "1.6.0" - resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" + resolved "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz" 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" + resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== cacache@^15.2.0: version "15.3.0" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.3.0.tgz#dc85380fb2f556fe3dda4c719bfa0ec875a7f1eb" + resolved "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz" integrity sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ== dependencies: "@npmcli/fs" "^1.0.0" @@ -541,7 +706,7 @@ cacache@^15.2.0: 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" + resolved "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz" integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== dependencies: es-errors "^1.3.0" @@ -549,7 +714,7 @@ call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: call-bound@^1.0.2: version "1.0.4" - resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a" + resolved "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz" integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== dependencies: call-bind-apply-helpers "^1.0.2" @@ -557,22 +722,22 @@ call-bound@^1.0.2: 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" + resolved "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz" 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" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" 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" + resolved "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz" 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" + resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" @@ -581,7 +746,7 @@ chalk@^2.3.2: chokidar@^3.5.2: version "3.6.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz" integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== dependencies: anymatch "~3.1.2" @@ -596,22 +761,22 @@ chokidar@^3.5.2: chownr@^1.1.1: version "1.1.4" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + resolved "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== chownr@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + resolved "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz" integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== clean-stack@^2.0.0: version "2.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + resolved "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== cliui@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + resolved "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz" integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== dependencies: string-width "^4.2.0" @@ -620,46 +785,46 @@ cliui@^6.0.0: color-convert@^1.9.0: version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" 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" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" 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" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" 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" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== color-support@^1.1.3: version "1.1.3" - resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + resolved "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz" integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== colorette@2.0.19: version "2.0.19" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" + resolved "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz" 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" + resolved "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz" integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== compress-commons@^6.0.2: version "6.0.2" - resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-6.0.2.tgz#26d31251a66b9d6ba23a84064ecd3a6a71d2609e" + resolved "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz" integrity sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg== dependencies: crc-32 "^1.2.0" @@ -670,14 +835,14 @@ compress-commons@^6.0.2: compressible@~2.0.18: version "2.0.18" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + resolved "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz" integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== dependencies: mime-db ">= 1.43.0 < 2" compression@^1.7.4: version "1.8.1" - resolved "https://registry.yarnpkg.com/compression/-/compression-1.8.1.tgz#4a45d909ac16509195a9a28bd91094889c180d79" + resolved "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz" integrity sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w== dependencies: bytes "3.1.2" @@ -690,47 +855,47 @@ compression@^1.7.4: concat-map@0.0.1: version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== console-control-strings@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + resolved "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz" integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== content-disposition@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-1.0.1.tgz#a8b7bbeb2904befdfb6787e5c0c086959f605f9b" + resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz" 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" + resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz" 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" + resolved "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz" integrity sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg== cookie@^0.7.1: version "0.7.2" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" + resolved "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz" 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" + resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz" 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" + resolved "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz" integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== crc32-stream@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-6.0.0.tgz#8529a3868f8b27abb915f6c3617c0fadedbf9430" + resolved "https://registry.npmjs.org/crc32-stream/-/crc32-stream-6.0.0.tgz" integrity sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g== dependencies: crc-32 "^1.2.0" @@ -738,7 +903,7 @@ crc32-stream@^6.0.0: cross-spawn@^7.0.6: version "7.0.6" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz" integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== dependencies: path-key "^3.1.0" @@ -747,55 +912,55 @@ cross-spawn@^7.0.6: data-uri-to-buffer@^6.0.2: version "6.0.2" - resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz#8a58bb67384b261a38ef18bea1810cb01badd28b" + resolved "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz" integrity sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw== db-errors@^0.2.3: version "0.2.3" - resolved "https://registry.yarnpkg.com/db-errors/-/db-errors-0.2.3.tgz#a6a38952e00b20e790f2695a6446b3c65497ffa2" + resolved "https://registry.npmjs.org/db-errors/-/db-errors-0.2.3.tgz" integrity sha512-OOgqgDuCavHXjYSJoV2yGhv6SeG8nk42aoCSoyXLZUH7VwFG27rxbavU1z+VrZbZjphw5UkDQwUlD21MwZpUng== debug@2.6.9: version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" debug@4, debug@^4, debug@^4.3.3, 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" + resolved "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz" integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== dependencies: ms "^2.1.3" debug@4.3.4: version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" decamelize@^1.2.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + resolved "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" 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" + resolved "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz" 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" + resolved "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== degenerator@^5.0.0: version "5.0.1" - resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-5.0.1.tgz#9403bf297c6dad9a1ece409b37db27954f91f2f5" + resolved "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz" integrity sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ== dependencies: ast-types "^0.13.4" @@ -804,27 +969,27 @@ degenerator@^5.0.0: delegates@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + resolved "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz" integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== denque@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1" + resolved "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz" 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" + resolved "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== detect-libc@^2.0.0: version "2.0.4" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.4.tgz#f04715b8ba815e53b4d8109655b6508a6865a7e8" + resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz" integrity sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA== dunder-proto@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + resolved "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz" integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== dependencies: call-bind-apply-helpers "^1.0.1" @@ -833,107 +998,107 @@ dunder-proto@^1.0.1: eastasianwidth@^0.2.0: version "0.2.0" - resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + resolved "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz" integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== 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" + resolved "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz" 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" + resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" 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" + resolved "https://registry.npmjs.org/email-validator/-/email-validator-2.0.4.tgz" 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" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== emoji-regex@^9.2.2: version "9.2.2" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== encodeurl@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" + resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz" integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== encoding@^0.1.12: version "0.1.13" - resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" + resolved "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz" integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== dependencies: iconv-lite "^0.6.2" 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" + resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz" 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" + resolved "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz" integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== err-code@^2.0.2: version "2.0.3" - resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" + resolved "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz" integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== error-ex@^1.3.1: version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== 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" + resolved "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz" 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" + resolved "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz" 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" + resolved "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz" 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" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz" 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" + resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" 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" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== escodegen@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.1.0.tgz#ba93bbb7a43986d29d6041f99f5262da773e2e17" + resolved "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz" integrity sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w== dependencies: esprima "^4.0.1" @@ -944,61 +1109,61 @@ escodegen@^2.1.0: esm@^3.2.25: version "3.2.25" - resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10" + resolved "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz" integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA== esprima@^4.0.1: version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" 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" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" 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" + resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" 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" + resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz" 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" + resolved "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz" 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" + resolved "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz" 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" + resolved "https://registry.npmjs.org/events/-/events-3.3.0.tgz" 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" + resolved "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz" integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== express-fileupload@^1.5.2: version "1.5.2" - resolved "https://registry.yarnpkg.com/express-fileupload/-/express-fileupload-1.5.2.tgz#4da70ba6f2ffd4c736eab0776445865a9dbd9bfa" + resolved "https://registry.npmjs.org/express-fileupload/-/express-fileupload-1.5.2.tgz" 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" + resolved "https://registry.npmjs.org/express/-/express-5.2.1.tgz" integrity sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw== dependencies: accepts "^2.0.0" @@ -1032,41 +1197,41 @@ express@^5.2.1: 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" + resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" 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" + resolved "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz" integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ== fast-uri@^3.0.1: version "3.1.0" - resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.0.tgz#66eecff6c764c0df9b762e62ca7edcfb53b4edfa" + resolved "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz" integrity sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA== figures@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + resolved "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz" 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" + 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== fill-range@^7.1.1: version "7.1.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz" 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" + resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz" integrity sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA== dependencies: debug "^4.4.0" @@ -1078,14 +1243,14 @@ finalhandler@^2.1.0: find-up@^2.0.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + resolved "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz" 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" + resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== dependencies: locate-path "^5.0.0" @@ -1093,7 +1258,7 @@ find-up@^4.1.0: foreground-child@^3.1.0: version "3.3.1" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f" + resolved "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz" integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw== dependencies: cross-spawn "^7.0.6" @@ -1101,29 +1266,29 @@ foreground-child@^3.1.0: forwarded@0.2.0: version "0.2.0" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + resolved "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz" integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== fresh@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-2.0.0.tgz#8dd7df6a1b3a1b3a5cf186c05a5dd267622635a4" + resolved "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz" 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" + resolved "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz" integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== fs-minipass@^2.0.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + resolved "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz" integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== dependencies: minipass "^3.0.0" fs.realpath@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@~2.3.2: @@ -1133,12 +1298,12 @@ fsevents@~2.3.2: function-bind@^1.1.2: version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== gauge@^4.0.3: version "4.0.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-4.0.4.tgz#52ff0652f2bbf607a989793d53b751bef2328dce" + resolved "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz" integrity sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg== dependencies: aproba "^1.0.3 || ^2.0.0" @@ -1152,19 +1317,19 @@ gauge@^4.0.3: generate-function@^2.3.1: version "2.3.1" - resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.3.1.tgz#f069617690c10c868e73b8465746764f97c3479f" + resolved "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz" 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" + resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" 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" + resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz" integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== dependencies: call-bind-apply-helpers "^1.0.2" @@ -1180,12 +1345,12 @@ get-intrinsic@^1.2.5, get-intrinsic@^1.3.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" + resolved "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz" 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" + resolved "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz" integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== dependencies: dunder-proto "^1.0.1" @@ -1193,7 +1358,7 @@ get-proto@^1.0.1: get-uri@^6.0.1: version "6.0.5" - resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-6.0.5.tgz#714892aa4a871db671abc5395e5e9447bc306a16" + resolved "https://registry.npmjs.org/get-uri/-/get-uri-6.0.5.tgz" integrity sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg== dependencies: basic-ftp "^5.0.2" @@ -1202,24 +1367,24 @@ get-uri@^6.0.1: getopts@2.3.0: version "2.3.0" - resolved "https://registry.yarnpkg.com/getopts/-/getopts-2.3.0.tgz#71e5593284807e03e2427449d4f6712a268666f4" + resolved "https://registry.npmjs.org/getopts/-/getopts-2.3.0.tgz" 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" + resolved "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz" 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" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" glob@^10.0.0: version "10.5.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.5.0.tgz#8ec0355919cd3338c28428a23d4f24ecc5fe738c" + resolved "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz" integrity sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg== dependencies: foreground-child "^3.1.0" @@ -1231,7 +1396,7 @@ glob@^10.0.0: glob@^7.1.3, glob@^7.1.4: version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" @@ -1243,17 +1408,17 @@ glob@^7.1.3, glob@^7.1.4: gopd@^1.2.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + resolved "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz" integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.2.0, graceful-fs@^4.2.6: version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" 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" + resolved "https://registry.npmjs.org/gravatar/-/gravatar-1.8.2.tgz" integrity sha512-GdRwLM3oYpFQKy47MKuluw9hZ2gaCtiKPbDGdcDEuYDKlc8eNnW27KYL9LVbIDzEsx88WtDWQm2ClBcsgBnj6w== dependencies: blueimp-md5 "^2.16.0" @@ -1263,34 +1428,34 @@ gravatar@^1.8.2: has-flag@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" 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" + resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz" integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== has-unicode@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + resolved "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz" integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== hasown@^2.0.2: version "2.0.2" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz" integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== dependencies: function-bind "^1.1.2" http-cache-semantics@^4.1.0: version "4.2.0" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz#205f4db64f8562b76a4ff9235aa5279839a09dd5" + resolved "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz" integrity sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ== 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" + resolved "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz" integrity sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ== dependencies: depd "~2.0.0" @@ -1301,7 +1466,7 @@ http-errors@^2.0.0, http-errors@^2.0.1, http-errors@~2.0.1: http-proxy-agent@^4.0.1: version "4.0.1" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" + resolved "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz" integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== dependencies: "@tootallnate/once" "1" @@ -1310,7 +1475,7 @@ http-proxy-agent@^4.0.1: http-proxy-agent@^7.0.0, http-proxy-agent@^7.0.1: version "7.0.2" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" + resolved "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz" integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig== dependencies: agent-base "^7.1.0" @@ -1318,7 +1483,7 @@ http-proxy-agent@^7.0.0, http-proxy-agent@^7.0.1: https-proxy-agent@^5.0.0: version "5.0.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz" integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== dependencies: agent-base "6" @@ -1326,7 +1491,7 @@ https-proxy-agent@^5.0.0: https-proxy-agent@^7.0.6: version "7.0.6" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz#da8dfeac7da130b05c2ba4b59c9b6cd66611a6b9" + resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz" integrity sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw== dependencies: agent-base "^7.1.2" @@ -1334,53 +1499,53 @@ https-proxy-agent@^7.0.6: humanize-ms@^1.2.1: version "1.2.1" - resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" + resolved "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz" integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ== dependencies: ms "^2.0.0" iconv-lite@^0.6.2: version "0.6.3" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz" integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== dependencies: safer-buffer ">= 2.1.2 < 3.0.0" 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" + resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz" 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" + resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" 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" + resolved "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz" integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA== imurmurhash@^0.1.4: version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== indent-string@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + resolved "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== infer-owner@^1.0.4: version "1.0.4" - resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" + resolved "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz" integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== inflight@^1.0.4: version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" @@ -1388,108 +1553,108 @@ inflight@^1.0.4: inherits@2, 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" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== inherits@2.0.3: version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== ini@~1.3.0: version "1.3.8" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" 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" + resolved "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz" integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== ip-address@^10.0.1: version "10.0.1" - resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-10.0.1.tgz#a8180b783ce7788777d796286d61bce4276818ed" + resolved "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz" integrity sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA== ipaddr.js@1.9.1: version "1.9.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz" 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" + resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" 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" + resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== dependencies: binary-extensions "^2.0.0" is-core-module@^2.16.0: version "2.16.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" + resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz" 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" + resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" 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" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" 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" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" is-lambda@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" + resolved "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz" integrity sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ== is-number@^7.0.0: version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" 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" + resolved "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz" 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" + resolved "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz" integrity sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g== is-stream@^2.0.0, is-stream@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== isarray@~1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== isexe@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== jackspeak@^3.1.2: version "3.4.3" - resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" + resolved "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz" integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== dependencies: "@isaacs/cliui" "^8.0.2" @@ -1498,24 +1663,24 @@ jackspeak@^3.1.2: js-yaml@^4.1.0: version "4.1.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz" 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" + resolved "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz" 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" + resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz" 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" + resolved "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz" integrity sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g== dependencies: jws "^4.0.1" @@ -1531,7 +1696,7 @@ jsonwebtoken@^9.0.3: jwa@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/jwa/-/jwa-2.0.1.tgz#bf8176d1ad0cd72e0f3f58338595a13e110bc804" + resolved "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz" integrity sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg== dependencies: buffer-equal-constant-time "^1.0.1" @@ -1540,7 +1705,7 @@ jwa@^2.0.1: jws@^4.0.1: version "4.0.1" - resolved "https://registry.yarnpkg.com/jws/-/jws-4.0.1.tgz#07edc1be8fac20e677b283ece261498bd38f0690" + resolved "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz" integrity sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA== dependencies: jwa "^2.0.1" @@ -1548,7 +1713,7 @@ jws@^4.0.1: knex@3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/knex/-/knex-3.1.0.tgz#b6ddd5b5ad26a6315234a5b09ec38dc4a370bd8c" + resolved "https://registry.npmjs.org/knex/-/knex-3.1.0.tgz" integrity sha512-GLoII6hR0c4ti243gMs5/1Rb3B+AjwMOfjYm97pu0FOQa7JH56hgBxYf5WK2525ceSbBY1cjeZ9yk99GPMB6Kw== dependencies: colorette "2.0.19" @@ -1568,21 +1733,21 @@ knex@3.1.0: lazystream@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.1.tgz#494c831062f1f9408251ec44db1cba29242a2638" + resolved "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz" integrity sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw== dependencies: readable-stream "^2.0.5" liquidjs@10.24.0: version "10.24.0" - resolved "https://registry.yarnpkg.com/liquidjs/-/liquidjs-10.24.0.tgz#1aa832189b48b4102049dfa7a8eea40281fa9389" + resolved "https://registry.npmjs.org/liquidjs/-/liquidjs-10.24.0.tgz" integrity sha512-TAUNAdgwaAXjjcUFuYVJm9kOVH7zc0mTKxsG9t9Lu4qdWjB2BEblyVIYpjWcmJLMGgiYqnGNJjpNMHx0gp/46A== 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" + resolved "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz" integrity sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw== dependencies: graceful-fs "^4.1.2" @@ -1592,7 +1757,7 @@ load-json-file@^4.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" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz" integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== dependencies: p-locate "^2.0.0" @@ -1600,88 +1765,88 @@ locate-path@^2.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" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" 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" + resolved "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz" 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" + resolved "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz" 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" + resolved "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz" 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" + resolved "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz" 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" + resolved "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz" 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" + resolved "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz" 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" + resolved "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz" integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== lodash@^4.17.15, lodash@^4.17.21, lodash@^4.17.23: version "4.17.23" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.23.tgz#f113b0378386103be4f6893388c73d0bde7f2c5a" + resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz" integrity sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w== long@^5.3.2: version "5.3.2" - resolved "https://registry.yarnpkg.com/long/-/long-5.3.2.tgz#1d84463095999262d7d7b7f8bfd4a8cc55167f83" + resolved "https://registry.npmjs.org/long/-/long-5.3.2.tgz" integrity sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA== lru-cache@^10.2.0: version "10.4.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz" integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== lru-cache@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== dependencies: yallist "^4.0.0" lru-cache@^7.14.1: version "7.18.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz" integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== lru.min@^1.1.0, lru.min@^1.1.3: version "1.1.3" - resolved "https://registry.yarnpkg.com/lru.min/-/lru.min-1.1.3.tgz#c8c3d001dfb4cbe5b8d1f4bea207d4a320e5d76f" + resolved "https://registry.npmjs.org/lru.min/-/lru.min-1.1.3.tgz" integrity sha512-Lkk/vx6ak3rYkRR0Nhu4lFUT2VDnQSxBe8Hbl7f36358p6ow8Bnvr8lrLt98H8J1aGxfhbX4Fs5tYg2+FTwr5Q== make-dir@^3.0.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + resolved "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz" integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== dependencies: semver "^6.0.0" make-fetch-happen@^9.1.0: version "9.1.0" - resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz#53085a09e7971433e6765f7971bf63f4e05cb968" + resolved "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz" integrity sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg== dependencies: agentkeepalive "^4.1.3" @@ -1703,72 +1868,72 @@ make-fetch-happen@^9.1.0: math-intrinsics@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" + resolved "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz" 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" + resolved "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz" 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" + resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz" 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" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz" 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" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz" 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" + resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz" integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" minimatch@^5.1.0: version "5.1.6" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz" integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== dependencies: brace-expansion "^2.0.1" minimatch@^9.0.4: version "9.0.5" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz" integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== dependencies: brace-expansion "^2.0.1" minimist@^1.2.0, minimist@^1.2.3: version "1.2.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== minipass-collect@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" + resolved "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz" integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA== dependencies: minipass "^3.0.0" minipass-fetch@^1.3.2: version "1.4.1" - resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-1.4.1.tgz#d75e0091daac1b0ffd7e9d41629faff7d0c1f1b6" + resolved "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz" integrity sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw== dependencies: minipass "^3.1.0" @@ -1779,45 +1944,45 @@ minipass-fetch@^1.3.2: minipass-flush@^1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" + resolved "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz" integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== dependencies: minipass "^3.0.0" minipass-pipeline@^1.2.2, minipass-pipeline@^1.2.4: version "1.2.4" - resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" + resolved "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz" integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== dependencies: minipass "^3.0.0" minipass-sized@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/minipass-sized/-/minipass-sized-1.0.3.tgz#70ee5a7c5052070afacfbc22977ea79def353b70" + resolved "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz" integrity sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g== dependencies: minipass "^3.0.0" minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3: version "3.3.6" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" + resolved "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz" integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== dependencies: yallist "^4.0.0" minipass@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" + resolved "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz" integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== "minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: version "7.1.2" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + resolved "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz" integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== minizlib@^2.0.0, minizlib@^2.1.1: version "2.1.2" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + resolved "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz" integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== dependencies: minipass "^3.0.0" @@ -1825,37 +1990,37 @@ minizlib@^2.0.0, minizlib@^2.1.1: 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" + resolved "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz" integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== mkdirp@^1.0.3, mkdirp@^1.0.4: version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== moment@^2.30.1: version "2.30.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" + resolved "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz" 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" + resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== ms@2.1.2: version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== ms@^2.0.0, ms@^2.1.1, ms@^2.1.3: version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== mysql2@^3.16.2: version "3.16.2" - resolved "https://registry.yarnpkg.com/mysql2/-/mysql2-3.16.2.tgz#b56d8917bfbc01af02f9c301029c019868b6ab6d" + resolved "https://registry.npmjs.org/mysql2/-/mysql2-3.16.2.tgz" integrity sha512-JsqBpYNy7pH20lGfPuSyRSIcCxSeAIwxWADpV64nP9KeyN3ZKpHZgjKXuBKsh7dH6FbOvf1bOgoVKjSUPXRMTw== dependencies: aws-ssl-profiles "^1.1.2" @@ -1870,56 +2035,56 @@ mysql2@^3.16.2: named-placeholders@^1.1.6: version "1.1.6" - resolved "https://registry.yarnpkg.com/named-placeholders/-/named-placeholders-1.1.6.tgz#c50c6920b43f258f59c16add1e56654f5cc02bb5" + resolved "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.6.tgz" 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" + resolved "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz" integrity sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA== negotiator@^0.6.2, negotiator@~0.6.4: version "0.6.4" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.4.tgz#777948e2452651c570b712dd01c23e262713fff7" + resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz" integrity sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w== negotiator@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-1.0.0.tgz#b6c91bb47172d69f93cfd7c357bbb529019b5f6a" + resolved "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz" integrity sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg== netmask@^2.0.2: version "2.0.2" - resolved "https://registry.yarnpkg.com/netmask/-/netmask-2.0.2.tgz#8b01a07644065d536383835823bc52004ebac5e7" + resolved "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz" integrity sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg== node-abi@^3.3.0: version "3.78.0" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.78.0.tgz#fd0ecbd0aa89857b98da06bd3909194abb0821ba" + resolved "https://registry.npmjs.org/node-abi/-/node-abi-3.78.0.tgz" integrity sha512-E2wEyrgX/CqvicaQYU3Ze1PFGjc4QYPGsjUrlYkqAE0WjHEZwgOsGMPMzkMse4LjJbDmaEuDX3CM036j5K2DSQ== dependencies: semver "^7.3.5" node-addon-api@^7.0.0: version "7.1.1" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.1.1.tgz#1aba6693b0f255258a049d621329329322aad558" + resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz" integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ== 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" + resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.5.0.tgz" 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" + resolved "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz" integrity sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ== node-gyp@8.x: version "8.4.1" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-8.4.1.tgz#3d49308fc31f768180957d6b5746845fbd429937" + resolved "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz" integrity sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w== dependencies: env-paths "^2.2.0" @@ -1935,14 +2100,14 @@ node-gyp@8.x: node-rsa@^1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/node-rsa/-/node-rsa-1.1.1.tgz#efd9ad382097782f506153398496f79e4464434d" + resolved "https://registry.npmjs.org/node-rsa/-/node-rsa-1.1.1.tgz" integrity sha512-Jd4cvbJMryN21r5HgxQOpMEqv+ooke/korixNNK3mGqfGJmy0M77WDDzo/05969+OkMy3XW1UuZsSmW9KQm7Fw== dependencies: asn1 "^0.2.4" nodemon@^3.1.11: version "3.1.11" - resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.1.11.tgz#04a54d1e794fbec9d8f6ffd8bf1ba9ea93a756ed" + resolved "https://registry.npmjs.org/nodemon/-/nodemon-3.1.11.tgz" integrity sha512-is96t8F/1//UHAjNPHpbsNY46ELPpftGUoSVNXwUfMk/qdjSylYrWSu1XavVTBOn526kFiOR733ATgNBCQyH0g== dependencies: chokidar "^3.5.2" @@ -1958,19 +2123,19 @@ nodemon@^3.1.11: nopt@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" + resolved "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz" integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== dependencies: abbrev "1" 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" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== npmlog@^6.0.0: version "6.0.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-6.0.2.tgz#c8166017a42f2dea92d6453168dd865186a70830" + resolved "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz" integrity sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg== dependencies: are-we-there-yet "^3.0.0" @@ -1980,12 +2145,12 @@ npmlog@^6.0.0: object-inspect@^1.13.3: version "1.13.4" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" + resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz" integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== objection@3.1.5: version "3.1.5" - resolved "https://registry.yarnpkg.com/objection/-/objection-3.1.5.tgz#53c32f6b6cba2958bc28cf723de96c2676da8286" + resolved "https://registry.npmjs.org/objection/-/objection-3.1.5.tgz" integrity sha512-Hx/ipAwXSuRBbOMWFKtRsAN0yITafqXtWB4OT4Z9wED7ty1h7bOnBdhLtcNus23GwLJqcMsRWdodL2p5GwlnfQ== dependencies: ajv "^8.17.1" @@ -1994,19 +2159,19 @@ objection@3.1.5: on-finished@^2.4.1: version "2.4.1" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz" 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" + resolved "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz" integrity sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A== once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" @@ -2025,52 +2190,52 @@ otplib@^13.2.1: p-limit@^1.1.0: version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz" 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" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" 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" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz" 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" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz" integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== dependencies: p-limit "^2.2.0" p-map@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + resolved "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz" integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== dependencies: aggregate-error "^3.0.0" p-try@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + resolved "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz" 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" + resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== pac-proxy-agent@^7.1.0: version "7.2.0" - resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz#9cfaf33ff25da36f6147a20844230ec92c06e5df" + resolved "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz" integrity sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA== dependencies: "@tootallnate/quickjs-emscripten" "^0.23.0" @@ -2084,7 +2249,7 @@ pac-proxy-agent@^7.1.0: pac-resolver@^7.0.1: version "7.0.1" - resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-7.0.1.tgz#54675558ea368b64d210fd9c92a640b5f3b8abb6" + resolved "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz" integrity sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg== dependencies: degenerator "^5.0.0" @@ -2092,12 +2257,12 @@ pac-resolver@^7.0.1: package-json-from-dist@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" + resolved "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz" integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== parse-json@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + resolved "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz" integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw== dependencies: error-ex "^1.3.1" @@ -2105,37 +2270,37 @@ parse-json@^4.0.0: parseurl@^1.3.3: version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz" 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" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" 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" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== path-is-absolute@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== path-key@^3.1.0: version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== path-parse@^1.0.7: version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== path-scurry@^1.11.1: version "1.11.1" - resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + resolved "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz" integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== dependencies: lru-cache "^10.2.0" @@ -2143,12 +2308,12 @@ path-scurry@^1.11.1: path-to-regexp@^8.0.0: version "8.3.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-8.3.0.tgz#aa818a6981f99321003a08987d3cec9c3474cd1f" + resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz" integrity sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA== path@^0.12.7: version "0.12.7" - resolved "https://registry.yarnpkg.com/path/-/path-0.12.7.tgz#d4dc2a506c4ce2197eb481ebfcd5b36c0140b10f" + resolved "https://registry.npmjs.org/path/-/path-0.12.7.tgz" integrity sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q== dependencies: process "^0.11.1" @@ -2156,12 +2321,12 @@ path@^0.12.7: pg-cloudflare@^1.3.0: version "1.3.0" - resolved "https://registry.yarnpkg.com/pg-cloudflare/-/pg-cloudflare-1.3.0.tgz#386035d4bfcf1a7045b026f8b21acf5353f14d65" + resolved "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.3.0.tgz" integrity sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ== 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" + resolved "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz" integrity sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA== pg-connection-string@^2.11.0: @@ -2171,22 +2336,22 @@ pg-connection-string@^2.11.0: pg-int8@1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" + resolved "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz" integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== pg-pool@^3.11.0: version "3.11.0" - resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.11.0.tgz#adf9a6651a30c839f565a3cc400110949c473d69" + resolved "https://registry.npmjs.org/pg-pool/-/pg-pool-3.11.0.tgz" integrity sha512-MJYfvHwtGp870aeusDh+hg9apvOe2zmpZJpyt+BMtzUWlVqbhFmMK6bOBXLBUPd7iRtIF9fZplDc7KrPN3PN7w== pg-protocol@^1.11.0: version "1.11.0" - resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.11.0.tgz#2502908893edaa1e8c0feeba262dd7b40b317b53" + resolved "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.11.0.tgz" integrity sha512-pfsxk2M9M3BuGgDOfuy37VNRRX3jmKgMjcvAcWqNDpZSf4cUmv8HSOl5ViRQFsfARFn0KuUQTgLxVMbNq5NW3g== pg-types@2.2.0: version "2.2.0" - resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3" + resolved "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz" integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA== dependencies: pg-int8 "1.0.1" @@ -2210,24 +2375,24 @@ pg@^8.18.0: pgpass@1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.5.tgz#9b873e4a564bb10fa7a7dbd55312728d422a223d" + resolved "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz" integrity sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug== dependencies: split2 "^4.1.0" picomatch@^2.0.4, picomatch@^2.2.1: version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== pify@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + resolved "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz" 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" + resolved "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.1.0.tgz" integrity sha512-C+VUP+8jis7EsQZIhDYmS5qlNtjv2yP4SNtjXK9AP1ZcTRlnSfuumaTnRfYZnYgUUYVIKqL0fRvmUGDV2fmp6g== dependencies: find-up "^2.0.0" @@ -2235,29 +2400,29 @@ pkg-conf@^2.1.0: postgres-array@~2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" + resolved "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz" integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA== postgres-bytea@~1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" + resolved "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz" integrity sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w== postgres-date@~1.0.4: version "1.0.7" - resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.7.tgz#51bc086006005e5061c591cee727f2531bf641a8" + resolved "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz" 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" + resolved "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz" integrity sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ== dependencies: xtend "^4.0.0" prebuild-install@^7.1.1: version "7.1.3" - resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.3.tgz#d630abad2b147443f20a212917beae68b8092eec" + resolved "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz" integrity sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug== dependencies: detect-libc "^2.0.0" @@ -2275,22 +2440,22 @@ prebuild-install@^7.1.1: 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" + resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" 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" + resolved "https://registry.npmjs.org/process/-/process-0.11.10.tgz" integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== promise-inflight@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" + resolved "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz" integrity sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g== promise-retry@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-2.0.1.tgz#ff747a13620ab57ba688f5fc67855410c370da22" + resolved "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz" integrity sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g== dependencies: err-code "^2.0.2" @@ -2298,7 +2463,7 @@ promise-retry@^2.0.1: proxy-addr@^2.0.7: version "2.0.7" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz" integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== dependencies: forwarded "0.2.0" @@ -2306,7 +2471,7 @@ proxy-addr@^2.0.7: proxy-agent@^6.5.0: version "6.5.0" - resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-6.5.0.tgz#9e49acba8e4ee234aacb539f89ed9c23d02f232d" + resolved "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz" integrity sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A== dependencies: agent-base "^7.1.2" @@ -2320,42 +2485,54 @@ proxy-agent@^6.5.0: proxy-from-env@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== pstree.remy@^1.1.8: version "1.1.8" - resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" + resolved "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz" 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" + resolved "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz" integrity sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA== dependencies: end-of-stream "^1.1.0" once "^1.3.1" +pvtsutils@^1.3.6: + version "1.3.6" + resolved "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.6.tgz" + integrity sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg== + dependencies: + tslib "^2.8.1" + +pvutils@^1.1.3: + version "1.1.5" + resolved "https://registry.npmjs.org/pvutils/-/pvutils-1.1.5.tgz" + integrity sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA== + qs@^6.14.0, qs@^6.14.1: version "6.14.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.14.1.tgz#a41d85b9d3902f31d27861790506294881871159" + resolved "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz" integrity sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ== 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" + resolved "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g== range-parser@^1.2.1: version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" 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" + resolved "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz" integrity sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA== dependencies: bytes "~3.1.2" @@ -2365,7 +2542,7 @@ raw-body@^3.0.1: rc@^1.2.7: version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + resolved "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz" integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== dependencies: deep-extend "^0.6.0" @@ -2375,7 +2552,7 @@ rc@^1.2.7: readable-stream@^2.0.5: version "2.3.8" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz" integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== dependencies: core-util-is "~1.0.0" @@ -2388,7 +2565,7 @@ readable-stream@^2.0.5: readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== dependencies: inherits "^2.0.3" @@ -2397,7 +2574,7 @@ readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: readable-stream@^4.0.0: version "4.7.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.7.0.tgz#cedbd8a1146c13dfff8dab14068028d58c15ac91" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz" integrity sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg== dependencies: abort-controller "^3.0.0" @@ -2408,48 +2585,53 @@ readable-stream@^4.0.0: readdir-glob@^1.1.2: version "1.1.3" - resolved "https://registry.yarnpkg.com/readdir-glob/-/readdir-glob-1.1.3.tgz#c3d831f51f5e7bfa62fa2ffbe4b508c640f09584" + resolved "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz" integrity sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA== dependencies: minimatch "^5.1.0" readdirp@~3.6.0: version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" 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" + resolved "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz" integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ== dependencies: resolve "^1.20.0" +reflect-metadata@^0.2.2: + version "0.2.2" + resolved "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz" + integrity sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q== + require-directory@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" 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" + 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== 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" + resolved "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz" 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" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== resolve@^1.20.0: version "1.22.10" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz" integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w== dependencies: is-core-module "^2.16.0" @@ -2458,19 +2640,19 @@ resolve@^1.20.0: retry@^0.12.0: version "0.12.0" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + resolved "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz" integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== rimraf@^3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== dependencies: glob "^7.1.3" router@^2.2.0: version "2.2.0" - resolved "https://registry.yarnpkg.com/router/-/router-2.2.0.tgz#019be620b711c87641167cc79b99090f00b146ef" + resolved "https://registry.npmjs.org/router/-/router-2.2.0.tgz" integrity sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ== dependencies: debug "^4.4.0" @@ -2481,32 +2663,32 @@ router@^2.2.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" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" 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" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" 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" + resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== semver@^6.0.0: version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== semver@^7.3.5, semver@^7.5.3, semver@^7.5.4: version "7.7.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.3.tgz#4b5f4143d007633a8dc671cd0a6ef9147b8bb946" + resolved "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz" integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q== send@^1.1.0, send@^1.2.0: version "1.2.1" - resolved "https://registry.yarnpkg.com/send/-/send-1.2.1.tgz#9eab743b874f3550f40a26867bf286ad60d3f3ed" + resolved "https://registry.npmjs.org/send/-/send-1.2.1.tgz" integrity sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ== dependencies: debug "^4.4.3" @@ -2523,12 +2705,12 @@ send@^1.1.0, send@^1.2.0: seq-queue@^0.0.5: version "0.0.5" - resolved "https://registry.yarnpkg.com/seq-queue/-/seq-queue-0.0.5.tgz#d56812e1c017a6e4e7c3e3a37a1da6d78dd3c93e" + resolved "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz" integrity sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q== serve-static@^2.2.0: version "2.2.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-2.2.1.tgz#7f186a4a4e5f5b663ad7a4294ff1bf37cf0e98a9" + resolved "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz" integrity sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw== dependencies: encodeurl "^2.0.0" @@ -2538,29 +2720,29 @@ serve-static@^2.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" + resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz" 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" + resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz" integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== shebang-command@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== dependencies: shebang-regex "^3.0.0" shebang-regex@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== 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" + resolved "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz" integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA== dependencies: es-errors "^1.3.0" @@ -2568,7 +2750,7 @@ side-channel-list@^1.0.0: 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" + resolved "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz" integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA== dependencies: call-bound "^1.0.2" @@ -2578,7 +2760,7 @@ side-channel-map@^1.0.1: 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" + resolved "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz" integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== dependencies: call-bound "^1.0.2" @@ -2589,7 +2771,7 @@ side-channel-weakmap@^1.0.2: side-channel@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" + resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz" integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== dependencies: es-errors "^1.3.0" @@ -2600,17 +2782,17 @@ side-channel@^1.1.0: signal-exit@^3.0.7: version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== signal-exit@^4.0.1: version "4.1.0" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== signale@1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/signale/-/signale-1.4.0.tgz#c4be58302fb0262ac00fc3d886a7c113759042f1" + resolved "https://registry.npmjs.org/signale/-/signale-1.4.0.tgz" integrity sha512-iuh+gPf28RkltuJC7W5MRi6XAjTDCAPC/prJUpQoG4vIP3MJZ+GTydVnodXA7pwvTKb2cA0m9OFZW/cdWy/I/w== dependencies: chalk "^2.3.2" @@ -2619,12 +2801,12 @@ signale@1.4.0: simple-concat@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + resolved "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz" 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" + resolved "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz" integrity sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA== dependencies: decompress-response "^6.0.0" @@ -2633,19 +2815,19 @@ simple-get@^4.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" + resolved "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz" 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" + resolved "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz" integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== socks-proxy-agent@^6.0.0: version "6.2.1" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz#2687a31f9d7185e38d530bef1944fe1f1496d6ce" + resolved "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz" integrity sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ== dependencies: agent-base "^6.0.2" @@ -2654,7 +2836,7 @@ socks-proxy-agent@^6.0.0: socks-proxy-agent@^8.0.5: version "8.0.5" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz#b9cdb4e7e998509d7659d689ce7697ac21645bee" + resolved "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz" integrity sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw== dependencies: agent-base "^7.1.2" @@ -2663,7 +2845,7 @@ socks-proxy-agent@^8.0.5: socks@^2.6.2, socks@^2.8.3: version "2.8.7" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.8.7.tgz#e2fb1d9a603add75050a2067db8c381a0b5669ea" + resolved "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz" integrity sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A== dependencies: ip-address "^10.0.1" @@ -2671,17 +2853,17 @@ socks@^2.6.2, socks@^2.8.3: source-map@~0.6.1: version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== split2@^4.1.0: version "4.2.0" - resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" + resolved "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz" integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== sqlite3@^5.1.7: version "5.1.7" - resolved "https://registry.yarnpkg.com/sqlite3/-/sqlite3-5.1.7.tgz#59ca1053c1ab38647396586edad019b1551041b7" + resolved "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz" integrity sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog== dependencies: bindings "^1.5.0" @@ -2693,29 +2875,29 @@ sqlite3@^5.1.7: sqlstring@^2.3.3: version "2.3.3" - resolved "https://registry.yarnpkg.com/sqlstring/-/sqlstring-2.3.3.tgz#2ddc21f03bce2c387ed60680e739922c65751d0c" + resolved "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz" integrity sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg== ssri@^8.0.0, ssri@^8.0.1: version "8.0.1" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af" + resolved "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz" integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ== dependencies: minipass "^3.1.1" 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" + resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz" integrity sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw== streamsearch@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" + resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz" 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" + resolved "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz" integrity sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg== dependencies: events-universal "^1.0.0" @@ -2724,7 +2906,7 @@ streamx@^2.15.0: "string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: emoji-regex "^8.0.0" @@ -2733,7 +2915,7 @@ streamx@^2.15.0: "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: emoji-regex "^8.0.0" @@ -2742,7 +2924,7 @@ streamx@^2.15.0: string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + resolved "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz" integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== dependencies: eastasianwidth "^0.2.0" @@ -2751,64 +2933,64 @@ string-width@^5.0.1, string-width@^5.1.2: 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" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" 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" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== dependencies: safe-buffer "~5.1.0" "strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" 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" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" strip-ansi@^7.0.1: version "7.1.2" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.2.tgz#132875abde678c7ea8d691533f2e7e22bb744dba" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz" integrity sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA== dependencies: ansi-regex "^6.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" + resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz" 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" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz" 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" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" 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" + resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" 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" + resolved "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz" integrity sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ== dependencies: chownr "^1.1.1" @@ -2818,7 +3000,7 @@ tar-fs@^2.0.0: tar-stream@^2.1.4: version "2.2.0" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" + resolved "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz" integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== dependencies: bl "^4.0.3" @@ -2829,7 +3011,7 @@ tar-stream@^2.1.4: tar-stream@^3.0.0: version "3.1.7" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-3.1.7.tgz#24b3fb5eabada19fe7338ed6d26e5f7c482e792b" + resolved "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz" integrity sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ== dependencies: b4a "^1.6.4" @@ -2838,7 +3020,7 @@ tar-stream@^3.0.0: tar@^6.0.2, tar@^6.1.11, tar@^6.1.2: version "6.2.1" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a" + resolved "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz" integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A== dependencies: chownr "^2.0.0" @@ -2850,17 +3032,17 @@ tar@^6.0.2, tar@^6.1.11, tar@^6.1.2: tarn@^3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/tarn/-/tarn-3.0.2.tgz#73b6140fbb881b71559c4f8bfde3d9a4b3d27693" + resolved "https://registry.npmjs.org/tarn/-/tarn-3.0.2.tgz" integrity sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ== temp-dir@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" + resolved "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz" integrity sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ== temp-write@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/temp-write/-/temp-write-4.0.0.tgz#cd2e0825fc826ae72d201dc26eef3bf7e6fc9320" + resolved "https://registry.npmjs.org/temp-write/-/temp-write-4.0.0.tgz" integrity sha512-HIeWmj77uOOHb0QX7siN3OtwV3CTntquin6TNVg6SHOqCP3hYKmox90eeFOGaY1MqJ9WYDDjkyZrW6qS5AWpbw== dependencies: graceful-fs "^4.1.15" @@ -2871,48 +3053,60 @@ temp-write@^4.0.0: text-decoder@^1.1.0: version "1.2.3" - resolved "https://registry.yarnpkg.com/text-decoder/-/text-decoder-1.2.3.tgz#b19da364d981b2326d5f43099c310cc80d770c65" + resolved "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz" integrity sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA== 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" + resolved "https://registry.npmjs.org/tildify/-/tildify-2.0.0.tgz" integrity sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw== 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" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" 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" + resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz" 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" + resolved "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz" integrity sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA== -tslib@^2.0.1: +tslib@^1.9.3: + version "1.14.1" + resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tslib@^2.0.1, tslib@^2.8.1: version "2.8.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== +tsyringe@^4.10.0: + version "4.10.0" + resolved "https://registry.npmjs.org/tsyringe/-/tsyringe-4.10.0.tgz" + integrity sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw== + dependencies: + tslib "^1.9.3" + tunnel-agent@^0.6.0: version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + resolved "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz" 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" + resolved "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz" integrity sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw== dependencies: content-type "^1.0.5" @@ -2921,72 +3115,72 @@ type-is@^2.0.1: undefsafe@^2.0.5: version "2.0.5" - resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" + resolved "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz" integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA== unique-filename@^1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" + resolved "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz" integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== dependencies: unique-slug "^2.0.0" unique-slug@^2.0.0: version "2.0.2" - resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" + resolved "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz" integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== dependencies: imurmurhash "^0.1.4" unpipe@~1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" 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" + resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== util@^0.10.3: version "0.10.4" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" + resolved "https://registry.npmjs.org/util/-/util-0.10.4.tgz" integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== dependencies: inherits "2.0.3" uuid@^3.3.2: version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + resolved "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== vary@^1.1.2, vary@~1.1.2: version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" 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" + resolved "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz" integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== which@^2.0.1, which@^2.0.2: version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" wide-align@^1.1.5: version "1.1.5" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + resolved "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz" integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== dependencies: string-width "^1.0.2 || 2 || 3 || 4" "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== dependencies: ansi-styles "^4.0.0" @@ -2995,7 +3189,7 @@ wide-align@^1.1.5: wrap-ansi@^6.2.0: version "6.2.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz" integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== dependencies: ansi-styles "^4.0.0" @@ -3004,7 +3198,7 @@ wrap-ansi@^6.2.0: wrap-ansi@^8.1.0: version "8.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz" integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== dependencies: ansi-styles "^6.1.0" @@ -3013,27 +3207,27 @@ wrap-ansi@^8.1.0: wrappy@1: version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" 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" + resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz" 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" + resolved "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz" integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== yallist@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== yargs-parser@^18.1.2: version "18.1.3" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz" integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== dependencies: camelcase "^5.0.0" @@ -3041,7 +3235,7 @@ yargs-parser@^18.1.2: yargs@^15.4.1: version "15.4.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + resolved "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz" integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== dependencies: cliui "^6.0.0" @@ -3058,7 +3252,7 @@ yargs@^15.4.1: zip-stream@^6.0.1: version "6.0.1" - resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-6.0.1.tgz#e141b930ed60ccaf5d7fa9c8260e0d1748a2bbfb" + resolved "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.1.tgz" integrity sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA== dependencies: archiver-utils "^5.0.0" diff --git a/frontend/package.json b/frontend/package.json index da684a037f..df98ce985c 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -16,6 +16,7 @@ "test": "vitest" }, "dependencies": { + "@simplewebauthn/browser": "^13.2.2", "@tabler/core": "^1.4.0", "@tabler/icons-react": "^3.36.1", "@tanstack/react-query": "^5.90.20", diff --git a/frontend/src/api/backend/index.ts b/frontend/src/api/backend/index.ts index 40cb4142fc..809211f148 100644 --- a/frontend/src/api/backend/index.ts +++ b/frontend/src/api/backend/index.ts @@ -61,3 +61,4 @@ export * from "./updateUser"; export * from "./uploadCertificate"; export * from "./validateCertificate"; export * from "./twoFactor"; +export * from "./passkeys"; diff --git a/frontend/src/api/backend/passkeys.ts b/frontend/src/api/backend/passkeys.ts new file mode 100644 index 0000000000..c48460802e --- /dev/null +++ b/frontend/src/api/backend/passkeys.ts @@ -0,0 +1,80 @@ +import * as api from "./base"; +import type { + PasskeyAuthOptionsResponse, + PasskeyAuthVerifyResponse, + PasskeyCredential, + PasskeyRegOptionsResponse, +} from "./responseTypes"; + +// === Authentication (login) === + +export async function getPasskeyAuthOptions( + email?: string, +): Promise { + return await api.post({ + url: "/tokens/passkey/options", + data: email ? { email } : {}, + noAuth: true, + }); +} + +export async function verifyPasskeyAuth( + challengeToken: string, + credential: string, +): Promise { + return await api.post({ + url: "/tokens/passkey/verify", + data: { challengeToken, credential }, + noAuth: true, + }); +} + +// === Registration (management, requires auth) === + +export async function getPasskeyRegOptions( + userId: number | "me", +): Promise { + return await api.post({ + url: `/users/${userId}/passkeys/register/options`, + }); +} + +export async function verifyPasskeyRegistration( + userId: number | "me", + challengeToken: string, + credential: string, + friendlyName: string, +): Promise { + return await api.post({ + url: `/users/${userId}/passkeys/register/verify`, + data: { challengeToken, credential, friendlyName }, + }); +} + +export async function listPasskeys( + userId: number | "me", +): Promise { + return await api.get({ + url: `/users/${userId}/passkeys`, + }); +} + +export async function renamePasskey( + userId: number | "me", + passkeyId: number, + friendlyName: string, +): Promise { + return await api.put({ + url: `/users/${userId}/passkeys/${passkeyId}`, + data: { friendlyName }, + }); +} + +export async function deletePasskey( + userId: number | "me", + passkeyId: number, +): Promise { + return await api.del({ + url: `/users/${userId}/passkeys/${passkeyId}`, + }); +} diff --git a/frontend/src/api/backend/responseTypes.ts b/frontend/src/api/backend/responseTypes.ts index 2f88ede547..68010c2c90 100644 --- a/frontend/src/api/backend/responseTypes.ts +++ b/frontend/src/api/backend/responseTypes.ts @@ -44,3 +44,26 @@ export interface TwoFactorSetupResponse { export interface TwoFactorEnableResponse { backupCodes: string[]; } + +export interface PasskeyAuthOptionsResponse { + options: any; + challengeToken: string; +} + +export interface PasskeyAuthVerifyResponse { + token: string; + expires: number; +} + +export interface PasskeyRegOptionsResponse { + options: any; + challengeToken: string; +} + +export interface PasskeyCredential { + id: number; + friendlyName: string; + createdOn: string; + deviceType: string; + backedUp: boolean; +} diff --git a/frontend/src/components/SiteHeader.tsx b/frontend/src/components/SiteHeader.tsx index f00d38d6ed..54c01f4c3d 100644 --- a/frontend/src/components/SiteHeader.tsx +++ b/frontend/src/components/SiteHeader.tsx @@ -1,9 +1,9 @@ -import { IconLock, IconLogout, IconShieldLock, IconUser } from "@tabler/icons-react"; +import { IconFingerprint, IconLock, IconLogout, IconShieldLock, IconUser } from "@tabler/icons-react"; import { LocalePicker, NavLink, ThemeSwitcher } from "src/components"; import { useAuthState } from "src/context"; import { useUser } from "src/hooks"; import { T } from "src/locale"; -import { showChangePasswordModal, showTwoFactorModal, showUserModal } from "src/modals"; +import { showChangePasswordModal, showPasskeyModal, showTwoFactorModal, showUserModal } from "src/modals"; import styles from "./SiteHeader.module.css"; export function SiteHeader() { @@ -119,6 +119,17 @@ export function SiteHeader() { + { + e.preventDefault(); + showPasskeyModal("me"); + }} + > + + +
Promise; + loginWithPasskey: () => Promise; verifyTwoFactor: (code: string) => Promise; cancelTwoFactor: () => void; loginAs: (id: number) => Promise; @@ -56,6 +60,13 @@ function AuthProvider({ children, tokenRefreshInterval = 5 * 60 * 1000 }: Props) handleTokenUpdate(response); }; + const loginWithPasskey = async () => { + const { options, challengeToken } = await getPasskeyAuthOptions(); + const credential = await startAuthentication({ optionsJSON: options }); + const response = await verifyPasskeyAuth(challengeToken, JSON.stringify(credential)); + handleTokenUpdate(response); + }; + const verifyTwoFactor = async (code: string) => { if (!twoFactorChallenge) { throw new Error("No 2FA challenge pending"); @@ -106,6 +117,7 @@ function AuthProvider({ children, tokenRefreshInterval = 5 * 60 * 1000 }: Props) authenticated, twoFactorChallenge, login, + loginWithPasskey, verifyTwoFactor, cancelTwoFactor, loginAs, diff --git a/frontend/src/locale/src/en.json b/frontend/src/locale/src/en.json index ae02605e98..1a67710f64 100644 --- a/frontend/src/locale/src/en.json +++ b/frontend/src/locale/src/en.json @@ -470,6 +470,12 @@ "login.2fa-verify": { "defaultMessage": "Verify" }, + "login.or": { + "defaultMessage": "or" + }, + "login.passkey-sign-in": { + "defaultMessage": "Sign in with Passkey" + }, "login.title": { "defaultMessage": "Login to your account" }, @@ -557,6 +563,39 @@ "options": { "defaultMessage": "Options" }, + "passkey.backed-up": { + "defaultMessage": "Backed Up" + }, + "passkey.delete": { + "defaultMessage": "Delete" + }, + "passkey.delete-confirm": { + "defaultMessage": "Are you sure you want to delete this passkey? You will no longer be able to use it to sign in." + }, + "passkey.device-type.multi": { + "defaultMessage": "Multi-Device" + }, + "passkey.device-type.single": { + "defaultMessage": "Single Device" + }, + "passkey.friendly-name": { + "defaultMessage": "Passkey Name" + }, + "passkey.no-passkeys": { + "defaultMessage": "No passkeys registered" + }, + "passkey.no-passkeys-description": { + "defaultMessage": "Register a passkey to enable passwordless sign-in." + }, + "passkey.register": { + "defaultMessage": "Register New Passkey" + }, + "passkey.rename": { + "defaultMessage": "Rename" + }, + "passkey.title": { + "defaultMessage": "Passkeys" + }, "password": { "defaultMessage": "Password" }, @@ -746,6 +785,9 @@ "user.nickname": { "defaultMessage": "Nickname" }, + "user.passkeys": { + "defaultMessage": "Passkeys" + }, "user.set-password": { "defaultMessage": "Set Password" }, diff --git a/frontend/src/modals/PasskeyModal.tsx b/frontend/src/modals/PasskeyModal.tsx new file mode 100644 index 0000000000..bea5c4c84f --- /dev/null +++ b/frontend/src/modals/PasskeyModal.tsx @@ -0,0 +1,312 @@ +import EasyModal, { type InnerModalProps } from "ez-modal-react"; +import { startRegistration } from "@simplewebauthn/browser"; +import { Field, Form, Formik } from "formik"; +import { type ReactNode, useCallback, useEffect, useState } from "react"; +import { Alert } from "react-bootstrap"; +import Modal from "react-bootstrap/Modal"; +import { + deletePasskey, + getPasskeyRegOptions, + listPasskeys, + renamePasskey, + verifyPasskeyRegistration, + type PasskeyCredential, +} from "src/api/backend"; +import { Button } from "src/components"; +import { T } from "src/locale"; +import { validateString } from "src/modules/Validations"; + +type Step = "loading" | "list" | "register-name" | "confirm-delete"; + +const showPasskeyModal = (id: number | "me") => { + EasyModal.show(PasskeyModal, { id }); +}; + +interface Props extends InnerModalProps { + id: number | "me"; +} + +const PasskeyModal = EasyModal.create(({ id, visible, remove }: Props) => { + const [error, setError] = useState(null); + const [step, setStep] = useState("loading"); + const [passkeys, setPasskeys] = useState([]); + const [isSubmitting, setIsSubmitting] = useState(false); + const [deleteTarget, setDeleteTarget] = useState(null); + const [editingId, setEditingId] = useState(null); + const [editingName, setEditingName] = useState(""); + + const loadPasskeys = useCallback(async () => { + try { + const result = await listPasskeys(id); + setPasskeys(result); + setStep("list"); + } catch (err: any) { + setError(err.message || "Failed to load passkeys"); + setStep("list"); + } + }, [id]); + + useEffect(() => { + loadPasskeys(); + }, [loadPasskeys]); + + const handleRegister = async (values: { friendlyName: string }) => { + setError(null); + setIsSubmitting(true); + try { + const { options, challengeToken } = await getPasskeyRegOptions(id); + const credential = await startRegistration({ optionsJSON: options }); + await verifyPasskeyRegistration( + id, + challengeToken, + JSON.stringify(credential), + values.friendlyName, + ); + await loadPasskeys(); + } catch (err: any) { + if (err.name === "NotAllowedError") { + setError("Registration was cancelled or not allowed"); + } else { + setError(err.message || "Failed to register passkey"); + } + } + setIsSubmitting(false); + }; + + const handleRename = async (passkeyId: number) => { + if (!editingName.trim()) return; + setError(null); + try { + await renamePasskey(id, passkeyId, editingName.trim()); + setEditingId(null); + setEditingName(""); + await loadPasskeys(); + } catch (err: any) { + setError(err.message || "Failed to rename passkey"); + } + }; + + const handleDelete = async () => { + if (!deleteTarget) return; + setError(null); + setIsSubmitting(true); + try { + await deletePasskey(id, deleteTarget.id); + setDeleteTarget(null); + setStep("list"); + await loadPasskeys(); + } catch (err: any) { + setError(err.message || "Failed to delete passkey"); + } + setIsSubmitting(false); + }; + + const renderContent = () => { + if (step === "loading") { + return ( +
+
+ Loading... +
+
+ ); + } + + if (step === "confirm-delete" && deleteTarget) { + return ( +
+ + + +

+ {deleteTarget.friendlyName || `Passkey #${deleteTarget.id}`} +

+
+ + +
+
+ ); + } + + if (step === "register-name") { + return ( +
+ + {() => ( +
+ + {({ field, form }: any) => ( + + )} + +
+ + +
+
+ )} +
+
+ ); + } + + // step === "list" + return ( +
+ {passkeys.length === 0 ? ( +
+

+ +

+

+ +

+
+ ) : ( +
+ {passkeys.map((passkey) => ( +
+
+
+ {editingId === passkey.id ? ( +
+ setEditingName(e.target.value)} + onKeyDown={(e) => { + if (e.key === "Enter") handleRename(passkey.id); + if (e.key === "Escape") { + setEditingId(null); + setEditingName(""); + } + }} + /> + +
+ ) : ( +
+ {passkey.friendlyName || `Passkey #${passkey.id}`} +
+ )} +
+ + {passkey.deviceType === "multiDevice" + ? + : } + + {passkey.backedUp && ( + + + + )} + + {new Date(passkey.createdOn).toLocaleDateString()} + +
+
+ {editingId !== passkey.id && ( +
+ + +
+ )} +
+
+ ))} +
+ )} + +
+ ); + }; + + return ( + + + + + + + + setError(null)} dismissible> + {error} + + {renderContent()} + + + ); +}); + +export { showPasskeyModal }; diff --git a/frontend/src/modals/index.ts b/frontend/src/modals/index.ts index a06a0c0d71..4a7d12fa3f 100644 --- a/frontend/src/modals/index.ts +++ b/frontend/src/modals/index.ts @@ -14,4 +14,5 @@ export * from "./RenewCertificateModal"; export * from "./SetPasswordModal"; export * from "./StreamModal"; export * from "./TwoFactorModal"; +export * from "./PasskeyModal"; export * from "./UserModal"; diff --git a/frontend/src/pages/Login/index.tsx b/frontend/src/pages/Login/index.tsx index ebf7eeb376..1be15c1c65 100644 --- a/frontend/src/pages/Login/index.tsx +++ b/frontend/src/pages/Login/index.tsx @@ -80,7 +80,9 @@ function TwoFactorForm() { function LoginForm() { const emailRef = useRef(null); const [formErr, setFormErr] = useState(""); - const { login } = useAuthState(); + const [passkeyLoading, setPasskeyLoading] = useState(false); + const [passkeySupported] = useState(() => typeof window.PublicKeyCredential !== "undefined"); + const { login, loginWithPasskey } = useAuthState(); const onSubmit = async (values: any, { setSubmitting }: any) => { setFormErr(""); @@ -94,6 +96,19 @@ function LoginForm() { setSubmitting(false); }; + const onPasskeyLogin = async () => { + setFormErr(""); + setPasskeyLoading(true); + try { + await loginWithPasskey(); + } catch (err) { + if (err instanceof Error) { + setFormErr(err.message); + } + } + setPasskeyLoading(false); + }; + useEffect(() => { emailRef.current?.focus(); }, []); @@ -162,6 +177,21 @@ function LoginForm() { )} + {passkeySupported && ( + <> +
+ +
+ + + )} ); } diff --git a/frontend/yarn.lock b/frontend/yarn.lock index ecd07e5ab6..62075e2a14 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -7,18 +7,9 @@ resolved "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.4.tgz" integrity sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg== -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.27.1": - version "7.27.1" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz" - integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== - dependencies: - "@babel/helper-validator-identifier" "^7.27.1" - js-tokens "^4.0.0" - picocolors "^1.1.1" - -"@babel/code-frame@^7.28.6", "@babel/code-frame@^7.29.0": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.27.1", "@babel/code-frame@^7.28.6", "@babel/code-frame@^7.29.0": version "7.29.0" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.29.0.tgz#7cd7a59f15b3cc0dcd803038f7792712a7d0b15c" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz" integrity sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw== dependencies: "@babel/helper-validator-identifier" "^7.28.5" @@ -27,12 +18,12 @@ "@babel/compat-data@^7.28.6": version "7.29.0" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.29.0.tgz#00d03e8c0ac24dd9be942c5370990cbe1f17d88d" + resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz" integrity sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg== "@babel/core@^7.29.0": version "7.29.0" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.29.0.tgz#5286ad785df7f79d656e88ce86e650d16ca5f322" + resolved "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz" integrity sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA== dependencies: "@babel/code-frame" "^7.29.0" @@ -51,20 +42,9 @@ json5 "^2.2.3" semver "^6.3.1" -"@babel/generator@^7.28.5": - version "7.28.5" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz" - integrity sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ== - dependencies: - "@babel/parser" "^7.28.5" - "@babel/types" "^7.28.5" - "@jridgewell/gen-mapping" "^0.3.12" - "@jridgewell/trace-mapping" "^0.3.28" - jsesc "^3.0.2" - "@babel/generator@^7.29.0": version "7.29.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.29.0.tgz#4cba5a76b3c71d8be31761b03329d5dc7768447f" + resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.29.0.tgz" integrity sha512-vSH118/wwM/pLR38g/Sgk05sNtro6TlTJKuiMXDaZqPUfjTFcudpCOt00IhOfj+1BFAX+UFAlzCU+6WXr3GLFQ== dependencies: "@babel/parser" "^7.29.0" @@ -75,7 +55,7 @@ "@babel/helper-compilation-targets@^7.28.6": version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz#32c4a3f41f12ed1532179b108a4d746e105c2b25" + resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz" integrity sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA== dependencies: "@babel/compat-data" "^7.28.6" @@ -89,17 +69,9 @@ resolved "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz" integrity sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw== -"@babel/helper-module-imports@^7.16.7": - version "7.27.1" - resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz" - integrity sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w== - dependencies: - "@babel/traverse" "^7.27.1" - "@babel/types" "^7.27.1" - -"@babel/helper-module-imports@^7.28.6": +"@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.28.6": version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz#60632cbd6ffb70b22823187201116762a03e2d5c" + resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz" integrity sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw== dependencies: "@babel/traverse" "^7.28.6" @@ -107,7 +79,7 @@ "@babel/helper-module-transforms@^7.28.6": version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz#9312d9d9e56edc35aeb6e95c25d4106b50b9eb1e" + resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz" integrity sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA== dependencies: "@babel/helper-module-imports" "^7.28.6" @@ -124,7 +96,7 @@ resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz" integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== -"@babel/helper-validator-identifier@^7.27.1", "@babel/helper-validator-identifier@^7.28.5": +"@babel/helper-validator-identifier@^7.28.5": version "7.28.5" resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz" integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q== @@ -136,22 +108,15 @@ "@babel/helpers@^7.28.6": version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.28.6.tgz#fca903a313ae675617936e8998b814c415cbf5d7" + resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz" integrity sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw== dependencies: "@babel/template" "^7.28.6" "@babel/types" "^7.28.6" -"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.27.2", "@babel/parser@^7.28.5": - version "7.28.5" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz" - integrity sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ== - dependencies: - "@babel/types" "^7.28.5" - -"@babel/parser@^7.28.6", "@babel/parser@^7.29.0": +"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.28.6", "@babel/parser@^7.29.0": version "7.29.0" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.29.0.tgz#669ef345add7d057e92b7ed15f0bac07611831b6" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz" integrity sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww== dependencies: "@babel/types" "^7.29.0" @@ -175,40 +140,18 @@ resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.3.tgz" integrity sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA== -"@babel/template@^7.27.2": - version "7.27.2" - resolved "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz" - integrity sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw== - dependencies: - "@babel/code-frame" "^7.27.1" - "@babel/parser" "^7.27.2" - "@babel/types" "^7.27.1" - "@babel/template@^7.28.6": version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.28.6.tgz#0e7e56ecedb78aeef66ce7972b082fce76a23e57" + resolved "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz" integrity sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ== dependencies: "@babel/code-frame" "^7.28.6" "@babel/parser" "^7.28.6" "@babel/types" "^7.28.6" -"@babel/traverse@^7.27.1": - version "7.28.5" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz" - integrity sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ== - dependencies: - "@babel/code-frame" "^7.27.1" - "@babel/generator" "^7.28.5" - "@babel/helper-globals" "^7.28.0" - "@babel/parser" "^7.28.5" - "@babel/template" "^7.27.2" - "@babel/types" "^7.28.5" - debug "^4.3.1" - "@babel/traverse@^7.28.6", "@babel/traverse@^7.29.0": version "7.29.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.29.0.tgz#f323d05001440253eead3c9c858adbe00b90310a" + resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz" integrity sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA== dependencies: "@babel/code-frame" "^7.29.0" @@ -219,17 +162,9 @@ "@babel/types" "^7.29.0" debug "^4.3.1" -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.27.1", "@babel/types@^7.28.2", "@babel/types@^7.28.5": - version "7.28.5" - resolved "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz" - integrity sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA== - dependencies: - "@babel/helper-string-parser" "^7.27.1" - "@babel/helper-validator-identifier" "^7.28.5" - -"@babel/types@^7.28.6", "@babel/types@^7.29.0": +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.28.2", "@babel/types@^7.28.6", "@babel/types@^7.29.0": version "7.29.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.29.0.tgz#9f5b1e838c446e72cf3cd4b918152b8c605e37c7" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz" integrity sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A== dependencies: "@babel/helper-string-parser" "^7.27.1" @@ -399,7 +334,7 @@ "@esbuild/darwin-arm64@0.27.2": version "0.27.2" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz#2cb7659bd5d109803c593cfc414450d5430c8256" + resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz" integrity sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg== "@esbuild/darwin-x64@0.27.2": @@ -529,12 +464,12 @@ "@formatjs/cli@^6.12.2": version "6.12.2" - resolved "https://registry.yarnpkg.com/@formatjs/cli/-/cli-6.12.2.tgz#0ca91899249f41860deb2b2921e6ad0a4db55de9" + resolved "https://registry.npmjs.org/@formatjs/cli/-/cli-6.12.2.tgz" integrity sha512-y215aarLZXei3u1WDRAiet/VajgvUXzvz4ifPENDSPXfIog0aBJKtFvIU7EWbcFWy7rstbn5GcwwQW4F1G3TJg== "@formatjs/ecma402-abstract@3.1.1": version "3.1.1" - resolved "https://registry.yarnpkg.com/@formatjs/ecma402-abstract/-/ecma402-abstract-3.1.1.tgz#329fa5eed8024ee389e9c82be8c798315631b11d" + resolved "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-3.1.1.tgz" integrity sha512-jhZbTwda+2tcNrs4kKvxrPLPjx8QsBCLCUgrrJ/S+G9YrGHWLhAyFMMBHJBnBoOwuLHd7L14FgYudviKaxkO2Q== dependencies: "@formatjs/fast-memoize" "3.1.0" @@ -544,14 +479,14 @@ "@formatjs/fast-memoize@3.1.0": version "3.1.0" - resolved "https://registry.yarnpkg.com/@formatjs/fast-memoize/-/fast-memoize-3.1.0.tgz#f8643d44803df8f579506d40804f4faeba6f5da2" + resolved "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-3.1.0.tgz" integrity sha512-b5mvSWCI+XVKiz5WhnBCY3RJ4ZwfjAidU0yVlKa3d3MSgKmH1hC3tBGEAtYyN5mqL7N0G5x0BOUYyO8CEupWgg== dependencies: tslib "^2.8.1" "@formatjs/icu-messageformat-parser@3.5.1": version "3.5.1" - resolved "https://registry.yarnpkg.com/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-3.5.1.tgz#a08faadbbb333d9e4fa7276c92a2b66a37788aa1" + resolved "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-3.5.1.tgz" integrity sha512-sSDmSvmmoVQ92XqWb499KrIhv/vLisJU8ITFrx7T7NZHUmMY7EL9xgRowAosaljhqnj/5iufG24QrdzB6X3ItA== dependencies: "@formatjs/ecma402-abstract" "3.1.1" @@ -560,7 +495,7 @@ "@formatjs/icu-skeleton-parser@2.1.1": version "2.1.1" - resolved "https://registry.yarnpkg.com/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-2.1.1.tgz#a05b45733bd0f277c50f31b32e4a73375569d3c8" + resolved "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-2.1.1.tgz" integrity sha512-PSFABlcNefjI6yyk8f7nyX1DC7NHmq6WaCHZLySEXBrXuLOB2f935YsnzuPjlz+ibhb9yWTdPeVX1OVcj24w2Q== dependencies: "@formatjs/ecma402-abstract" "3.1.1" @@ -568,7 +503,7 @@ "@formatjs/intl-localematcher@0.8.1": version "0.8.1" - resolved "https://registry.yarnpkg.com/@formatjs/intl-localematcher/-/intl-localematcher-0.8.1.tgz#554fe5f8c746ba52d430674de9a242fae64f67ff" + resolved "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.8.1.tgz" integrity sha512-xwEuwQFdtSq1UKtQnyTZWC+eHdv7Uygoa+H2k/9uzBVQjDyp9r20LNDNKedWXll7FssT3GRHvqsdJGYSUWqYFA== dependencies: "@formatjs/fast-memoize" "3.1.0" @@ -576,7 +511,7 @@ "@formatjs/intl@4.1.2": version "4.1.2" - resolved "https://registry.yarnpkg.com/@formatjs/intl/-/intl-4.1.2.tgz#4a0d487e6290067462f93d034ef36a8aaf6f671b" + resolved "https://registry.npmjs.org/@formatjs/intl/-/intl-4.1.2.tgz" integrity sha512-V60fNY/X/7zqmRffr7qPwscGmVGYDmlKF069mSQ2a/7fE22q602NtIfOQY8vzRA63Gr/O/U6vjRVBHMabrnA9A== dependencies: "@formatjs/ecma402-abstract" "3.1.1" @@ -751,7 +686,7 @@ "@rolldown/pluginutils@1.0.0-rc.2": version "1.0.0-rc.2" - resolved "https://registry.yarnpkg.com/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.2.tgz#10324e74cb3396cb7b616042ea7e9e6aa7d8d458" + resolved "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.2.tgz" integrity sha512-izyXV/v+cHiRfozX62W9htOAvwMo4/bXKDrQ+vom1L1qRuexPock/7VZDAhnpHCLNejd3NJ6hiab+tO0D44Rgw== "@rollup/rollup-android-arm-eabi@4.50.0": @@ -859,6 +794,11 @@ resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.0.tgz#d81efe6a12060c7feddf9805e2a94c3ab0679f48" integrity sha512-xMmiWRR8sp72Zqwjgtf3QbZfF1wdh8X2ABu3EaozvZcyHJeU0r+XAnXdKgs4cCAp6ORoYoCygipYP1mjmbjrsg== +"@simplewebauthn/browser@^13.2.2": + version "13.2.2" + resolved "https://registry.npmjs.org/@simplewebauthn/browser/-/browser-13.2.2.tgz" + integrity sha512-FNW1oLQpTJyqG5kkDg5ZsotvWgmBaC6jCHR7Ej0qUNep36Wl9tj2eZu7J5rP+uhXgHaLk+QQ3lqcw2vS5MX1IA== + "@standard-schema/spec@^1.0.0": version "1.0.0" resolved "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz" @@ -881,36 +821,36 @@ "@tabler/icons-react@^3.36.1": version "3.36.1" - resolved "https://registry.yarnpkg.com/@tabler/icons-react/-/icons-react-3.36.1.tgz#332d4407b5e2a9a783ce0a26567727aaedd5a9a8" + resolved "https://registry.npmjs.org/@tabler/icons-react/-/icons-react-3.36.1.tgz" integrity sha512-/8nOXeNeMoze9xY/QyEKG65wuvRhkT3q9aytaur6Gj8bYU2A98YVJyLc9MRmc5nVvpy+bRlrrwK/Ykr8WGyUWg== dependencies: "@tabler/icons" "" "@tabler/icons@": version "3.36.1" - resolved "https://registry.yarnpkg.com/@tabler/icons/-/icons-3.36.1.tgz#a893104b3c56e02458b13342abb6e466d4a81a8d" + resolved "https://registry.npmjs.org/@tabler/icons/-/icons-3.36.1.tgz" integrity sha512-f4Jg3Fof/Vru5ioix/UO4GX+sdDsF9wQo47FbtvG+utIYYVQ/QVAC0QYgcBbAjQGfbdOh2CCf0BgiFOF9Ixtjw== "@tanstack/query-core@5.90.20": version "5.90.20" - resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-5.90.20.tgz#e12128e39210715d4ce4fb299c33498ac297771e" + resolved "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.20.tgz" integrity sha512-OMD2HLpNouXEfZJWcKeVKUgQ5n+n3A2JFmBaScpNDUqSrQSjiveC7dKMe53uJUg1nDG16ttFPz2xfilz6i2uVg== "@tanstack/query-devtools@5.93.0": version "5.93.0" - resolved "https://registry.yarnpkg.com/@tanstack/query-devtools/-/query-devtools-5.93.0.tgz#517f61d4e2cfb9af671e34ad5e7e871052bca814" + resolved "https://registry.npmjs.org/@tanstack/query-devtools/-/query-devtools-5.93.0.tgz" integrity sha512-+kpsx1NQnOFTZsw6HAFCW3HkKg0+2cepGtAWXjiiSOJJ1CtQpt72EE2nyZb+AjAbLRPoeRmPJ8MtQd8r8gsPdg== "@tanstack/react-query-devtools@^5.91.3": version "5.91.3" - resolved "https://registry.yarnpkg.com/@tanstack/react-query-devtools/-/react-query-devtools-5.91.3.tgz#0f65340fa3f7e7d5575de928ad70cfa6b5f74ff1" + resolved "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-5.91.3.tgz" integrity sha512-nlahjMtd/J1h7IzOOfqeyDh5LNfG0eULwlltPEonYy0QL+nqrBB+nyzJfULV+moL7sZyxc2sHdNJki+vLA9BSA== dependencies: "@tanstack/query-devtools" "5.93.0" "@tanstack/react-query@^5.90.20": version "5.90.20" - resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-5.90.20.tgz#42bb7018bfedc72f216b6e9b4052c919063f350b" + resolved "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.20.tgz" integrity sha512-vXBxa+qeyveVO7OA0jX1z+DeyCA4JKnThKv411jd5SORpBKgkcVnYKCiBgECvADvniBX7tobwBmg01qq9JmMJw== dependencies: "@tanstack/query-core" "5.90.20" @@ -955,7 +895,7 @@ "@testing-library/react@^16.3.2": version "16.3.2" - resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-16.3.2.tgz#672883b7acb8e775fc0492d9e9d25e06e89786d0" + resolved "https://registry.npmjs.org/@testing-library/react/-/react-16.3.2.tgz" integrity sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g== dependencies: "@babel/runtime" "^7.12.5" @@ -1074,7 +1014,7 @@ "@types/node@*", "@types/node@>=20.0.0": version "25.0.10" - resolved "https://registry.yarnpkg.com/@types/node/-/node-25.0.10.tgz#4864459c3c9459376b8b75fd051315071c8213e7" + resolved "https://registry.npmjs.org/@types/node/-/node-25.0.10.tgz" integrity sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg== dependencies: undici-types "~7.16.0" @@ -1113,7 +1053,7 @@ "@types/react@*", "@types/react@>=16.9.11", "@types/react@^19.2.10": version "19.2.10" - resolved "https://registry.yarnpkg.com/@types/react/-/react-19.2.10.tgz#f3ea799e6b4cebad6dfd231c238fc9de7652e2d2" + resolved "https://registry.npmjs.org/@types/react/-/react-19.2.10.tgz" integrity sha512-WPigyYuGhgZ/cTPRXB2EwUw+XvsRA3GqHlsP4qteqrnnjDrApbS7MxcGr/hke5iUoeB7E/gQtrs9I37zAJ0Vjw== dependencies: csstype "^3.2.2" @@ -1140,7 +1080,7 @@ "@types/ws@^8.18.1": version "8.18.1" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.18.1.tgz#48464e4bf2ddfd17db13d845467f6070ffea4aa9" + resolved "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz" integrity sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg== dependencies: "@types/node" "*" @@ -1161,7 +1101,7 @@ "@vitejs/plugin-react@^5.1.3": version "5.1.3" - resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-5.1.3.tgz#05eba092cc89a6ff89668d3f62258e2c5a8a9122" + resolved "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.3.tgz" integrity sha512-NVUnA6gQCl8jfoYqKqQU5Clv0aPw14KkZYCsX6T9Lfu9slI0LOU10OTwFHS/WmptsMMpshNd/1tuWsHQ2Uk+cg== dependencies: "@babel/core" "^7.29.0" @@ -1173,7 +1113,7 @@ "@vitest/expect@4.0.18": version "4.0.18" - resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-4.0.18.tgz#361510d99fbf20eb814222e4afcb8539d79dc94d" + resolved "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.18.tgz" integrity sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ== dependencies: "@standard-schema/spec" "^1.0.0" @@ -1185,7 +1125,7 @@ "@vitest/mocker@4.0.18": version "4.0.18" - resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-4.0.18.tgz#b9735da114ef65ea95652c5bdf13159c6fab4865" + resolved "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.18.tgz" integrity sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ== dependencies: "@vitest/spy" "4.0.18" @@ -1194,14 +1134,14 @@ "@vitest/pretty-format@4.0.18": version "4.0.18" - resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-4.0.18.tgz#fbccd4d910774072ec15463553edb8ca5ce53218" + resolved "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.18.tgz" integrity sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw== dependencies: tinyrainbow "^3.0.3" "@vitest/runner@4.0.18": version "4.0.18" - resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-4.0.18.tgz#c2c0a3ed226ec85e9312f9cc8c43c5b3a893a8b1" + resolved "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.18.tgz" integrity sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw== dependencies: "@vitest/utils" "4.0.18" @@ -1209,7 +1149,7 @@ "@vitest/snapshot@4.0.18": version "4.0.18" - resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-4.0.18.tgz#bcb40fd6d742679c2ac927ba295b66af1c6c34c5" + resolved "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.18.tgz" integrity sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA== dependencies: "@vitest/pretty-format" "4.0.18" @@ -1218,12 +1158,12 @@ "@vitest/spy@4.0.18": version "4.0.18" - resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-4.0.18.tgz#ba0f20503fb6d08baf3309d690b3efabdfa88762" + resolved "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.18.tgz" integrity sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw== "@vitest/utils@4.0.18": version "4.0.18" - resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-4.0.18.tgz#9636b16d86a4152ec68a8d6859cff702896433d4" + resolved "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.18.tgz" integrity sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA== dependencies: "@vitest/pretty-format" "4.0.18" @@ -1312,7 +1252,7 @@ ccount@^2.0.0: chai@^6.2.1: version "6.2.2" - resolved "https://registry.yarnpkg.com/chai/-/chai-6.2.2.tgz#ae41b52c9aca87734505362717f3255facda360e" + resolved "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz" integrity sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg== character-entities-html4@^2.0.0: @@ -1385,7 +1325,7 @@ cosmiconfig@^7.0.0: country-flag-icons@^1.6.12: version "1.6.12" - resolved "https://registry.yarnpkg.com/country-flag-icons/-/country-flag-icons-1.6.12.tgz#f32f9fd6f371bf3dc9389ed5cf85150b80b20c00" + resolved "https://registry.npmjs.org/country-flag-icons/-/country-flag-icons-1.6.12.tgz" integrity sha512-tWxbBylam6Fkkg0nu+112jmny4WomHXgmdTQFobs/+evTyizSc06bCp//HAh4W1i+g1m06uqlbPuyLC5mrimkQ== css.escape@^1.5.1: @@ -1412,7 +1352,7 @@ debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: decimal.js@^10.6.0: version "10.6.0" - resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.6.0.tgz#e649a43e3ab953a72192ff5983865e509f37ed9a" + resolved "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz" integrity sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg== decode-named-character-reference@^1.0.0: @@ -1474,7 +1414,7 @@ electron-to-chromium@^1.5.211: entities@^4.5.0: version "4.5.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + resolved "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz" integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== entities@^6.0.0: @@ -1496,7 +1436,7 @@ es-module-lexer@^1.7.0: esbuild@^0.27.0: version "0.27.2" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.27.2.tgz#d83ed2154d5813a5367376bb2292a9296fc83717" + resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz" integrity sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw== optionalDependencies: "@esbuild/aix-ppc64" "0.27.2" @@ -1592,7 +1532,7 @@ find-root@^1.1.0: formik@^2.4.9: version "2.4.9" - resolved "https://registry.yarnpkg.com/formik/-/formik-2.4.9.tgz#7e5b81e9c9e215d0ce2ac8fed808cf7fba0cd204" + resolved "https://registry.npmjs.org/formik/-/formik-2.4.9.tgz" integrity sha512-5nI94BMnlFDdQRBY4Sz39WkhxajZJ57Fzs8wVbtsQlm5ScKIR1QLYqv/ultBnobObtlUyxpxoLodpixrsf36Og== dependencies: "@types/hoist-non-react-statics" "^3.3.1" @@ -1606,7 +1546,7 @@ formik@^2.4.9: fsevents@~2.3.2, fsevents@~2.3.3: version "2.3.3" - resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== function-bind@^1.1.2: @@ -1817,7 +1757,7 @@ inline-style-parser@0.2.4: intl-messageformat@11.1.2: version "11.1.2" - resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-11.1.2.tgz#c72879165d15633f38b092479822c5d831c21ac5" + resolved "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-11.1.2.tgz" integrity sha512-ucSrQmZGAxfiBHfBRXW/k7UC8MaGFlEj4Ry1tKiDcmgwQm1y3EDl40u+4VNHYomxJQMJi9NEI3riDRlth96jKg== dependencies: "@formatjs/ecma402-abstract" "3.1.1" @@ -1916,7 +1856,7 @@ lines-and-columns@^1.1.6: lodash-es@^4.17.21: version "4.17.23" - resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.23.tgz#58c4360fd1b5d33afc6c0bbd3d1149349b1138e0" + resolved "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.23.tgz" integrity sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg== lodash.debounce@^4.0.8: @@ -1926,7 +1866,7 @@ lodash.debounce@^4.0.8: lodash@^4.17.21: version "4.17.23" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.23.tgz#f113b0378386103be4f6893388c73d0bde7f2c5a" + resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz" integrity sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w== longest-streak@^3.0.0: @@ -1955,7 +1895,7 @@ lz-string@^1.5.0: magic-string@^0.30.21: version "0.30.21" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.21.tgz#56763ec09a0fa8091df27879fd94d19078c00d91" + resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz" integrity sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ== dependencies: "@jridgewell/sourcemap-codec" "^1.5.5" @@ -2312,7 +2252,7 @@ object-assign@^4.1.1: obug@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/obug/-/obug-2.1.1.tgz#2cba74ff241beb77d63055ddf4cd1e9f90b538be" + resolved "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz" integrity sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ== parent-module@^1.0.0: @@ -2491,7 +2431,7 @@ react-bootstrap@^2.10.10: react-dom@^19.2.4: version "19.2.4" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.2.4.tgz#6fac6bd96f7db477d966c7ec17c1a2b1ad8e6591" + resolved "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz" integrity sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ== dependencies: scheduler "^0.27.0" @@ -2553,14 +2493,14 @@ react-refresh@^0.18.0: react-router-dom@^7.13.0: version "7.13.0" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-7.13.0.tgz#8b5f7204fadca680f0e94f207c163f0dcd1cfdf5" + resolved "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.13.0.tgz" integrity sha512-5CO/l5Yahi2SKC6rGZ+HDEjpjkGaG/ncEP7eWFTvFxbHP8yeeI0PxTDjimtpXYlR3b3i9/WIL4VJttPrESIf2g== dependencies: react-router "7.13.0" react-router@7.13.0: version "7.13.0" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-7.13.0.tgz#de9484aee764f4f65b93275836ff5944d7f5bd3b" + resolved "https://registry.npmjs.org/react-router/-/react-router-7.13.0.tgz" integrity sha512-PZgus8ETambRT17BUm/LL8lX3Of+oiLaPuVTRH3l1eLvSPpKO3AvhAEb5N7ihAFZQrYDqkvvWfFh9p0z9VsjLw== dependencies: cookie "^1.0.1" @@ -2600,7 +2540,7 @@ react-transition-group@^4.3.0, react-transition-group@^4.4.5: react@^19.2.4: version "19.2.4" - resolved "https://registry.yarnpkg.com/react/-/react-19.2.4.tgz#438e57baa19b77cb23aab516cf635cd0579ee09a" + resolved "https://registry.npmjs.org/react/-/react-19.2.4.tgz" integrity sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ== readdirp@^4.0.1: @@ -2733,7 +2673,7 @@ rollup@^4.43.0: rooks@^9.5.0: version "9.5.0" - resolved "https://registry.yarnpkg.com/rooks/-/rooks-9.5.0.tgz#bbe15fdf64fff44b9a1750cc913de3401572f012" + resolved "https://registry.npmjs.org/rooks/-/rooks-9.5.0.tgz" integrity sha512-AtmaX8yjQkJAW7EXW+UU481bpGwuk455hjD/aEUuy7N7VjvXlNmO8BErQ+jEUQp1DRA/PTWonv+Dq1nEkJdgkw== dependencies: fast-deep-equal "^3.1.3" @@ -2748,7 +2688,7 @@ safe-buffer@^5.1.0: sass@^1.97.3: version "1.97.3" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.97.3.tgz#9cb59339514fa7e2aec592b9700953ac6e331ab2" + resolved "https://registry.npmjs.org/sass/-/sass-1.97.3.tgz" integrity sha512-fDz1zJpd5GycprAbu4Q2PV/RprsRtKC/0z82z0JLgdytmcq0+ujJbJ/09bPGDxCLkKY3Np5cRAOcWiVkLXJURg== dependencies: chokidar "^4.0.0" @@ -2804,7 +2744,7 @@ stackback@0.0.2: std-env@^3.10.0: version "3.10.0" - resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.10.0.tgz#d810b27e3a073047b2b5e40034881f5ea6f9c83b" + resolved "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz" integrity sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg== stringify-entities@^4.0.0: @@ -2863,7 +2803,7 @@ tinybench@^2.9.0: tinyexec@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-1.0.2.tgz#bdd2737fe2ba40bd6f918ae26642f264b99ca251" + resolved "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz" integrity sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg== tinyglobby@^0.2.15: @@ -2933,7 +2873,7 @@ uncontrollable@^8.0.4: undici-types@~7.16.0: version "7.16.0" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.16.0.tgz#ffccdff36aea4884cbfce9a750a0580224f58a46" + resolved "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz" integrity sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw== unicorn-magic@^0.3.0: @@ -3045,7 +2985,7 @@ vfile@^6.0.0: vite-plugin-checker@^0.12.0: version "0.12.0" - resolved "https://registry.yarnpkg.com/vite-plugin-checker/-/vite-plugin-checker-0.12.0.tgz#1e9688a5a10f5de1fd833bc1351618eed54db3bc" + resolved "https://registry.npmjs.org/vite-plugin-checker/-/vite-plugin-checker-0.12.0.tgz" integrity sha512-CmdZdDOGss7kdQwv73UyVgLPv0FVYe5czAgnmRX2oKljgEvSrODGuClaV3PDR2+3ou7N/OKGauDDBjy2MB07Rg== dependencies: "@babel/code-frame" "^7.27.1" @@ -3059,7 +2999,7 @@ vite-plugin-checker@^0.12.0: vite-tsconfig-paths@^6.0.5: version "6.0.5" - resolved "https://registry.yarnpkg.com/vite-tsconfig-paths/-/vite-tsconfig-paths-6.0.5.tgz#5bcbb44d6ae0d12fe42f5915a6ad9846b0ed7805" + resolved "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-6.0.5.tgz" integrity sha512-f/WvY6ekHykUF1rWJUAbCU7iS/5QYDIugwpqJA+ttwKbxSbzNlqlE8vZSrsnxNQciUW+z6lvhlXMaEyZn9MSig== dependencies: debug "^4.1.1" @@ -3068,7 +3008,7 @@ vite-tsconfig-paths@^6.0.5: "vite@^6.0.0 || ^7.0.0", vite@^7.3.1: version "7.3.1" - resolved "https://registry.yarnpkg.com/vite/-/vite-7.3.1.tgz#7f6cfe8fb9074138605e822a75d9d30b814d6507" + resolved "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz" integrity sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA== dependencies: esbuild "^0.27.0" @@ -3082,7 +3022,7 @@ vite-tsconfig-paths@^6.0.5: vitest@^4.0.18: version "4.0.18" - resolved "https://registry.yarnpkg.com/vitest/-/vitest-4.0.18.tgz#56f966353eca0b50f4df7540cd4350ca6d454a05" + resolved "https://registry.npmjs.org/vitest/-/vitest-4.0.18.tgz" integrity sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ== dependencies: "@vitest/expect" "4.0.18" @@ -3138,7 +3078,7 @@ why-is-node-running@^2.3.0: ws@^8.18.3: version "8.19.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.19.0.tgz#ddc2bdfa5b9ad860204f5a72a4863a8895fd8c8b" + resolved "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz" integrity sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg== yallist@^3.0.2: From 680a5979889d63b8c7fbdd68f60df37f9263b031 Mon Sep 17 00:00:00 2001 From: florida117 <77394159+florida117@users.noreply.github.com> Date: Tue, 3 Feb 2026 17:05:39 +0000 Subject: [PATCH 02/12] Trigger CI re-run Co-Authored-By: Claude Opus 4.5 From 72d2cbeae5098fcb3110f2bdf51bf31896339fb8 Mon Sep 17 00:00:00 2001 From: florida117 <77394159+florida117@users.noreply.github.com> Date: Tue, 3 Feb 2026 17:54:48 +0000 Subject: [PATCH 03/12] Fix securityScheme name in passkey OpenAPI schemas BearerAuth -> bearerAuth to match the scheme defined in components/security-schemes.json. Co-Authored-By: Claude Opus 4.5 --- backend/schema/paths/users/userID/passkeys/get.json | 6 +++++- .../paths/users/userID/passkeys/passkeyID/delete.json | 6 +++++- .../schema/paths/users/userID/passkeys/passkeyID/put.json | 6 +++++- .../paths/users/userID/passkeys/register/options/post.json | 6 +++++- .../paths/users/userID/passkeys/register/verify/post.json | 6 +++++- 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/backend/schema/paths/users/userID/passkeys/get.json b/backend/schema/paths/users/userID/passkeys/get.json index c8b1312982..613d727d9b 100644 --- a/backend/schema/paths/users/userID/passkeys/get.json +++ b/backend/schema/paths/users/userID/passkeys/get.json @@ -2,7 +2,11 @@ "operationId": "listPasskeys", "summary": "List user's registered passkeys", "tags": ["users"], - "security": [{ "BearerAuth": [] }], + "security": [ + { + "bearerAuth": [] + } + ], "parameters": [ { "in": "path", diff --git a/backend/schema/paths/users/userID/passkeys/passkeyID/delete.json b/backend/schema/paths/users/userID/passkeys/passkeyID/delete.json index 981772d930..471abc0513 100644 --- a/backend/schema/paths/users/userID/passkeys/passkeyID/delete.json +++ b/backend/schema/paths/users/userID/passkeys/passkeyID/delete.json @@ -2,7 +2,11 @@ "operationId": "deletePasskey", "summary": "Delete a passkey", "tags": ["users"], - "security": [{ "BearerAuth": [] }], + "security": [ + { + "bearerAuth": [] + } + ], "parameters": [ { "in": "path", diff --git a/backend/schema/paths/users/userID/passkeys/passkeyID/put.json b/backend/schema/paths/users/userID/passkeys/passkeyID/put.json index f693317ab3..199db5cbac 100644 --- a/backend/schema/paths/users/userID/passkeys/passkeyID/put.json +++ b/backend/schema/paths/users/userID/passkeys/passkeyID/put.json @@ -2,7 +2,11 @@ "operationId": "renamePasskey", "summary": "Rename a passkey", "tags": ["users"], - "security": [{ "BearerAuth": [] }], + "security": [ + { + "bearerAuth": [] + } + ], "parameters": [ { "in": "path", diff --git a/backend/schema/paths/users/userID/passkeys/register/options/post.json b/backend/schema/paths/users/userID/passkeys/register/options/post.json index 955c47f3e6..19474c167b 100644 --- a/backend/schema/paths/users/userID/passkeys/register/options/post.json +++ b/backend/schema/paths/users/userID/passkeys/register/options/post.json @@ -2,7 +2,11 @@ "operationId": "getPasskeyRegOptions", "summary": "Generate passkey registration options", "tags": ["users"], - "security": [{ "BearerAuth": [] }], + "security": [ + { + "bearerAuth": [] + } + ], "parameters": [ { "in": "path", diff --git a/backend/schema/paths/users/userID/passkeys/register/verify/post.json b/backend/schema/paths/users/userID/passkeys/register/verify/post.json index 8da4eb52a2..77af0f070c 100644 --- a/backend/schema/paths/users/userID/passkeys/register/verify/post.json +++ b/backend/schema/paths/users/userID/passkeys/register/verify/post.json @@ -2,7 +2,11 @@ "operationId": "verifyPasskeyRegistration", "summary": "Verify passkey registration and store credential", "tags": ["users"], - "security": [{ "BearerAuth": [] }], + "security": [ + { + "bearerAuth": [] + } + ], "parameters": [ { "in": "path", From fd3e5f1a5ae48f1c1b362fc3da4e607f13c77580 Mon Sep 17 00:00:00 2001 From: florida117 <77394159+florida117@users.noreply.github.com> Date: Tue, 3 Feb 2026 18:33:19 +0000 Subject: [PATCH 04/12] Fix passkey OpenAPI schema linting warnings Add missing parameter descriptions and examples for userID/passkeyID path parameters, add response/request examples to all passkey endpoint schemas, and suppress false-positive no-http-verbs-in-path warnings for WebAuthn "options" endpoints via x-lint-ignore. Co-Authored-By: Claude Opus 4.5 --- .../paths/tokens/passkey/options/post.json | 24 +++++++++++-- .../paths/tokens/passkey/verify/post.json | 6 ++-- .../paths/users/userID/passkeys/get.json | 27 +++++++++++---- .../userID/passkeys/passkeyID/delete.json | 13 +++++-- .../users/userID/passkeys/passkeyID/put.json | 32 ++++++++++++----- .../passkeys/register/options/post.json | 32 +++++++++++++++-- .../userID/passkeys/register/verify/post.json | 34 ++++++++++++++----- backend/schema/swagger.json | 2 ++ 8 files changed, 138 insertions(+), 32 deletions(-) diff --git a/backend/schema/paths/tokens/passkey/options/post.json b/backend/schema/paths/tokens/passkey/options/post.json index 2a618bcf25..f05675cf3d 100644 --- a/backend/schema/paths/tokens/passkey/options/post.json +++ b/backend/schema/paths/tokens/passkey/options/post.json @@ -25,14 +25,34 @@ "200": { "content": { "application/json": { + "examples": { + "default": { + "value": { + "options": { + "challenge": "dGVzdC1jaGFsbGVuZ2U", + "timeout": 60000, + "rpId": "example.com", + "allowCredentials": [] + }, + "challenge_token": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNzA3MjQwMDAwfQ.signature" + } + } + }, "schema": { "type": "object", "properties": { "options": { - "type": "object" + "type": "object", + "example": { + "challenge": "dGVzdC1jaGFsbGVuZ2U", + "timeout": 60000, + "rpId": "example.com", + "allowCredentials": [] + } }, "challenge_token": { - "type": "string" + "type": "string", + "example": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNzA3MjQwMDAwfQ.signature" } } } diff --git a/backend/schema/paths/tokens/passkey/verify/post.json b/backend/schema/paths/tokens/passkey/verify/post.json index e6bf6f1538..8727f92a9f 100644 --- a/backend/schema/paths/tokens/passkey/verify/post.json +++ b/backend/schema/paths/tokens/passkey/verify/post.json @@ -12,12 +12,14 @@ "properties": { "challenge_token": { "minLength": 1, - "type": "string" + "type": "string", + "example": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNzA3MjQwMDAwfQ.signature" }, "credential": { "minLength": 1, "type": "string", - "description": "JSON-stringified WebAuthn credential response" + "description": "JSON-stringified WebAuthn credential response", + "example": "{\"id\":\"abc123\",\"rawId\":\"abc123\",\"type\":\"public-key\",\"response\":{\"authenticatorData\":\"data\",\"clientDataJSON\":\"json\",\"signature\":\"sig\"}}" } }, "required": ["challenge_token", "credential"], diff --git a/backend/schema/paths/users/userID/passkeys/get.json b/backend/schema/paths/users/userID/passkeys/get.json index 613d727d9b..f1f80b54aa 100644 --- a/backend/schema/paths/users/userID/passkeys/get.json +++ b/backend/schema/paths/users/userID/passkeys/get.json @@ -12,23 +12,38 @@ "in": "path", "name": "userID", "schema": { "type": "integer", "minimum": 1 }, - "required": true + "required": true, + "description": "User ID", + "example": 1 } ], "responses": { "200": { "content": { "application/json": { + "examples": { + "default": { + "value": [ + { + "id": 1, + "friendly_name": "My Security Key", + "created_on": "2024-01-15T10:30:00.000Z", + "device_type": "multi_device", + "backed_up": true + } + ] + } + }, "schema": { "type": "array", "items": { "type": "object", "properties": { - "id": { "type": "integer" }, - "friendly_name": { "type": "string" }, - "created_on": { "type": "string" }, - "device_type": { "type": "string" }, - "backed_up": { "type": "boolean" } + "id": { "type": "integer", "example": 1 }, + "friendly_name": { "type": "string", "example": "My Security Key" }, + "created_on": { "type": "string", "example": "2024-01-15T10:30:00.000Z" }, + "device_type": { "type": "string", "example": "multi_device" }, + "backed_up": { "type": "boolean", "example": true } } } } diff --git a/backend/schema/paths/users/userID/passkeys/passkeyID/delete.json b/backend/schema/paths/users/userID/passkeys/passkeyID/delete.json index 471abc0513..3d15ef2ed0 100644 --- a/backend/schema/paths/users/userID/passkeys/passkeyID/delete.json +++ b/backend/schema/paths/users/userID/passkeys/passkeyID/delete.json @@ -12,19 +12,28 @@ "in": "path", "name": "userID", "schema": { "type": "integer", "minimum": 1 }, - "required": true + "required": true, + "description": "User ID", + "example": 1 }, { "in": "path", "name": "passkeyID", "schema": { "type": "integer", "minimum": 1 }, - "required": true + "required": true, + "description": "Passkey ID", + "example": 1 } ], "responses": { "200": { "content": { "application/json": { + "examples": { + "default": { + "value": true + } + }, "schema": { "type": "boolean" } diff --git a/backend/schema/paths/users/userID/passkeys/passkeyID/put.json b/backend/schema/paths/users/userID/passkeys/passkeyID/put.json index 199db5cbac..d60c314d2b 100644 --- a/backend/schema/paths/users/userID/passkeys/passkeyID/put.json +++ b/backend/schema/paths/users/userID/passkeys/passkeyID/put.json @@ -12,13 +12,17 @@ "in": "path", "name": "userID", "schema": { "type": "integer", "minimum": 1 }, - "required": true + "required": true, + "description": "User ID", + "example": 1 }, { "in": "path", "name": "passkeyID", "schema": { "type": "integer", "minimum": 1 }, - "required": true + "required": true, + "description": "Passkey ID", + "example": 1 } ], "requestBody": { @@ -32,7 +36,8 @@ "friendly_name": { "minLength": 1, "maxLength": 255, - "type": "string" + "type": "string", + "example": "My Security Key" } }, "required": ["friendly_name"], @@ -45,14 +50,25 @@ "200": { "content": { "application/json": { + "examples": { + "default": { + "value": { + "id": 1, + "friendly_name": "My Security Key", + "created_on": "2024-01-15T10:30:00.000Z", + "device_type": "multi_device", + "backed_up": true + } + } + }, "schema": { "type": "object", "properties": { - "id": { "type": "integer" }, - "friendly_name": { "type": "string" }, - "created_on": { "type": "string" }, - "device_type": { "type": "string" }, - "backed_up": { "type": "boolean" } + "id": { "type": "integer", "example": 1 }, + "friendly_name": { "type": "string", "example": "My Security Key" }, + "created_on": { "type": "string", "example": "2024-01-15T10:30:00.000Z" }, + "device_type": { "type": "string", "example": "multi_device" }, + "backed_up": { "type": "boolean", "example": true } } } } diff --git a/backend/schema/paths/users/userID/passkeys/register/options/post.json b/backend/schema/paths/users/userID/passkeys/register/options/post.json index 19474c167b..b4ceb3bbb0 100644 --- a/backend/schema/paths/users/userID/passkeys/register/options/post.json +++ b/backend/schema/paths/users/userID/passkeys/register/options/post.json @@ -12,18 +12,44 @@ "in": "path", "name": "userID", "schema": { "type": "integer", "minimum": 1 }, - "required": true + "required": true, + "description": "User ID", + "example": 1 } ], "responses": { "200": { "content": { "application/json": { + "examples": { + "default": { + "value": { + "options": { + "challenge": "dGVzdC1jaGFsbGVuZ2U", + "rp": { "name": "Nginx Proxy Manager", "id": "example.com" }, + "user": { "id": "dXNlci1pZA", "name": "user@example.com", "displayName": "User" }, + "timeout": 60000, + "attestation": "none" + }, + "challenge_token": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNzA3MjQwMDAwfQ.signature" + } + } + }, "schema": { "type": "object", "properties": { - "options": { "type": "object" }, - "challenge_token": { "type": "string" } + "options": { + "type": "object", + "example": { + "challenge": "dGVzdC1jaGFsbGVuZ2U", + "rp": { "name": "Nginx Proxy Manager", "id": "example.com" }, + "timeout": 60000 + } + }, + "challenge_token": { + "type": "string", + "example": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNzA3MjQwMDAwfQ.signature" + } } } } diff --git a/backend/schema/paths/users/userID/passkeys/register/verify/post.json b/backend/schema/paths/users/userID/passkeys/register/verify/post.json index 77af0f070c..974478f9f2 100644 --- a/backend/schema/paths/users/userID/passkeys/register/verify/post.json +++ b/backend/schema/paths/users/userID/passkeys/register/verify/post.json @@ -12,7 +12,9 @@ "in": "path", "name": "userID", "schema": { "type": "integer", "minimum": 1 }, - "required": true + "required": true, + "description": "User ID", + "example": 1 } ], "requestBody": { @@ -25,16 +27,19 @@ "properties": { "challenge_token": { "minLength": 1, - "type": "string" + "type": "string", + "example": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNzA3MjQwMDAwfQ.signature" }, "credential": { "minLength": 1, "type": "string", - "description": "JSON-stringified WebAuthn credential response" + "description": "JSON-stringified WebAuthn credential response", + "example": "{\"id\":\"abc123\",\"rawId\":\"abc123\",\"type\":\"public-key\",\"response\":{\"attestationObject\":\"data\",\"clientDataJSON\":\"json\"}}" }, "friendly_name": { "type": "string", - "maxLength": 255 + "maxLength": 255, + "example": "My Security Key" } }, "required": ["challenge_token", "credential"], @@ -47,14 +52,25 @@ "201": { "content": { "application/json": { + "examples": { + "default": { + "value": { + "id": 1, + "friendly_name": "My Security Key", + "created_on": "2024-01-15T10:30:00.000Z", + "device_type": "multi_device", + "backed_up": true + } + } + }, "schema": { "type": "object", "properties": { - "id": { "type": "integer" }, - "friendly_name": { "type": "string" }, - "created_on": { "type": "string" }, - "device_type": { "type": "string" }, - "backed_up": { "type": "boolean" } + "id": { "type": "integer", "example": 1 }, + "friendly_name": { "type": "string", "example": "My Security Key" }, + "created_on": { "type": "string", "example": "2024-01-15T10:30:00.000Z" }, + "device_type": { "type": "string", "example": "multi_device" }, + "backed_up": { "type": "boolean", "example": true } } } } diff --git a/backend/schema/swagger.json b/backend/schema/swagger.json index f5c65cac0c..ba5a2e0cf2 100644 --- a/backend/schema/swagger.json +++ b/backend/schema/swagger.json @@ -299,6 +299,7 @@ } }, "/tokens/passkey/options": { + "x-lint-ignore": ["no-http-verbs-in-path"], "post": { "$ref": "./paths/tokens/passkey/options/post.json" } @@ -359,6 +360,7 @@ } }, "/users/{userID}/passkeys/register/options": { + "x-lint-ignore": ["no-http-verbs-in-path"], "post": { "$ref": "./paths/users/userID/passkeys/register/options/post.json" } From b7b5a95488dcd6d7966d992f42cf9c53740eaa45 Mon Sep 17 00:00:00 2001 From: florida117 <77394159+florida117@users.noreply.github.com> Date: Wed, 4 Feb 2026 10:00:16 +0000 Subject: [PATCH 05/12] Add passkey option to setup page and fix WebAuthn origin detection Setup page now uses a three-step flow: enter name/email, choose between password or passkey, then complete the chosen method. The backend returns a JWT token in setup mode so the frontend can authenticate immediately without a separate login call. Also fix WebAuthn origin mismatch by preferring the Origin request header over constructing it from protocol/host, which dropped the port in proxied environments. Co-Authored-By: Claude Opus 4.5 --- backend/internal/webauthn.js | 1 + backend/routes/users.js | 10 +- frontend/src/context/AuthContext.tsx | 6 + frontend/src/locale/src/en.json | 12 + frontend/src/pages/Setup/index.tsx | 416 ++++++++++++++++++--------- 5 files changed, 304 insertions(+), 141 deletions(-) diff --git a/backend/internal/webauthn.js b/backend/internal/webauthn.js index e91ef3b6ac..9eb02a4427 100644 --- a/backend/internal/webauthn.js +++ b/backend/internal/webauthn.js @@ -20,6 +20,7 @@ const getRP = (req) => { const rpID = process.env.WEBAUTHN_RP_ID || req.hostname; const rpName = process.env.WEBAUTHN_RP_NAME || "Nginx Proxy Manager"; const origin = process.env.WEBAUTHN_ORIGIN + || req.get("origin") || `${req.protocol}://${req.get("host")}`; return { rpID, rpName, origin }; }; diff --git a/backend/routes/users.js b/backend/routes/users.js index e0358ba2bb..7830755146 100644 --- a/backend/routes/users.js +++ b/backend/routes/users.js @@ -1,5 +1,6 @@ import express from "express"; import internal2FA from "../internal/2fa.js"; +import internalToken from "../internal/token.js"; import internalUser from "../internal/user.js"; import internalWebauthn from "../internal/webauthn.js"; import Access from "../lib/access.js"; @@ -101,7 +102,14 @@ router body, ); const user = await internalUser.create(res.locals.access, payload); - res.status(201).send(user); + + if (!setup) { + // In setup mode, include a token so the frontend can authenticate immediately + const tokenResult = await internalToken.getTokenFromUser(user); + res.status(201).send({ ...user, token: tokenResult.token, expires: tokenResult.expires }); + } else { + res.status(201).send(user); + } } catch (err) { debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); diff --git a/frontend/src/context/AuthContext.tsx b/frontend/src/context/AuthContext.tsx index f7a18efe30..de0221611f 100644 --- a/frontend/src/context/AuthContext.tsx +++ b/frontend/src/context/AuthContext.tsx @@ -25,6 +25,7 @@ export interface AuthContextType { twoFactorChallenge: TwoFactorChallenge | null; login: (username: string, password: string) => Promise; loginWithPasskey: () => Promise; + authenticateWithToken: (response: TokenResponse) => void; verifyTwoFactor: (code: string) => Promise; cancelTwoFactor: () => void; loginAs: (id: number) => Promise; @@ -113,11 +114,16 @@ function AuthProvider({ children, tokenRefreshInterval = 5 * 60 * 1000 }: Props) true, ); + const authenticateWithToken = (response: TokenResponse) => { + handleTokenUpdate(response); + }; + const value = { authenticated, twoFactorChallenge, login, loginWithPasskey, + authenticateWithToken, verifyTwoFactor, cancelTwoFactor, loginAs, diff --git a/frontend/src/locale/src/en.json b/frontend/src/locale/src/en.json index 1a67710f64..da944e91d6 100644 --- a/frontend/src/locale/src/en.json +++ b/frontend/src/locale/src/en.json @@ -713,6 +713,18 @@ "settings.default-site.redirect": { "defaultMessage": "Redirect" }, + "setup.choose-auth-method": { + "defaultMessage": "Choose how to secure your account." + }, + "setup.create-with-passkey": { + "defaultMessage": "Set up with Passkey" + }, + "setup.create-with-password": { + "defaultMessage": "Set up with Password" + }, + "setup.next": { + "defaultMessage": "Next" + }, "setup.preamble": { "defaultMessage": "Get started by creating your admin account." }, diff --git a/frontend/src/pages/Setup/index.tsx b/frontend/src/pages/Setup/index.tsx index 4becf5faec..03cb052634 100644 --- a/frontend/src/pages/Setup/index.tsx +++ b/frontend/src/pages/Setup/index.tsx @@ -1,63 +1,311 @@ import { useQueryClient } from "@tanstack/react-query"; +import { startRegistration } from "@simplewebauthn/browser"; import cn from "classnames"; import { Field, Form, Formik } from "formik"; import { useState } from "react"; import { Alert } from "react-bootstrap"; -import { createUser } from "src/api/backend"; +import { + createUser, + getPasskeyRegOptions, + verifyPasskeyRegistration, +} from "src/api/backend"; import { Button, LocalePicker, Page, ThemeSwitcher } from "src/components"; import { useAuthState } from "src/context"; import { intl, T } from "src/locale"; import { validateEmail, validateString } from "src/modules/Validations"; import styles from "./index.module.css"; -interface Payload { +interface UserInfo { name: string; email: string; - password: string; } +type Step = "user-info" | "choose-method" | "password"; + export default function Setup() { const queryClient = useQueryClient(); - const { login } = useAuthState(); + const { authenticateWithToken } = useAuthState(); const [errorMsg, setErrorMsg] = useState(null); + const [userInfo, setUserInfo] = useState(null); + const [step, setStep] = useState("user-info"); + const [passkeyLoading, setPasskeyLoading] = useState(false); + const [passwordLoading, setPasswordLoading] = useState(false); + const [passkeySupported] = useState(() => typeof window.PublicKeyCredential !== "undefined"); - const onSubmit = async (values: Payload, { setSubmitting }: any) => { + const onUserInfoSubmit = async (values: UserInfo, { setSubmitting }: any) => { setErrorMsg(null); + setUserInfo(values); + setStep(passkeySupported ? "choose-method" : "password"); + setSubmitting(false); + }; - // Set a nickname, which is the first word of the name - const nickname = values.name.split(" ")[0]; + const onPasswordSubmit = async (values: { password: string }, { setSubmitting }: any) => { + if (!userInfo) return; + setErrorMsg(null); + setPasswordLoading(true); - const { password, ...payload } = { - ...values, - ...{ - nickname, - auth: { - type: "password", - secret: values.password, - }, - }, - }; + const nickname = userInfo.name.split(" ")[0]; try { - const user = await createUser(payload, true); - if (user?.id) { - try { - await login(user.email, password); - // Trigger a Health change - await queryClient.refetchQueries({ queryKey: ["health"] }); - // window.location.reload(); - } catch (err: any) { - setErrorMsg(err.message); - } + const result = await createUser( + { + name: userInfo.name, + email: userInfo.email, + nickname, + auth: { type: "password", secret: values.password }, + }, + true, + ); + if (result?.id) { + authenticateWithToken({ token: (result as any).token, expires: (result as any).expires }); + await queryClient.refetchQueries({ queryKey: ["health"] }); } else { setErrorMsg("cannot_create_user"); } } catch (err: any) { setErrorMsg(err.message); } + setPasswordLoading(false); setSubmitting(false); }; + const onPasskeySetup = async () => { + if (!userInfo) return; + setErrorMsg(null); + setPasskeyLoading(true); + + const nickname = userInfo.name.split(" ")[0]; + + try { + const result = await createUser( + { name: userInfo.name, email: userInfo.email, nickname }, + true, + ); + + if (!result?.id) { + setErrorMsg("cannot_create_user"); + setPasskeyLoading(false); + return; + } + + // Store the token so passkey registration API calls are authenticated + authenticateWithToken({ token: (result as any).token, expires: (result as any).expires }); + + // Now register a passkey + try { + const regOptions = await getPasskeyRegOptions(result.id); + const credential = await startRegistration({ optionsJSON: regOptions.options }); + await verifyPasskeyRegistration( + result.id, + regOptions.challengeToken, + JSON.stringify(credential), + "Setup passkey", + ); + } catch { + // If passkey registration fails (user cancels, device error, etc.), + // the user is already created and authenticated. They can configure + // auth from the settings menu. + } + + await queryClient.refetchQueries({ queryKey: ["health"] }); + } catch (err: any) { + setErrorMsg(err.message); + } + setPasskeyLoading(false); + }; + + const renderUserInfo = () => ( + + {({ isSubmitting }) => ( +
+
+

+ +

+

+ +

+
+
+
+
+ + {({ field, form }: any) => ( +
+ + + {form.errors.name ? ( +
+ {form.errors.name && form.touched.name + ? form.errors.name + : null} +
+ ) : null} +
+ )} +
+
+
+ + {({ field, form }: any) => ( +
+ + + {form.errors.email ? ( +
+ {form.errors.email && form.touched.email + ? form.errors.email + : null} +
+ ) : null} +
+ )} +
+
+
+
+ +
+
+ )} +
+ ); + + const renderChooseMethod = () => ( + <> +
+

+ +

+

+ +

+
+
+
+ +
+ +
+ +
+ + ); + + const renderPassword = () => ( + + {({ isSubmitting }) => ( +
+
+

+ +

+

+ +

+
+
+
+
+ + {({ field, form }: any) => ( +
+ + + {form.errors.password ? ( +
+ {form.errors.password && form.touched.password + ? form.errors.password + : null} +
+ ) : null} +
+ )} +
+
+
+
+ +
+
+ )} +
+ ); + + const renderStep = () => { + switch (step) { + case "choose-method": + return renderChooseMethod(); + case "password": + return renderPassword(); + default: + return renderUserInfo(); + } + }; + return (
@@ -76,119 +324,7 @@ export default function Setup() { setErrorMsg(null)} dismissible> {errorMsg} - - {({ isSubmitting }) => ( -
-
-

- -

-

- -

-
-
-
-
- - {({ field, form }: any) => ( -
- - - {form.errors.name ? ( -
- {form.errors.name && form.touched.name - ? form.errors.name - : null} -
- ) : null} -
- )} -
-
-
- - {({ field, form }: any) => ( -
- - - {form.errors.email ? ( -
- {form.errors.email && form.touched.email - ? form.errors.email - : null} -
- ) : null} -
- )} -
-
-
- - {({ field, form }: any) => ( -
- - - {form.errors.password ? ( -
- {form.errors.password && form.touched.password - ? form.errors.password - : null} -
- ) : null} -
- )} -
-
-
-
- -
-
- )} -
+ {renderStep()}
From 9cd04b166b07e595433e7f04dbdf652fb23b1361 Mon Sep 17 00:00:00 2001 From: florida117 <77394159+florida117@users.noreply.github.com> Date: Wed, 4 Feb 2026 10:23:40 +0000 Subject: [PATCH 06/12] Add hasPassword support for passkey-only accounts Backend now returns has_password field when fetching user data, allowing the frontend to distinguish between password and passkey-only accounts. The change password modal hides the current password field and shows "Set Password" for accounts without a password. The backend setPassword handler skips the current password check when no password auth exists. Co-Authored-By: Claude Opus 4.5 --- backend/internal/user.js | 38 +++++++++++++++------ frontend/src/api/backend/models.ts | 1 + frontend/src/components/SiteHeader.tsx | 4 +-- frontend/src/modals/ChangePasswordModal.tsx | 15 ++++---- 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/backend/internal/user.js b/backend/internal/user.js index d13931d54a..9174bc0a38 100644 --- a/backend/internal/user.js +++ b/backend/internal/user.js @@ -170,7 +170,7 @@ const internalUser = { return query.then(utils.omitRow(omissions())); }) - .then((row) => { + .then(async (row) => { if (!row || !row.id) { throw new errs.ItemNotFoundError(thisData.id); } @@ -183,6 +183,16 @@ const internalUser = { row.avatar = DEFAULT_AVATAR; } + // Include has_password when user is fetching themselves or is an admin + if (row.id === access.token.getUserId(0) || access.token.hasScope("admin")) { + const passwordAuth = await authModel + .query() + .where("user_id", row.id) + .andWhere("type", "password") + .first(); + row.has_password = !!passwordAuth; + } + return row; }); }, @@ -350,7 +360,7 @@ const internalUser = { .then(() => { return internalUser.get(access, { id: data.id }); }) - .then((user) => { + .then(async (user) => { if (user.id !== data.id) { // Sanity check that something crazy hasn't happened throw new errs.InternalValidationError( @@ -359,19 +369,25 @@ const internalUser = { } if (user.id === access.token.getUserId(0)) { - // they're setting their own password. Make sure their current password is correct - if (typeof data.current === "undefined" || !data.current) { - throw new errs.ValidationError("Current password was not supplied"); - } + // Check if this user already has a password set + const existingAuth = await authModel + .query() + .where("user_id", user.id) + .andWhere("type", "password") + .first(); + + if (existingAuth) { + // Has password — require current password + if (typeof data.current === "undefined" || !data.current) { + throw new errs.ValidationError("Current password was not supplied"); + } - return internalToken - .getTokenFromEmail({ + await internalToken.getTokenFromEmail({ identity: user.email, secret: data.current, - }) - .then(() => { - return user; }); + } + // No password — skip current password check, allow setting a new one } return user; diff --git a/frontend/src/api/backend/models.ts b/frontend/src/api/backend/models.ts index d63d47aecc..b6f1eef49f 100644 --- a/frontend/src/api/backend/models.ts +++ b/frontend/src/api/backend/models.ts @@ -29,6 +29,7 @@ export interface User { avatar: string; roles: string[]; permissions?: UserPermissions; + hasPassword?: boolean; } export interface AuditLog { diff --git a/frontend/src/components/SiteHeader.tsx b/frontend/src/components/SiteHeader.tsx index 54c01f4c3d..6e44aca4c3 100644 --- a/frontend/src/components/SiteHeader.tsx +++ b/frontend/src/components/SiteHeader.tsx @@ -102,11 +102,11 @@ export function SiteHeader() { className="dropdown-item" onClick={(e) => { e.preventDefault(); - showChangePasswordModal("me"); + showChangePasswordModal("me", currentUser?.hasPassword ?? true); }} > - + { - EasyModal.show(ChangePasswordModal, { id }); +const showChangePasswordModal = (id: number | "me", hasPassword = true) => { + EasyModal.show(ChangePasswordModal, { userId: id, hasPassword }); }; interface Props extends InnerModalProps { - id: number | "me"; + userId: number | "me"; + hasPassword: boolean; } -const ChangePasswordModal = EasyModal.create(({ id, visible, remove }: Props) => { +const ChangePasswordModal = EasyModal.create(({ userId, hasPassword, visible, remove }: Props) => { const [error, setError] = useState(null); const [isSubmitting, setIsSubmitting] = useState(false); @@ -31,7 +32,7 @@ const ChangePasswordModal = EasyModal.create(({ id, visible, remove }: Props) => setError(null); try { - await updateAuth(id, values.new, values.current); + await updateAuth(userId, values.new, hasPassword ? values.current : undefined); remove(); } catch (err: any) { setError(); @@ -56,13 +57,14 @@ const ChangePasswordModal = EasyModal.create(({ id, visible, remove }: Props) =>
- + setError(null)} dismissible> {error} + {hasPassword && (
{({ field, form }: any) => ( @@ -92,6 +94,7 @@ const ChangePasswordModal = EasyModal.create(({ id, visible, remove }: Props) => )}
+ )}
{({ field, form }: any) => ( From 467abce57a26f76799411a57465067d30c155246 Mon Sep 17 00:00:00 2001 From: florida117 <77394159+florida117@users.noreply.github.com> Date: Wed, 4 Feb 2026 11:04:18 +0000 Subject: [PATCH 07/12] Add ability to remove password for passkey-enabled accounts Users with at least one registered passkey can now remove their password to go fully passwordless. Backend validates passkey existence before allowing removal, and the frontend shows a "Remove Password" button in the Change Password modal when both a password and passkeys are present. Co-Authored-By: Claude Opus 4.5 --- backend/internal/user.js | 60 +++++++++++++++++ backend/routes/users.js | 18 +++++ .../paths/users/userID/auth/delete.json | 67 +++++++++++++++++++ frontend/src/api/backend/base.ts | 12 +++- frontend/src/api/backend/index.ts | 1 + frontend/src/api/backend/removeAuth.ts | 8 +++ frontend/src/components/SiteHeader.tsx | 10 ++- frontend/src/locale/src/en.json | 3 + frontend/src/modals/ChangePasswordModal.tsx | 35 ++++++++-- 9 files changed, 205 insertions(+), 9 deletions(-) create mode 100644 backend/schema/paths/users/userID/auth/delete.json create mode 100644 frontend/src/api/backend/removeAuth.ts diff --git a/backend/internal/user.js b/backend/internal/user.js index 9174bc0a38..e9ad1065f6 100644 --- a/backend/internal/user.js +++ b/backend/internal/user.js @@ -5,6 +5,7 @@ import utils from "../lib/utils.js"; import authModel from "../models/auth.js"; import userModel from "../models/user.js"; import userPermissionModel from "../models/user_permission.js"; +import webauthnCredentialModel from "../models/webauthn_credential.js"; import internalAuditLog from "./audit-log.js"; import internalToken from "./token.js"; @@ -439,6 +440,65 @@ const internalUser = { * @param {Object} data * @return {Promise} */ + /** + * @param {Access} access + * @param {Object} data + * @param {Integer} data.id + * @param {String} [data.current] + * @return {Promise} + */ + removePassword: async (access, data) => { + await access.can("users:password", data.id); + + const user = await internalUser.get(access, { id: data.id }); + if (user.id !== data.id) { + throw new errs.InternalValidationError( + `User could not be updated, IDs do not match: ${user.id} !== ${data.id}`, + ); + } + + // Verify user has at least one passkey as an alternative auth method + const passkeys = await webauthnCredentialModel + .query() + .where("user_id", user.id) + .andWhere("is_deleted", 0); + + if (passkeys.length === 0) { + throw new errs.ValidationError("Cannot remove password without an alternative authentication method (passkey)"); + } + + // If user is removing their own password, verify current password + if (user.id === access.token.getUserId(0)) { + if (typeof data.current === "undefined" || !data.current) { + throw new errs.ValidationError("Current password was not supplied"); + } + + await internalToken.getTokenFromEmail({ + identity: user.email, + secret: data.current, + }); + } + + // Delete the password auth row + await authModel + .query() + .where("user_id", user.id) + .andWhere("type", "password") + .delete(); + + await internalAuditLog.add(access, { + action: "updated", + object_type: "user", + object_id: user.id, + meta: { + name: user.name, + password_removed: true, + }, + }); + + return true; + }, + setPermissions: (access, data) => { return access .can("users:permissions", data.id) diff --git a/backend/routes/users.js b/backend/routes/users.js index 7830755146..2ef600db80 100644 --- a/backend/routes/users.js +++ b/backend/routes/users.js @@ -268,6 +268,24 @@ router debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); next(err); } + }) + + /** + * DELETE /api/users/123/auth + * + * Remove password for a user (requires passkey as alternative auth) + */ + .delete(async (req, res, next) => { + try { + const result = await internalUser.removePassword(res.locals.access, { + id: req.params.user_id, + current: req.body?.current, + }); + res.status(200).send(result); + } catch (err) { + debug(logger, `${req.method.toUpperCase()} ${req.path}: ${err}`); + next(err); + } }); /** diff --git a/backend/schema/paths/users/userID/auth/delete.json b/backend/schema/paths/users/userID/auth/delete.json new file mode 100644 index 0000000000..6f6d08d46c --- /dev/null +++ b/backend/schema/paths/users/userID/auth/delete.json @@ -0,0 +1,67 @@ +{ + "operationId": "deleteUserAuth", + "summary": "Remove a User's Password Authentication", + "tags": ["users"], + "security": [ + { + "bearerAuth": ["admin"] + } + ], + "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": "Optional current password for verification", + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "current": { + "type": "string", + "minLength": 1, + "maxLength": 64, + "example": "changeme" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "200 response", + "content": { + "application/json": { + "examples": { + "default": { + "value": true + } + }, + "schema": { + "type": "boolean" + } + } + } + } + } +} diff --git a/frontend/src/api/backend/base.ts b/frontend/src/api/backend/base.ts index d56f120c7f..7072fdcc0a 100644 --- a/frontend/src/api/backend/base.ts +++ b/frontend/src/api/backend/base.ts @@ -150,14 +150,20 @@ export async function put({ url, params, data }: PutArgs, abortController?: Abor interface DeleteArgs { url: string; params?: queryString.StringifiableRecord; + data?: Record; } -export async function del({ url, params }: DeleteArgs, abortController?: AbortController) { +export async function del({ url, params, data }: DeleteArgs, abortController?: AbortController) { const apiUrl = buildUrl({ url, params }); const method = "DELETE"; - const headers = { + const headers: Record = { ...buildAuthHeader(), }; const signal = abortController?.signal; - const response = await fetch(apiUrl, { method, headers, signal }); + let body: string | undefined; + if (data) { + headers[contentTypeHeader] = "application/json"; + body = buildBody(data); + } + const response = await fetch(apiUrl, { method, headers, body, signal }); return processResponse(response); } diff --git a/frontend/src/api/backend/index.ts b/frontend/src/api/backend/index.ts index 809211f148..ce1ec17a5f 100644 --- a/frontend/src/api/backend/index.ts +++ b/frontend/src/api/backend/index.ts @@ -62,3 +62,4 @@ export * from "./uploadCertificate"; export * from "./validateCertificate"; export * from "./twoFactor"; export * from "./passkeys"; +export * from "./removeAuth"; diff --git a/frontend/src/api/backend/removeAuth.ts b/frontend/src/api/backend/removeAuth.ts new file mode 100644 index 0000000000..309d5143c1 --- /dev/null +++ b/frontend/src/api/backend/removeAuth.ts @@ -0,0 +1,8 @@ +import * as api from "./base"; + +export async function removeAuth(userId: number | "me", current?: string): Promise { + return await api.del({ + url: `/users/${userId}/auth`, + data: current ? { current } : undefined, + }); +} diff --git a/frontend/src/components/SiteHeader.tsx b/frontend/src/components/SiteHeader.tsx index 6e44aca4c3..5ceacd7824 100644 --- a/frontend/src/components/SiteHeader.tsx +++ b/frontend/src/components/SiteHeader.tsx @@ -1,4 +1,6 @@ import { IconFingerprint, IconLock, IconLogout, IconShieldLock, IconUser } from "@tabler/icons-react"; +import { useQuery } from "@tanstack/react-query"; +import { listPasskeys } from "src/api/backend"; import { LocalePicker, NavLink, ThemeSwitcher } from "src/components"; import { useAuthState } from "src/context"; import { useUser } from "src/hooks"; @@ -8,7 +10,13 @@ import styles from "./SiteHeader.module.css"; export function SiteHeader() { const { data: currentUser } = useUser("me"); + const { data: passkeys } = useQuery({ + queryKey: ["passkeys", "me"], + queryFn: () => listPasskeys("me"), + enabled: !!currentUser, + }); const isAdmin = currentUser?.roles.includes("admin"); + const hasPasskeys = (passkeys?.length ?? 0) > 0; const { logout } = useAuthState(); return ( @@ -102,7 +110,7 @@ export function SiteHeader() { className="dropdown-item" onClick={(e) => { e.preventDefault(); - showChangePasswordModal("me", currentUser?.hasPassword ?? true); + showChangePasswordModal("me", currentUser?.hasPassword ?? true, hasPasskeys); }} > diff --git a/frontend/src/locale/src/en.json b/frontend/src/locale/src/en.json index da944e91d6..2924d256e9 100644 --- a/frontend/src/locale/src/en.json +++ b/frontend/src/locale/src/en.json @@ -800,6 +800,9 @@ "user.passkeys": { "defaultMessage": "Passkeys" }, + "user.remove-password": { + "defaultMessage": "Remove Password" + }, "user.set-password": { "defaultMessage": "Set Password" }, diff --git a/frontend/src/modals/ChangePasswordModal.tsx b/frontend/src/modals/ChangePasswordModal.tsx index 2d490ac555..1a365a6919 100644 --- a/frontend/src/modals/ChangePasswordModal.tsx +++ b/frontend/src/modals/ChangePasswordModal.tsx @@ -3,20 +3,21 @@ import { Field, Form, Formik } from "formik"; import { type ReactNode, useState } from "react"; import { Alert } from "react-bootstrap"; import Modal from "react-bootstrap/Modal"; -import { updateAuth } from "src/api/backend"; +import { removeAuth, updateAuth } from "src/api/backend"; import { Button } from "src/components"; import { intl, T } from "src/locale"; import { validateString } from "src/modules/Validations"; -const showChangePasswordModal = (id: number | "me", hasPassword = true) => { - EasyModal.show(ChangePasswordModal, { userId: id, hasPassword }); +const showChangePasswordModal = (id: number | "me", hasPassword = true, hasPasskeys = false) => { + EasyModal.show(ChangePasswordModal, { userId: id, hasPassword, hasPasskeys }); }; interface Props extends InnerModalProps { userId: number | "me"; hasPassword: boolean; + hasPasskeys: boolean; } -const ChangePasswordModal = EasyModal.create(({ userId, hasPassword, visible, remove }: Props) => { +const ChangePasswordModal = EasyModal.create(({ userId, hasPassword, hasPasskeys, visible, remove }: Props) => { const [error, setError] = useState(null); const [isSubmitting, setIsSubmitting] = useState(false); @@ -41,6 +42,20 @@ const ChangePasswordModal = EasyModal.create(({ userId, hasPassword, visible, re setSubmitting(false); }; + const onRemovePassword = async (values: any) => { + if (isSubmitting) return; + setIsSubmitting(true); + setError(null); + + try { + await removeAuth(userId, values.current); + remove(); + } catch (err: any) { + setError(); + } + setIsSubmitting(false); + }; + return ( - {() => ( + {({ values }) => ( @@ -152,6 +167,16 @@ const ChangePasswordModal = EasyModal.create(({ userId, hasPassword, visible, re + {hasPassword && hasPasskeys && ( + + )}