From bfd5c32061ab1be97f395186d4e76443319f9287 Mon Sep 17 00:00:00 2001 From: Parth Bhatt Date: Sun, 14 Sep 2025 19:15:47 -0700 Subject: [PATCH 01/18] Add MRZ scanning support with Dynamsoft native camera UI. - Implements plugin architecture for optical scanning with MRZ, QR, and PDF417 support. - Integrates Dynamsoft MRZ scanner with native camera interface for passport/ID scanning. - Adds scan type selection UI with dedicated modes for different document types. - Includes validation logic for MRZ field integrity and critical field checking. - Configures timeout handling and scanning mode coordination between continuous and camera-based scanning. - Provides Vue.js components (OpticalScanner, ScannerUI) with reactive state management. --- .gitignore | 1 + CHANGELOG.md | 115 +- README.md | 196 +- components/OpticalScanner.vue | 803 ++++++ components/ScannerUI.vue | 493 ++++ index.html | 13 + lib/ConfigStorage.js | 107 - lib/Hmac.js | 63 - lib/Kek.js | 75 - lib/P256Kak.js | 59 - lib/PouchEdvClient.js | 344 --- lib/PouchTransport.js | 140 - lib/X25519Kak.js | 87 - lib/assert.js | 170 -- lib/chunks.js | 178 -- lib/docs.js | 345 --- lib/edvs.js | 70 - lib/helpers.js | 116 - lib/index.js | 12 +- lib/initialize.js | 21 - lib/pbkdf2.js | 55 - lib/pouchdb.js | 297 --- lib/secrets.js | 279 -- package-lock.json | 4496 ++++++++++++++++++++++++++++++++ package.json | 57 +- src/App.vue | 3 + src/components/ScannerDemo.vue | 210 ++ src/main.js | 10 + src/router/index.js | 13 + src/views/HomeView.vue | 14 + vite.config.js | 17 + 31 files changed, 6313 insertions(+), 2546 deletions(-) create mode 100644 components/OpticalScanner.vue create mode 100644 components/ScannerUI.vue create mode 100644 index.html delete mode 100644 lib/ConfigStorage.js delete mode 100644 lib/Hmac.js delete mode 100644 lib/Kek.js delete mode 100644 lib/P256Kak.js delete mode 100644 lib/PouchEdvClient.js delete mode 100644 lib/PouchTransport.js delete mode 100644 lib/X25519Kak.js delete mode 100644 lib/assert.js delete mode 100644 lib/chunks.js delete mode 100644 lib/docs.js delete mode 100644 lib/edvs.js delete mode 100644 lib/helpers.js delete mode 100644 lib/initialize.js delete mode 100644 lib/pbkdf2.js delete mode 100644 lib/pouchdb.js delete mode 100644 lib/secrets.js create mode 100644 package-lock.json create mode 100644 src/App.vue create mode 100644 src/components/ScannerDemo.vue create mode 100644 src/main.js create mode 100644 src/router/index.js create mode 100644 src/views/HomeView.vue create mode 100644 vite.config.js diff --git a/.gitignore b/.gitignore index cfac74e..33d5369 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ coverage node_modules reports .cache +.DS_STORE diff --git a/CHANGELOG.md b/CHANGELOG.md index 63ccf13..b23cf85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,114 +1,9 @@ -# bedrock-web-pouch-edv ChangeLog +# bedrock-vue-optical-scanner ChangeLog -## 8.2.0 - 2025-07-18 - -### Changed -- Update dependencies: - - `@digitalbazaar/ecdsa-multikey@1.8` - - `pouchdb@9` - - `pouchdb-adapter-indexeddb@9` - - `pouchdb-find@9` - - dev deps and removal of `uuid`. -- Note: While pouchdb* packages have been bumped by two major versions, no - significant breaking changes are expected. The changes included internal - ES5 => ES6+ API changes that were not relevant here and a new default - limit on `find()` queries of `25`, but every `find()` query is already - expected to have provided a default or a default is provided by this - library. - -## 8.1.0 - 2023-11-07 - -### Added -- Add new `cipherVersion` parameter to control whether the cipher version - is "recommended" or "fips". The default (and previous only option) - remains "recommended". - -## 8.0.0 - 2023-10-16 - -### Changed -- **BREAKING**: Drop support for Node.js < 18. -- Use `@digitalbazaar/edv-client@16.0` that drops support for Node.js < 18 and - uses `@digitalbazaar/http-client@4` and `canonicalize@2`. - -## 7.0.0 - 2022-08-19 - -### Changed -- **BREAKING**: Use `exports` instead of `module`. -- Update dependencies. -- Lint module. - -## 6.0.1 - 2022-05-30 - -### Fixed -- Add purge operation to clean up deleted docs to prevent premature storage - quota overflow. - -## 6.0.0 - 2022-05-30 - -### Changed -- **BREAKING**: Use `indexeddb` adapter instead of `idb` adapter. This version - will also impose a `br_edv_` (bedrock EDV) prefix on database names, - causing all new databases to be created, leaving old ones alone. There is - no migration code available to convert an old database to a new one in this - version. - -## 5.0.0 - 2022-05-05 - -### Changed -- **BREAKING**: Use `@digitalbazaar/edv-client@14` with new blind - attributes version. - -## 4.1.0 - 2022-05-03 - -### Changed -- Improve pouchdb index performance by marking deleted EDV doc - records with `_deleted` flag. - -## 4.0.0 - 2022-04-05 - -### Changed -- **BREAKING**: Rename package to `@bedrock/web-pouch-edv`. -- **BREAKING**: Convert to module (ESM). -- **BREAKING**: Remove default export. -- **BREAKING**: Require node 14.x. - -## 3.0.0 - 2022-03-01 - -### Changed -- **BREAKING**: Use `@digitalbazaar/edv-client@13`. - -## 2.0.1 - 2022-02-24 - -### Fixed -- Provide alternative to `crypto.randomUUID` via `uuid` package. - -## 2.0.0 - 2022-02-23 - -### Changed -- **BREAKING**: Use `@digitalbazaar/edv-client@12`. This new version - produces encrypted indexes differently (more privacy preserving) - and is incompatible with the previous version. - -## 1.2.0 - 2022-02-05 - -### Added -- Add support for `limit` in EDV queries. - -## 1.1.0 - 2022-02-03 +## 1.0.0 - 2025-09-14 ### Added -- Automatically initialize databases when using - `PouchEdvClient` to generate a new EDV or load an one. - -### Fixed -- Fix `db.type()` deprecation warnings. -- Prevent double initialization of databases. - -## 1.0.1 - 2022-02-02 - -### Changed -- Update dependencies. - -## 1.0.0 - 2022-01-31 -- See git history for changes. +- Vue.js components `OpticalScanner.vue` and `ScannerUI.vue` with reactive state management. +- Scan type selection interface allowing users to choose between barcode/QR scanning and MRZ document scanning. +- Timeout configuration system with format-specific timeouts (no timeout for MRZ camera mode, configurable timeouts for other formats). diff --git a/README.md b/README.md index 9dfa508..24f5a90 100644 --- a/README.md +++ b/README.md @@ -1 +1,195 @@ -# bedrock-web-pouch-edv +# @bedrock/vue-optical-scanner + +A Vue.js component library for optical scanning that provides reusable UI components +for barcode, QR code, MRZ (Machine Readable Zone), and other optical code scanning. +This library follows a plugin-based architecture and separates scanning logic from +UI components. + +## Architecture + +This library is part of a two-tier architecture for optical scanning: + +### Core Libraries + +- **@bedrock/web-optical-scanner**: Low-level scanning engine with plugin architecture +- **@bedrock/vue-optical-scanner**: Vue-specific UI components (this library) + +### Architecture Principles + +#### Plugin-Based Scanning Engine + +The underlying `@bedrock/web-optical-scanner` provides: + +- Async API that accepts elements/images and options, returns scan results +- Multiple scan modes: + - `first`: Resolves as soon as any specified format is detected + - `all`: Resolves when all specified formats have results + - `exhaustive`: Resolves after all plugins have completed their efforts +- Extensible plugin system for adding new scanning formats +- Future-ready for web worker threading (API designed to support this) + +#### Vue UI Components + +This library provides: + +- Reusable Vue components for optical scanning interfaces +- Camera handling utilities and helpers +- Simple APIs with input props and async event outputs +- Modular components that can be used independently or together + +### Supported Formats + +- **QR Codes**: Standard QR code scanning +- **PDF417**: Standard PDF417 barcode format +- **Enhanced PDF417**: Advanced PDF417 with additional processing for driver licenses +- **MRZ**: Machine Readable Zone for passports and ID documents + +## Components + +### OpticalScanner + +The main scanning component that orchestrates camera access and scanning operations. + +**Props:** + +- `scanType` (required): `'mrz'` or `'barcode'` +- `scanMode`: `'first'` (default), `'all'`, or `'exhaustive'` +- `tipText`: Instruction text for users +- `showQrBox`: Boolean to show/hide scanning frame overlay +- `torchOn`: Boolean to control camera flash +- `licenseKey`: Dynamsoft License key for enhanced scanning features + +**Events:** + +- `@result`: Emitted when scan is successful +- `@error`: Emitted when scan fails +- `@close`: Emitted when scanner is closed + +### ScannerUI + +Lower-level UI component that handles camera display and controls. + +## Usage + +### Basic Usage + +```vue + + + +``` + +ScannerDemo Component +The ScannerDemo component provides a complete example implementation showing: + +- Document type selection (MRZ vs Barcode) +- Scanner controls and modal integration +- Result display for different scan types +- Error handling + +Key Features Demonstrated: + +- MRZ Scanning: Passport and ID document recognition with field validation +- Barcode Scanning: QR codes, PDF417, and enhanced PDF417 for driver licenses +- Result Processing: Type-specific result handling and display +- Camera Management: Start/stop controls with proper lifecycle management + +Usage in Demo: + +```vue + +``` + +Installation + +```bash +npm install @bedrock/vue-optical-scanner +``` + +Peer Dependencies + +```bash +npm install vue@^3.4.21 @bedrock/quasar@^10.0.0 @bedrock/web-fontawesome@^2.0.0 +``` + +Development Setup +Prerequisites + +- Node.js >= 20 +- npm or yarn + +Getting Started + +1. Clone and install dependencies: + +```bash +git clone URL +cd vue-optical-scanner +npm install +``` + +2. Start development server: + +```bash +npm run dev +``` + +3. Access the demo: Navigate to `http://localhost:5173` to see the ScannerDemo component in action. + +Development Scripts + +```bash +# Start development server with hot reload +npm run dev + +# Lint code +npm run lint + +# Fix linting issues +npm run lint:fix +``` diff --git a/components/OpticalScanner.vue b/components/OpticalScanner.vue new file mode 100644 index 0000000..f50af18 --- /dev/null +++ b/components/OpticalScanner.vue @@ -0,0 +1,803 @@ + + + diff --git a/components/ScannerUI.vue b/components/ScannerUI.vue new file mode 100644 index 0000000..d13535b --- /dev/null +++ b/components/ScannerUI.vue @@ -0,0 +1,493 @@ + + + + + diff --git a/index.html b/index.html new file mode 100644 index 0000000..21393c0 --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + + + + + + Vue Optical Scanner Demo + + +
+ + + \ No newline at end of file diff --git a/lib/ConfigStorage.js b/lib/ConfigStorage.js deleted file mode 100644 index a782343..0000000 --- a/lib/ConfigStorage.js +++ /dev/null @@ -1,107 +0,0 @@ -/*! - * Copyright (c) 2021-2022 Digital Bazaar, Inc. All rights reserved. - */ -import {assert} from './assert.js'; -import {createDatabase} from './pouchdb.js'; - -export class ConfigStorage { - constructor({assertConfig = () => {}, collectionName} = {}) { - this.assertConfig = assertConfig; - this.collectionName = collectionName; - this.client = null; - } - - /** - * Initializes a configurations database if it has not already - * been initialized. - * - * @returns {Promise} Settles once the operation completes. - */ - async initialize() { - if(this.client) { - // already initialized - return; - } - - this.client = await createDatabase({name: this.collectionName}); - - // Note: `_id` is populated using `config.id` and serves as the primary - // unique index for this collection - } - - /** - * Establishes a new object by inserting its configuration into storage. - * - * @param {object} options - The options to use. - * @param {object} options.config - The configuration. - * - * @returns {Promise} Resolves to the database record. - */ - async insert({config} = {}) { - this.assertConfig(config); - - // require starting sequence to be 0 - if(config.sequence !== 0) { - throw new Error('Configuration sequence must be "0".'); - } - - // insert config and return record - const record = {_id: config.id, config}; - const result = await this.client.insertOne({doc: record}); - return result.record; - } - - /** - * Updates a config if its sequence number is next. - * - * @param {object} options - The options to use. - * @param {object} options.config - The configuration. - * - * @returns {Promise} Resolves to the database record. - */ - async update({config} = {}) { - this.assertConfig(config); - - const record = {_id: config.id, config}; - const result = await this.client.updateOne({ - doc: record, - query: { - selector: { - _id: config.id, - 'config.sequence': config.sequence - 1 - } - } - }); - if(!result) { - const error = new Error( - 'Could not update configuration. Sequence does not match or ' + - 'configuration does not exist.'); - error.name = 'InvalidStateError'; - throw error; - } - return result.record; - } - - /** - * Gets a configuration. - * - * @param {object} options - The options to use. - * @param {object} options.id - The ID of the configuration. - * - * @returns {Promise} Resolves to the database record. - */ - async get({id} = {}) { - assert.string(id, 'id'); - - const {docs: [record]} = await this.client.find({ - selector: {_id: id}, - limit: 1 - }); - if(!record) { - const error = new Error('Configuration not found.'); - error.name = 'NotFoundError'; - throw error; - } - return record; - } -} diff --git a/lib/Hmac.js b/lib/Hmac.js deleted file mode 100644 index ac2fa74..0000000 --- a/lib/Hmac.js +++ /dev/null @@ -1,63 +0,0 @@ -/*! - * Copyright (c) 2022 Digital Bazaar, Inc. All rights reserved. - */ -import {assert} from './assert.js'; - -// eslint-disable-next-line no-undef -const {crypto} = globalThis; - -const ALGORITHM = {name: 'HMAC', hash: {name: 'SHA-256'}, length: 256}; -const EXTRACTABLE = true; -const KEY_USAGE = ['sign', 'verify']; - -export class Hmac { - constructor({key} = {}) { - this.key = key; - this.algorithm = 'HS256'; - this.type = 'Sha256HmacKey2019'; - } - - /** - * Signs some data. - * - * @param {object} options - The options to use. - * @param {Uint8Array} options.data - The data to sign. - * - * @returns {Promise} The signature. - */ - async sign({data} = {}) { - assert.uint8Array(data, 'data'); - const key = this.key; - return new Uint8Array(await crypto.subtle.sign(key.algorithm, key, data)); - } - - /** - * Verifies some data. - * - * @param {object} options - The options to use. - * @param {Uint8Array} options.data - The data to sign as a Uint8Array. - * @param {Uint8Array} options.signature - The Uint8Array signature - * to verify. - * - * @returns {Promise} `true` if verified, `false` if not. - */ - async verify({data, signature} = {}) { - assert.uint8Array(data, 'data'); - assert.uint8Array(signature, 'signature'); - const key = this.key; - return crypto.subtle.verify(key.algorithm, key, signature, data); - } - - static async generate() { - const key = await crypto.subtle.generateKey( - ALGORITHM, EXTRACTABLE, KEY_USAGE); - return new Hmac({key}); - } - - static async import({secret} = {}) { - assert.uint8Array(secret, 'secret'); - const key = await crypto.subtle.importKey( - 'raw', secret, ALGORITHM, EXTRACTABLE, KEY_USAGE); - return new Hmac({key}); - } -} diff --git a/lib/Kek.js b/lib/Kek.js deleted file mode 100644 index 1ff02be..0000000 --- a/lib/Kek.js +++ /dev/null @@ -1,75 +0,0 @@ -/*! - * Copyright (c) 2022-2023 Digital Bazaar, Inc. All rights reserved. - */ -// eslint-disable-next-line no-undef -const {crypto} = globalThis; - -const EXTRACTABLE = true; - -export class Kek { - constructor({key} = {}) { - this.key = key; - } - - /** - * Wraps a cryptographic key. - * - * @param {object} options - The options to use. - * @param {Uint8Array|CryptoKey} options.unwrappedKey - The key material as a - * `Uint8Array` or CryptoKey. - * - * @returns {Promise} - The wrapped key bytes. - */ - async wrapKey({unwrappedKey} = {}) { - const kek = this.key; - - if(unwrappedKey instanceof Uint8Array) { - // Note: `HMAC` algorithm name doesn't matter; will be exported raw. - const extractable = true; - unwrappedKey = await crypto.subtle.importKey( - 'raw', unwrappedKey, { - name: 'HMAC', hash: 'SHA-512', length: unwrappedKey.length * 8 - }, - // key usage of `sign` refers to the key that is to be wrapped not - // the KEK itself; we just treat it like an HMAC key regardless of - // what it is - extractable, ['sign']); - } - const wrappedKey = await crypto.subtle.wrapKey( - 'raw', unwrappedKey, kek, kek.algorithm); - return new Uint8Array(wrappedKey); - } - - /** - * Unwraps a cryptographic key. - * - * @param {object} options - The options to use. - * @param {Uint8Array} options.wrappedKey - The wrapped key material. - * - * @returns {Promise} - Resolves to the key bytes or null if - * the unwrapping fails because the key does not match. - */ - async unwrapKey({wrappedKey}) { - const kek = this.key; - // Note: `HMAC` algorithm name doesn't matter; will be exported raw. - try { - const key = await crypto.subtle.unwrapKey( - 'raw', wrappedKey, kek, kek.algorithm, - // key usage of `encrypt` refers to the key that is being unwrapped; - // we just treat it like an HMAC key regardless of what it is - {name: 'HMAC', hash: 'SHA-512'}, EXTRACTABLE, ['sign']); - const keyBytes = await crypto.subtle.exportKey('raw', key); - return new Uint8Array(keyBytes); - } catch(e) { - // unwrapping key failed - return null; - } - } - - static async import({secret} = {}) { - const key = await crypto.subtle.importKey( - 'raw', secret, {name: 'AES-KW', length: 256}, EXTRACTABLE, - ['wrapKey', 'unwrapKey']); - return new Kek({key}); - } -} diff --git a/lib/P256Kak.js b/lib/P256Kak.js deleted file mode 100644 index 965d888..0000000 --- a/lib/P256Kak.js +++ /dev/null @@ -1,59 +0,0 @@ -/*! - * Copyright (c) 2022-2023 Digital Bazaar, Inc. All rights reserved. - */ -import * as EcdsaMultikey from '@digitalbazaar/ecdsa-multikey'; -import {assert} from './assert.js'; - -export class P256Kak { - constructor({id, keyPair} = {}) { - this.id = id; - this.keyPair = keyPair; - this.type = 'Multikey'; - } - - /** - * Derives a shared secret via the given peer public key, typically for use - * as one parameter for computing a shared key. It should not be used as - * a shared key itself, but rather input into a key derivation function (KDF) - * to produce a shared key. - * - * @param {object} options - The options to use. - * @param {object} options.publicKey - The public key to compute the shared - * secret against; the public key type must match this KeyAgreementKey's - * type. - * - * @returns {Promise} The shared secret bytes. - */ - async deriveSecret({publicKey} = {}) { - assert.object(publicKey); - if(publicKey.type !== this.type) { - throw Error( - `The given public key type "${publicKey.type}" does not match this ` + - `key agreement key's ${this.type}.`); - } - const {publicKeyMultibase} = publicKey; - assert.string(publicKeyMultibase); - return this.keyPair.deriveSecret({publicKey}); - } - - async export({publicKey = true, privateKey = false} = {}) { - const {id, type, keyPair} = this; - const exported = await keyPair.export( - {publicKey, secretKey: privateKey, includeContext: true}); - exported.id = id; - exported.type = type; - return exported; - } - - static async generate() { - const keyPair = await EcdsaMultikey.generate( - {curve: 'P-256', keyAgreement: true}); - return new P256Kak({keyPair}); - } - - static async import({secretKey, publicKey} = {}) { - const keyPair = await EcdsaMultikey.fromRaw( - {curve: 'P-256', secretKey, publicKey, keyAgreement: true}); - return new P256Kak({keyPair}); - } -} diff --git a/lib/PouchEdvClient.js b/lib/PouchEdvClient.js deleted file mode 100644 index 3020537..0000000 --- a/lib/PouchEdvClient.js +++ /dev/null @@ -1,344 +0,0 @@ -/*! - * Copyright (c) 2022-2023 Digital Bazaar, Inc. All rights reserved. - */ -import * as edvs from './edvs.js'; -import * as secrets from './secrets.js'; -import {assert} from './assert.js'; -import {EdvClientCore} from '@digitalbazaar/edv-client'; -import {initialize} from './initialize.js'; -import {PouchTransport} from './PouchTransport.js'; - -export class PouchEdvClient extends EdvClientCore { - /** - * Creates a new EDV client for connecting to an Encrypted Data Vault (EDV) - * that is stored in PouchDB. - * - * @param {object} options - The options to use. - * @param {object} [options.hmac] - A default HMAC API for blinding - * indexable attributes. - * @param {string} [options.id] - The ID of the EDV. - * @param {object} [options.keyAgreementKey] - A default KeyAgreementKey - * API for deriving shared KEKs for wrapping content encryption keys. - * @param {Function} [options.keyResolver] - A default function that returns - * a Promise that resolves a key ID to a DH public key. - * @param {string} [options.cipherVersion='recommended'] - Sets the cipher - * version to either "recommended" or "fips". - * - * @returns {PouchEdvClient} - PouchEdvClient. - */ - constructor({hmac, id, keyAgreementKey, keyResolver, cipherVersion} = {}) { - super({hmac, id, keyAgreementKey, keyResolver, cipherVersion}); - this.transport = new PouchTransport({edvId: this.id}); - // create a transport for marking tombstoned EDV docs as deleted to - // improve pouchdb index performance - this._deleteTransport = Object.create(this.transport); - this._deleteTransport.update = async ({encrypted}) => - this.transport.update({encrypted, deleted: true}); - } - - /** - * @inheritdoc - * - * @param {object} options - The options to use. - * @param {object} options.doc - The document to insert. - * @param {ReadableStream} [options.stream] - A WHATWG Readable stream to read - * from to associate chunked data with this document. - * @param {number} [options.chunkSize=1048576] - The size, in bytes, of the - * chunks to break the incoming stream data into. - * @param {object[]} [options.recipients=[]] - A set of JWE recipients - * to encrypt the document for; if not present, a default recipient will - * be added using `this.keyAgreementKey` and if no `keyAgreementKey` is - * set, an error will be thrown. - * - * @returns {Promise} - Resolves to the inserted document. - */ - async insert({ - doc, stream, chunkSize, recipients = [] - } = {}) { - const {transport} = this; - return super.insert({doc, stream, chunkSize, recipients, transport}); - } - - /** - * @inheritdoc - * - * @param {object} options - The options to use. - * @param {object} options.doc - The document to insert. - * @param {ReadableStream} [options.stream] - A WHATWG Readable stream to read - * from to associate chunked data with this document. - * @param {number} [options.chunkSize=1048576] - The size, in bytes, of the - * chunks to break the incoming stream data into. - * @param {object} [options.recipients=[]] - A set of JWE recipients to - * encrypt the document for; if present, recipients will be added to any - * existing recipients; to remove existing recipients, modify the - * `encryptedDoc.jwe.recipients` field. - * - * @returns {Promise} - Resolves to the updated document. - */ - async update({doc, stream, chunkSize, recipients = []} = {}) { - const {transport} = this; - return super.update({doc, stream, chunkSize, recipients, transport}); - } - - /** - * @inheritdoc - * - * @param {object} options - The options to use. - * @param {object} options.doc - The document to delete. - * @param {object} [options.recipients=[]] - A set of JWE recipients to - * encrypt the document for; if present, recipients will be added to - * any existing recipients; to remove existing recipients, modify - * the `encryptedDoc.jwe.recipients` field. - * - * @returns {Promise} - Resolves to `true` if the document was - * deleted. - */ - async delete({doc, recipients = []} = {}) { - const {_deleteTransport} = this; - return super.delete({doc, recipients, transport: _deleteTransport}); - } - - /** - * @inheritdoc - * - * @param {object} options - The options to use. - * @param {string} options.id - The ID of the document to get. - * - * @returns {Promise} - Resolves to the document. - */ - async get({id} = {}) { - const {transport} = this; - return super.get({id, transport}); - } - - /** - * @inheritdoc - * - * @param {object} options - The options to use. - * @param {object} options.doc - The document to get a stream for. - * - * @returns {Promise} - Resolves to a `ReadableStream` to - * read the chunked data from. - */ - async getStream({doc} = {}) { - const {transport} = this; - return super.getStream({doc, transport}); - } - - /** - * @inheritdoc - * - * @see find - For more detailed documentation on the search options. - * - * @param {object} options - The options to use. - * @param {object|Array} [options.equals] - An object with key-value - * attribute pairs to match or an array of such objects. - * @param {string|Array} [options.has] - A string with an attribute name to - * match or an array of such strings. - * - * @returns {Promise} - Resolves to the number of matching documents. - */ - async count({equals, has} = {}) { - const {transport} = this; - return super.count({equals, has, transport}); - } - - /** - * @inheritdoc - * - * @param {object} options - The options to use. - * @param {object|Array} [options.equals] - An object with key-value - * attribute pairs to match or an array of such objects. - * @param {string|Array} [options.has] - A string with an attribute name to - * match or an array of such strings. - * @param {boolean} [options.count] - Set to `false` to find all documents - * that match a query or to `true` to give a count of documents. - * @param {number} [options.limit] - Set to limit the number of documents - * to be returned from a query (min=1, max=1000). - * - * @returns {Promise} - Resolves to the matching documents: - * {documents: [...]}. - */ - async find({equals, has, count = false, limit} = {}) { - const {transport} = this; - return super.find({equals, has, count, limit, transport}); - } - - /** - * @inheritdoc - * - * @param {object} options - The options to use. - * - * @returns {Promise} - Resolves to the configuration for the EDV. - */ - async getConfig({} = {}) { - const {transport} = this; - return super.getConfig({transport}); - } - - /** - * @inheritdoc - * - * @param {object} options - The options to use. - * @param {object} options.config - The new EDV config. - * - * @returns {Promise} - Resolves once the operation completes. - */ - async updateConfig({config} = {}) { - const {transport} = this; - return super.updateConfig({config, transport}); - } - - /** - * Creates a new EDV using the given configuration. - * - * @param {object} options - The options to use. - * @param {string} options.config - The EDV's configuration. - * @param {string} [options.password] - A password to use if the keys for - * the EDV should be generated and stored locally in encrypted storage. - * @param {string} [options.cipherVersion='recommended'] - Sets the cipher - * version to either "recommended" or "fips". - * - * @returns {Promise} - Resolves to an object with: - * `{config, edvClient}`; `edvClient` will be set if `password` is passed. - */ - static async createEdv({config, password, cipherVersion} = {}) { - // initialize EDV databases (if not already initialized) - await initialize(); - - let edvClient; - if(password !== undefined) { - if(config.hmac || config.keyAgreementKey) { - throw new Error( - '"config" must not have "hmac" or "keyAgreementKey" if these are ' + - 'to be populated using locally generated secrets.'); - } - - // generate encrypted secret, use the EDV ID as the secret's ID ... if - // it already exists, try to reuse it - const {hmac, keyAgreementKey} = await _lazyCreateSecret({ - id: config.id, password, cipherVersion - }); - config = { - ...config, - hmac: {id: hmac.id, type: hmac.type}, - keyAgreementKey: {id: keyAgreementKey.id, type: keyAgreementKey.type} - }; - edvClient = new PouchEdvClient({ - hmac, id: config.id, keyAgreementKey, - keyResolver: await _createKeyResolver({ - keyAgreementKey, edvConfig: config - }), - cipherVersion - }); - } - - assert.edvConfig(config); - const transport = new PouchTransport({edvId: config.id}); - const newConfig = await transport.createEdv({config}); - return {config: newConfig, edvClient}; - } - - /** - * Creates a new EDV client based on encrypted secrets saved in a local - * PouchDB instance. The password to decrypt the secrets must be given. - * - * @param {object} options - The options to use. - * @param {string} [options.edvId] - The ID of the EDV. - * @param {string} [options.password] - The password to use to decrypt - * the secrets. - * - * @returns {PouchEdvClient} - PouchEdvClient. - */ - static async fromLocalSecrets({edvId, password} = {}) { - // initialize EDV databases (if not already initialized) - await initialize(); - - // start getting EDV config - const edvConfigPromise = edvs.get({id: edvId}); - edvConfigPromise.catch(e => e); - - // load secret using the EDV ID as the secret ID - const {config} = await secrets.get({id: edvId}); - const result = await secrets.decrypt({config, password}); - if(!result) { - throw new Error('Invalid password.'); - } - const {hmac, keyAgreementKey, cipherVersion} = result; - - // finish getting EDV config - const edvConfigResult = await edvConfigPromise; - if(edvConfigResult instanceof Error) { - throw edvConfigResult; - } - const {config: edvConfig} = edvConfigResult; - - return new PouchEdvClient({ - hmac, id: config.id, keyAgreementKey, - keyResolver: await _createKeyResolver({keyAgreementKey, edvConfig}), - cipherVersion - }); - } - - /** - * Generates a multibase encoded random 128-bit identifier for a document. - * - * @returns {Promise} - Resolves to the identifier. - */ - static async generateId() { - return EdvClientCore.generateId(); - } -} - -async function _createKeyResolver({keyAgreementKey, edvConfig} = {}) { - // create key resolver for the EDV's key agreement key (and no other keys) - const key = await keyAgreementKey.export(); - key.controller = edvConfig.controller; - return async function keyResolver({id}) { - if(id === keyAgreementKey.id) { - return key; - } - const error = new Error('Key not found.'); - error.name = 'NotFoundError'; - throw error; - }; -} - -// called during EDV creation -async function _lazyCreateSecret({id, password, cipherVersion} = {}) { - // generate encrypted secret, use the EDV ID as the secret's ID - const {hmac, keyAgreementKey, config} = await secrets.generate( - {id, password, cipherVersion}); - try { - await secrets.insert({config}); - return {hmac, keyAgreementKey, config}; - } catch(e) { - if(e.name === 'ConstraintError') { - // secret already exists... if EDV config already exists, throw a - // duplicate error - try { - await edvs.get({id}); - const error = new Error('Duplicate EDV configuration.'); - error.name = 'DuplicateError'; - throw error; - } catch(e) { - if(e.name !== 'NotFoundError') { - throw e; - } - } - - // try to load existing secret and reuse it as it doesn't have a - // matching EDV config yet - const {config} = await secrets.get({id}); - const result = await secrets.decrypt({config, password}); - if(!result) { - throw new Error( - `Secret already exists for EDV ID (${id}) but password to unlock ` + - 'it is invalid.'); - } - const {hmac, keyAgreementKey} = result; - return {hmac, keyAgreementKey, config}; - } - throw e; - } -} diff --git a/lib/PouchTransport.js b/lib/PouchTransport.js deleted file mode 100644 index 7a3c8c2..0000000 --- a/lib/PouchTransport.js +++ /dev/null @@ -1,140 +0,0 @@ -/*! - * Copyright (c) 2022 Digital Bazaar, Inc. All rights reserved. - */ -import * as chunks from './chunks.js'; -import * as docs from './docs.js'; -import * as edvs from './edvs.js'; - -export class PouchTransport { - /** - * Creates a transport layer for an EDV client to use to perform an - * operation with an EDV stored using PouchDB. - * - * @param {object} options - The options to use. - * @param {string} [options.edvId] - The ID of the target EDV. - * - * @returns {PouchTransport} - PouchTransport. - */ - constructor({edvId} = {}) { - this.edvId = edvId; - } - - /** - * @inheritdoc - */ - async createEdv({config} = {}) { - try { - const record = await edvs.insert({config}); - return record.config; - } catch(e) { - if(e.name === 'ConstraintError') { - const err = new Error('Duplicate error.'); - err.name = 'DuplicateError'; - err.cause = e; - throw err; - } - throw e; - } - } - - /** - * @inheritdoc - */ - async getConfig({id = this.edvId} = {}) { - const record = await edvs.get({id}); - return record.config; - } - - /** - * @inheritdoc - */ - async updateConfig({config} = {}) { - const record = await edvs.update({config}); - return record.config; - } - - /** - * @inheritdoc - */ - async insert({encrypted} = {}) { - try { - await docs.insert({edvId: this.edvId, doc: encrypted}); - } catch(e) { - if(e.name === 'ConstraintError') { - const err = new Error('Duplicate error.'); - err.name = 'DuplicateError'; - err.cause = e; - throw err; - } - throw e; - } - } - - /** - * @inheritdoc - */ - async update({encrypted, deleted = false} = {}) { - try { - await docs.upsert({edvId: this.edvId, doc: encrypted, deleted}); - } catch(e) { - if(e.name === 'ConstraintError') { - const err = new Error('Duplicate error.'); - err.name = 'DuplicateError'; - err.cause = e; - throw err; - } - throw e; - } - } - - /** - * @inheritdoc - */ - async get({id} = {}) { - const record = await docs.get({edvId: this.edvId, id}); - return record.doc; - } - - /** - * @inheritdoc - */ - async find({query} = {}) { - const {edvId} = this; - const findQuery = docs.createQuery({edvId, edvQuery: query}); - const {limit} = query; - if(limit) { - // add `1` to limit to detect if more results were possible - findQuery.options.limit = limit + 1; - } - const {records} = await docs.find({edvId, query: findQuery}); - if(query.count === true) { - return {count: records.length}; - } - const result = {documents: records}; - if(limit) { - result.hasMore = result.documents.length > limit; - if(result.hasMore) { - result.documents.length = limit; - } - } - result.documents = result.documents.map(({doc}) => doc); - return result; - } - - /** - * @inheritdoc - */ - async storeChunk({docId, chunk}) { - return chunks.upsert({edvId: this.edvId, docId, chunk}); - } - - /** - * @inheritdoc - */ - async getChunk({docId, chunkIndex} = {}) { - const record = await chunks.get({ - edvId: this.edvId, docId, index: chunkIndex - }); - return record.doc; - } -} diff --git a/lib/X25519Kak.js b/lib/X25519Kak.js deleted file mode 100644 index 827e401..0000000 --- a/lib/X25519Kak.js +++ /dev/null @@ -1,87 +0,0 @@ -/*! - * Copyright (c) 2022-2023 Digital Bazaar, Inc. All rights reserved. - */ -import {multibaseDecode, multibaseEncode} from './helpers.js'; -import {assert} from './assert.js'; -import nacl from 'tweetnacl'; - -const CONTEXT_URL = 'https://w3id.org/security/suites/x25519-2020/v1'; -// multicodec x25519-pub header as varint -const MULTICODEC_X25519_PUB_HEADER = new Uint8Array([0xec, 0x01]); -// multicodec x25519-priv header as varint -const MULTICODEC_X25519_PRIV_HEADER = new Uint8Array([0x82, 0x26]); - -export class X25519Kak { - constructor({id, keyPair} = {}) { - this.id = id; - this.keyPair = keyPair; - this.type = 'X25519KeyAgreementKey2020'; - } - - /** - * Derives a shared secret via the given peer public key, typically for use - * as one parameter for computing a shared key. It should not be used as - * a shared key itself, but rather input into a key derivation function (KDF) - * to produce a shared key. - * - * @param {object} options - The options to use. - * @param {object} options.publicKey - The public key to compute the shared - * secret against; the public key type must match this KeyAgreementKey's - * type. - * - * @returns {Promise} The shared secret bytes. - */ - async deriveSecret({publicKey} = {}) { - assert.object(publicKey); - if(publicKey.type !== this.type) { - throw Error( - `The given public key type "${publicKey.type}" does not match this ` + - `key agreement key's ${this.type}.`); - } - const {publicKeyMultibase} = publicKey; - assert.string(publicKeyMultibase); - - // get public key bytes as remote public key - const remotePublicKey = multibaseDecode({ - expectedHeader: MULTICODEC_X25519_PUB_HEADER, - encoded: publicKeyMultibase - }); - - // `scalarMult` takes secret key as param 1, public key as param 2 - const {keyPair: {privateKey}} = this; - return nacl.scalarMult(privateKey, remotePublicKey); - } - - async export({publicKey = true, privateKey = false} = {}) { - const {id, type, keyPair} = this; - const exported = { - '@context': CONTEXT_URL, - id, - type - }; - if(publicKey) { - exported.publicKeyMultibase = multibaseEncode({ - header: MULTICODEC_X25519_PUB_HEADER, data: keyPair.publicKey - }); - } - if(privateKey) { - exported.privateKeyMultibase = multibaseEncode({ - header: MULTICODEC_X25519_PRIV_HEADER, data: keyPair.privateKey - }); - } - return exported; - } - - static async generate() { - const {secretKey: privateKey, publicKey} = nacl.box.keyPair(); - const keyPair = {privateKey, publicKey}; - return new X25519Kak({keyPair}); - } - - static async import({secret} = {}) { - assert.uint8Array(secret, 'secret'); - const {publicKey} = nacl.box.keyPair.fromSecretKey(secret); - const keyPair = {privateKey: new Uint8Array(secret).slice(), publicKey}; - return new X25519Kak({keyPair}); - } -} diff --git a/lib/assert.js b/lib/assert.js deleted file mode 100644 index 6188107..0000000 --- a/lib/assert.js +++ /dev/null @@ -1,170 +0,0 @@ -/*! - * Copyright (c) 2022 Digital Bazaar, Inc. All rights reserved. - */ -import * as base58 from 'base58-universal'; - -export const assert = { - array, chunk, doc, edvConfig, edvQuery, localId, nonNegativeSafeInteger, - number, object, secretConfig, sequence, string, uint8Array -}; - -function array(x, name) { - if(!(x && Array.isArray(x))) { - throw new TypeError(`"${name}" must be an array.`); - } -} - -function chunk(x) { - assert.object(x, 'chunk'); - assert.nonNegativeSafeInteger(x.index, 'chunk.index'); - assert.nonNegativeSafeInteger(x.offset, 'chunk.offset'); - assert.sequence(x.sequence, 'chunk.sequence'); - assert.object(x.jwe, 'chunk.jwe'); -} - -function doc(x) { - assert.object(x, 'doc'); - assert.localId(x.id, 'doc.id'); - assert.sequence(x.sequence, 'doc.sequence'); - assert.object(x.jwe, 'doc.jwe'); - if(x.indexed !== undefined) { - assert.array(x.indexed, 'doc.indexed'); - } -} - -function edvConfig(x) { - assert.object(x, 'config'); - assert.string(x.id, 'config.id'); - assert.string(x.controller, 'config.controller'); - assert.sequence(x.sequence, 'config.sequence'); - - assert.object(x.keyAgreementKey, 'config.keyAgreementKey'); - assert.object(x.hmac, 'config.hmac'); - if(x.keyAgreementKey) { - assert.string(x.keyAgreementKey.id, 'config.keyAgreementKey.id'); - assert.string(x.keyAgreementKey.type, 'config.keyAgreementKey.type'); - } - if(x.hmac) { - assert.string(x.hmac.id, 'config.hmac.id'); - assert.string(x.hmac.type, 'config.hmac.type'); - } -} - -function edvQuery(x, name) { - assert.object(x, name); - const {index, equals, has, count, limit} = x; - assert.string(index, `${name}.index`); - if(!!equals === !!has) { - throw new TypeError( - `"${name}" must contain exactly one of "equals" or "has".`); - } - if(equals !== undefined) { - assert.array(equals, `${name}.equals`); - if(equals.length === 0) { - throw new Error(`"${name}.equals" must have of a length > 0.`); - } - // every `equals` entry must be an object w/key+value strings - for(const [i, e] of equals.entries()) { - const subName = `${name}.equals[${i}]`; - assert.object(e, subName); - for(const key in e) { - assert.string(e[key], `${subName}.${key}`); - } - } - } - if(has !== undefined) { - assert.array(has, `${name}.has`); - if(has.length === 0) { - throw new Error(`"${name}.equals" must have of a length > 0.`); - } - // every `has` entry must be a string - for(const [i, e] of has.entries()) { - assert.string(e, `${name}.equals[${i}]`); - } - } - if(count !== undefined && typeof count !== 'boolean') { - throw new TypeError(`"${name}.count" must be a boolean.`); - } - if(limit !== undefined) { - assert.number(limit, `${name}.limit`); - if(!(limit >= 1 && limit <= 1000)) { - throw new Error(`"${name}.limit" must be an integer >= 1 and <= 1000.`); - } - } -} - -function localId(x, name) { - assert.string(x, name); - - try { - // verify ID is base58-encoded multibase multihash encoded 16 bytes - const buf = base58.decode(x.substr(1)); - // multibase base58 (starts with 'z') - // 128-bit random number, identity multihash encoded - // 0x00 = identity tag, 0x10 = length (16 bytes) + 16 random bytes - if(!(x.startsWith('z') && - buf.length === 18 && buf[0] === 0x00 && buf[1] === 0x10)) { - throw new Error('Invalid identifier.'); - } - } catch(e) { - const error = new Error( - `Identifier "${x}" must be base58-encoded multibase, ` + - 'multihash array of 16 random bytes.'); - error.name = 'ConstraintError'; - throw error; - } -} - -function nonNegativeSafeInteger(x, name) { - if(!(x >= 0 && Number.isSafeInteger(x))) { - throw new TypeError(`"${name}" must be a non-negative safe integer.`); - } -} - -function number(x, name) { - _assertType({x, name, type: 'number', article: 'a'}); -} - -function object(x, name) { - _assertType({x, name, type: 'object', article: 'an', truthy: true}); -} - -function secretConfig(x) { - assert.object(x, 'config'); - assert.string(x.id, 'config.id'); - assert.string(x.hmacId, 'config.hmacId'); - assert.string(x.keyAgreementKeyId, 'config.keyAgreementKeyId'); - assert.object(x.secret, 'config.secret'); - assert.string(x.secret.version, 'config.secret.version'); - if(x.secret.version !== '1') { - throw new Error('"config.secret.version" must be "1".'); - } - assert.string(x.secret.salt, 'config.secret.salt'); - assert.string(x.secret.wrappedKey, 'config.secret.wrappedKey'); - assert.sequence(x.sequence, 'config.sequence'); -} - -function sequence(x, name) { - // `sequence` is limited to MAX_SAFE_INTEGER - 1 - assert.nonNegativeSafeInteger(x, name); - if(x === Number.MAX_SAFE_INTEGER) { - throw new TypeError( - `"${name}" must be less than ${Number.MAX_SAFE_INTEGER}.`); - } -} - -function string(x, name) { - _assertType({x, name, type: 'string', article: 'a'}); -} - -function uint8Array(x, name) { - if(!(x instanceof Uint8Array)) { - throw new TypeError(`"${name}" must be a Uint8Array.`); - } -} - -function _assertType({x, name, type, article, truthy}) { - if(!(typeof x === type && (x || !truthy))) { - throw new TypeError(`"${name}" must be ${article} ${type}.`); - } -} diff --git a/lib/chunks.js b/lib/chunks.js deleted file mode 100644 index f149461..0000000 --- a/lib/chunks.js +++ /dev/null @@ -1,178 +0,0 @@ -/*! - * Copyright (c) 2021-2022 Digital Bazaar, Inc. All rights reserved. - */ -import {createDatabase, purge} from './pouchdb.js'; -import {assert} from './assert.js'; -import {get as getDoc} from './docs.js'; -import {parseLocalId} from './helpers.js'; - -const COLLECTION_NAME = 'edv-storage-chunk'; - -let _client; -let _purgeOp; - -/** - * Initializes the encrypted document chunks database if it has not already - * been initialized. - * - * @returns {Promise} Settles once the operation completes. - */ -export async function initialize() { - if(_client) { - // already initialized - return; - } - - _client = await createDatabase({name: COLLECTION_NAME}); - - // Note: `_id` is populated using the combination of `localEdvId`, - // `docId` and `chunk.index` and serves as the primary unique index for - // this collection - - // since no indexes are created, get database info to ensure database upgrade - // events fire and object stores are created, etc. prior to scheduling a - // purge -- otherwise database upgrades could be blocked and the database - // will fail to load / be created properly - await _client.info(); - - // schedule purge op to clean up any deleted docs - _schedulePurge(); -} - -/** - * Updates (replaces) an EDV document chunk. If the document chunk does not - * exist, it will be inserted. - * - * @param {object} options - The options to use. - * @param {string} options.edvId - The ID of the EDV to store the chunk in. - * @param {string} options.docId - The ID of the document the chunk is - * associated with. - * @param {object} options.chunk - The chunk to store. - * - * @returns {Promise} Resolves to the database record. - */ -export async function upsert({edvId, docId, chunk} = {}) { - assert.string(edvId, 'edvId'); - assert.localId(docId, 'docId'); - assert.chunk(chunk); - - // TODO: implement garbage collector worker that removes chunks with stale - // sequences (e.g., can happen because uploads failed or because associated - // data shrunk in size, i.e., fewer chunks) - - // ensure `chunk.sequence` is proper (on par with associated doc) - // TODO: optimize retrieval of only sequence number - const {doc} = await getDoc({edvId, id: docId}); - if(chunk.sequence !== doc.sequence) { - const error = new Error( - 'Could not update document chunk. Sequence does not match the ' + - 'associated document.'); - error.name = 'InvalidStateError'; - error.expected = doc.sequence; - error.actual = chunk.sequence; - throw error; - } - - // create record - const {localId: localEdvId} = parseLocalId({id: edvId}); - const _id = _createId({localEdvId, docId, index: chunk.index}); - const record = {_id, localEdvId, docId, chunk}; - - let result; - try { - result = await _client.updateOne({ - doc: record, - query: { - selector: {_id} - }, - upsert: true - }); - } catch(e) { - if(e.name === 'ConstraintError') { - // if the error was with the same document, then the same chunk was - // upserted concurrently -- and we treat this one as if it succeeded - // but was overwritten by whatever is in the database now - if(e.existing._id === _id) { - return e.existing; - } - } - throw e; - } - return result.record; -} - -/** - * Gets an EDV document chunk. - * - * @param {object} options - The options to use. - * @param {string} options.edvId - The ID of the EDV. - * @param {string} options.docId - The ID of the document the chunk is - * associated with. - * @param {number} options.index - The index of the chunk. - * - * @returns {Promise} Resolves to the database record. - */ -export async function get({edvId, docId, index} = {}) { - assert.string(edvId, 'edvId'); - assert.localId(docId, 'docId'); - assert.nonNegativeSafeInteger(index, 'index'); - - const {localId: localEdvId} = parseLocalId({id: edvId}); - const {docs: [record]} = await _client.find({ - selector: {_id: _createId({localEdvId, docId, index})}, - limit: 1 - }); - if(!record) { - const error = new Error('Document chunk not found.'); - error.name = 'NotFoundError'; - throw error; - } - return record; -} - -/** - * Removes an EDV document chunk. - * - * @param {object} options - The options to use. - * @param {string} options.edvId - The ID of the EDV. - * @param {string} options.docId - The ID of the document the chunk is - * associated with. - * @param {number} options.index - The index of the chunk. - * - * @returns {Promise} `true` if the chunk was removed, `false` if it - * was not found. - */ -export async function remove({edvId, docId, index} = {}) { - // sadly, this is non-atomic because PouchDB does not offer the necessary - // primitives - let record; - try { - record = await get({edvId, docId, index}); - } catch(e) { - if(e.name === 'NotFoundError') { - return false; - } - } - - // delete record - record._deleted = true; - await _client.put(record); - - // schedule purge operation to clean up deleted docs - _schedulePurge(); - - return true; -} - -function _createId({localEdvId, docId, index}) { - return `${localEdvId}:${docId}:${index}`; -} - -function _schedulePurge() { - if(_purgeOp) { - return; - } - _purgeOp = purge({name: COLLECTION_NAME}) - .catch(e => console.error(e)) - .finally(() => _purgeOp = null); -} diff --git a/lib/docs.js b/lib/docs.js deleted file mode 100644 index e36719c..0000000 --- a/lib/docs.js +++ /dev/null @@ -1,345 +0,0 @@ -/*! - * Copyright (c) 2021-2022 Digital Bazaar, Inc. All rights reserved. - */ -import {createDatabase, purge} from './pouchdb.js'; -import {assert} from './assert.js'; -import {parseLocalId} from './helpers.js'; - -const COLLECTION_NAME = 'edv-storage-doc'; - -let _client; -let _purgeOp; - -/** - * Initializes the encrypted documents database if it has not already - * been initialized. - * - * @returns {Promise} Settles once the operation completes. - */ -export async function initialize() { - if(_client) { - // already initialized - return; - } - - _client = await createDatabase({name: COLLECTION_NAME}); - - /* Note: `_id` is populated using the combination of `localEdvId` and - `doc.id` and serves as the primary unique index for this collection. - - Additionally, index information from each encrypted document is massaged to - work within the limitations of PouchDB's indexing system. For example, since - PouchDB does not support deep referencing fields within arrays (only within - objects), the `doc.indexed` array must be transformed to enable indexing - here. That array is transformed into three different arrays that are stored - at the top level of each record in the database: - - `attributes` - Holds the names and values of every encrypted attribute and - value pair, enabling queries that check full attributes to be checked. - - `attributeNames` - Holds the names of every encrypted attribute so that - queries that just check for the presence of attributes (but not their - values) can be performed. - - `uniqueAttributes` - Holds the names and values of every encrypted attribute - that is marked as `unique`. This allows unique constraints to be applied - to encrypted attributes. - */ - - // attribute name + value queries - await _client.createIndex({ - index: { - ddoc: 'edv-doc', - name: 'attributes', - fields: [ - 'localEdvId', - 'attributes' - ], - partial_filter_selector: { - attributes: {$exists: true} - } - } - }); - - // attribute name queries - await _client.createIndex({ - index: { - ddoc: 'edv-doc', - name: 'attributes.name', - fields: [ - 'localEdvId', - 'attributeNames' - ], - partial_filter_selector: { - attributeNames: {$exists: true} - } - } - }); - - // used to enforce uniqueness on insert / update - await _client.createIndex({ - index: { - ddoc: 'edv-doc', - name: 'attributes.unique', - fields: [ - 'localEdvId', - 'uniqueAttributes' - ], - partial_filter_selector: { - uniqueAttributes: {$exists: true} - } - } - }); - - // schedule purge op to clean up any deleted docs - _schedulePurge(); -} - -/** - * Inserts an EDV document. - * - * @param {object} options - The options to use. - * @param {string} options.edvId - The ID of the EDV to store the document in. - * @param {object} options.doc - The document to insert. - * - * @returns {Promise} Resolves to the database record. - */ -export async function insert({edvId, doc} = {}) { - assert.string(edvId, 'edvId'); - assert.doc(doc); - - // create record - const {record, uniqueConstraints} = _createRecord({edvId, doc}); - - // insert and return updated record - const result = await _client.insertOne({doc: record, uniqueConstraints}); - return result.record; -} - -/** - * Updates (replaces) an EDV document. If the document does not exist, it will - * be inserted. - * - * @param {object} options - The options to use. - * @param {string} options.edvId - The ID of the EDV to store the document in. - * @param {object} options.doc - The document to store. - * @param {boolean} [options.deleted=false] - Set to `true` if the EDV - * document is a tombstone, i.e., it has been deleted. - * - * @returns {Promise} Resolves to the database record. - */ -export async function upsert({edvId, doc, deleted = false} = {}) { - assert.string(edvId, 'edvId'); - assert.doc(doc); - - // create record - const {localEdvId, record, uniqueConstraints} = _createRecord({edvId, doc}); - const _id = _createId({localEdvId, docId: doc.id}); - - if(deleted) { - // mark record as deleted; important to improve pouchdb indexing speed - record._deleted = true; - } - - let result; - try { - result = await _client.updateOne({ - doc: record, - query: { - selector: { - _id, - 'doc.sequence': doc.sequence - 1 - } - }, - upsert: true, - uniqueConstraints - }); - } catch(e) { - if(e.name === 'ConstraintError') { - // if the error was with the same document, then the sequence did not - // match - if(e.existing._id === _id) { - const error = new Error( - 'Could not update document. Sequence does not match.'); - error.name = 'InvalidStateError'; - throw error; - } - } - throw e; - } - - if(deleted) { - // schedule purge operation to clean up deleted docs - _schedulePurge(); - } - - return result.record; -} - -/** - * Gets an EDV document. - * - * @param {object} options - The options to use. - * @param {string} options.edvId - The ID of the EDV. - * @param {string} options.id - The ID of the document. - * - * @returns {Promise} Resolves to the database record. - */ -export async function get({edvId, id} = {}) { - assert.string(edvId, 'edvId'); - assert.localId(id, 'id'); - - const {localId: localEdvId} = parseLocalId({id: edvId}); - const {docs: [record]} = await _client.find({ - selector: {_id: _createId({localEdvId, docId: id})}, - limit: 1 - }); - if(!record) { - const error = new Error('Document not found.'); - error.name = 'NotFoundError'; - throw error; - } - return record; -} - -/** - * Retrieves all EDV documents matching the given query. - * - * @param {object} options - The options to use. - * @param {string} options.edvId - The ID of the EDV. - * @param {object} [options.query={}] - The query to use with `selector` and - * `options`, etc. - * - * @returns {Promise} Resolves with the records that matched the query. - */ -export async function find({edvId, query = {selector: {}}}) { - assert.object(query); - assert.object(query.selector); - - // force local EDV ID to be in query if not present - let {selector} = query; - if(!selector.localEdvId) { - const {localId: localEdvId} = parseLocalId({id: edvId}); - selector = {localEdvId, ...selector}; - } - - const {docs: records} = await _client.find({ - selector, - ...query.options - }); - return {records}; -} - -/** - * Creates a query to pass to `find` based on the given `edvQuery`. The - * `edvQuery` can have these properties: `{index, equals, has, count, limit}`. - * The `index` property must be given and include an hmac ID associated with an - * encrypted index and only one of `equals` or `has` must be given. - * - * @param {object} options - The options to use. - * @param {string} options.edvId - The ID of the EDV. - * @param {object} options.edvQuery - The EDV query. - * - * @returns {Promise} Resolves to a `query` to pass to `find`. - */ -export function createQuery({edvId, edvQuery} = {}) { - assert.string(edvId, 'edvId'); - assert.edvQuery(edvQuery, 'edvQuery'); - - const use_index = ['edv-doc']; - const {index, equals, has} = edvQuery; - const encodedIndex = encodeURIComponent(index); - const {localId: localEdvId} = parseLocalId({id: edvId}); - const selector = {localEdvId}; - if(equals) { - // must provide this to enable use of the attributes query; the PouchDB - // query planner needs it to determine start / end keys in the index - selector.attributes = {$gt: null}; - selector.$or = equals.map(e => ({ - attributes: { - $all: Object.entries(e).map(([name, value]) => - `${encodedIndex}:${encodeURIComponent(name)}:` + - `${encodeURIComponent(value)}`) - } - })); - use_index.push('attributes'); - } else { - // `has` query - selector.attributeNames = { - $all: has.map(name => `${encodedIndex}:${encodeURIComponent(name)}`) - }; - use_index.push('attributes.name'); - } - return {selector, options: {use_index}}; -} - -function _createRecord({edvId, doc}) { - const {localId: localEdvId} = parseLocalId({id: edvId}); - const _id = _createId({localEdvId, docId: doc.id}); - const record = {_id, localEdvId, doc}; - - // build top-level attribute index fields - const { - attributes, attributeNames, uniqueAttributes - } = _buildAttributesIndex({doc}); - - if(attributes.length > 0) { - record.attributes = attributes; - } - - if(attributeNames.length > 0) { - record.attributeNames = attributeNames; - } - - const uniqueConstraints = []; - if(uniqueAttributes.length > 0) { - record.uniqueAttributes = uniqueAttributes; - uniqueConstraints.push({ - selector: {localEdvId, uniqueAttributes: {$in: uniqueAttributes}}, - options: {use_index: ['edv-doc', 'attributes.unique']} - }); - } - - return {localEdvId, record, uniqueConstraints}; -} - -function _buildAttributesIndex({doc}) { - const attributes = []; - const attributeNames = []; - const uniqueAttributes = []; - - // build top-level index fields - if(doc.indexed) { - for(const entry of doc.indexed) { - if(!entry.attributes) { - continue; - } - const encodedHmacId = encodeURIComponent(entry.hmac.id); - for(const attribute of entry.attributes) { - // concat hash of hmac ID, name, and value - const name = `${encodedHmacId}:${encodeURIComponent(attribute.name)}`; - const full = `${name}:${encodeURIComponent(attribute.value)}`; - attributes.push(full); - attributeNames.push(name); - if(attribute.unique) { - uniqueAttributes.push(full); - } - } - } - } - - return {attributes, attributeNames, uniqueAttributes}; -} - -function _createId({localEdvId, docId}) { - return `${localEdvId}:${docId}`; -} - -function _schedulePurge() { - if(_purgeOp) { - return; - } - _purgeOp = purge({name: COLLECTION_NAME}) - .catch(e => console.error(e)) - .finally(() => _purgeOp = null); -} diff --git a/lib/edvs.js b/lib/edvs.js deleted file mode 100644 index cccaab9..0000000 --- a/lib/edvs.js +++ /dev/null @@ -1,70 +0,0 @@ -/*! - * Copyright (c) 2021-2022 Digital Bazaar, Inc. All rights reserved. - */ -import {assert} from './assert.js'; -import {ConfigStorage} from './ConfigStorage.js'; - -let _storage; - -/** - * Initializes the encrypted data vault configurations database if it has not - * already been initialized. - * - * @returns {Promise} Settles once the operation completes. - */ -export async function initialize() { - if(_storage) { - // already initialized - return; - } - - _storage = new ConfigStorage({ - assertConfig: assert.edvConfig, - collectionName: 'edv-storage-config' - }); - - await _storage.initialize(); - - // queries by controller - await _storage.client.createIndex({ - index: { - fields: ['config.controller'] - } - }); -} - -/** - * Establishes a new EDV by inserting its configuration into storage. - * - * @param {object} options - The options to use. - * @param {object} options.config - The EDV configuration. - * - * @returns {Promise} Resolves to the database record. - */ -export async function insert({config} = {}) { - return _storage.insert({config}); -} - -/** - * Updates an EDV config if its sequence number is next. - * - * @param {object} options - The options to use. - * @param {object} options.config - The EDV configuration. - * - * @returns {Promise} Resolves to the database record. - */ -export async function update({config} = {}) { - return _storage.update({config}); -} - -/** - * Gets an EDV configuration. - * - * @param {object} options - The options to use. - * @param {object} options.id - The ID of the EDV. - * - * @returns {Promise} Resolves to the database record. - */ -export async function get({id} = {}) { - return _storage.get({id}); -} diff --git a/lib/helpers.js b/lib/helpers.js deleted file mode 100644 index d6c1410..0000000 --- a/lib/helpers.js +++ /dev/null @@ -1,116 +0,0 @@ -/*! - * Copyright (c) 2022-2025 Digital Bazaar, Inc. All rights reserved. - */ -import * as base58 from 'base58-universal'; -import {assert} from './assert.js'; - -let _getRandomBytes; - -export async function generateLocalId() { - // 128-bit random number, multibase + identity multihash encoded - // 0x00 = identity tag, 0x10 = length (16 bytes) - const data = await getRandomBytes(16); - return multihashEncode({codec: 0x00, data, multibase: 'z'}); -} - -export function parseLocalId({id} = {}) { - assert.string(id, 'id'); - /* Note: Current implementation just returns the `id` as it is not prefixed - with a base URI. This may change in the future. */ - return {base: '', localId: id}; -} - -export function getRandomBytes(n) { - assert.number(n, 'n'); - // lazily create random bytes function - if(!_getRandomBytes) { - _getRandomBytes = _createGetRandomBytes(); - } - return _getRandomBytes(n); -} - -export function multibaseDecode({expectedHeader, encoded} = {}) { - assert.uint8Array(expectedHeader, 'expectedHeader'); - assert.string(encoded, 'encoded'); - if(!encoded.startsWith('z')) { - throw new Error('"encoded" must be base58-multibase-encoded.'); - } - - const mcValue = base58.decode(encoded.slice(1)); - if(!expectedHeader.every((val, i) => mcValue[i] === val)) { - throw new Error('Multibase value does not have expected header.'); - } - return mcValue.slice(expectedHeader.length); -} - -export function multibaseEncode({header, data} = {}) { - assert.uint8Array(header, 'header'); - assert.uint8Array(data, 'data'); - const buf = new Uint8Array(header.length + data.length); - buf.set(header); - buf.set(data, header.length); - // multibase encoding for base58 starts with 'z' - return `z${base58.encode(buf)}`; -} - -export function multihashDecode({ - expectedCodec = 0x00, expectedSize, encoded -} = {}) { - assert.number(expectedSize, 'expectedSize'); - assert.string(encoded, 'encoded'); - if(expectedSize >= 128) { - // varint encoding required and not supported - throw new Error('"data.length" must be less than 128.'); - } - const expectedHeader = new Uint8Array([expectedCodec, expectedSize]); - const decoded = multibaseDecode({expectedHeader, encoded}); - if(decoded.length !== expectedSize) { - throw new Error( - `Actual decoded data size (${decoded.length}) is not as ` + - `expected (${expectedSize}).`); - } - return decoded; -} - -export function multihashEncode({codec = 0x00, data, multibase = 'z'} = {}) { - assert.uint8Array(data, 'data'); - if(multibase !== 'z') { - // only base58 encoding is supported - throw new Error('"multibase" character must be "z".'); - } - if(data.length >= 128) { - // varint encoding required and not supported - throw new Error('"data.length" must be less than 128.'); - } - - // multibase + multihash encoded - // byte 1 = multihash identifier (e.g., 0x00 = identity tag) - // byte 2 = length - const buf = new Uint8Array(2 + data.length); - buf[0] = codec; - buf[1] = data.length; - buf.set(data, 2); - // multibase encoding for base58 starts with 'z' - return `z${base58.encode(buf)}`; -} - -export function uuid() { - return globalThis.crypto.randomUUID(); -} - -function _createGetRandomBytes() { - // eslint-disable-next-line no-undef - const {crypto} = globalThis; - - if(crypto.getRandomValues) { - return async n => crypto.getRandomValues(new Uint8Array(n)); - } - - if(crypto.randomFill) { - return async n => new Promise( - (resolve, reject) => crypto.randomFill( - new Uint8Array(n), (err, buf) => err ? reject(err) : resolve(buf))); - } - - throw new Error('"crypto.getRandomValues" or "crypto.randomFill" required.'); -} diff --git a/lib/index.js b/lib/index.js index 63cc352..3b63428 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,12 +1,6 @@ /*! - * Copyright (c) 2022 Digital Bazaar, Inc. All rights reserved. + * Copyright (c) 2025 Digital Bazaar, Inc. All rights reserved. */ -import * as chunks from './chunks.js'; -import * as docs from './docs.js'; -import * as edvs from './edvs.js'; -import * as secrets from './secrets.js'; -export {chunks, docs, edvs, secrets}; -export {initialize} from './initialize.js'; -export {generateLocalId} from './helpers.js'; -export {PouchEdvClient} from './PouchEdvClient.js'; +export {default as OpticalScanner} from '../components/OpticalScanner.vue'; +export {default as ScannerUI} from '../components/ScannerUI.vue'; diff --git a/lib/initialize.js b/lib/initialize.js deleted file mode 100644 index d75e7c7..0000000 --- a/lib/initialize.js +++ /dev/null @@ -1,21 +0,0 @@ -/*! - * Copyright (c) 2022 Digital Bazaar, Inc. All rights reserved. - */ -import * as chunks from './chunks.js'; -import * as docs from './docs.js'; -import * as edvs from './edvs.js'; -import * as secrets from './secrets.js'; - -/** - * Initializes all databases required to work with local EDVs. - * - * @returns {Promise} Settles once the operation completes. - */ -export async function initialize() { - return Promise.all([ - chunks.initialize(), - docs.initialize(), - edvs.initialize(), - secrets.initialize() - ]); -} diff --git a/lib/pbkdf2.js b/lib/pbkdf2.js deleted file mode 100644 index 057085b..0000000 --- a/lib/pbkdf2.js +++ /dev/null @@ -1,55 +0,0 @@ -/*! - * Copyright (c) 2022 Digital Bazaar, Inc. All rights reserved. - */ -import {assert} from './assert.js'; -import {getRandomBytes} from './helpers.js'; - -// eslint-disable-next-line no-undef -const {crypto} = globalThis; - -const ALGORITHM = {name: 'PBKDF2'}; -const EXTRACTABLE = false; -const KEY_USAGE = ['deriveBits', 'deriveKey']; - -/** - * Derive key bits from a password. - * - * @param {object} options - The options to use. - * @param {number} options.bitLength - The number of bytes to derive. - * @param {number} [options.iterations=100000] - The number of iterations to - * use. - * @param {string} options.password - The password to use. - * @param {Uint8Array} [options.salt] - The salt to use; one will be - * generated if not provided. - * @param {number} [options.saltSize] - The salt size, in bytes, to generate, - * if `salt` was not provided. - * - * @returns {Promise} The derived bits. - */ -export async function deriveBits({ - bitLength, iterations = 100000, password, salt, saltSize -} = {}) { - assert.nonNegativeSafeInteger(bitLength, 'bitLength'); - assert.nonNegativeSafeInteger(iterations, 'iterations'); - assert.string(password, 'password'); - if(salt !== undefined) { - assert.uint8Array(salt, 'salt'); - } else { - assert.nonNegativeSafeInteger(saltSize, 'saltSize'); - salt = await getRandomBytes(saltSize); - } - - const kdk = await crypto.subtle.importKey( - 'raw', new TextEncoder().encode(password), - ALGORITHM, EXTRACTABLE, KEY_USAGE); - - const algorithm = { - ...ALGORITHM, - salt, - iterations, - hash: 'SHA-256' - }; - const derivedBits = new Uint8Array(await crypto.subtle.deriveBits( - algorithm, kdk, bitLength)); - return {algorithm, derivedBits}; -} diff --git a/lib/pouchdb.js b/lib/pouchdb.js deleted file mode 100644 index 3942a62..0000000 --- a/lib/pouchdb.js +++ /dev/null @@ -1,297 +0,0 @@ -/*! - * Copyright (c) 2021-2022 Digital Bazaar, Inc. All rights reserved. - */ -import {assert} from './assert.js'; -import PouchDB from 'pouchdb'; -import pouchFind from 'pouchdb-find'; -import pouchIndexedDB from 'pouchdb-adapter-indexeddb'; - -export {PouchDB}; - -const PREFIX = 'br_edv_'; - -// support queries and indexing -PouchDB.plugin(pouchFind); -// support native IndexedDB indexes -PouchDB.plugin(pouchIndexedDB); - -/* Add some plugins to get pseudo-uniqueness properties. PouchDB does not have -some basic uniqueness primitives that other databases have. This includes no -ability to set unique constraints on custom indexes. These plugins provide -`insertOne` and `updateOne` APIs that approximate these behaviors but since the -system primitives are not present, they do not have atomic guarantees. */ -PouchDB.plugin({insertOne, updateOne}); - -// enable for debugging purposes only -// import debugPouch from 'pouchdb-debug'; -// debugPouch(PouchDB); -// PouchDB.debug.enable('pouchdb:find'); - -// create a pouch DB database w/auto-upgrade flag -export async function createDatabase({ - name, auto_compaction = true, adapter = 'indexeddb' -} = {}) { - const client = new PouchDB(PREFIX + name, { - auto_compaction, - adapter - }); - // force internal remote flag to false to avoid deprecation warnings - client._remote = false; - return client; -} - -// purge all deleted documents in a pouch DB database -export async function purge({name} = {}) { - // purge any deleted records to recover storage space - let db; - let deleted = 0; - try { - // apply prefixes to database name - name = '_pouch_' + PREFIX + name; - // open database and handle various events - db = await new Promise((resolve, reject) => { - const request = indexedDB.open(name); - request.onblocked = event => { - db = event.target.result; - reject(new Error('Cannot purge right now; database access blocked.')); - }; - request.onupgradeneeded = event => { - db = event.target.result; - reject(new Error('Nothing to purge; database not ready yet.')); - }; - request.onsuccess = event => resolve(event.target.result); - request.onerror = event => reject(event.target.error); - }); - if(![...db.objectStoreNames].includes('docs')) { - return; - } - const transaction = db.transaction(['docs'], 'readwrite'); - const transactionPromise = new Promise((resolve, reject) => { - transaction.oncomplete = resolve; - transaction.onabort = () => reject(transaction.error); - transaction.onerror = () => reject(transaction.error); - }); - const objectStore = transaction.objectStore('docs'); - const request = objectStore.openCursor(); - let cursor = await _promisifyIDBInterface(request); - while(cursor) { - const {value} = cursor; - if(value.deleted === 1) { - await _promisifyIDBInterface(cursor.delete()); - deleted++; - } - const next = _promisifyIDBInterface(request); - cursor.continue(); - cursor = await next; - } - await transactionPromise; - } catch(e) { - throw e; - } finally { - db?.close(); - } - - return {deleted}; -} - -/** - * Inserts a document into a PouchDB database, if `doc._id` is unique and if - * the selectors and options in the given `uniqueConstraints` array do not - * return any results. - * - * @param {object} options - The options to use. - * @param {object} options.doc - The document to insert. - * @param {object} [options.uniqueConstraints] - Any additional uniqueness - * constraints to enforce beyond the `_id` index (each entry includes - * `selector` and `options`). - * - * @returns {Promise} Resolves to the insert result. - */ -async function insertOne({doc, uniqueConstraints = []} = {}) { - assert.object(doc, 'doc'); - assert.array(uniqueConstraints, 'uniqueConstraints'); - - // build default unique constraints for `_id` - if(doc._id) { - uniqueConstraints = uniqueConstraints.slice(); - uniqueConstraints.push({selector: {_id: doc._id}}); - } - - // keep attempting insert whilst conflict errors arise -- this mitigates - // concurrency issues w/`_id` (but not other unique constraints) - while(true) { - try { - // check all uniqueness constraints - const [existing] = await Promise.all(uniqueConstraints - .map(({selector, options}) => _getExisting.call( - this, {doc, selector, options}))); - if(existing) { - // document already exists, throw error - const error = new Error( - 'Could not insert document; uniqueness constraint violation.'); - error.name = 'ConstraintError'; - error.doc = doc; - error.existing = existing; - error.uniqueConstraints = uniqueConstraints; - throw error; - } - - // this is not atomic w/the unique contraints check, so if concurrent - // processes update the same information the constraints may no longer - // be met - const result = await (doc._id ? this.put(doc) : this.post(doc)); - - // build the full record - const record = { - ...doc, - _id: result.id, - _rev: result.rev - }; - return {...result, record}; - } catch(e) { - // only capture PouchErrors here, not local `ConstraintError`, the latter - // should be thrown and stop this loop - if(e.status === 409) { - continue; - } - throw e; - } - } -} - -/** - * Updates a single document in the PouchDB database, if the selectors and - * options in the given `uniqueConstraints` array return a single result and - * the given `query` matches that same result. If `upsert` is set to `true` - * and both the `query` does not match and there are no documents matching - * the uniqueness constraints, the document will be inserted. If `doc._id` is - * set then unique constraints for it will be auto-generated. - * - * @param {object} options - The options to use. - * @param {object} options.doc - The document to update. - * @param {object} options.query - The selector and options to use to query. - * @param {boolean} [options.upsert=false] - `true` to insert the document - * if the query does not match, `false` if not. - * @param {object} [options.uniqueConstraints] - Any additional uniqueness - * constraints to enforce beyond the `_id` index (each entry includes - * `selector` and `options`). - * - * @returns {Promise} Resolves to the update result or - * `false` if `upsert=false` and no matching record was found. - */ -async function updateOne({ - doc, query, upsert = false, uniqueConstraints = [] -} = {}) { - // use a separate `uniqueConstraints` variable for updating (vs. inserting) - // to avoid passing a modified version to `insertOne` - let updateUniqueConstraints; - - // keep attempting update whilst conflict errors arise -- this mitigates - // concurrency issues w/`_id` (but not other unique constraints) - while(true) { - try { - // get matching record - const {selector, options} = query; - const existing = await _getExisting.call(this, {doc, selector, options}); - if(!existing) { - if(!upsert) { - // no match, and no insert requested, so nothing to update - return false; - } - // attempt an insert - return await this.insertOne({doc, uniqueConstraints}); - } - - // create unique constraints for update - if(!updateUniqueConstraints) { - if(!doc._id) { - updateUniqueConstraints = uniqueConstraints; - } else { - updateUniqueConstraints = uniqueConstraints.slice(); - updateUniqueConstraints.push({selector: {_id: doc._id}}); - } - } - - // check all uniqueness constraints - const existingRecords = await Promise.all(updateUniqueConstraints - .map(({selector, options}) => _getExisting.call( - this, {doc, selector, options}))); - // ensure all matching records are the same as the existing record across - // all uniqueness constraints, otherwise reject the update as it would - // violate them - for(const record of existingRecords) { - if(existing._id !== record?._id) { - const error = new Error( - 'Could not update document; uniqueness constraint violation.'); - error.name = 'ConstraintError'; - error.doc = doc; - error.existing = record; - error.uniqueConstraints = updateUniqueConstraints; - throw error; - } - } - - /* Note: Sadly, this is not atomic with the unique contraints checks, so - degenerate cases where concurrent inserts/updates are made may cause - uniqueness violations. This is an accepted limitation of this - implementation and the primitives currently offered by PouchDB. The - remedy to this problem when it occurs is to update N-1 of the documents - that duplicate each other in some way (to remove the duplication). */ - const result = await this.put({ - _id: existing._id, - _rev: existing._rev, - ...doc - }); - - // build the full record - const record = { - ...doc, - _id: result.id, - _rev: result.rev - }; - return {...result, record}; - } catch(e) { - // only capture PouchErrors here, not local `ConstraintError`, the latter - // should be thrown and stop this loop - if(e.status === 409) { - continue; - } - throw e; - } - } -} - -async function _getExisting({doc, selector, options}) { - if(!selector && !doc._id) { - throw new Error('Either "selector" or "doc._id" must be set.'); - } - - // set default selector - if(!selector) { - selector = {_id: doc._id}; - } - - /* Note: The calls that use this helper function expect a single document - to be returned. Those calls are either updating a single document or are - checking for uniqueness. If we are updating a single document, any document - will do (to be returned). - - In the case of a uniqueness check, we presume a single document will be - returned at most from a query based on unique constraints. This will only not - be the case if the lack of atomic primitives for enforcing uniqueness have - been violated via concurrent inserts/updates. In that case, the database has - entered a state with a unique constraints violation that must be remedied - by updating N-1 of the documents that duplicate one another in some way (to - remove the duplication). */ - const {docs: [existing]} = await this.find({ - selector, limit: 1, ...options - }); - return existing; -} - -function _promisifyIDBInterface(idbInterface) { - return new Promise((resolve, reject) => { - idbInterface.onsuccess = event => resolve(event.target.result); - idbInterface.onerror = event => reject(event.target.error); - }); -} diff --git a/lib/secrets.js b/lib/secrets.js deleted file mode 100644 index a925bfe..0000000 --- a/lib/secrets.js +++ /dev/null @@ -1,279 +0,0 @@ -/*! - * Copyright (c) 2021-2023 Digital Bazaar, Inc. All rights reserved. - */ -import * as EcdsaMultikey from '@digitalbazaar/ecdsa-multikey'; -import {multihashDecode, multihashEncode, uuid} from './helpers.js'; -import {assert} from './assert.js'; -import {ConfigStorage} from './ConfigStorage.js'; -import {deriveBits} from './pbkdf2.js'; -import {Hmac} from './Hmac.js'; -import {Kek} from './Kek.js'; -import {P256Kak} from './P256Kak.js'; -import {X25519Kak} from './X25519Kak.js'; - -// P-256 unwrapped key is 32 secret key bytes + 33 public key bytes + 7 padding -const UNWRAPPED_KAK_SIZE = 72; -// wrapped KAK + 8 byte AES-KW overhead -const WRAPPED_KAK_SIZE = 80; - -const VERSIONS = new Map([ - ['1', { - // parameters for version 1 - iterations: 100000, - // AES-KW is used on a 32 byte key w/8 byte overhead - wrappedKeySize: 40, - // salt size in bytes - saltSize: 16 - }] -]); - -let _storage; - -/** - * Initializes the encrypted secrets database. - * - * @returns {Promise} Settles once the operation completes. - */ -export async function initialize() { - if(_storage) { - // already initialized - return; - } - - _storage = new ConfigStorage({ - assertConfig: assert.secretConfig, - collectionName: 'edv-storage-secret' - }); - - await _storage.initialize(); - - // queries by hmac ID - await _storage.client.createIndex({ - index: { - fields: ['config.hmacId'] - } - }); - - // queries by keyAgreementKeyId (key agreement key ID) - await _storage.client.createIndex({ - index: { - fields: ['config.keyAgreementKeyId'] - } - }); -} - -/** - * Decrypts a secret so its derived keys can be used. - * - * @param {object} options - The options to use. - * @param {object} options.config - The secret configuration. - * @param {object} options.password - The password to use to decrypt. - * - * @returns {Promise} Returns {hmac, keyAgreementKey, cipherVersion} on - * success and `null` if the password was invalid. - */ -export async function decrypt({config, password} = {}) { - assert.secretConfig(config); - assert.string(password, 'password'); - - // use password and version parameters to derive key encryption - const {secret} = config; - const {version, salt, wrappedKey} = secret; - const {wrappedKeySize, saltSize} = VERSIONS.get(version); - const {kek} = await _deriveKek({ - password, - salt: await multihashDecode({ - expectedSize: saltSize, encoded: salt - }), - version - }); - - // unwrap key derivation key - const unwrappedKey = await kek.unwrapKey({ - wrappedKey: await multihashDecode({ - expectedSize: wrappedKeySize, encoded: wrappedKey - }) - }); - if(!unwrappedKey) { - // invalid password - return null; - } - - // import KDK and clear secret value from memory - const kdk = await Hmac.import({secret: unwrappedKey}); - unwrappedKey.fill(0); - - // derive HMAC and key agreement keys - const { - hmac, keyAgreementKey, cipherVersion - } = await _deriveKeys({kdk, kek, secret}); - hmac.id = config.hmacId; - keyAgreementKey.id = config.keyAgreementKeyId; - return {hmac, keyAgreementKey, cipherVersion}; -} - -/** - * Generates a new encrypted secret configuration. - * - * @param {object} options - The options to use. - * @param {string} options.id - The ID for the secret. - * @param {string} options.password - The password to encrypt the secret. - * @param {string} options.version - The secret version. - * @param {string} [options.cipherVersion='recommended'] - Sets the cipher - * version to either "recommended" or "fips". - * - * @returns {Promise} Resolves to `{hmac, keyAgreementKey, config}`. - */ -export async function generate({ - id, version = '1', password, cipherVersion = 'recommended' -} = {}) { - if(version !== '1') { - throw new Error('"version" must be "1".'); - } - assert.string(id, 'id'); - assert.string(password, 'password'); - - // generate an HMAC key for deriving other keys - const kdk = await Hmac.generate(); - - // create encrypted secret from key derivation key - const {kek, secret} = await _createSecret( - {kdk, password, version, cipherVersion}); - - // derive blinded index key (HMAC) and key agreement key - const {hmac, keyAgreementKey} = await _deriveKeys({kdk, kek, secret}); - - const config = { - id, - hmacId: `urn:uuid:${uuid()}`, - keyAgreementKeyId: `urn:uuid:${uuid()}`, - secret, - sequence: 0 - }; - - hmac.id = config.hmacId; - keyAgreementKey.id = config.keyAgreementKeyId; - - return {hmac, keyAgreementKey, config}; -} - -/** - * Establishes a new secret by inserting its config into storage. - * - * @param {object} options - The options to use. - * @param {object} options.config - The secret configuration. - * - * @returns {Promise} Resolves to the database record. - */ -export async function insert({config} = {}) { - return _storage.insert({config}); -} - -/** - * Updates a secret config if its sequence number is next. - * - * @param {object} options - The options to use. - * @param {object} options.config - The secret configuration. - * - * @returns {Promise} Resolves to the database record. - */ -export async function update({config} = {}) { - return _storage.update({config}); -} - -/** - * Gets a secret configuration. - * - * @param {object} options - The options to use. - * @param {object} options.id - The ID of the EDV. - * - * @returns {Promise} Resolves to the database record. - */ -export async function get({id} = {}) { - return _storage.get({id}); -} - -async function _createSecret({kdk, password, version, cipherVersion} = {}) { - // use password and version parameters to derive key encryption - const {kek, algorithm} = await _deriveKek({password, version}); - - // wrap key derivation key for storage and reuse later - const wrappedKey = await kek.wrapKey({unwrappedKey: kdk.key}); - - const secret = { - version, - salt: multihashEncode({data: algorithm.salt}), - wrappedKey: multihashEncode({data: wrappedKey}) - }; - // if `fips` cipher version is used, generate random key agreement key - // instead of deriving it from a secret; this is a requirement for creating - // fips-compliant P-* curve keys - if(cipherVersion === 'fips') { - const kak = await EcdsaMultikey.generate({curve: 'P-256'}); - // export key for wrapping (secret key + public key) - const {secretKey, publicKey} = await kak.export( - {publicKey: true, secretKey: true, raw: true}); - const unwrappedKey = new Uint8Array(UNWRAPPED_KAK_SIZE); - unwrappedKey.set(secretKey); - unwrappedKey.set(publicKey, secretKey.length); - const wrappedKeyAgreementKey = await kek.wrapKey({unwrappedKey}); - secretKey.fill(0); - unwrappedKey.fill(0); - secret.wrappedKeyAgreementKey = multihashEncode( - {data: wrappedKeyAgreementKey}); - wrappedKeyAgreementKey.fill(0); - } - - return {kek, secret}; -} - -async function _deriveKek({password, salt, version} = {}) { - const {iterations, saltSize} = VERSIONS.get(version); - const { - derivedBits: kekSecret, - algorithm - } = await deriveBits({ - bitLength: 256, iterations, password, salt, saltSize - }); - const kek = await Kek.import({secret: kekSecret}); - kekSecret.fill(0); - return {kek, algorithm}; -} - -async function _deriveKeys({kdk, kek, secret} = {}) { - const encoder = new TextEncoder(); - - // generate secret and derive HMAC key - const hmacSecret = await kdk.sign({data: encoder.encode('hmac')}); - const hmac = await Hmac.import({secret: hmacSecret}); - hmacSecret.fill(0); - - // unwrap or generate secret and derive key agreement key - let keyAgreementKey; - let cipherVersion; - if(secret.wrappedKeyAgreementKey) { - cipherVersion = 'fips'; - // unwrap key derivation key (P-256 ) - const unwrappedKey = await kek.unwrapKey({ - wrappedKey: await multihashDecode({ - expectedSize: WRAPPED_KAK_SIZE, encoded: secret.wrappedKeyAgreementKey - }) - }); - if(!unwrappedKey) { - // invalid wrapped key agreement key - throw new Error('Invalid stored key agreement key.'); - } - const secretKey = unwrappedKey.subarray(0, 32); - const publicKey = unwrappedKey.subarray(32, 65); - keyAgreementKey = await P256Kak.import({secretKey, publicKey}); - unwrappedKey.fill(0); - } else { - cipherVersion = 'recommended'; - // generate secrets for an HMAC and a key agreement key - const kakSecret = await kdk.sign({data: encoder.encode('keyAgreementKey')}); - keyAgreementKey = await X25519Kak.import({secret: kakSecret}); - kakSecret.fill(0); - } - - return {hmac, keyAgreementKey, cipherVersion}; -} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..7b425a0 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,4496 @@ +{ + "name": "@bedrock/vue-optical-scanner", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@bedrock/vue-optical-scanner", + "version": "0.0.1", + "dependencies": { + "@bedrock/web-optical-scanner": "file:../bedrock-web-optical-scanner" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^6.0.1", + "eslint": "^8.57.1", + "eslint-config-digitalbazaar": "^5.2.0", + "eslint-plugin-jsdoc": "^51.4.1", + "eslint-plugin-quasar": "^1.1.0", + "eslint-plugin-unicorn": "^56.0.1", + "eslint-plugin-vue": "^9.23.0", + "jsdoc": "^4.0.2", + "jsdoc-to-markdown": "^9.0.2", + "vite": "^7.1.5", + "vue": "^3.4.21" + }, + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "@bedrock/quasar": "^10.0.0", + "@bedrock/web-fontawesome": "^2.0.0", + "vue": "^3.4.21" + } + }, + "../bedrock-web-optical-scanner": { + "name": "@bedrock/web-optical-scanner", + "version": "1.0.0-0", + "dependencies": { + "barcode-detector": "^3.0.5", + "dynamsoft-javascript-barcode": "=9.6.1", + "dynamsoft-mrz-scanner": "^3.0.1" + }, + "devDependencies": { + "@bedrock/webpack": "^11.2.2", + "eslint": "^8.57.1", + "eslint-config-digitalbazaar": "^5.2.0", + "eslint-plugin-jsdoc": "^51.4.1", + "eslint-plugin-unicorn": "^56.0.1", + "webpack": "^5.101.3", + "webpack-cli": "^6.0.1" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", + "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.4" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", + "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bedrock/quasar": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@bedrock/quasar/-/quasar-10.0.1.tgz", + "integrity": "sha512-Os21koHpiKU/SP8nQKvM7ZSioboqEKwqRdgDqeBJpEzpHJk7DU3O42E2iJi93kY1HQHonSFQYd1+Alm5VEmD6A==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "animate.css": "^4.1.1", + "quasar": "~2.15.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@bedrock/vue": "^5.0.1", + "vue": "^3.4.21" + } + }, + "node_modules/@bedrock/vue": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@bedrock/vue/-/vue-5.1.0.tgz", + "integrity": "sha512-rvCEvFvAirQPhTx00fenxe6lVJLj/BIX7Z4OLiQbVe2aSDEPHlGUgLRYgcTmb8XPLs7br8vUR8UE4LjWBnAIhw==", + "license": "Apache-2.0", + "peer": true, + "peerDependencies": { + "@bedrock/web": "^3.0.0", + "vue": "^3.2.36", + "vue-router": "^4.0.15" + } + }, + "node_modules/@bedrock/web": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@bedrock/web/-/web-3.1.0.tgz", + "integrity": "sha512-1mbJeoLFfDeB9esPPAw49jkaKs5oKWtTonYvzakaQDmuEGFOnMdZaXP4KVwI10naB/mgTD65Pi+aNmCNbOTCJg==", + "license": "Apache-2.0", + "peer": true + }, + "node_modules/@bedrock/web-fontawesome": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@bedrock/web-fontawesome/-/web-fontawesome-2.1.0.tgz", + "integrity": "sha512-YUFAtNa8PAKQjL8+xJaju4kDHY72jHTLqV0UkbXsYhdzwaKl72MUmoGhhftzan7qP0zFj8FOYMwYkfvoSpLK0w==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@fortawesome/fontawesome-free": "^5.11.1" + } + }, + "node_modules/@bedrock/web-optical-scanner": { + "resolved": "../bedrock-web-optical-scanner", + "link": true + }, + "node_modules/@es-joy/jsdoccomment": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.52.0.tgz", + "integrity": "sha512-BXuN7BII+8AyNtn57euU2Yxo9yA/KUDNzrpXyi3pfqKmBhhysR6ZWOebFh3vyPoqA3/j1SOvGgucElMGwlXing==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.8", + "@typescript-eslint/types": "^8.34.1", + "comment-parser": "1.4.1", + "esquery": "^1.6.0", + "jsdoc-type-pratt-parser": "~4.1.0" + }, + "engines": { + "node": ">=20.11.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", + "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", + "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", + "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", + "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", + "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", + "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", + "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", + "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", + "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", + "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", + "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", + "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", + "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", + "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", + "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", + "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", + "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", + "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", + "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", + "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", + "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", + "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", + "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", + "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", + "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", + "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@fortawesome/fontawesome-free": { + "version": "5.15.4", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.4.tgz", + "integrity": "sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg==", + "hasInstallScript": true, + "license": "(CC-BY-4.0 AND OFL-1.1 AND MIT)", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jsdoc/salty": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.9.tgz", + "integrity": "sha512-yYxMVH7Dqw6nO0d5NIV8OQWnitU8k6vXH8NtgqAfIa/IUqRMxRv/NUJJ08VEKbAakwxlgBl5PJdrU0dMPStsnw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=v12.0.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.29", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.29.tgz", + "integrity": "sha512-NIJgOsMjbxAXvoGq/X0gD7VPMQ8j9g0BiDaNjVNVjvl+iKXxL3Jre0v31RmBYeLEmkbj2s02v8vFTbUXi5XS2Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.1.tgz", + "integrity": "sha512-HJXwzoZN4eYTdD8bVV22DN8gsPCAj3V20NHKOs8ezfXanGpmVPR7kalUHd+Y31IJp9stdB87VKPFbsGY3H/2ag==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.50.1.tgz", + "integrity": "sha512-PZlsJVcjHfcH53mOImyt3bc97Ep3FJDXRpk9sMdGX0qgLmY0EIWxCag6EigerGhLVuL8lDVYNnSo8qnTElO4xw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.1.tgz", + "integrity": "sha512-xc6i2AuWh++oGi4ylOFPmzJOEeAa2lJeGUGb4MudOtgfyyjr4UPNK+eEWTPLvmPJIY/pgw6ssFIox23SyrkkJw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.50.1.tgz", + "integrity": "sha512-2ofU89lEpDYhdLAbRdeyz/kX3Y2lpYc6ShRnDjY35bZhd2ipuDMDi6ZTQ9NIag94K28nFMofdnKeHR7BT0CATw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.50.1.tgz", + "integrity": "sha512-wOsE6H2u6PxsHY/BeFHA4VGQN3KUJFZp7QJBmDYI983fgxq5Th8FDkVuERb2l9vDMs1D5XhOrhBrnqcEY6l8ZA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.50.1.tgz", + "integrity": "sha512-A/xeqaHTlKbQggxCqispFAcNjycpUEHP52mwMQZUNqDUJFFYtPHCXS1VAG29uMlDzIVr+i00tSFWFLivMcoIBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.50.1.tgz", + "integrity": "sha512-54v4okehwl5TaSIkpp97rAHGp7t3ghinRd/vyC1iXqXMfjYUTm7TfYmCzXDoHUPTTf36L8pr0E7YsD3CfB3ZDg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.50.1.tgz", + "integrity": "sha512-p/LaFyajPN/0PUHjv8TNyxLiA7RwmDoVY3flXHPSzqrGcIp/c2FjwPPP5++u87DGHtw+5kSH5bCJz0mvXngYxw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.50.1.tgz", + "integrity": "sha512-2AbMhFFkTo6Ptna1zO7kAXXDLi7H9fGTbVaIq2AAYO7yzcAsuTNWPHhb2aTA6GPiP+JXh85Y8CiS54iZoj4opw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.50.1.tgz", + "integrity": "sha512-Cgef+5aZwuvesQNw9eX7g19FfKX5/pQRIyhoXLCiBOrWopjo7ycfB292TX9MDcDijiuIJlx1IzJz3IoCPfqs9w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.50.1.tgz", + "integrity": "sha512-RPhTwWMzpYYrHrJAS7CmpdtHNKtt2Ueo+BlLBjfZEhYBhK00OsEqM08/7f+eohiF6poe0YRDDd8nAvwtE/Y62Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.50.1.tgz", + "integrity": "sha512-eSGMVQw9iekut62O7eBdbiccRguuDgiPMsw++BVUg+1K7WjZXHOg/YOT9SWMzPZA+w98G+Fa1VqJgHZOHHnY0Q==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.50.1.tgz", + "integrity": "sha512-S208ojx8a4ciIPrLgazF6AgdcNJzQE4+S9rsmOmDJkusvctii+ZvEuIC4v/xFqzbuP8yDjn73oBlNDgF6YGSXQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.50.1.tgz", + "integrity": "sha512-3Ag8Ls1ggqkGUvSZWYcdgFwriy2lWo+0QlYgEFra/5JGtAd6C5Hw59oojx1DeqcA2Wds2ayRgvJ4qxVTzCHgzg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.50.1.tgz", + "integrity": "sha512-t9YrKfaxCYe7l7ldFERE1BRg/4TATxIg+YieHQ966jwvo7ddHJxPj9cNFWLAzhkVsbBvNA4qTbPVNsZKBO4NSg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.1.tgz", + "integrity": "sha512-MCgtFB2+SVNuQmmjHf+wfI4CMxy3Tk8XjA5Z//A0AKD7QXUYFMQcns91K6dEHBvZPCnhJSyDWLApk40Iq/H3tA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.1.tgz", + "integrity": "sha512-nEvqG+0jeRmqaUMuwzlfMKwcIVffy/9KGbAGyoa26iu6eSngAYQ512bMXuqqPrlTyfqdlB9FVINs93j534UJrg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.50.1.tgz", + "integrity": "sha512-RDsLm+phmT3MJd9SNxA9MNuEAO/J2fhW8GXk62G/B4G7sLVumNFbRwDL6v5NrESb48k+QMqdGbHgEtfU0LCpbA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.50.1.tgz", + "integrity": "sha512-hpZB/TImk2FlAFAIsoElM3tLzq57uxnGYwplg6WDyAxbYczSi8O2eQ+H2Lx74504rwKtZ3N2g4bCUkiamzS6TQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.50.1.tgz", + "integrity": "sha512-SXjv8JlbzKM0fTJidX4eVsH+Wmnp0/WcD8gJxIZyR6Gay5Qcsmdbi9zVtnbkGPG8v2vMR1AD06lGWy5FLMcG7A==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.1.tgz", + "integrity": "sha512-StxAO/8ts62KZVRAm4JZYq9+NqNsV7RvimNK+YM7ry//zebEH6meuugqW/P5OFUCjyQgui+9fUxT6d5NShvMvA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/markdown-it": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/types": { + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.43.0.tgz", + "integrity": "sha512-vQ2FZaxJpydjSZJKiSW/LJsabFFvV7KgLC5DiLhkBcykhQj8iK9BOaDmQt74nnKdLvceM5xmhaTF+pLekrxEkw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.1.tgz", + "integrity": "sha512-+MaE752hU0wfPFJEUAIxqw18+20euHHdxVtMvbFcOEpjEyfqXH/5DCoTHiVJ0J29EhTJdoTkjEv5YBKU9dnoTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "1.0.0-beta.29" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.21.tgz", + "integrity": "sha512-8i+LZ0vf6ZgII5Z9XmUvrCyEzocvWT+TeR2VBUVlzIH6Tyv57E20mPZ1bCS+tbejgUgmjrEh7q/0F0bibskAmw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.3", + "@vue/shared": "3.5.21", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.21.tgz", + "integrity": "sha512-jNtbu/u97wiyEBJlJ9kmdw7tAr5Vy0Aj5CgQmo+6pxWNQhXZDPsRr1UWPN4v3Zf82s2H3kF51IbzZ4jMWAgPlQ==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.21", + "@vue/shared": "3.5.21" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.21.tgz", + "integrity": "sha512-SXlyk6I5eUGBd2v8Ie7tF6ADHE9kCR6mBEuPyH1nUZ0h6Xx6nZI29i12sJKQmzbDyr2tUHMhhTt51Z6blbkTTQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.3", + "@vue/compiler-core": "3.5.21", + "@vue/compiler-dom": "3.5.21", + "@vue/compiler-ssr": "3.5.21", + "@vue/shared": "3.5.21", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.18", + "postcss": "^8.5.6", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.21.tgz", + "integrity": "sha512-vKQ5olH5edFZdf5ZrlEgSO1j1DMA4u23TVK5XR1uMhvwnYvVdDF0nHXJUblL/GvzlShQbjhZZ2uvYmDlAbgo9w==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.21", + "@vue/shared": "3.5.21" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT", + "peer": true + }, + "node_modules/@vue/reactivity": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.21.tgz", + "integrity": "sha512-3ah7sa+Cwr9iiYEERt9JfZKPw4A2UlbY8RbbnH2mGCE8NwHkhmlZt2VsH0oDA3P08X3jJd29ohBDtX+TbD9AsA==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.21" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.21.tgz", + "integrity": "sha512-+DplQlRS4MXfIf9gfD1BOJpk5RSyGgGXD/R+cumhe8jdjUcq/qlxDawQlSI8hCKupBlvM+3eS1se5xW+SuNAwA==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.21", + "@vue/shared": "3.5.21" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.21.tgz", + "integrity": "sha512-3M2DZsOFwM5qI15wrMmNF5RJe1+ARijt2HM3TbzBbPSuBHOQpoidE+Pa+XEaVN+czbHf81ETRoG1ltztP2em8w==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.21", + "@vue/runtime-core": "3.5.21", + "@vue/shared": "3.5.21", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.21.tgz", + "integrity": "sha512-qr8AqgD3DJPJcGvLcJKQo2tAc8OnXRcfxhOJCPF+fcfn5bBGz7VCcO7t+qETOPxpWK1mgysXvVT/j+xWaHeMWA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.21", + "@vue/shared": "3.5.21" + }, + "peerDependencies": { + "vue": "3.5.21" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.21.tgz", + "integrity": "sha512-+2k1EQpnYuVuu3N7atWyG3/xoFWIVJZq4Mz8XNOdScFI0etES75fbny/oU4lKWk/577P1zmg0ioYvpGEDZ3DLw==", + "license": "MIT" + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/animate.css": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/animate.css/-/animate.css-4.1.1.tgz", + "integrity": "sha512-+mRmCTv6SbCmtYJCN4faJMNFVNN5EuCTTprDTAo7YzIGji2KADmakjVA3+8mVDkZ2Bf09vayB35lSQIex2+QaQ==", + "license": "MIT", + "peer": true + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/are-docs-informative": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", + "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-back": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", + "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.17" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.2.tgz", + "integrity": "sha512-NvcIedLxrs9llVpX7wI+Jz4Hn9vJQkCPKrTaHIE0sW/Rj1iq6Fzby4NbyTZjQJNoypBXNaG7tEHkTgONZpwgxQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.0.tgz", + "integrity": "sha512-P9go2WrP9FiPwLv3zqRD/Uoxo0RSHjzFCiQz7d4vbmwNqQFo9T9WCeP/Qn5EbcKQY6DBbkxEXNcpJOmncNrb7A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.8.2", + "caniuse-lite": "^1.0.30001741", + "electron-to-chromium": "^1.5.218", + "node-releases": "^2.0.21", + "update-browserslist-db": "^1.1.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cache-point": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/cache-point/-/cache-point-3.0.1.tgz", + "integrity": "sha512-itTIMLEKbh6Dw5DruXbxAgcyLnh/oPGVLBfTPqBOftASxHe8bAeXy7JkO4F0LvHqht7XqP5O/09h5UcHS2w0FA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-back": "^6.2.2" + }, + "engines": { + "node": ">=12.17" + }, + "peerDependencies": { + "@75lb/nature": "latest" + }, + "peerDependenciesMeta": { + "@75lb/nature": { + "optional": true + } + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001741", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001741.tgz", + "integrity": "sha512-QGUGitqsc8ARjLdgAfxETDhRbJ0REsP6O3I96TAth/mVjh2cYzN2u+3AzPP3aVSm2FehEItaJw1xd+IGBXWeSw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/catharsis": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.15" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk-template": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz", + "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/chalk-template?sponsor=1" + } + }, + "node_modules/ci-info": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/clean-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", + "integrity": "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/clean-regexp/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/command-line-args": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-6.0.1.tgz", + "integrity": "sha512-Jr3eByUjqyK0qd8W0SGFW1nZwqCaNCtbXjRo2cRJC1OYxWl3MZ5t1US3jq+cO4sPavqgw4l9BMGX0CBe+trepg==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-back": "^6.2.2", + "find-replace": "^5.0.2", + "lodash.camelcase": "^4.3.0", + "typical": "^7.2.0" + }, + "engines": { + "node": ">=12.20" + }, + "peerDependencies": { + "@75lb/nature": "latest" + }, + "peerDependenciesMeta": { + "@75lb/nature": { + "optional": true + } + } + }, + "node_modules/command-line-usage": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-7.0.3.tgz", + "integrity": "sha512-PqMLy5+YGwhMh1wS04mVG44oqDsgyLRSKJBdOo1bnYhMKBW65gZF1dRp2OZRhiTjgUHljy99qkO7bsctLaw35Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-back": "^6.2.2", + "chalk-template": "^0.4.0", + "table-layout": "^4.1.0", + "typical": "^7.1.1" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/comment-parser": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", + "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/common-sequence": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-sequence/-/common-sequence-3.0.0.tgz", + "integrity": "sha512-g/CgSYk93y+a1IKm50tKl7kaT/OjjTYVQlEbUlt/49ZLV1mcKpUU7iyDiqTAeLdb4QDtQfq3ako8y8v//fzrWQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.17" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/config-master": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/config-master/-/config-master-3.1.0.tgz", + "integrity": "sha512-n7LBL1zBzYdTpF1mx5DNcZnZn05CWIdsdvtPL4MosvqbBUK3Rq6VWEtGUuF3Y0s9/CIhMejezqlSkP6TnCJ/9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "walk-back": "^2.0.1" + } + }, + "node_modules/config-master/node_modules/walk-back": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-2.0.1.tgz", + "integrity": "sha512-Nb6GvBR8UWX1D+Le+xUq0+Q1kFmRBIWVrfLnQAOmcpEzA9oAxwJ9gIr36t9TWYfzvWRvuMtjHiVsJYEkXWaTAQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/core-js-compat": { + "version": "3.45.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.45.1.tgz", + "integrity": "sha512-tqTt5T4PzsMIZ430XGviK4vzYSoeNJ6CXODi6c/voxOT6IZqBht5/EKaSNnYiEjjRYxjVz7DQIsOsY0XNi8PIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserslist": "^4.25.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, + "node_modules/current-module-paths": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/current-module-paths/-/current-module-paths-1.1.2.tgz", + "integrity": "sha512-H4s4arcLx/ugbu1XkkgSvcUZax0L6tXUqnppGniQb8l5VjUKGHoayXE5RiriiPhYDd+kjZnaok1Uig13PKtKYQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.17" + } + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/dmd": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/dmd/-/dmd-7.1.1.tgz", + "integrity": "sha512-Ap2HP6iuOek7eShReDLr9jluNJm9RMZESlt29H/Xs1qrVMkcS9X6m5h1mBC56WMxNiSo0wvjGICmZlYUSFjwZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-back": "^6.2.2", + "cache-point": "^3.0.0", + "common-sequence": "^3.0.0", + "file-set": "^5.2.2", + "handlebars": "^4.7.8", + "marked": "^4.3.0", + "walk-back": "^5.1.1" + }, + "engines": { + "node": ">=12.17" + }, + "peerDependencies": { + "@75lb/nature": "latest" + }, + "peerDependenciesMeta": { + "@75lb/nature": { + "optional": true + } + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.218", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.218.tgz", + "integrity": "sha512-uwwdN0TUHs8u6iRgN8vKeWZMRll4gBkz+QMqdS7DDe49uiK68/UX92lFb61oiFPrpYZNeZIqa4bA7O6Aiasnzg==", + "dev": true, + "license": "ISC" + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/esbuild": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", + "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.9", + "@esbuild/android-arm": "0.25.9", + "@esbuild/android-arm64": "0.25.9", + "@esbuild/android-x64": "0.25.9", + "@esbuild/darwin-arm64": "0.25.9", + "@esbuild/darwin-x64": "0.25.9", + "@esbuild/freebsd-arm64": "0.25.9", + "@esbuild/freebsd-x64": "0.25.9", + "@esbuild/linux-arm": "0.25.9", + "@esbuild/linux-arm64": "0.25.9", + "@esbuild/linux-ia32": "0.25.9", + "@esbuild/linux-loong64": "0.25.9", + "@esbuild/linux-mips64el": "0.25.9", + "@esbuild/linux-ppc64": "0.25.9", + "@esbuild/linux-riscv64": "0.25.9", + "@esbuild/linux-s390x": "0.25.9", + "@esbuild/linux-x64": "0.25.9", + "@esbuild/netbsd-arm64": "0.25.9", + "@esbuild/netbsd-x64": "0.25.9", + "@esbuild/openbsd-arm64": "0.25.9", + "@esbuild/openbsd-x64": "0.25.9", + "@esbuild/openharmony-arm64": "0.25.9", + "@esbuild/sunos-x64": "0.25.9", + "@esbuild/win32-arm64": "0.25.9", + "@esbuild/win32-ia32": "0.25.9", + "@esbuild/win32-x64": "0.25.9" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-digitalbazaar": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-config-digitalbazaar/-/eslint-config-digitalbazaar-5.2.0.tgz", + "integrity": "sha512-b401QVIkHpN60kNEix7gAosVFX0TOQCOPw6RPp4rlGN4zIVL5E6oMPcuXeoE5AxAuJrVmt+nQQTKNuQ5gmyeOg==", + "deprecated": "Upgrade to eslint@9 and @digitalbazaar/eslint-config@6.", + "dev": true, + "license": "BSD-3-Clause", + "peerDependencies": { + "eslint": "^8.14.0", + "eslint-plugin-jsdoc": ">=42.0.0" + }, + "peerDependenciesMeta": { + "eslint-plugin-jsdoc": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-jsdoc": { + "version": "51.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-51.4.1.tgz", + "integrity": "sha512-y4CA9OkachG8v5nAtrwvcvjIbdcKgSyS6U//IfQr4FZFFyeBFwZFf/tfSsMr46mWDJgidZjBTqoCRlXywfFBMg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@es-joy/jsdoccomment": "~0.52.0", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.4.1", + "debug": "^4.4.1", + "escape-string-regexp": "^4.0.0", + "espree": "^10.4.0", + "esquery": "^1.6.0", + "parse-imports-exports": "^0.2.4", + "semver": "^7.7.2", + "spdx-expression-parse": "^4.0.0" + }, + "engines": { + "node": ">=20.11.0" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-quasar": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-quasar/-/eslint-plugin-quasar-1.1.0.tgz", + "integrity": "sha512-lVOfr6kTRPu91pAVYisiziMwU+bW33Z+AMnmnj3hM1xjzqeo0KBHovcX5J+YDyna8GWwiL8kAzrDvy0eG52aIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "requireindex": "~1.2.0", + "semver-compare": "^1.0.0" + }, + "engines": { + "node": ">= 8.9.0", + "npm": ">= 5.6.0", + "yarn": ">= 1.6.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/hawkeye64" + } + }, + "node_modules/eslint-plugin-unicorn": { + "version": "56.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-56.0.1.tgz", + "integrity": "sha512-FwVV0Uwf8XPfVnKSGpMg7NtlZh0G0gBarCaFcMUOoqPxXryxdYxTRRv4kH6B9TFCVIrjRXG+emcxIk2ayZilog==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.24.7", + "@eslint-community/eslint-utils": "^4.4.0", + "ci-info": "^4.0.0", + "clean-regexp": "^1.0.0", + "core-js-compat": "^3.38.1", + "esquery": "^1.6.0", + "globals": "^15.9.0", + "indent-string": "^4.0.0", + "is-builtin-module": "^3.2.1", + "jsesc": "^3.0.2", + "pluralize": "^8.0.0", + "read-pkg-up": "^7.0.1", + "regexp-tree": "^0.1.27", + "regjsparser": "^0.10.0", + "semver": "^7.6.3", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=18.18" + }, + "funding": { + "url": "https://github.com/sindresorhus/eslint-plugin-unicorn?sponsor=1" + }, + "peerDependencies": { + "eslint": ">=8.56.0" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/globals": { + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", + "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-vue": { + "version": "9.33.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.33.0.tgz", + "integrity": "sha512-174lJKuNsuDIlLpjeXc5E2Tss8P44uIimAfGD0b90k0NoirJqpG7stLuU9Vp/9ioTOrQdWVREc4mRd1BD+CvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "globals": "^13.24.0", + "natural-compare": "^1.4.0", + "nth-check": "^2.1.1", + "postcss-selector-parser": "^6.0.15", + "semver": "^7.6.3", + "vue-eslint-parser": "^9.4.3", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/file-set": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/file-set/-/file-set-5.3.0.tgz", + "integrity": "sha512-FKCxdjLX0J6zqTWdT0RXIxNF/n7MyXXnsSUp0syLEOCKdexvPZ02lNNv2a+gpK9E3hzUYF3+eFZe32ci7goNUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-back": "^6.2.2", + "fast-glob": "^3.3.2" + }, + "engines": { + "node": ">=12.17" + }, + "peerDependencies": { + "@75lb/nature": "latest" + }, + "peerDependenciesMeta": { + "@75lb/nature": { + "optional": true + } + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-replace": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-5.0.2.tgz", + "integrity": "sha512-Y45BAiE3mz2QsrN2fb5QEtO4qb44NcS7en/0y9PEVsg351HsLeVclP8QPMH79Le9sH3rs5RSwJu99W0WPZO43Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@75lb/nature": "latest" + }, + "peerDependenciesMeta": { + "@75lb/nature": { + "optional": true + } + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true, + "license": "ISC" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-builtin-module": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", + "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "dev": true, + "license": "MIT", + "dependencies": { + "builtin-modules": "^3.3.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/js2xmlparser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", + "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "xmlcreate": "^2.0.4" + } + }, + "node_modules/jsdoc": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.4.tgz", + "integrity": "sha512-zeFezwyXeG4syyYHbvh1A967IAqq/67yXtXvuL5wnqCkFZe8I0vKfm+EO+YEvLguo6w9CDUbrAXVtJSHh2E8rw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@babel/parser": "^7.20.15", + "@jsdoc/salty": "^0.2.1", + "@types/markdown-it": "^14.1.1", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.2", + "klaw": "^3.0.0", + "markdown-it": "^14.1.0", + "markdown-it-anchor": "^8.6.7", + "marked": "^4.0.10", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "underscore": "~1.13.2" + }, + "bin": { + "jsdoc": "jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/jsdoc-api": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/jsdoc-api/-/jsdoc-api-9.3.5.tgz", + "integrity": "sha512-TQwh1jA8xtCkIbVwm/XA3vDRAa5JjydyKx1cC413Sh3WohDFxcMdwKSvn4LOsq2xWyAmOU/VnSChTQf6EF0R8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-back": "^6.2.2", + "cache-point": "^3.0.1", + "current-module-paths": "^1.1.2", + "file-set": "^5.3.0", + "jsdoc": "^4.0.4", + "object-to-spawn-args": "^2.0.1", + "walk-back": "^5.1.1" + }, + "engines": { + "node": ">=12.17" + }, + "peerDependencies": { + "@75lb/nature": "latest" + }, + "peerDependenciesMeta": { + "@75lb/nature": { + "optional": true + } + } + }, + "node_modules/jsdoc-parse": { + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/jsdoc-parse/-/jsdoc-parse-6.2.4.tgz", + "integrity": "sha512-MQA+lCe3ioZd0uGbyB3nDCDZcKgKC7m/Ivt0LgKZdUoOlMJxUWJQ3WI6GeyHp9ouznKaCjlp7CU9sw5k46yZTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-back": "^6.2.2", + "find-replace": "^5.0.1", + "lodash.omit": "^4.5.0", + "sort-array": "^5.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jsdoc-to-markdown": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/jsdoc-to-markdown/-/jsdoc-to-markdown-9.1.2.tgz", + "integrity": "sha512-0rhxIZeolCJzQ1SPIqmdtPd4VsK8Jt22sKUnnjHpFaXPDkhmdEuZhkrUQKuQidXGi+j3otleQyqn2BEYhxOpYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-back": "^6.2.2", + "command-line-args": "^6.0.1", + "command-line-usage": "^7.0.3", + "config-master": "^3.1.0", + "dmd": "^7.1.1", + "jsdoc-api": "^9.3.5", + "jsdoc-parse": "^6.2.4", + "walk-back": "^5.1.1" + }, + "bin": { + "jsdoc2md": "bin/cli.js" + }, + "engines": { + "node": ">=12.17" + }, + "peerDependencies": { + "@75lb/nature": "latest" + }, + "peerDependenciesMeta": { + "@75lb/nature": { + "optional": true + } + } + }, + "node_modules/jsdoc-type-pratt-parser": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.1.0.tgz", + "integrity": "sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/jsdoc/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.9" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.omit": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", + "integrity": "sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==", + "deprecated": "This package is deprecated. Use destructuring assignment syntax instead.", + "dev": true, + "license": "MIT" + }, + "node_modules/magic-string": { + "version": "0.30.19", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz", + "integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdown-it-anchor": { + "version": "8.6.7", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz", + "integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==", + "dev": true, + "license": "Unlicense", + "peerDependencies": { + "@types/markdown-it": "*", + "markdown-it": "*" + } + }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true, + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dev": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.21.tgz", + "integrity": "sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-to-spawn-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object-to-spawn-args/-/object-to-spawn-args-2.0.1.tgz", + "integrity": "sha512-6FuKFQ39cOID+BMZ3QaphcC8Y4cw6LXBLyIgPU+OhIYwviJamPAn+4mITapnSBQrejB+NNp+FMskhD8Cq+Ys3w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-imports-exports": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/parse-imports-exports/-/parse-imports-exports-0.2.4.tgz", + "integrity": "sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parse-statements": "1.0.11" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-statements": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/parse-statements/-/parse-statements-1.0.11.tgz", + "integrity": "sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/quasar": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/quasar/-/quasar-2.15.4.tgz", + "integrity": "sha512-6Rtj0KrsVA0IV9zMZ6R7U7hOpwLS/6E06hsISVHRPn21KEm3XAwHdvy9xWz5kwqWraHRlcisFSDu/KPL4VQK1w==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 10.18.1", + "npm": ">= 6.13.4", + "yarn": ">= 1.21.1" + }, + "funding": { + "type": "github", + "url": "https://donate.quasar.dev" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/regexp-tree": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", + "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==", + "dev": true, + "license": "MIT", + "bin": { + "regexp-tree": "bin/regexp-tree" + } + }, + "node_modules/regjsparser": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.10.0.tgz", + "integrity": "sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/requireindex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", + "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.5" + } + }, + "node_modules/requizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", + "integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.21" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.50.1.tgz", + "integrity": "sha512-78E9voJHwnXQMiQdiqswVLZwJIzdBKJ1GdI5Zx6XwoFKUIk09/sSrr+05QFzvYb8q6Y9pPV45zzDuYa3907TZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.50.1", + "@rollup/rollup-android-arm64": "4.50.1", + "@rollup/rollup-darwin-arm64": "4.50.1", + "@rollup/rollup-darwin-x64": "4.50.1", + "@rollup/rollup-freebsd-arm64": "4.50.1", + "@rollup/rollup-freebsd-x64": "4.50.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.50.1", + "@rollup/rollup-linux-arm-musleabihf": "4.50.1", + "@rollup/rollup-linux-arm64-gnu": "4.50.1", + "@rollup/rollup-linux-arm64-musl": "4.50.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.50.1", + "@rollup/rollup-linux-ppc64-gnu": "4.50.1", + "@rollup/rollup-linux-riscv64-gnu": "4.50.1", + "@rollup/rollup-linux-riscv64-musl": "4.50.1", + "@rollup/rollup-linux-s390x-gnu": "4.50.1", + "@rollup/rollup-linux-x64-gnu": "4.50.1", + "@rollup/rollup-linux-x64-musl": "4.50.1", + "@rollup/rollup-openharmony-arm64": "4.50.1", + "@rollup/rollup-win32-arm64-msvc": "4.50.1", + "@rollup/rollup-win32-ia32-msvc": "4.50.1", + "@rollup/rollup-win32-x64-msvc": "4.50.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true, + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/sort-array": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/sort-array/-/sort-array-5.1.1.tgz", + "integrity": "sha512-EltS7AIsNlAFIM9cayrgKrM6XP94ATWwXP4LCL4IQbvbYhELSt2hZTrixg+AaQwnWFs/JGJgqU3rxMcNNWxGAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-back": "^6.2.2", + "typical": "^7.1.1" + }, + "engines": { + "node": ">=12.17" + }, + "peerDependencies": { + "@75lb/nature": "^0.1.1" + }, + "peerDependenciesMeta": { + "@75lb/nature": { + "optional": true + } + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-correct/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", + "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.22", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", + "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/table-layout": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-4.1.1.tgz", + "integrity": "sha512-iK5/YhZxq5GO5z8wb0bY1317uDF3Zjpha0QFFLA8/trAoiLbQD0HUbMesEaxyzUgDxi2QlcbM8IvqOlEjgoXBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-back": "^6.2.2", + "wordwrapjs": "^5.1.0" + }, + "engines": { + "node": ">=12.17" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typical": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-7.3.0.tgz", + "integrity": "sha512-ya4mg/30vm+DOWfBg4YK3j2WD6TWtRkCbasOJr40CseYENzCUby/7rIvXA99JGsQHeNxLbnXdyLLxKSv3tauFw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.17" + } + }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dev": true, + "license": "MIT" + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/underscore": { + "version": "1.13.7", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz", + "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==", + "dev": true, + "license": "MIT" + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/vite": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.5.tgz", + "integrity": "sha512-4cKBO9wR75r0BeIWWWId9XK9Lj6La5X846Zw9dFfzMRw38IlTk2iCcUt6hsyiDRcPidc55ZParFYDXi0nXOeLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vue": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.21.tgz", + "integrity": "sha512-xxf9rum9KtOdwdRkiApWL+9hZEMWE90FHh8yS1+KJAiWYh+iGWV1FquPjoO9VUHQ+VIhsCXNNyZ5Sf4++RVZBA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.21", + "@vue/compiler-sfc": "3.5.21", + "@vue/runtime-dom": "3.5.21", + "@vue/server-renderer": "3.5.21", + "@vue/shared": "3.5.21" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-eslint-parser": { + "version": "9.4.3", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz", + "integrity": "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", + "lodash": "^4.17.21", + "semver": "^7.3.6" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/vue-router": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.5.1.tgz", + "integrity": "sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/walk-back": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-5.1.1.tgz", + "integrity": "sha512-e/FRLDVdZQWFrAzU6Hdvpm7D7m2ina833gIKLptQykRK49mmCYHLHq7UqjPDbxbKLZkTkW1rFqbengdE3sLfdw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.17" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/wordwrapjs": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-5.1.0.tgz", + "integrity": "sha512-JNjcULU2e4KJwUNv6CHgI46UvDGitb6dGryHajXTDiLgg1/RiGoPSDw4kZfYnwGtEXf2ZMeIewDQgFGzkCB2Sg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.17" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12" + } + }, + "node_modules/xmlcreate": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", + "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json index e8c583f..91430a1 100644 --- a/package.json +++ b/package.json @@ -1,43 +1,60 @@ { - "name": "@bedrock/web-pouch-edv", - "version": "8.2.1-0", + "name": "@bedrock/vue-optical-scanner", + "version": "0.0.1", "type": "module", - "description": "PouchDB EDV Storage", - "exports": "./lib/index.js", + "description": "Vue-specific UI component library consumes the bedrock-web-optical-scanner for all scanning logic, provides reusable Vue components for optical scanning UIs, replaces the combined scanning+UI approach in existing libraries", + "exports": { + ".": "./lib/index.js", + "./components/": "./components/" + }, "files": [ - "lib/**/*.js" + "components/*", + "lib/*" ], "scripts": { - "lint": "eslint ." + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "lint": "eslint --ext .cjs,.js,.vue .", + "lint:fix": "eslint --ext .cjs,.js,.vue . --fix" }, "dependencies": { - "@digitalbazaar/ecdsa-multikey": "^1.8.0", - "@digitalbazaar/edv-client": "^16.1.0", - "base58-universal": "^2.0.0", - "pouchdb": "^9.0.0", - "pouchdb-adapter-indexeddb": "^9.0.0", - "pouchdb-find": "^9.0.0" + "@bedrock/web-optical-scanner": "file:../bedrock-web-optical-scanner" + }, + "peerDependencies": { + "@bedrock/quasar": "^10.0.0", + "@bedrock/web-fontawesome": "^2.0.0", + "vue": "^3.4.21" }, "devDependencies": { + "@vitejs/plugin-vue": "^6.0.1", "eslint": "^8.57.1", "eslint-config-digitalbazaar": "^5.2.0", "eslint-plugin-jsdoc": "^51.4.1", + "eslint-plugin-quasar": "^1.1.0", "eslint-plugin-unicorn": "^56.0.1", - "pouchdb-debug": "^7.2.1" + "eslint-plugin-vue": "^9.23.0", + "jsdoc": "^4.0.2", + "jsdoc-to-markdown": "^9.0.2", + "vite": "^7.1.5", + "vue": "^3.4.21" }, "engines": { "node": ">=20" }, "repository": { "type": "git", - "url": "https://github.com/digitalbazaar/bedrock-web-pouch-edv" + "url": "https://github.com/digitalbazaar/bedrock-vue-optical-scanner" }, "keywords": [ "bedrock", - "pouchdb", - "edv", - "encrypted data vault", - "web" + "vue", + "optical", + "scanner", + "barcode", + "qr", + "pdf417", + "mrz" ], "author": { "name": "Digital Bazaar, Inc.", @@ -45,7 +62,7 @@ "url": "https://digitalbazaar.com" }, "bugs": { - "url": "https://github.com/digitalbazaar/bedrock-pouch-edv/issues" + "url": "https://github.com/digitalbazaar/bedrock-vue-optical-scanner/issues" }, - "homepage": "https://github.com/digitalbazaar/bedrock-pouch-edv" + "homepage": "https://github.com/digitalbazaar/bedrock-vue-optical-scanner" } diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..98240ae --- /dev/null +++ b/src/App.vue @@ -0,0 +1,3 @@ + diff --git a/src/components/ScannerDemo.vue b/src/components/ScannerDemo.vue new file mode 100644 index 0000000..c7f2a32 --- /dev/null +++ b/src/components/ScannerDemo.vue @@ -0,0 +1,210 @@ + + + + + diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..c0a377c --- /dev/null +++ b/src/main.js @@ -0,0 +1,10 @@ +import App from './App.vue'; +import {createApp} from 'vue'; +import {Quasar} from 'quasar'; +import router from './router'; +import 'quasar/dist/quasar.css'; + +const app = createApp(App); +app.use(router); +app.use(Quasar, {plugins: {}}); +app.mount('#app'); diff --git a/src/router/index.js b/src/router/index.js new file mode 100644 index 0000000..f7da1d2 --- /dev/null +++ b/src/router/index.js @@ -0,0 +1,13 @@ +import {createRouter, createWebHistory} from 'vue-router'; +import HomeView from '@/views/HomeView.vue'; + +const routes = [ + {path: '/', name: 'home', component: HomeView} +]; + +const router = createRouter({ + history: createWebHistory(), + routes +}); + +export default router; diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue new file mode 100644 index 0000000..02e762e --- /dev/null +++ b/src/views/HomeView.vue @@ -0,0 +1,14 @@ + + + diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 0000000..d908c7d --- /dev/null +++ b/vite.config.js @@ -0,0 +1,17 @@ +import {defineConfig} from 'vite'; +import {fileURLToPath} from 'node:url'; +import path from 'node:path'; +import vue from '@vitejs/plugin-vue'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +export default defineConfig({ + plugins: [vue()], + resolve: { + alias: { + '@': path.resolve(__dirname, './src'), + }, + }, +}); + From 79f7fadd3570ae7a49b3b021289873e261b1faba Mon Sep 17 00:00:00 2001 From: Parth Bhatt Date: Mon, 15 Sep 2025 10:37:26 -0700 Subject: [PATCH 02/18] constrain MRZ scanner to component container using Dynamsoft container option --- components/OpticalScanner.vue | 26 ++++++++++++++++++- components/ScannerUI.vue | 46 +++++++++++++++++++++++++++++++--- src/components/ScannerDemo.vue | 18 +------------ 3 files changed, 68 insertions(+), 22 deletions(-) diff --git a/components/OpticalScanner.vue b/components/OpticalScanner.vue index f50af18..bf79555 100644 --- a/components/OpticalScanner.vue +++ b/components/OpticalScanner.vue @@ -3,6 +3,7 @@ ref="scannerUIRef" :tip-text="tipText" :show-qr-box="showQrBox" + :scan-type="scanType" :formats="scanConfig.formats" :loading="loading" :scanning="scanning" @@ -383,11 +384,34 @@ export default { let timeout; let scanSucceeded = false; + // Get container reference at scan time (when it's available) + const mrzContainer = scannerUIRef.value?.mrzContainer; + console.log('=== CONTAINER DEBUG ==='); + console.log('scannerUIRef.value:', scannerUIRef.value); + console.log('mrzContainer element:', mrzContainer); + console.log('mrzContainer type:', mrzContainer?.constructor?.name); + console.log('========================'); + + // Create modified plugin options with the runtime container + const runtimePluginOptions = { + ...scannerPluginOptions, // Copy everything + mrz: scannerPluginOptions.mrz ? { + ...scannerPluginOptions.mrz, // Copy all mrz properties + scannerConfig: { + ...scannerPluginOptions.mrz.scannerConfig, // Copy all scannerConfig + targetContainer: mrzContainer // Override ONLY targetContainer + } + } : undefined, + // Explicitly preserve other plugins: + pdf417_enhanced: scannerPluginOptions.pdf417_enhanced + }; + + try { const scanPromise = opticalScanner.scan( video.value, - {...scanOptions, pluginOptions: scannerPluginOptions, signal} + {...scanOptions, pluginOptions: runtimePluginOptions, signal} ); // Only create timeout promise if timeoutMs > 0 const promises = [scanPromise]; diff --git a/components/ScannerUI.vue b/components/ScannerUI.vue index d13535b..a15e86b 100644 --- a/components/ScannerUI.vue +++ b/components/ScannerUI.vue @@ -43,9 +43,16 @@ - +
+
+ + +
- +
['qr_code', 'pdf417', 'pdf417_enhanced', 'mrz'] + }, + scanType: { + type: String, + required: true, + validator: value => ['mrz', 'barcode'].includes(value) } }, emits: [ @@ -269,9 +281,12 @@ export default { setup(props, {emit}) { const fileInput = ref(null); const videoRef = ref(null); + const mrzContainer = ref(null); const currentCameraIndex = ref(0); const zoomLevel = ref(1); + const isMrzMode = computed(() => props.scanType === 'mrz'); + const showVideo = computed(() => !props.loading && !props.cameraError ); @@ -372,9 +387,11 @@ export default { return { fileInput, videoRef, + mrzContainer, zoomLevel, showVideo, showControls, + isMrzMode, switchToNextCamera, handleFileUpload, openFileDialog, @@ -393,6 +410,13 @@ export default { overflow: hidden; } +.mrz-container { + position: relative; + background: #000; + /* border: 5px solid red !important; */ /* Debug border */ + /* box-sizing: border-box; */ /* Debug border */ +} + .controls-bar { z-index: 10; } @@ -490,4 +514,18 @@ export default { .optical-scanner-container { touch-action: pan-y; } + +/* Target any remaining global Dynamsoft elements */ +:global(.mrz-scanner-scanner-view-container), +:global(.dynamsoft-mrz-loading-screen), +:global(.dynamsoft-mrz-loading), +:global(.dynamsoft-mrz-loading-content), +:global(.dynamsoft-mrz-loading-message) { + position: absolute !important; + top: 0 !important; + left: 0 !important; + width: 100% !important; + height: 100% !important; + z-index: 10 !important; +} diff --git a/src/components/ScannerDemo.vue b/src/components/ScannerDemo.vue index c7f2a32..d1d46c1 100644 --- a/src/components/ScannerDemo.vue +++ b/src/components/ScannerDemo.vue @@ -32,7 +32,7 @@ - - From 4431075622d784c52a17883a77c45ab74ac48f3b Mon Sep 17 00:00:00 2001 From: Parth Bhatt Date: Wed, 17 Sep 2025 15:52:24 -0700 Subject: [PATCH 03/18] functional mrz scan - working demo --- components/OpticalScanner.vue | 652 ++++++++++++--------------------- components/ScannerUI.vue | 132 ++++--- lib/index.js | 1 + src/components/ScannerDemo.vue | 66 +--- src/views/HomeView.vue | 1 - 5 files changed, 330 insertions(+), 522 deletions(-) diff --git a/components/OpticalScanner.vue b/components/OpticalScanner.vue index bf79555..712f917 100644 --- a/components/OpticalScanner.vue +++ b/components/OpticalScanner.vue @@ -3,8 +3,8 @@ ref="scannerUIRef" :tip-text="tipText" :show-qr-box="showQrBox" - :scan-type="scanType" :formats="scanConfig.formats" + :scan-type="scanType" :loading="loading" :scanning="scanning" :camera-error="cameraError" @@ -23,16 +23,9 @@ + + \ No newline at end of file From 33e046303c3f2c867985718153312ced0d3dd4da Mon Sep 17 00:00:00 2001 From: Parth Bhatt Date: Fri, 26 Sep 2025 10:48:26 -0700 Subject: [PATCH 07/18] Update eslint and ensure eslint rules followed in all files --- .eslintrc.cjs | 5 +- components/OpticalScanner.vue | 119 +++++++++++++++------------- components/ScannerUI.vue | 29 ++++--- src/components/ScannerDemo.vue | 140 +++++++++++++++++++++------------ 4 files changed, 175 insertions(+), 118 deletions(-) diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 4362006..9f5c330 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -5,9 +5,12 @@ module.exports = { node: true }, extends: [ + 'plugin:quasar/standard', 'digitalbazaar', 'digitalbazaar/jsdoc', - 'digitalbazaar/module' + 'digitalbazaar/module', + 'digitalbazaar/vue3' ], + rules: {}, ignorePatterns: ['node_modules/'] }; diff --git a/components/OpticalScanner.vue b/components/OpticalScanner.vue index 3246ed1..1e61322 100644 --- a/components/OpticalScanner.vue +++ b/components/OpticalScanner.vue @@ -24,8 +24,8 @@ /*! * Copyright (c) 2025 Digital Bazaar, Inc. All rights reserved. V3 */ -import {CameraScanner} from '@bedrock/web-optical-scanner'; import {computed, onBeforeUnmount, onMounted, reactive, ref} from 'vue'; +import {CameraScanner} from '@bedrock/web-optical-scanner'; import ScannerUI from './ScannerUI.vue'; export default { @@ -34,7 +34,8 @@ export default { ScannerUI }, props: { - // NOTE: formats prop moved this logic to CameraScanner class and driven by scanType + // NOTE: formats prop moved this logic to CameraScanner class + // and driven by scanType // formats: { // type: Array, // default: () => ['qr_code', 'pdf417', 'pdf417_enhanced', 'mrz'] @@ -84,7 +85,7 @@ export default { torch: false }); - // TODO: double check and remove this logic from OpticalScanner as + // TODO: double check and remove this logic from OpticalScanner as // CameraScanner should be handle this const cameraConstraints = reactive({ zoom: {min: 1, max: 8, step: 1} @@ -105,7 +106,8 @@ export default { // === INITIALIZATION === async function initializeCameraScanner() { - // console.log('Initializing CameraScanner with scanType:', props.scanType); + // console.log('Initializing CameraScanner with scanType:', + // props.scanType); try { // Create CameraScanner with current configuration @@ -116,13 +118,13 @@ export default { }); // === Set up event listener for auto-scan === - cameraScanner.on('result', (result) => { + cameraScanner.on('result', result => { console.log('Vue: Auto-scan result received:', result); scanning.value = false; emit('result', result); }); - cameraScanner.on('error', (error) => { + cameraScanner.on('error', error => { console.log('Vue: Auto-scan error received:', error); scanning.value = false; emit('error', error); @@ -140,76 +142,80 @@ export default { // === DELEGATION TO CAMERA SCANNER === async function startCamera() { - if(!cameraScanner) { - console.error('CameraScanner not initialized'); - return; - } - - loading.value = true; - cameraError.value = false; + if(!cameraScanner) { + console.error('CameraScanner not initialized'); + return; + } - try { - // === GET CONTAINER FROM UI === - const targetContainer = scannerUIRef.value?.cameraContainer; + loading.value = true; + cameraError.value = false; - console.log('Vue: Delegating camera setup and scanning to CameraScanner...'); + try { + // === GET CONTAINER FROM UI === + const targetContainer = scannerUIRef.value?.cameraContainer; - // === PURE DELEGATION === - const result = await cameraScanner.start(targetContainer, { autoScan: true }); + console.log('Vue: Delegating camera setup and scanning to' + + ' CameraScanner...'); - if(result.success) { - console.log('Vue: Camera and scanning started successfully'); - console.log('Auto-scan initiated:', result.autoScanStarted); - // === UPDATE UI STATE FROM CAMERA SCANNER === - await updateCameraInfo(); + // === PURE DELEGATION === + const result = await cameraScanner.start( + targetContainer, + {autoScan: true} + ); - } else { - cameraError.value = true; - emit('error', { - message: result.error, - code: result.code || 'CAMERA_START_ERROR' - }); - } + if(result.success) { + console.log('Vue: Camera and scanning started successfully'); + console.log('Auto-scan initiated:', result.autoScanStarted); + // === UPDATE UI STATE FROM CAMERA SCANNER === + await updateCameraInfo(); - } catch(error) { - console.error('Vue: Camera start error:', error); + } else { cameraError.value = true; emit('error', { - message: error.message || 'Camera start failed', - code: error.code || 'CAMERA_START_ERROR' + message: result.error, + code: result.code || 'CAMERA_START_ERROR' }); - } finally { - loading.value = false; } + + } catch(error) { + console.error('Vue: Camera start error:', error); + cameraError.value = true; + emit('error', { + message: error.message || 'Camera start failed', + code: error.code || 'CAMERA_START_ERROR' + }); + } finally { + loading.value = false; } + } // TODO: Comeback and double check if updateCameraInfo is needed here // CameraScanner should be able to manage. // Additionally, camera.js utils file functions can be reused. async function updateCameraInfo() { - if(!cameraScanner) { - return; - } + if(!cameraScanner) { + return; + } - try { - // === PURE DELEGATION TO CAMERA SCANNER === - const caps = cameraScanner.getCameraCapabilities(); - capabilities.zoom = caps.zoom; - capabilities.torch = caps.torch; + try { + // === PURE DELEGATION TO CAMERA SCANNER === + const caps = cameraScanner.getCameraCapabilities(); + capabilities.zoom = caps.zoom; + capabilities.torch = caps.torch; - if(caps.zoomRange) { - const {max = 8, min = 1, step = 1} = caps.zoomRange; - Object.assign(cameraConstraints.zoom, {min, max, step}); - } + if(caps.zoomRange) { + const {max = 8, min = 1, step = 1} = caps.zoomRange; + Object.assign(cameraConstraints.zoom, {min, max, step}); + } - const devices = await cameraScanner.getCameraList(); - cameraList.value = devices; + const devices = await cameraScanner.getCameraList(); + cameraList.value = devices; - } catch(error) { - console.error('Error updating camera info:', error); - } + } catch(error) { + console.error('Error updating camera info:', error); } + } function stopCamera() { // Cancel any ongoing operations @@ -239,7 +245,8 @@ export default { } catch(error) { console.error('File scanning error:', error); - // Only reset scanning state if events weren't emitted (validation errors) + // Only reset scanning state if events weren't emitted + // (validation errors) if(scanning.value === true) { scanning.value = false; } @@ -247,7 +254,7 @@ export default { // message: error.message || 'File scanning failed', // code: error.code || 'FILE_SCAN_ERROR' // }); - } + } // finally { // scanning.value = false; // } diff --git a/components/ScannerUI.vue b/components/ScannerUI.vue index 9f3e378..1872d23 100644 --- a/components/ScannerUI.vue +++ b/components/ScannerUI.vue @@ -2,7 +2,7 @@ @@ -59,7 +59,8 @@
- +
@@ -234,9 +235,9 @@ export default { // default: () => ['qr_code', 'pdf417', 'pdf417_enhanced', 'mrz'] // }, scanType: { - type: String, - required: true, - validator: value => ['mrz', 'barcode', 'auto'].includes(value) + type: String, + required: true, + validator: value => ['mrz', 'barcode', 'auto'].includes(value) } }, emits: [ @@ -260,7 +261,8 @@ export default { // === COMPUTED PROPERTIES === // Show overlays only for barcode mode (MRZ camera mode uses native UI) const showOverlays = computed(() => { - // Show overlays for any mode that uses video element (not Dynamsoft native UI) + // Show overlays for any mode that uses video element + // (not Dynamsoft native UI) const usesVideoElement = props.scanType === 'barcode' || props.scanType === 'auto'; @@ -288,7 +290,9 @@ export default { // Dynamic overlay styling based on scan type const overlayClasses = computed(() => { - if(!showOverlays.value) return ''; + if(!showOverlays.value) { + return ''; + } // Auto mode gets its own overlay size if(props.scanType === 'auto') { @@ -323,7 +327,9 @@ export default { }); const overlayText = computed(() => { - if(!showOverlays.value) return ''; + if(!showOverlays.value) { + return ''; + } // Safety check - ensure formats array exists const formats = expectedFormats.value; @@ -337,7 +343,7 @@ export default { const hasMRZ = formats.includes('mrz'); if(formats.length === 1) { - if (hasQR) { + if(hasQR) { return 'Hold QR code here'; } if(hasPDF417) { @@ -370,6 +376,9 @@ export default { /** * Handle file selection from input element. * Converts FileList to Array and emits to parent component. + * + * @param {Event} event - The change event triggered by the file input + * element. */ function handleFileUpload(event) { const files = Array.from(event.target.files); @@ -393,7 +402,7 @@ export default { // DOM Refs - SINGLE CONTAINER APPROACH fileInput, // For file upload functionality cameraContainer, // CameraScanner will use this - + // State zoomLevel, diff --git a/src/components/ScannerDemo.vue b/src/components/ScannerDemo.vue index a1a9482..0ea8a07 100644 --- a/src/components/ScannerDemo.vue +++ b/src/components/ScannerDemo.vue @@ -6,9 +6,11 @@
-
Scan Configuration
+
+ Scan Configuration +
- + -
Architecture Flow:
+
+ Architecture Flow: +
- Vue (UI Only) → CameraScanner (Business Logic) → OpticalScanner (Core Engine) → Plugins (Format-Specific) + Vue (UI Only) -> CameraScanner (Business Logic)
+ -> OpticalScanner (Core Engine)
+ -> Plugins (Format-Specific)
@@ -55,18 +61,20 @@
-
Current Configuration:
+
+ Current Configuration: +
- Scan Type: {{ scanType }}
- Scan Mode: {{ scanMode }}
- License Key: {{ licenseKey ? 'Configured' : 'Not configured' }}
- Expected Behavior: {{ expectedBehavior }} + Scan Type: {{scanType}}
+ Scan Mode: {{scanMode}}
+ License Key: + {{licenseKey ? 'Configured' : 'Not configured'}}
+ Expected Behavior: {{expectedBehavior}}
-
Architecture Test Passed!
- Vue → CameraScanner → OpticalScanner → Plugins delegation worked successfully + Vue -> CameraScanner -> OpticalScanner ->
+ Plugins delegation worked successfully
- Scan Type: {{ scanResult.scanType || 'Unknown' }}
- Format Detected: {{ scanResult.format || scanResult.type }}
- Timestamp: {{ scanResult.timestamp || 'Not provided' }}
- Success: {{ scanResult.success ? 'Yes' : 'No' }} + Scan Type: {{scanResult.scanType || 'Unknown'}}
+ Format Detected: + {{scanResult.format || scanResult.type}}
+ Timestamp: + {{scanResult.timestamp || 'Not provided'}}
+ Success: {{scanResult.success ? 'Yes' : 'No'}}
-
MRZ Document Data:
- +
+ MRZ Document Data: +
+
@@ -127,40 +140,53 @@ class="text-red text-subtitle2 q-mb-sm"> MRZ Validation: Invalid
- + - {{ formatFieldName(key) }}: {{ value || 'N/A' }} + {{formatFieldName(key)}}: {{value || 'N/A'}} -
+
Validation Details - +
-
-
Overall Status: {{ scanResult.validation.overallStatus }}
+
+ Overall Status: + {{scanResult.validation.overallStatus}} +
- Completeness: {{ scanResult.validation.statistics.overallCompleteness }}% + Completeness: + {{scanResult.validation.statistics.overallCompleteness}} + %
-
- Invalid Fields: {{ scanResult.invalidFields.join(', ') }} +
+ Invalid Fields: + {{scanResult.invalidFields.join(', ')}}
@@ -172,16 +198,18 @@
-
Driver License Data:
- +
+ Driver License Data: +
+ - {{ key }}: - {{ formatDriverLicenseField(fieldData) }} + {{key}}: + {{formatDriverLicenseField(fieldData)}} @@ -190,9 +218,14 @@
-
Barcode Content:
+
+ Barcode Content: +
-
{{ scanResult.text || 'No text content' }}
+
+                {{scanResult.text || 'No text content'}}
+              
@@ -201,27 +234,30 @@
🛠️ Raw Scan Data (Debug) - +
-
-
{{ JSON.stringify(scanResult, null, 2) }}
+ ">{{JSON.stringify(scanResult, null, 2)}}
-
@@ -235,8 +271,8 @@ Scan Error
- Message: {{ scanError.message || scanError }}
- Code: {{ scanError.code || 'Unknown' }} + Message: {{scanError.message || scanError}}
+ Code: {{scanError.code || 'Unknown'}}
@@ -246,8 +282,8 @@ + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 7b425a0..f20d1db 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "@bedrock/vue-optical-scanner", "version": "0.0.1", "dependencies": { - "@bedrock/web-optical-scanner": "file:../bedrock-web-optical-scanner" + "@bedrock/web-optical-scanner": "digitalbazaar/bedrock-web-optical-scanner#refactor-camera-scanner-v1" }, "devDependencies": { "@vitejs/plugin-vue": "^6.0.1", @@ -28,31 +28,10 @@ }, "peerDependencies": { "@bedrock/quasar": "^10.0.0", - "@bedrock/web-fontawesome": "^2.0.0", + "@bedrock/web-fontawesome": "^2.1.0", "vue": "^3.4.21" } }, - "../bedrock-web-optical-scanner": { - "name": "@bedrock/web-optical-scanner", - "version": "1.0.0-0", - "dependencies": { - "barcode-detector": "^3.0.5", - "dynamsoft-javascript-barcode": "=9.6.1", - "dynamsoft-mrz-scanner": "^3.0.1" - }, - "devDependencies": { - "@bedrock/webpack": "^11.2.2", - "eslint": "^8.57.1", - "eslint-config-digitalbazaar": "^5.2.0", - "eslint-plugin-jsdoc": "^51.4.1", - "eslint-plugin-unicorn": "^56.0.1", - "webpack": "^5.101.3", - "webpack-cli": "^6.0.1" - }, - "engines": { - "node": ">=20" - } - }, "node_modules/@babel/code-frame": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", @@ -162,8 +141,16 @@ } }, "node_modules/@bedrock/web-optical-scanner": { - "resolved": "../bedrock-web-optical-scanner", - "link": true + "version": "0.0.1-0", + "resolved": "git+ssh://git@github.com/digitalbazaar/bedrock-web-optical-scanner.git#c51dc7b67ff03c1481849f507de8e6f02a74b659", + "dependencies": { + "barcode-detector": "^3.0.5", + "dynamsoft-javascript-barcode": "=9.6.1", + "dynamsoft-mrz-scanner": "^3.0.1" + }, + "engines": { + "node": ">=20" + } }, "node_modules/@es-joy/jsdoccomment": { "version": "0.52.0", @@ -1094,6 +1081,12 @@ "win32" ] }, + "node_modules/@types/emscripten": { + "version": "1.41.2", + "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.41.2.tgz", + "integrity": "sha512-0EVXosRnffZuF+rsMM1ZVbfpwpvL2/hWycYQ/0GaH/VaoSJvcSmMl6fiPel9TZXHL3EhANxzqKOVFC6NFXyn8A==", + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -1385,6 +1378,15 @@ "dev": true, "license": "MIT" }, + "node_modules/barcode-detector": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/barcode-detector/-/barcode-detector-3.0.5.tgz", + "integrity": "sha512-SWeGhJ8SEW0T3Anbr2wEugUXW2bSCld3PauZh+LjTgN1lSInnIrI+RnG53NkzS4pl3cfPCl1AZ10Rq+hSkXBSw==", + "license": "MIT", + "dependencies": { + "zxing-wasm": "2.2.0" + } + }, "node_modules/baseline-browser-mapping": { "version": "2.8.2", "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.2.tgz", @@ -1807,6 +1809,21 @@ "dev": true, "license": "MIT" }, + "node_modules/dm-fabric": { + "version": "5.1.17", + "resolved": "https://registry.npmjs.org/dm-fabric/-/dm-fabric-5.1.17.tgz", + "integrity": "sha512-YouI4F+svfqTi3FM9fKG8ZqtdygzLbAzaA53QfekreLvJRqaHhCplk+2EF+cgMmuO5kY62m2Pm0pBqqV/sc5Vg==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/dm-howler": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/dm-howler/-/dm-howler-2.2.4.tgz", + "integrity": "sha512-h+iDEP/cyALeqWNtGdZZRwm3buSwaG26wzF6fCUGhvkF/yxYoWb8F/v7qN+urqdZw3wotZGO/01rDlzOxJUUGw==", + "license": "MIT" + }, "node_modules/dmd": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/dmd/-/dmd-7.1.1.tgz", @@ -1847,6 +1864,60 @@ "node": ">=6.0.0" } }, + "node_modules/dynamsoft-camera-enhancer": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/dynamsoft-camera-enhancer/-/dynamsoft-camera-enhancer-3.3.10.tgz", + "integrity": "sha512-end8agwVRIpPF+Ixz4Kb5wY8Nn7Qq7XIa+mtysB/X1GubXm/2Vjh1YFiqA3XSPDhy65yYtqX0OA1G9vg7phfOg==", + "license": "SEE LICENSE IN LICENSE", + "dependencies": { + "dm-fabric": "^5.1.17" + } + }, + "node_modules/dynamsoft-capture-vision-bundle": { + "version": "3.0.6001", + "resolved": "https://registry.npmjs.org/dynamsoft-capture-vision-bundle/-/dynamsoft-capture-vision-bundle-3.0.6001.tgz", + "integrity": "sha512-UZnhaiiLY1ZU/40LCVUfyDMN5nBqZXQOjzCpWjaqwt+WlkZBx6kO1uTtDlc5XMLM3bKXUFxNCsz7asv5dDjfTw==", + "license": "SEE LICENSE IN LICENSE" + }, + "node_modules/dynamsoft-capture-vision-data": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dynamsoft-capture-vision-data/-/dynamsoft-capture-vision-data-1.0.1.tgz", + "integrity": "sha512-qZDhSVD9r1XSrDl6alDZ+ocn+gmO3hCjMtzYnwEB9O/Y2TgpthHsDA7tuD1Gcfk+fycfSoI8eW3w0LcelzJFRw==", + "license": "SEE LICENSE IN LICENSE" + }, + "node_modules/dynamsoft-javascript-barcode": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/dynamsoft-javascript-barcode/-/dynamsoft-javascript-barcode-9.6.1.tgz", + "integrity": "sha512-wAaCrihkiX7YudisJNUMy21/jo5BJUqIc+mW54iNeJ9I4qDowfYA07uQEfw3XKCNUVRE50rbg4zGQIaH4Cb06g==", + "deprecated": "This package is deprecated. Please use 'dynamsoft-barcode-reader-bundle' instead: https://www.npmjs.com/package/dynamsoft-barcode-reader-bundle", + "license": "SEE LICENSE IN LICENSE", + "dependencies": { + "dm-howler": "^2.2.4", + "dynamsoft-camera-enhancer": "^3.2.0" + }, + "peerDependencies": { + "node-fetch": "^2.6.5", + "node-localstorage": "^2.2.1" + }, + "peerDependenciesMeta": { + "node-fetch": { + "optional": true + }, + "node-localstorage": { + "optional": true + } + } + }, + "node_modules/dynamsoft-mrz-scanner": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dynamsoft-mrz-scanner/-/dynamsoft-mrz-scanner-3.0.3.tgz", + "integrity": "sha512-nBqLbh3rFUeurH2d50gmDzW3etg1Zf41w+suQaez97IEavlGpNYVfjmN68dATZgutupl7og+NgjK48gW65scEg==", + "license": "SEE LICENSE IN LICENSE", + "dependencies": { + "dynamsoft-capture-vision-bundle": "3.0.6001", + "dynamsoft-capture-vision-data": "1.0.1" + } + }, "node_modules/electron-to-chromium": { "version": "1.5.218", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.218.tgz", @@ -4491,6 +4562,31 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zxing-wasm": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/zxing-wasm/-/zxing-wasm-2.2.0.tgz", + "integrity": "sha512-RyHxVaAHsLSDzmwcAG05IF8sVOE5Ta2JT1dRDh0mzVZOIiDXZstsjkqvKHasN1n4lvFSbX7ngkHDufnt/XI07Q==", + "license": "MIT", + "dependencies": { + "@types/emscripten": "^1.40.1", + "type-fest": "^4.41.0" + }, + "peerDependencies": { + "@types/emscripten": ">=1.39.6" + } + }, + "node_modules/zxing-wasm/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index 2c883ea..12a28a0 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "lint:fix": "eslint --ext .cjs,.js,.vue . --fix" }, "dependencies": { - "@bedrock/web-optical-scanner": "bparth24/bedrock-web-optical-scanner#refactor-camera-scanner" + "@bedrock/web-optical-scanner": "digitalbazaar/bedrock-web-optical-scanner#refactor-camera-scanner-v1" }, "peerDependencies": { "@bedrock/quasar": "^10.0.0", diff --git a/test/package.json b/test/package.json index 9fa8e62..d319142 100644 --- a/test/package.json +++ b/test/package.json @@ -1,5 +1,5 @@ { - "name": "bedrock-web-pouch-edv-test", + "name": "bedrock-vue-optical-scanner-test", "version": "0.0.1-0", "type": "module", "private": true, diff --git a/vite.config.js b/vite.config.js index d908c7d..3af7b8d 100644 --- a/vite.config.js +++ b/vite.config.js @@ -10,7 +10,7 @@ export default defineConfig({ plugins: [vue()], resolve: { alias: { - '@': path.resolve(__dirname, './src'), + '@': path.resolve(__dirname, './demo'), }, }, }); From 850cb90e818cc023d6cb5742cbc2319b43f3d1fb Mon Sep 17 00:00:00 2001 From: Parth Bhatt Date: Sun, 28 Sep 2025 14:13:59 -0700 Subject: [PATCH 13/18] docs: remove word from OpticalScanner comment --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 652c895..41057ec 100644 --- a/README.md +++ b/README.md @@ -112,10 +112,10 @@ Lower-level UI component that handles camera display and controls. ``` +### Basic Example - MRZ Scanning (Passport/ID) + +```vue + + + +``` + +**Note:** MRZ scanning requires license key configuration (see Configuration section). + +## Functional Demo App + ScannerDemo Component + The ScannerDemo component provides a complete example implementation showing: - Document type selection (MRZ vs Barcode) @@ -145,7 +246,7 @@ The ScannerDemo component provides a complete example implementation showing: Key Features Demonstrated: - MRZ Scanning: Passport and ID document recognition with field validation -- Barcode Scanning: QR codes, PDF417, and enhanced PDF417 for driver licenses +- Barcode Scanning: QR codes, and PDF417 for driver licenses - Result Processing: Type-specific result handling and display - Camera Management: Start/stop controls with proper lifecycle management @@ -166,25 +267,14 @@ Usage in Demo: ``` -Installation +## Development Setup -```bash -npm install @bedrock/vue-optical-scanner -``` - -Peer Dependencies - -```bash -npm install vue@^3.4.21 @bedrock/quasar@^10.0.0 @bedrock/web-fontawesome@^2.0.0 -``` - -Development Setup -Prerequisites +### Prerequisites - Node.js >= 20 - npm or yarn -Getting Started +### Getting Started 1. Clone and install dependencies: @@ -214,3 +304,29 @@ npm run lint # Fix linting issues npm run lint:fix ``` + +## Understanding Mode-Specific Props + +**Question:** Why doesn't `showQrBox` work for MRZ mode? + +**Answer:** Different scan types use different UI architectures: + +| Scan Type | UI Architecture | Props Available | +|-----------|-----------------|-----------------| +| `barcode` | Vue-controlled video + overlays | `showQrBox`, `torchOn` | +| `mrz` | Dynamsoft native UI | None (Dynamsoft controls UI) | +| `auto` | Vue-controlled video + overlays | `showQrBox`, `torchOn` | + +**Why the difference?** + +- **Barcode mode:** Uses standard browser camera APIs... +- **MRZ mode:** Uses Dynamsoft's specialized document detection... +- **Auto mode:** Attempts all formats using browser APIs... + +**Implementation Detail:** The component uses `effectiveShowQrBox` computed property... + +## Troubleshooting | FAQ + +### QR box doesn't show for MRZ scanning + +**Expected behavior:** MRZ mode uses Dynamsoft's native UI, so Vue overlays (including QR box) are automatically disabled. This is correct behavior. diff --git a/components/OpticalScanner.vue b/components/OpticalScanner.vue index 1e61322..b897b11 100644 --- a/components/OpticalScanner.vue +++ b/components/OpticalScanner.vue @@ -34,12 +34,15 @@ export default { ScannerUI }, props: { - // NOTE: formats prop moved this logic to CameraScanner class - // and driven by scanType - // formats: { - // type: Array, - // default: () => ['qr_code', 'pdf417', 'pdf417_enhanced', 'mrz'] - // }, + // NOTE: formats prop to override scanType (power-user mode) + formats: { + type: Array, + default: null, // null = use scanType default or ['pdf417_enhanced'] + validator: value => { + const validFormats = ['pdf417_enhanced']; + return value === null || value.every(f => validFormats.includes(f)); + } + }, scanType: { type: String, required: true, @@ -60,14 +63,12 @@ export default { torchOn: { type: Boolean, default: false - }, - licenseKey: { - type: String, - default: '' } }, emits: ['result', 'error', 'close'], setup(props, {emit}) { + console.log('🔍 Props:', props); + // === CAMERA SCANNER INSTANCE === let cameraScanner = null; let abortController = new AbortController(); @@ -107,14 +108,14 @@ export default { // === INITIALIZATION === async function initializeCameraScanner() { // console.log('Initializing CameraScanner with scanType:', - // props.scanType); + // props.scanType); try { // Create CameraScanner with current configuration cameraScanner = new CameraScanner({ scanType: props.scanType, scanMode: props.scanMode, - licenseKey: props.licenseKey + formats: props.formats }); // === Set up event listener for auto-scan === diff --git a/components/ScannerUI.vue b/components/ScannerUI.vue index 1872d23..d886cea 100644 --- a/components/ScannerUI.vue +++ b/components/ScannerUI.vue @@ -60,14 +60,14 @@
+ (only show for barcode mode, hidden for MRZ camera mode) -->
showOverlays.value && !props.loading ); + // Make showQrBox mode-aware + const effectiveShowQrBox = computed(() => { + // Only show QR box for barcode-based modes + // MRZ uses Dynamsoft native UI (no Vue overlays) + const isBarcodeMode = ['barcode', 'auto'].includes(props.scanType); + const result = isBarcodeMode && props.showQrBox; + // console.log('effectiveShowQrBox:', { + // scanType: props.scanType, + // isBarcodeMode, + // showQrBox: props.showQrBox, + // result + // }); + return result; + }); + // Infer expected formats from scanType for overlay purposes const expectedFormats = computed(() => { // Infer formats from scanType for UI overlay purposes @@ -412,6 +436,7 @@ export default { expectedFormats, overlayClasses, overlayText, + effectiveShowQrBox, // Methods switchToNextCamera, diff --git a/demo/components/ScannerDemo.vue b/demo/components/ScannerDemo.vue index 67771e3..35bcb3c 100644 --- a/demo/components/ScannerDemo.vue +++ b/demo/components/ScannerDemo.vue @@ -48,6 +48,30 @@
+
+ + +
+ UI Props Testing +
+
+ + + + + + + + +
+
+
Scan Type: {{scanType}}
Scan Mode: {{scanMode}}
- License Key: - {{licenseKey ? 'Configured' : 'Not configured'}}
+ Tip Text: "{{tipText}}"
Expected Behavior: {{expectedBehavior}}
@@ -76,6 +99,8 @@
+ + @@ -289,10 +317,6 @@ export default { name: 'ScannerDemo', components: {OpticalScanner}, setup() { - // Add real license key - // eslint-disable-next-line max-len - const licenseKey = 'DLS2eyJoYW5kc2hha2VDb2RlIjoiMTA0NjQ0MTIxLU1UQTBOalEwTVRJeExYZGxZaTFVY21saGJGQnliMm8iLCJtYWluU2VydmVyVVJMIjoiaHR0cHM6Ly9tZGxzLmR5bmFtc29mdG9ubGluZS5jb20iLCJvcmdhbml6YXRpb25JRCI6IjEwNDY0NDEyMSIsInN0YW5kYnlTZXJ2ZXJVUkwiOiJodHRwczovL3NkbHMuZHluYW1zb2Z0b25saW5lLmNvbSIsImNoZWNrQ29kZSI6NTUxMjk4MTI3fQ=='; - const scanner = ref(null); const scannerOpen = ref(false); const scanResult = ref(null); @@ -311,6 +335,8 @@ export default { {label: 'All Formats', value: 'all'}, {label: 'Exhaustive Scan', value: 'exhaustive'} ]; + const showQrBox = ref(true); + const torchOn = ref(false); // Dynamic tip text based on scan type const tipText = computed(() => { @@ -324,22 +350,20 @@ export default { // Expected behavior description const expectedBehavior = computed(() => { if(scanType.value === 'mrz') { - if(licenseKey) { - return 'Dynamsoft native camera UI with document detection'; - } else { - return 'Will show license key error - MRZ requires valid license'; - } - } else { - return 'Video stream with Vue overlay guides for barcodes'; + return 'MRZ scanning with Dynamsoft (requires license in config)'; + } else if(scanType.value === 'barcode') { + return 'Open-source barcode scanning (QR + PDF417)'; + } else if(scanType.value === 'auto') { + return 'Auto-detect: tries all available formats'; } + return 'Video stream with overlay guides'; }); function openScanner() { - console.log('openScanner called with config:', { - scanType: scanType.value, - scanMode: scanMode.value, - hasLicense: !!licenseKey - }); + // console.log('openScanner called with config:', { + // scanType: scanType.value, + // scanMode: scanMode.value + // }); // Clear previous results scanResult.value = null; scanError.value = null; @@ -394,8 +418,9 @@ export default { scanTypeOptions, scanModeOptions, tipText, + showQrBox, + torchOn, expectedBehavior, - licenseKey, openScanner, onResult, onError, diff --git a/package-lock.json b/package-lock.json index f20d1db..ef0ce6a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "@bedrock/vue-optical-scanner", "version": "0.0.1", "dependencies": { - "@bedrock/web-optical-scanner": "digitalbazaar/bedrock-web-optical-scanner#refactor-camera-scanner-v1" + "@bedrock/web-optical-scanner": "digitalbazaar/bedrock-web-optical-scanner#3ed24c3c5e2865edf0e0be948c6b03e02f187966" }, "devDependencies": { "@vitejs/plugin-vue": "^6.0.1", @@ -141,8 +141,9 @@ } }, "node_modules/@bedrock/web-optical-scanner": { - "version": "0.0.1-0", - "resolved": "git+ssh://git@github.com/digitalbazaar/bedrock-web-optical-scanner.git#c51dc7b67ff03c1481849f507de8e6f02a74b659", + "version": "1.0.0", + "resolved": "git+ssh://git@github.com/digitalbazaar/bedrock-web-optical-scanner.git#3ed24c3c5e2865edf0e0be948c6b03e02f187966", + "integrity": "sha512-wcNpIcOl9ZjRcZdTJu73DBp35irc05/9n7CqlcKKdhM+ESVy2qoi5TkbYf17akKan3pZMFm8tg8RYFW55OP+vA==", "dependencies": { "barcode-detector": "^3.0.5", "dynamsoft-javascript-barcode": "=9.6.1", @@ -170,9 +171,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", - "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.10.tgz", + "integrity": "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==", "cpu": [ "ppc64" ], @@ -187,9 +188,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", - "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.10.tgz", + "integrity": "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==", "cpu": [ "arm" ], @@ -204,9 +205,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", - "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.10.tgz", + "integrity": "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==", "cpu": [ "arm64" ], @@ -221,9 +222,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", - "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.10.tgz", + "integrity": "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==", "cpu": [ "x64" ], @@ -238,9 +239,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", - "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.10.tgz", + "integrity": "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==", "cpu": [ "arm64" ], @@ -255,9 +256,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", - "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.10.tgz", + "integrity": "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==", "cpu": [ "x64" ], @@ -272,9 +273,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", - "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.10.tgz", + "integrity": "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==", "cpu": [ "arm64" ], @@ -289,9 +290,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", - "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.10.tgz", + "integrity": "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==", "cpu": [ "x64" ], @@ -306,9 +307,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", - "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.10.tgz", + "integrity": "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==", "cpu": [ "arm" ], @@ -323,9 +324,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", - "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.10.tgz", + "integrity": "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==", "cpu": [ "arm64" ], @@ -340,9 +341,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", - "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.10.tgz", + "integrity": "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==", "cpu": [ "ia32" ], @@ -357,9 +358,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", - "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.10.tgz", + "integrity": "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==", "cpu": [ "loong64" ], @@ -374,9 +375,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", - "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.10.tgz", + "integrity": "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==", "cpu": [ "mips64el" ], @@ -391,9 +392,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", - "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.10.tgz", + "integrity": "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==", "cpu": [ "ppc64" ], @@ -408,9 +409,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", - "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.10.tgz", + "integrity": "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==", "cpu": [ "riscv64" ], @@ -425,9 +426,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", - "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.10.tgz", + "integrity": "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==", "cpu": [ "s390x" ], @@ -442,9 +443,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", - "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.10.tgz", + "integrity": "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==", "cpu": [ "x64" ], @@ -459,9 +460,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", - "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.10.tgz", + "integrity": "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==", "cpu": [ "arm64" ], @@ -476,9 +477,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", - "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.10.tgz", + "integrity": "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==", "cpu": [ "x64" ], @@ -493,9 +494,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", - "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.10.tgz", + "integrity": "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==", "cpu": [ "arm64" ], @@ -510,9 +511,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", - "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.10.tgz", + "integrity": "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==", "cpu": [ "x64" ], @@ -527,9 +528,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", - "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.10.tgz", + "integrity": "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==", "cpu": [ "arm64" ], @@ -544,9 +545,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", - "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.10.tgz", + "integrity": "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==", "cpu": [ "x64" ], @@ -561,9 +562,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", - "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.10.tgz", + "integrity": "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==", "cpu": [ "arm64" ], @@ -578,9 +579,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", - "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.10.tgz", + "integrity": "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==", "cpu": [ "ia32" ], @@ -595,9 +596,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", - "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.10.tgz", + "integrity": "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==", "cpu": [ "x64" ], @@ -788,9 +789,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.1.tgz", - "integrity": "sha512-HJXwzoZN4eYTdD8bVV22DN8gsPCAj3V20NHKOs8ezfXanGpmVPR7kalUHd+Y31IJp9stdB87VKPFbsGY3H/2ag==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.4.tgz", + "integrity": "sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA==", "cpu": [ "arm" ], @@ -802,9 +803,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.50.1.tgz", - "integrity": "sha512-PZlsJVcjHfcH53mOImyt3bc97Ep3FJDXRpk9sMdGX0qgLmY0EIWxCag6EigerGhLVuL8lDVYNnSo8qnTElO4xw==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.4.tgz", + "integrity": "sha512-P9LDQiC5vpgGFgz7GSM6dKPCiqR3XYN1WwJKA4/BUVDjHpYsf3iBEmVz62uyq20NGYbiGPR5cNHI7T1HqxNs2w==", "cpu": [ "arm64" ], @@ -816,9 +817,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.1.tgz", - "integrity": "sha512-xc6i2AuWh++oGi4ylOFPmzJOEeAa2lJeGUGb4MudOtgfyyjr4UPNK+eEWTPLvmPJIY/pgw6ssFIox23SyrkkJw==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.4.tgz", + "integrity": "sha512-QRWSW+bVccAvZF6cbNZBJwAehmvG9NwfWHwMy4GbWi/BQIA/laTIktebT2ipVjNncqE6GLPxOok5hsECgAxGZg==", "cpu": [ "arm64" ], @@ -830,9 +831,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.50.1.tgz", - "integrity": "sha512-2ofU89lEpDYhdLAbRdeyz/kX3Y2lpYc6ShRnDjY35bZhd2ipuDMDi6ZTQ9NIag94K28nFMofdnKeHR7BT0CATw==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.4.tgz", + "integrity": "sha512-hZgP05pResAkRJxL1b+7yxCnXPGsXU0fG9Yfd6dUaoGk+FhdPKCJ5L1Sumyxn8kvw8Qi5PvQ8ulenUbRjzeCTw==", "cpu": [ "x64" ], @@ -844,9 +845,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.50.1.tgz", - "integrity": "sha512-wOsE6H2u6PxsHY/BeFHA4VGQN3KUJFZp7QJBmDYI983fgxq5Th8FDkVuERb2l9vDMs1D5XhOrhBrnqcEY6l8ZA==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.4.tgz", + "integrity": "sha512-xmc30VshuBNUd58Xk4TKAEcRZHaXlV+tCxIXELiE9sQuK3kG8ZFgSPi57UBJt8/ogfhAF5Oz4ZSUBN77weM+mQ==", "cpu": [ "arm64" ], @@ -858,9 +859,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.50.1.tgz", - "integrity": "sha512-A/xeqaHTlKbQggxCqispFAcNjycpUEHP52mwMQZUNqDUJFFYtPHCXS1VAG29uMlDzIVr+i00tSFWFLivMcoIBQ==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.4.tgz", + "integrity": "sha512-WdSLpZFjOEqNZGmHflxyifolwAiZmDQzuOzIq9L27ButpCVpD7KzTRtEG1I0wMPFyiyUdOO+4t8GvrnBLQSwpw==", "cpu": [ "x64" ], @@ -872,9 +873,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.50.1.tgz", - "integrity": "sha512-54v4okehwl5TaSIkpp97rAHGp7t3ghinRd/vyC1iXqXMfjYUTm7TfYmCzXDoHUPTTf36L8pr0E7YsD3CfB3ZDg==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.4.tgz", + "integrity": "sha512-xRiOu9Of1FZ4SxVbB0iEDXc4ddIcjCv2aj03dmW8UrZIW7aIQ9jVJdLBIhxBI+MaTnGAKyvMwPwQnoOEvP7FgQ==", "cpu": [ "arm" ], @@ -886,9 +887,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.50.1.tgz", - "integrity": "sha512-p/LaFyajPN/0PUHjv8TNyxLiA7RwmDoVY3flXHPSzqrGcIp/c2FjwPPP5++u87DGHtw+5kSH5bCJz0mvXngYxw==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.4.tgz", + "integrity": "sha512-FbhM2p9TJAmEIEhIgzR4soUcsW49e9veAQCziwbR+XWB2zqJ12b4i/+hel9yLiD8pLncDH4fKIPIbt5238341Q==", "cpu": [ "arm" ], @@ -900,9 +901,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.50.1.tgz", - "integrity": "sha512-2AbMhFFkTo6Ptna1zO7kAXXDLi7H9fGTbVaIq2AAYO7yzcAsuTNWPHhb2aTA6GPiP+JXh85Y8CiS54iZoj4opw==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.4.tgz", + "integrity": "sha512-4n4gVwhPHR9q/g8lKCyz0yuaD0MvDf7dV4f9tHt0C73Mp8h38UCtSCSE6R9iBlTbXlmA8CjpsZoujhszefqueg==", "cpu": [ "arm64" ], @@ -914,9 +915,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.50.1.tgz", - "integrity": "sha512-Cgef+5aZwuvesQNw9eX7g19FfKX5/pQRIyhoXLCiBOrWopjo7ycfB292TX9MDcDijiuIJlx1IzJz3IoCPfqs9w==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.4.tgz", + "integrity": "sha512-u0n17nGA0nvi/11gcZKsjkLj1QIpAuPFQbR48Subo7SmZJnGxDpspyw2kbpuoQnyK+9pwf3pAoEXerJs/8Mi9g==", "cpu": [ "arm64" ], @@ -927,10 +928,10 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.50.1.tgz", - "integrity": "sha512-RPhTwWMzpYYrHrJAS7CmpdtHNKtt2Ueo+BlLBjfZEhYBhK00OsEqM08/7f+eohiF6poe0YRDDd8nAvwtE/Y62Q==", + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.4.tgz", + "integrity": "sha512-0G2c2lpYtbTuXo8KEJkDkClE/+/2AFPdPAbmaHoE870foRFs4pBrDehilMcrSScrN/fB/1HTaWO4bqw+ewBzMQ==", "cpu": [ "loong64" ], @@ -942,9 +943,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.50.1.tgz", - "integrity": "sha512-eSGMVQw9iekut62O7eBdbiccRguuDgiPMsw++BVUg+1K7WjZXHOg/YOT9SWMzPZA+w98G+Fa1VqJgHZOHHnY0Q==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.4.tgz", + "integrity": "sha512-teSACug1GyZHmPDv14VNbvZFX779UqWTsd7KtTM9JIZRDI5NUwYSIS30kzI8m06gOPB//jtpqlhmraQ68b5X2g==", "cpu": [ "ppc64" ], @@ -956,9 +957,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.50.1.tgz", - "integrity": "sha512-S208ojx8a4ciIPrLgazF6AgdcNJzQE4+S9rsmOmDJkusvctii+ZvEuIC4v/xFqzbuP8yDjn73oBlNDgF6YGSXQ==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.4.tgz", + "integrity": "sha512-/MOEW3aHjjs1p4Pw1Xk4+3egRevx8Ji9N6HUIA1Ifh8Q+cg9dremvFCUbOX2Zebz80BwJIgCBUemjqhU5XI5Eg==", "cpu": [ "riscv64" ], @@ -970,9 +971,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.50.1.tgz", - "integrity": "sha512-3Ag8Ls1ggqkGUvSZWYcdgFwriy2lWo+0QlYgEFra/5JGtAd6C5Hw59oojx1DeqcA2Wds2ayRgvJ4qxVTzCHgzg==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.4.tgz", + "integrity": "sha512-1HHmsRyh845QDpEWzOFtMCph5Ts+9+yllCrREuBR/vg2RogAQGGBRC8lDPrPOMnrdOJ+mt1WLMOC2Kao/UwcvA==", "cpu": [ "riscv64" ], @@ -984,9 +985,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.50.1.tgz", - "integrity": "sha512-t9YrKfaxCYe7l7ldFERE1BRg/4TATxIg+YieHQ966jwvo7ddHJxPj9cNFWLAzhkVsbBvNA4qTbPVNsZKBO4NSg==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.4.tgz", + "integrity": "sha512-seoeZp4L/6D1MUyjWkOMRU6/iLmCU2EjbMTyAG4oIOs1/I82Y5lTeaxW0KBfkUdHAWN7j25bpkt0rjnOgAcQcA==", "cpu": [ "s390x" ], @@ -998,9 +999,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.1.tgz", - "integrity": "sha512-MCgtFB2+SVNuQmmjHf+wfI4CMxy3Tk8XjA5Z//A0AKD7QXUYFMQcns91K6dEHBvZPCnhJSyDWLApk40Iq/H3tA==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.4.tgz", + "integrity": "sha512-Wi6AXf0k0L7E2gteNsNHUs7UMwCIhsCTs6+tqQ5GPwVRWMaflqGec4Sd8n6+FNFDw9vGcReqk2KzBDhCa1DLYg==", "cpu": [ "x64" ], @@ -1012,9 +1013,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.1.tgz", - "integrity": "sha512-nEvqG+0jeRmqaUMuwzlfMKwcIVffy/9KGbAGyoa26iu6eSngAYQ512bMXuqqPrlTyfqdlB9FVINs93j534UJrg==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.4.tgz", + "integrity": "sha512-dtBZYjDmCQ9hW+WgEkaffvRRCKm767wWhxsFW3Lw86VXz/uJRuD438/XvbZT//B96Vs8oTA8Q4A0AfHbrxP9zw==", "cpu": [ "x64" ], @@ -1026,9 +1027,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.50.1.tgz", - "integrity": "sha512-RDsLm+phmT3MJd9SNxA9MNuEAO/J2fhW8GXk62G/B4G7sLVumNFbRwDL6v5NrESb48k+QMqdGbHgEtfU0LCpbA==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.4.tgz", + "integrity": "sha512-1ox+GqgRWqaB1RnyZXL8PD6E5f7YyRUJYnCqKpNzxzP0TkaUh112NDrR9Tt+C8rJ4x5G9Mk8PQR3o7Ku2RKqKA==", "cpu": [ "arm64" ], @@ -1040,9 +1041,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.50.1.tgz", - "integrity": "sha512-hpZB/TImk2FlAFAIsoElM3tLzq57uxnGYwplg6WDyAxbYczSi8O2eQ+H2Lx74504rwKtZ3N2g4bCUkiamzS6TQ==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.4.tgz", + "integrity": "sha512-8GKr640PdFNXwzIE0IrkMWUNUomILLkfeHjXBi/nUvFlpZP+FA8BKGKpacjW6OUUHaNI6sUURxR2U2g78FOHWQ==", "cpu": [ "arm64" ], @@ -1054,9 +1055,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.50.1.tgz", - "integrity": "sha512-SXjv8JlbzKM0fTJidX4eVsH+Wmnp0/WcD8gJxIZyR6Gay5Qcsmdbi9zVtnbkGPG8v2vMR1AD06lGWy5FLMcG7A==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.4.tgz", + "integrity": "sha512-AIy/jdJ7WtJ/F6EcfOb2GjR9UweO0n43jNObQMb6oGxkYTfLcnN7vYYpG+CN3lLxrQkzWnMOoNSHTW54pgbVxw==", "cpu": [ "ia32" ], @@ -1067,10 +1068,24 @@ "win32" ] }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.4.tgz", + "integrity": "sha512-UF9KfsH9yEam0UjTwAgdK0anlQ7c8/pWPU2yVjyWcF1I1thABt6WXE47cI71pGiZ8wGvxohBoLnxM04L/wj8mQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.1.tgz", - "integrity": "sha512-StxAO/8ts62KZVRAm4JZYq9+NqNsV7RvimNK+YM7ry//zebEH6meuugqW/P5OFUCjyQgui+9fUxT6d5NShvMvA==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.4.tgz", + "integrity": "sha512-bf9PtUa0u8IXDVxzRToFQKsNCRz9qLYfR/MpECxl4mRoWYjAeFjgxj1XdZr2M/GNVpT05p+LgQOHopYDlUu6/w==", "cpu": [ "x64" ], @@ -1127,9 +1142,9 @@ "license": "MIT" }, "node_modules/@typescript-eslint/types": { - "version": "8.43.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.43.0.tgz", - "integrity": "sha512-vQ2FZaxJpydjSZJKiSW/LJsabFFvV7KgLC5DiLhkBcykhQj8iK9BOaDmQt74nnKdLvceM5xmhaTF+pLekrxEkw==", + "version": "8.46.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.0.tgz", + "integrity": "sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA==", "dev": true, "license": "MIT", "engines": { @@ -1165,53 +1180,53 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.21.tgz", - "integrity": "sha512-8i+LZ0vf6ZgII5Z9XmUvrCyEzocvWT+TeR2VBUVlzIH6Tyv57E20mPZ1bCS+tbejgUgmjrEh7q/0F0bibskAmw==", + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.22.tgz", + "integrity": "sha512-jQ0pFPmZwTEiRNSb+i9Ow/I/cHv2tXYqsnHKKyCQ08irI2kdF5qmYedmF8si8mA7zepUFmJ2hqzS8CQmNOWOkQ==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.3", - "@vue/shared": "3.5.21", + "@babel/parser": "^7.28.4", + "@vue/shared": "3.5.22", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "node_modules/@vue/compiler-dom": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.21.tgz", - "integrity": "sha512-jNtbu/u97wiyEBJlJ9kmdw7tAr5Vy0Aj5CgQmo+6pxWNQhXZDPsRr1UWPN4v3Zf82s2H3kF51IbzZ4jMWAgPlQ==", + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.22.tgz", + "integrity": "sha512-W8RknzUM1BLkypvdz10OVsGxnMAuSIZs9Wdx1vzA3mL5fNMN15rhrSCLiTm6blWeACwUwizzPVqGJgOGBEN/hA==", "license": "MIT", "dependencies": { - "@vue/compiler-core": "3.5.21", - "@vue/shared": "3.5.21" + "@vue/compiler-core": "3.5.22", + "@vue/shared": "3.5.22" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.21.tgz", - "integrity": "sha512-SXlyk6I5eUGBd2v8Ie7tF6ADHE9kCR6mBEuPyH1nUZ0h6Xx6nZI29i12sJKQmzbDyr2tUHMhhTt51Z6blbkTTQ==", + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.22.tgz", + "integrity": "sha512-tbTR1zKGce4Lj+JLzFXDq36K4vcSZbJ1RBu8FxcDv1IGRz//Dh2EBqksyGVypz3kXpshIfWKGOCcqpSbyGWRJQ==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.3", - "@vue/compiler-core": "3.5.21", - "@vue/compiler-dom": "3.5.21", - "@vue/compiler-ssr": "3.5.21", - "@vue/shared": "3.5.21", + "@babel/parser": "^7.28.4", + "@vue/compiler-core": "3.5.22", + "@vue/compiler-dom": "3.5.22", + "@vue/compiler-ssr": "3.5.22", + "@vue/shared": "3.5.22", "estree-walker": "^2.0.2", - "magic-string": "^0.30.18", + "magic-string": "^0.30.19", "postcss": "^8.5.6", "source-map-js": "^1.2.1" } }, "node_modules/@vue/compiler-ssr": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.21.tgz", - "integrity": "sha512-vKQ5olH5edFZdf5ZrlEgSO1j1DMA4u23TVK5XR1uMhvwnYvVdDF0nHXJUblL/GvzlShQbjhZZ2uvYmDlAbgo9w==", + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.22.tgz", + "integrity": "sha512-GdgyLvg4R+7T8Nk2Mlighx7XGxq/fJf9jaVofc3IL0EPesTE86cP/8DD1lT3h1JeZr2ySBvyqKQJgbS54IX1Ww==", "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.21", - "@vue/shared": "3.5.21" + "@vue/compiler-dom": "3.5.22", + "@vue/shared": "3.5.22" } }, "node_modules/@vue/devtools-api": { @@ -1222,53 +1237,53 @@ "peer": true }, "node_modules/@vue/reactivity": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.21.tgz", - "integrity": "sha512-3ah7sa+Cwr9iiYEERt9JfZKPw4A2UlbY8RbbnH2mGCE8NwHkhmlZt2VsH0oDA3P08X3jJd29ohBDtX+TbD9AsA==", + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.22.tgz", + "integrity": "sha512-f2Wux4v/Z2pqc9+4SmgZC1p73Z53fyD90NFWXiX9AKVnVBEvLFOWCEgJD3GdGnlxPZt01PSlfmLqbLYzY/Fw4A==", "license": "MIT", "dependencies": { - "@vue/shared": "3.5.21" + "@vue/shared": "3.5.22" } }, "node_modules/@vue/runtime-core": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.21.tgz", - "integrity": "sha512-+DplQlRS4MXfIf9gfD1BOJpk5RSyGgGXD/R+cumhe8jdjUcq/qlxDawQlSI8hCKupBlvM+3eS1se5xW+SuNAwA==", + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.22.tgz", + "integrity": "sha512-EHo4W/eiYeAzRTN5PCextDUZ0dMs9I8mQ2Fy+OkzvRPUYQEyK9yAjbasrMCXbLNhF7P0OUyivLjIy0yc6VrLJQ==", "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.21", - "@vue/shared": "3.5.21" + "@vue/reactivity": "3.5.22", + "@vue/shared": "3.5.22" } }, "node_modules/@vue/runtime-dom": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.21.tgz", - "integrity": "sha512-3M2DZsOFwM5qI15wrMmNF5RJe1+ARijt2HM3TbzBbPSuBHOQpoidE+Pa+XEaVN+czbHf81ETRoG1ltztP2em8w==", + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.22.tgz", + "integrity": "sha512-Av60jsryAkI023PlN7LsqrfPvwfxOd2yAwtReCjeuugTJTkgrksYJJstg1e12qle0NarkfhfFu1ox2D+cQotww==", "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.21", - "@vue/runtime-core": "3.5.21", - "@vue/shared": "3.5.21", + "@vue/reactivity": "3.5.22", + "@vue/runtime-core": "3.5.22", + "@vue/shared": "3.5.22", "csstype": "^3.1.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.21.tgz", - "integrity": "sha512-qr8AqgD3DJPJcGvLcJKQo2tAc8OnXRcfxhOJCPF+fcfn5bBGz7VCcO7t+qETOPxpWK1mgysXvVT/j+xWaHeMWA==", + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.22.tgz", + "integrity": "sha512-gXjo+ao0oHYTSswF+a3KRHZ1WszxIqO7u6XwNHqcqb9JfyIL/pbWrrh/xLv7jeDqla9u+LK7yfZKHih1e1RKAQ==", "license": "MIT", "dependencies": { - "@vue/compiler-ssr": "3.5.21", - "@vue/shared": "3.5.21" + "@vue/compiler-ssr": "3.5.22", + "@vue/shared": "3.5.22" }, "peerDependencies": { - "vue": "3.5.21" + "vue": "3.5.22" } }, "node_modules/@vue/shared": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.21.tgz", - "integrity": "sha512-+2k1EQpnYuVuu3N7atWyG3/xoFWIVJZq4Mz8XNOdScFI0etES75fbny/oU4lKWk/577P1zmg0ioYvpGEDZ3DLw==", + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.22.tgz", + "integrity": "sha512-F4yc6palwq3TT0u+FYf0Ns4Tfl9GRFURDN2gWG7L1ecIaS/4fCIuFOjMTnCyjsu/OK6vaDKLCrGAa+KvvH+h4w==", "license": "MIT" }, "node_modules/acorn": { @@ -1379,18 +1394,18 @@ "license": "MIT" }, "node_modules/barcode-detector": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/barcode-detector/-/barcode-detector-3.0.5.tgz", - "integrity": "sha512-SWeGhJ8SEW0T3Anbr2wEugUXW2bSCld3PauZh+LjTgN1lSInnIrI+RnG53NkzS4pl3cfPCl1AZ10Rq+hSkXBSw==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/barcode-detector/-/barcode-detector-3.0.6.tgz", + "integrity": "sha512-v4xTr6B+FINl/p1RDl38qzIwF+Repfo+k/a/HlKTJKAJpNvACD6v7AH7LSPvfR4AdzXXuwai04huA4TWn02Znw==", "license": "MIT", "dependencies": { - "zxing-wasm": "2.2.0" + "zxing-wasm": "2.2.2" } }, "node_modules/baseline-browser-mapping": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.2.tgz", - "integrity": "sha512-NvcIedLxrs9llVpX7wI+Jz4Hn9vJQkCPKrTaHIE0sW/Rj1iq6Fzby4NbyTZjQJNoypBXNaG7tEHkTgONZpwgxQ==", + "version": "2.8.14", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.14.tgz", + "integrity": "sha512-GM9c0cWWR8Ga7//Ves/9KRgTS8nLausCkP3CGiFLrnwA2CDUluXgaQqvrULoR2Ujrd/mz/lkX87F5BHFsNr5sQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -1436,9 +1451,9 @@ } }, "node_modules/browserslist": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.0.tgz", - "integrity": "sha512-P9go2WrP9FiPwLv3zqRD/Uoxo0RSHjzFCiQz7d4vbmwNqQFo9T9WCeP/Qn5EbcKQY6DBbkxEXNcpJOmncNrb7A==", + "version": "4.26.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.3.tgz", + "integrity": "sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==", "dev": true, "funding": [ { @@ -1456,9 +1471,9 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.8.2", - "caniuse-lite": "^1.0.30001741", - "electron-to-chromium": "^1.5.218", + "baseline-browser-mapping": "^2.8.9", + "caniuse-lite": "^1.0.30001746", + "electron-to-chromium": "^1.5.227", "node-releases": "^2.0.21", "update-browserslist-db": "^1.1.3" }, @@ -1514,9 +1529,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001741", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001741.tgz", - "integrity": "sha512-QGUGitqsc8ARjLdgAfxETDhRbJ0REsP6O3I96TAth/mVjh2cYzN2u+3AzPP3aVSm2FehEItaJw1xd+IGBXWeSw==", + "version": "1.0.30001749", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001749.tgz", + "integrity": "sha512-0rw2fJOmLfnzCRbkm8EyHL8SvI2Apu5UbnQuTsJ0ClgrH8hcwFooJ1s5R0EP8o8aVrFu8++ae29Kt9/gZAZp/Q==", "dev": true, "funding": [ { @@ -1581,9 +1596,9 @@ } }, "node_modules/ci-info": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", - "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", + "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", "dev": true, "funding": [ { @@ -1785,9 +1800,9 @@ } }, "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -1919,9 +1934,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.218", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.218.tgz", - "integrity": "sha512-uwwdN0TUHs8u6iRgN8vKeWZMRll4gBkz+QMqdS7DDe49uiK68/UX92lFb61oiFPrpYZNeZIqa4bA7O6Aiasnzg==", + "version": "1.5.233", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.233.tgz", + "integrity": "sha512-iUdTQSf7EFXsDdQsp8MwJz5SVk4APEFqXU/S47OtQ0YLqacSwPXdZ5vRlMX3neb07Cy2vgioNuRnWUXFwuslkg==", "dev": true, "license": "ISC" }, @@ -1938,9 +1953,9 @@ } }, "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1948,9 +1963,9 @@ } }, "node_modules/esbuild": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", - "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.10.tgz", + "integrity": "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -1961,32 +1976,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.9", - "@esbuild/android-arm": "0.25.9", - "@esbuild/android-arm64": "0.25.9", - "@esbuild/android-x64": "0.25.9", - "@esbuild/darwin-arm64": "0.25.9", - "@esbuild/darwin-x64": "0.25.9", - "@esbuild/freebsd-arm64": "0.25.9", - "@esbuild/freebsd-x64": "0.25.9", - "@esbuild/linux-arm": "0.25.9", - "@esbuild/linux-arm64": "0.25.9", - "@esbuild/linux-ia32": "0.25.9", - "@esbuild/linux-loong64": "0.25.9", - "@esbuild/linux-mips64el": "0.25.9", - "@esbuild/linux-ppc64": "0.25.9", - "@esbuild/linux-riscv64": "0.25.9", - "@esbuild/linux-s390x": "0.25.9", - "@esbuild/linux-x64": "0.25.9", - "@esbuild/netbsd-arm64": "0.25.9", - "@esbuild/netbsd-x64": "0.25.9", - "@esbuild/openbsd-arm64": "0.25.9", - "@esbuild/openbsd-x64": "0.25.9", - "@esbuild/openharmony-arm64": "0.25.9", - "@esbuild/sunos-x64": "0.25.9", - "@esbuild/win32-arm64": "0.25.9", - "@esbuild/win32-ia32": "0.25.9", - "@esbuild/win32-x64": "0.25.9" + "@esbuild/aix-ppc64": "0.25.10", + "@esbuild/android-arm": "0.25.10", + "@esbuild/android-arm64": "0.25.10", + "@esbuild/android-x64": "0.25.10", + "@esbuild/darwin-arm64": "0.25.10", + "@esbuild/darwin-x64": "0.25.10", + "@esbuild/freebsd-arm64": "0.25.10", + "@esbuild/freebsd-x64": "0.25.10", + "@esbuild/linux-arm": "0.25.10", + "@esbuild/linux-arm64": "0.25.10", + "@esbuild/linux-ia32": "0.25.10", + "@esbuild/linux-loong64": "0.25.10", + "@esbuild/linux-mips64el": "0.25.10", + "@esbuild/linux-ppc64": "0.25.10", + "@esbuild/linux-riscv64": "0.25.10", + "@esbuild/linux-s390x": "0.25.10", + "@esbuild/linux-x64": "0.25.10", + "@esbuild/netbsd-arm64": "0.25.10", + "@esbuild/netbsd-x64": "0.25.10", + "@esbuild/openbsd-arm64": "0.25.10", + "@esbuild/openbsd-x64": "0.25.10", + "@esbuild/openharmony-arm64": "0.25.10", + "@esbuild/sunos-x64": "0.25.10", + "@esbuild/win32-arm64": "0.25.10", + "@esbuild/win32-ia32": "0.25.10", + "@esbuild/win32-x64": "0.25.10" } }, "node_modules/escalade": { @@ -2833,9 +2848,9 @@ } }, "node_modules/jsdoc": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.4.tgz", - "integrity": "sha512-zeFezwyXeG4syyYHbvh1A967IAqq/67yXtXvuL5wnqCkFZe8I0vKfm+EO+YEvLguo6w9CDUbrAXVtJSHh2E8rw==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.5.tgz", + "integrity": "sha512-P4C6MWP9yIlMiK8nwoZvxN84vb6MsnXcHuy7XzVOvQoCizWX5JFCBsWIIWKXBltpoRZXddUOVQmCTOZt9yDj9g==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -2890,15 +2905,14 @@ } }, "node_modules/jsdoc-parse": { - "version": "6.2.4", - "resolved": "https://registry.npmjs.org/jsdoc-parse/-/jsdoc-parse-6.2.4.tgz", - "integrity": "sha512-MQA+lCe3ioZd0uGbyB3nDCDZcKgKC7m/Ivt0LgKZdUoOlMJxUWJQ3WI6GeyHp9ouznKaCjlp7CU9sw5k46yZTw==", + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/jsdoc-parse/-/jsdoc-parse-6.2.5.tgz", + "integrity": "sha512-8JaSNjPLr2IuEY4Das1KM6Z4oLHZYUnjRrr27hKSa78Cj0i5Lur3DzNnCkz+DfrKBDoljGMoWOiBVQbtUZJBPw==", "dev": true, "license": "MIT", "dependencies": { "array-back": "^6.2.2", "find-replace": "^5.0.1", - "lodash.omit": "^4.5.0", "sort-array": "^5.0.0" }, "engines": { @@ -2906,9 +2920,9 @@ } }, "node_modules/jsdoc-to-markdown": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/jsdoc-to-markdown/-/jsdoc-to-markdown-9.1.2.tgz", - "integrity": "sha512-0rhxIZeolCJzQ1SPIqmdtPd4VsK8Jt22sKUnnjHpFaXPDkhmdEuZhkrUQKuQidXGi+j3otleQyqn2BEYhxOpYA==", + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/jsdoc-to-markdown/-/jsdoc-to-markdown-9.1.3.tgz", + "integrity": "sha512-i9wi+6WHX0WKziv0ar88T8h7OmxA0LWdQaV23nY6uQyKvdUPzVt0o6YAaOceFuKRF5Rvlju5w/KnZBfdpDAlnw==", "dev": true, "license": "MIT", "dependencies": { @@ -2918,7 +2932,7 @@ "config-master": "^3.1.0", "dmd": "^7.1.1", "jsdoc-api": "^9.3.5", - "jsdoc-parse": "^6.2.4", + "jsdoc-parse": "^6.2.5", "walk-back": "^5.1.1" }, "bin": { @@ -3085,14 +3099,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash.omit": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", - "integrity": "sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==", - "deprecated": "This package is deprecated. Use destructuring assignment syntax instead.", - "dev": true, - "license": "MIT" - }, "node_modules/magic-string": { "version": "0.30.19", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz", @@ -3261,9 +3267,9 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.21", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.21.tgz", - "integrity": "sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==", + "version": "2.0.23", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.23.tgz", + "integrity": "sha512-cCmFDMSm26S6tQSDpBCg/NR8NENrVPhAJSf+XbxBG4rPFaaonlEoE9wHQmun+cls499TQGSb7ZyPBRlzgKfpeg==", "dev": true, "license": "MIT" }, @@ -3829,9 +3835,9 @@ } }, "node_modules/rollup": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.50.1.tgz", - "integrity": "sha512-78E9voJHwnXQMiQdiqswVLZwJIzdBKJ1GdI5Zx6XwoFKUIk09/sSrr+05QFzvYb8q6Y9pPV45zzDuYa3907TZA==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.4.tgz", + "integrity": "sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3845,27 +3851,28 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.50.1", - "@rollup/rollup-android-arm64": "4.50.1", - "@rollup/rollup-darwin-arm64": "4.50.1", - "@rollup/rollup-darwin-x64": "4.50.1", - "@rollup/rollup-freebsd-arm64": "4.50.1", - "@rollup/rollup-freebsd-x64": "4.50.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.50.1", - "@rollup/rollup-linux-arm-musleabihf": "4.50.1", - "@rollup/rollup-linux-arm64-gnu": "4.50.1", - "@rollup/rollup-linux-arm64-musl": "4.50.1", - "@rollup/rollup-linux-loongarch64-gnu": "4.50.1", - "@rollup/rollup-linux-ppc64-gnu": "4.50.1", - "@rollup/rollup-linux-riscv64-gnu": "4.50.1", - "@rollup/rollup-linux-riscv64-musl": "4.50.1", - "@rollup/rollup-linux-s390x-gnu": "4.50.1", - "@rollup/rollup-linux-x64-gnu": "4.50.1", - "@rollup/rollup-linux-x64-musl": "4.50.1", - "@rollup/rollup-openharmony-arm64": "4.50.1", - "@rollup/rollup-win32-arm64-msvc": "4.50.1", - "@rollup/rollup-win32-ia32-msvc": "4.50.1", - "@rollup/rollup-win32-x64-msvc": "4.50.1", + "@rollup/rollup-android-arm-eabi": "4.52.4", + "@rollup/rollup-android-arm64": "4.52.4", + "@rollup/rollup-darwin-arm64": "4.52.4", + "@rollup/rollup-darwin-x64": "4.52.4", + "@rollup/rollup-freebsd-arm64": "4.52.4", + "@rollup/rollup-freebsd-x64": "4.52.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.52.4", + "@rollup/rollup-linux-arm-musleabihf": "4.52.4", + "@rollup/rollup-linux-arm64-gnu": "4.52.4", + "@rollup/rollup-linux-arm64-musl": "4.52.4", + "@rollup/rollup-linux-loong64-gnu": "4.52.4", + "@rollup/rollup-linux-ppc64-gnu": "4.52.4", + "@rollup/rollup-linux-riscv64-gnu": "4.52.4", + "@rollup/rollup-linux-riscv64-musl": "4.52.4", + "@rollup/rollup-linux-s390x-gnu": "4.52.4", + "@rollup/rollup-linux-x64-gnu": "4.52.4", + "@rollup/rollup-linux-x64-musl": "4.52.4", + "@rollup/rollup-openharmony-arm64": "4.52.4", + "@rollup/rollup-win32-arm64-msvc": "4.52.4", + "@rollup/rollup-win32-ia32-msvc": "4.52.4", + "@rollup/rollup-win32-x64-gnu": "4.52.4", + "@rollup/rollup-win32-x64-msvc": "4.52.4", "fsevents": "~2.3.2" } }, @@ -3894,9 +3901,9 @@ } }, "node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "dev": true, "license": "ISC", "bin": { @@ -4103,6 +4110,18 @@ "node": ">=12.17" } }, + "node_modules/tagged-tag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz", + "integrity": "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==", + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -4306,9 +4325,9 @@ } }, "node_modules/vite": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.5.tgz", - "integrity": "sha512-4cKBO9wR75r0BeIWWWId9XK9Lj6La5X846Zw9dFfzMRw38IlTk2iCcUt6hsyiDRcPidc55ZParFYDXi0nXOeLQ==", + "version": "7.1.9", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.9.tgz", + "integrity": "sha512-4nVGliEpxmhCL8DslSAUdxlB6+SMrhB0a1v5ijlh1xB1nEPuy1mxaHxysVucLHuWryAxLWg6a5ei+U4TLn/rFg==", "dev": true, "license": "MIT", "dependencies": { @@ -4412,16 +4431,16 @@ } }, "node_modules/vue": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.21.tgz", - "integrity": "sha512-xxf9rum9KtOdwdRkiApWL+9hZEMWE90FHh8yS1+KJAiWYh+iGWV1FquPjoO9VUHQ+VIhsCXNNyZ5Sf4++RVZBA==", + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.22.tgz", + "integrity": "sha512-toaZjQ3a/G/mYaLSbV+QsQhIdMo9x5rrqIpYRObsJ6T/J+RyCSFwN2LHNVH9v8uIcljDNa3QzPVdv3Y6b9hAJQ==", "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.21", - "@vue/compiler-sfc": "3.5.21", - "@vue/runtime-dom": "3.5.21", - "@vue/server-renderer": "3.5.21", - "@vue/shared": "3.5.21" + "@vue/compiler-dom": "3.5.22", + "@vue/compiler-sfc": "3.5.22", + "@vue/runtime-dom": "3.5.22", + "@vue/server-renderer": "3.5.22", + "@vue/shared": "3.5.22" }, "peerDependencies": { "typescript": "*" @@ -4564,25 +4583,28 @@ } }, "node_modules/zxing-wasm": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/zxing-wasm/-/zxing-wasm-2.2.0.tgz", - "integrity": "sha512-RyHxVaAHsLSDzmwcAG05IF8sVOE5Ta2JT1dRDh0mzVZOIiDXZstsjkqvKHasN1n4lvFSbX7ngkHDufnt/XI07Q==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/zxing-wasm/-/zxing-wasm-2.2.2.tgz", + "integrity": "sha512-Q9/B9whEwAUABvr7ScHl36wVZTBWVHAaumx45uGQLl2GGRp5ZRtDtwbz5scOwl/xzL07fximIqoQqqmzf9eJJA==", "license": "MIT", "dependencies": { - "@types/emscripten": "^1.40.1", - "type-fest": "^4.41.0" + "@types/emscripten": "^1.41.2", + "type-fest": "^5.0.1" }, "peerDependencies": { "@types/emscripten": ">=1.39.6" } }, "node_modules/zxing-wasm/node_modules/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.0.1.tgz", + "integrity": "sha512-9MpwAI52m8H6ssA542UxSLnSiSD2dsC3/L85g6hVubLSXd82wdI80eZwTWhdOfN67NlA+D+oipAs1MlcTcu3KA==", "license": "(MIT OR CC0-1.0)", + "dependencies": { + "tagged-tag": "^1.0.0" + }, "engines": { - "node": ">=16" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" diff --git a/package.json b/package.json index dd56362..d7410cd 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "lint:fix": "eslint --ext .cjs,.js,.vue . --fix" }, "dependencies": { - "@bedrock/web-optical-scanner": "digitalbazaar/bedrock-web-optical-scanner#20251002" + "@bedrock/web-optical-scanner": "digitalbazaar/bedrock-web-optical-scanner#3ed24c3c5e2865edf0e0be948c6b03e02f187966" }, "peerDependencies": { "@bedrock/quasar": "^10.0.0", From a37b8cd8819d2d7a4486d4b1b315f643aaa50b4d Mon Sep 17 00:00:00 2001 From: Parth Bhatt Date: Sat, 11 Oct 2025 19:28:48 -0700 Subject: [PATCH 18/18] Update Changelog. --- CHANGELOG.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e786d09..8846e39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,30 @@ # bedrock-vue-optical-scanner ChangeLog +## 1.2.0 - 2025-mm-dd + +### Changed + +- **NOTE**: License key configuration moved from component props to `@bedrock/web/config` + - Removed `licenseKey` prop from OpticalScanner component API + - License keys now configured once in bedrock config, automatically read by components + - Enables future removal of third-party dependencies without breaking changes +- Updated props documentation to clarify mode-specific behavior + - `showQrBox` and `torchOn` props only apply to barcode/auto modes + - MRZ mode uses Dynamsoft native UI (Vue overlays automatically disabled) + +### Added + +- Configuration section in README explaining bedrock config setup for license keys +- Troubleshooting section addressing common questions about mode-specific props +- Architecture documentation explaining license key management design rationale + +### Improved + +- Implemented `effectiveShowQrBox` computed property for mode-aware UI rendering + - Automatically disables QR box overlay when MRZ mode is active + - Makes mode-specific behavior explicit in code rather than implicit +- Enhanced PDF417 clarified as legacy feature accessible via `formats` prop override + ## 1.1.0 - 2025-09-27 ### Added