From a4598b65f51b55361bc6318c09c1d5bc5cea748b Mon Sep 17 00:00:00 2001 From: shakilhossain-cse Date: Mon, 29 Jun 2026 16:10:07 +0600 Subject: [PATCH 1/2] refactor: update package name and remove unused suppression list methods --- README.md | 8 ++---- adonis-typings/email-guard.ts | 10 ------- instructions.md | 6 ++--- package.json | 8 +++--- src/EmailGuard.ts | 11 -------- src/Suppression/index.ts | 24 ----------------- test/suppression.spec.ts | 49 ++--------------------------------- 7 files changed, 11 insertions(+), 105 deletions(-) diff --git a/README.md b/README.md index ea57359..f067fe0 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,8 @@ AdonisJS v5 package for email validation and a DB-backed suppression list. ## Install ```bash -npm i adonis-email-guard -node ace configure adonis-email-guard +npm i @ezycourse/adonis-email-guard +node ace configure @ezycourse/adonis-email-guard ``` The configure step copies `config/email-guard.ts` into your app and registers the provider. @@ -55,8 +55,6 @@ if (!c.valid || c.suppressed) return; // do not send await EmailGuard.suppress('bounce@x.com', 'bounce', 'webhook', {provider: 'postmark'}); await EmailGuard.isSuppressed('bounce@x.com'); // true await EmailGuard.find('bounce@x.com'); -await EmailGuard.list({reason: 'bounce', limit: 50}); -await EmailGuard.count({source: 'webhook'}); await EmailGuard.unsuppress('bounce@x.com'); ``` @@ -84,8 +82,6 @@ Returns `{ valid, email, reason?, checks, suggestion?, mxHost? }`. | `unsuppress(email)` | Delete. Returns `true` if a row was removed. | | `isSuppressed(email)` | Boolean lookup. | | `find(email)` | Row or `null`. | -| `list(filters?)` | Filter by `reason`/`source`/`search`, with paging. | -| `count(filters?)` | Same filters, returns a count. | | `ensureTable()` | Idempotent `CREATE TABLE IF NOT EXISTS`. | ## Suppression table schema diff --git a/adonis-typings/email-guard.ts b/adonis-typings/email-guard.ts index ab14fc1..70ddc4e 100644 --- a/adonis-typings/email-guard.ts +++ b/adonis-typings/email-guard.ts @@ -47,14 +47,6 @@ declare module '@ioc:Adonis/Addons/EmailGuard' { updated_at: Date; }; - export type SuppressionListFilters = { - reason?: SuppressionReason; - source?: SuppressionSource; - search?: string; - limit?: number; - offset?: number; - }; - export type EmailGuardConfig = { tableName?: string; /** Run `CREATE TABLE IF NOT EXISTS` for the suppression table on app boot. Default true. */ @@ -82,8 +74,6 @@ declare module '@ioc:Adonis/Addons/EmailGuard' { ): Promise; unsuppress(email: string): Promise; find(email: string): Promise; - list(filters?: SuppressionListFilters): Promise; - count(filters?: Omit): Promise; /** Validates and, on failure, optionally records a suppression. Combines validate + isSuppressed. */ check( email: string, diff --git a/instructions.md b/instructions.md index 28e1dfa..96db55c 100644 --- a/instructions.md +++ b/instructions.md @@ -2,13 +2,13 @@ Setup steps after install: -1. **Run the configure command** (already done if you used `node ace configure adonis-email-guard`). This copies `config/email-guard.ts` into your app. +1. **Run the configure command** (already done if you used `node ace configure @ezycourse/adonis-email-guard`). This copies `config/email-guard.ts` into your app. 2. **Verify the provider was registered** in `.adonisrc.json`: ```json { - "providers": ["./providers/AppProvider", "adonis-email-guard"] + "providers": ["./providers/AppProvider", "@ezycourse/adonis-email-guard"] } ``` @@ -17,7 +17,7 @@ Setup steps after install: ```json { "compilerOptions": { - "types": ["@adonisjs/core", "@adonisjs/lucid", "adonis-email-guard"] + "types": ["@adonisjs/core", "@adonisjs/lucid", "@ezycourse/adonis-email-guard"] } } ``` diff --git a/package.json b/package.json index b337718..fa7852e 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "adonis-email-guard", + "name": "@ezycourse/adonis-email-guard", "version": "0.1.0", "description": "AdonisJS v5 package: email validation (syntax, MX, SMTP, disposable, spam-trap) + DB-backed suppression list with configurable table and auto-create.", "main": "build/providers/EmailGuardProvider.js", @@ -62,9 +62,9 @@ }, "adonisjs": { "instructionsMd": "./build/instructions.md", - "types": "adonis-email-guard", + "types": "@ezycourse/adonis-email-guard", "providers": [ - "adonis-email-guard" + "@ezycourse/adonis-email-guard" ], "templates": { "config": [ @@ -76,7 +76,7 @@ } }, "publishConfig": { - "access": "public", + "access": "restricted", "tag": "latest" } } diff --git a/src/EmailGuard.ts b/src/EmailGuard.ts index cb78c2b..f8fb2c6 100644 --- a/src/EmailGuard.ts +++ b/src/EmailGuard.ts @@ -4,7 +4,6 @@ import type { EmailGuardConfig, EmailGuardContract, EmailValidationResult, - SuppressionListFilters, SuppressionReason, SuppressionRow, SuppressionSource, @@ -65,16 +64,6 @@ export class EmailGuard implements EmailGuardContract { return this.suppression.unsuppress(email); } - public list(filters?: SuppressionListFilters): Promise { - return this.suppression.list(filters); - } - - public count( - filters?: Omit - ): Promise { - return this.suppression.count(filters); - } - public ensureTable(): Promise { return this.suppression.ensureTable(); } diff --git a/src/Suppression/index.ts b/src/Suppression/index.ts index 7537d9b..4777d79 100644 --- a/src/Suppression/index.ts +++ b/src/Suppression/index.ts @@ -1,6 +1,5 @@ import type {DatabaseContract, QueryClientContract} from '@ioc:Adonis/Lucid/Database'; import type { - SuppressionListFilters, SuppressionReason, SuppressionRow, SuppressionSource, @@ -104,29 +103,6 @@ export class SuppressionService { return Number(count) > 0; } - public async list(filters: SuppressionListFilters = {}): Promise { - const q = this.client().from(this.tableName).select('*'); - if (filters.reason) q.where('reason', filters.reason); - if (filters.source) q.where('source', filters.source); - if (filters.search) q.where('email', 'like', `%${filters.search.toLowerCase()}%`); - if (filters.limit) q.limit(filters.limit); - if (filters.offset) q.offset(filters.offset); - q.orderBy('id', 'desc'); - const rows = await q; - return rows.map((r: any) => this.hydrate(r)); - } - - public async count( - filters: Omit = {} - ): Promise { - const q = this.client().from(this.tableName); - if (filters.reason) q.where('reason', filters.reason); - if (filters.source) q.where('source', filters.source); - if (filters.search) q.where('email', 'like', `%${filters.search.toLowerCase()}%`); - const row = (await q.count('* as total').first()) as {total: number | string} | undefined; - return row ? Number(row.total) : 0; - } - private hydrate(row: any): SuppressionRow { let metadata: Record | null = null; if (row.metadata !== null && row.metadata !== undefined) { diff --git a/test/suppression.spec.ts b/test/suppression.spec.ts index 36bdd31..2defa63 100644 --- a/test/suppression.spec.ts +++ b/test/suppression.spec.ts @@ -51,8 +51,8 @@ describe('SuppressionService', () => { assert.equal(updated.source, 'manual'); assert.deepEqual(updated.metadata, {note: 'updated'}); - const all = await service.list(); - assert.equal(all.length, 1); + const rows = await k(TABLE).select('id'); + assert.equal(rows.length, 1); }); it('handles null metadata', async () => { @@ -82,49 +82,4 @@ describe('SuppressionService', () => { assert.equal(await service.isSuppressed('gone@x.com'), false); }); }); - - describe('list / count', () => { - beforeEach(async () => { - await service.suppress('one@x.com', 'bounce', 'webhook'); - await service.suppress('two@x.com', 'bounce', 'manual'); - await service.suppress('three@x.com', 'complaint', 'webhook'); - await service.suppress('four@x.com', 'manual', 'manual'); - }); - - it('filters by reason', async () => { - const rows = await service.list({reason: 'bounce'}); - assert.equal(rows.length, 2); - assert.equal(await service.count({reason: 'bounce'}), 2); - }); - - it('filters by source', async () => { - const rows = await service.list({source: 'webhook'}); - assert.equal(rows.length, 2); - assert.equal(await service.count({source: 'webhook'}), 2); - }); - - it('filters by search (LIKE on email)', async () => { - const rows = await service.list({search: 'three'}); - assert.equal(rows.length, 1); - assert.equal(rows[0].email, 'three@x.com'); - }); - - it('paginates', async () => { - const page1 = await service.list({limit: 2, offset: 0}); - const page2 = await service.list({limit: 2, offset: 2}); - assert.equal(page1.length, 2); - assert.equal(page2.length, 2); - assert.notEqual(page1[0].email, page2[0].email); - }); - - it('orders newest first', async () => { - const all = await service.list(); - assert.equal(all[0].email, 'four@x.com'); - assert.equal(all[all.length - 1].email, 'one@x.com'); - }); - - it('counts all when no filter', async () => { - assert.equal(await service.count(), 4); - }); - }); }); From a95a63bc1e677a3ca31b841b815c7cc4f16036b3 Mon Sep 17 00:00:00 2001 From: shakilhossain-cse Date: Mon, 29 Jun 2026 16:30:27 +0600 Subject: [PATCH 2/2] feat: implement email validation and suppression service - Add EmailGuard class for managing email validation and suppression. - Introduce SuppressionService for handling suppressed email addresses in a database. - Create EmailValidator for validating email syntax, disposable domains, and spam traps. - Define configuration structure for EmailGuard with support for custom disposable and spam trap domains. - Implement disposable and spam trap domain lists. - Add tests for EmailGuard, SuppressionService, and EmailValidator functionalities. - Update TypeScript configuration for ES2022 and NodeNext module resolution. --- README.md | 58 +- adonis-typings/email-guard.ts | 88 - adonis-typings/index.ts | 3 - configure.ts | 13 + index.ts | 15 + instructions.md | 36 - instructions.ts | 20 - package-lock.json | 3810 ++++++++++------- package.json | 70 +- providers/EmailGuardProvider.ts | 35 - providers/email_guard_provider.ts | 40 + services/main.ts | 10 + src/Validator/index.ts | 228 - src/define_config.ts | 5 + ...sable-domains.ts => disposable_domains.ts} | 0 src/{EmailGuard.ts => email_guard.ts} | 73 +- src/{Suppression/index.ts => suppression.ts} | 107 +- src/types.ts | 76 + src/validator.ts | 224 + .../config/email_guard.stub | 11 +- stubs/main.ts | 3 + test/email-guard.spec.ts | 81 - test/helpers.ts | 26 - test/suppression.spec.ts | 85 - tests/email_guard.spec.ts | 81 + tests/helpers.ts | 27 + tests/suppression.spec.ts | 87 + {test => tests}/validator.spec.ts | 139 +- tsconfig.json | 25 +- 29 files changed, 3088 insertions(+), 2388 deletions(-) delete mode 100644 adonis-typings/email-guard.ts delete mode 100644 adonis-typings/index.ts create mode 100644 configure.ts create mode 100644 index.ts delete mode 100644 instructions.md delete mode 100644 instructions.ts delete mode 100644 providers/EmailGuardProvider.ts create mode 100644 providers/email_guard_provider.ts create mode 100644 services/main.ts delete mode 100644 src/Validator/index.ts create mode 100644 src/define_config.ts rename src/{Validator/disposable-domains.ts => disposable_domains.ts} (100%) rename src/{EmailGuard.ts => email_guard.ts} (56%) rename src/{Suppression/index.ts => suppression.ts} (54%) create mode 100644 src/types.ts create mode 100644 src/validator.ts rename templates/config.txt => stubs/config/email_guard.stub (87%) create mode 100644 stubs/main.ts delete mode 100644 test/email-guard.spec.ts delete mode 100644 test/helpers.ts delete mode 100644 test/suppression.spec.ts create mode 100644 tests/email_guard.spec.ts create mode 100644 tests/helpers.ts create mode 100644 tests/suppression.spec.ts rename {test => tests}/validator.spec.ts (59%) diff --git a/README.md b/README.md index f067fe0..26ad77f 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,42 @@ # adonis-email-guard -AdonisJS v5 package for email validation and a DB-backed suppression list. +AdonisJS v7 package for email validation and a DB-backed suppression list. - Syntax / MX / disposable / spam-trap / optional SMTP RCPT-TO checks - Suppression CRUD with configurable table name - Suppression table auto-created on boot (opt-out via config) -- Single IoC binding: `@ioc:Adonis/Addons/EmailGuard` +- Container binding: `emailGuard` + +## Requirements + +- AdonisJS `^7.0.0` +- `@adonisjs/lucid` `^22.0.0` +- Node.js `>=20.6.0` ## Install +```bash +node ace add @ezycourse/adonis-email-guard +``` + +This installs the package, copies `config/email_guard.ts` into your app, and +registers the provider in `adonisrc.ts`. + +To do it manually: + ```bash npm i @ezycourse/adonis-email-guard node ace configure @ezycourse/adonis-email-guard ``` -The configure step copies `config/email-guard.ts` into your app and registers the provider. - ## Configuration -`config/email-guard.ts`: +`config/email_guard.ts`: ```ts -import {EmailGuardConfig} from '@ioc:Adonis/Addons/EmailGuard'; +import { defineConfig } from '@ezycourse/adonis-email-guard' -const emailGuardConfig: EmailGuardConfig = { +export default defineConfig({ tableName: 'email_suppressions', autoCreateTable: true, // connection: 'primary', @@ -33,29 +46,35 @@ const emailGuardConfig: EmailGuardConfig = { }, extraDisposableDomains: [], extraSpamTrapDomains: [], -}; - -export default emailGuardConfig; +}) ``` ## Usage ```ts -import EmailGuard from '@ioc:Adonis/Addons/EmailGuard'; +import emailGuard from '@ezycourse/adonis-email-guard/services/main' // validate only -const v = await EmailGuard.validate('user@gmial.com'); +const v = await emailGuard.validate('user@gmial.com') // v.valid → false, v.suggestion → 'user@gmail.com' // validate + suppression lookup in one call -const c = await EmailGuard.check('user@example.com', {recordFailures: true}); -if (!c.valid || c.suppressed) return; // do not send +const c = await emailGuard.check('user@example.com', { recordFailures: true }) +if (!c.valid || c.suppressed) return // do not send // suppression CRUD -await EmailGuard.suppress('bounce@x.com', 'bounce', 'webhook', {provider: 'postmark'}); -await EmailGuard.isSuppressed('bounce@x.com'); // true -await EmailGuard.find('bounce@x.com'); -await EmailGuard.unsuppress('bounce@x.com'); +await emailGuard.suppress('bounce@x.com', 'bounce', 'webhook', { provider: 'postmark' }) +await emailGuard.isSuppressed('bounce@x.com') // true +await emailGuard.find('bounce@x.com') +await emailGuard.unsuppress('bounce@x.com') +``` + +You can also resolve it from the container: + +```ts +import app from '@adonisjs/core/services/app' + +const guard = await app.container.make('emailGuard') ``` ## API @@ -72,7 +91,8 @@ Returns `{ valid, email, reason?, checks, suggestion?, mxHost? }`. ### `check(email, options?)` -`validate` + suppression lookup. With `recordFailures: true`, failures are inserted into the suppression list with `source: 'validator'`. +`validate` + suppression lookup. With `recordFailures: true`, failures are +inserted into the suppression list with `source: 'validator'`. ### Suppression diff --git a/adonis-typings/email-guard.ts b/adonis-typings/email-guard.ts deleted file mode 100644 index 70ddc4e..0000000 --- a/adonis-typings/email-guard.ts +++ /dev/null @@ -1,88 +0,0 @@ -declare module '@ioc:Adonis/Addons/EmailGuard' { - export type SuppressionReason = - | 'bounce' - | 'complaint' - | 'manual' - | 'invalid-syntax' - | 'no-mx' - | 'smtp-failed' - | 'disposable' - | 'spam-trap' - | 'unsubscribe' - | (string & {}); - - export type SuppressionSource = 'manual' | 'validator' | 'webhook' | (string & {}); - - export type ValidateEmailOptions = { - /** Run SMTP RCPT-TO probe against MX. Many networks block outbound port 25. */ - checkSmtp?: boolean; - fromAddress?: string; - smtpTimeoutMs?: number; - /** Skip the suppression-list lookup during `check`. */ - skipSuppressionCheck?: boolean; - }; - - export type EmailValidationResult = { - valid: boolean; - email: string; - reason?: string; - checks: { - syntax: boolean; - mx: boolean; - smtp: boolean | null; - disposable: boolean; - spamTrap: boolean; - }; - suggestion?: string; - mxHost?: string; - }; - - export type SuppressionRow = { - id: number; - email: string; - reason: SuppressionReason | null; - source: SuppressionSource | null; - metadata: Record | null; - created_at: Date; - updated_at: Date; - }; - - export type EmailGuardConfig = { - tableName?: string; - /** Run `CREATE TABLE IF NOT EXISTS` for the suppression table on app boot. Default true. */ - autoCreateTable?: boolean; - /** Named Lucid connection. Defaults to the default Database connection. */ - connection?: string; - validator?: { - checkSmtp?: boolean; - fromAddress?: string; - smtpTimeoutMs?: number; - }; - /** Extra disposable / spam-trap domains to merge with the built-in lists. */ - extraDisposableDomains?: string[]; - extraSpamTrapDomains?: string[]; - }; - - export interface EmailGuardContract { - validate(email: string, options?: ValidateEmailOptions): Promise; - isSuppressed(email: string): Promise; - suppress( - email: string, - reason?: SuppressionReason, - source?: SuppressionSource, - metadata?: Record - ): Promise; - unsuppress(email: string): Promise; - find(email: string): Promise; - /** Validates and, on failure, optionally records a suppression. Combines validate + isSuppressed. */ - check( - email: string, - options?: ValidateEmailOptions & {recordFailures?: boolean} - ): Promise; - /** Ensure the suppression table exists (idempotent). Called automatically on boot when autoCreateTable=true. */ - ensureTable(): Promise; - } - - const EmailGuard: EmailGuardContract; - export default EmailGuard; -} diff --git a/adonis-typings/index.ts b/adonis-typings/index.ts deleted file mode 100644 index 1f4df6e..0000000 --- a/adonis-typings/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -/// -/// -/// diff --git a/configure.ts b/configure.ts new file mode 100644 index 0000000..7fadaeb --- /dev/null +++ b/configure.ts @@ -0,0 +1,13 @@ +import type Configure from '@adonisjs/core/commands/configure' + +import { stubsRoot } from './stubs/main.js' + +export async function configure(command: Configure): Promise { + const codemods = await command.createCodemods() + + await codemods.makeUsingStub(stubsRoot, 'config/email_guard.stub', {}) + + await codemods.updateRcFile((rcFile) => { + rcFile.addProvider('@ezycourse/adonis-email-guard/email_guard_provider') + }) +} diff --git a/index.ts b/index.ts new file mode 100644 index 0000000..089aba1 --- /dev/null +++ b/index.ts @@ -0,0 +1,15 @@ +export { configure } from './configure.js' +export { stubsRoot } from './stubs/main.js' +export { defineConfig } from './src/define_config.js' +export { EmailGuard } from './src/email_guard.js' +export { EmailValidator } from './src/validator.js' +export { SuppressionService } from './src/suppression.js' +export type { + EmailGuardConfig, + EmailGuardService, + EmailValidationResult, + SuppressionReason, + SuppressionRow, + SuppressionSource, + ValidateEmailOptions, +} from './src/types.js' diff --git a/instructions.md b/instructions.md deleted file mode 100644 index 96db55c..0000000 --- a/instructions.md +++ /dev/null @@ -1,36 +0,0 @@ -# adonis-email-guard - -Setup steps after install: - -1. **Run the configure command** (already done if you used `node ace configure @ezycourse/adonis-email-guard`). This copies `config/email-guard.ts` into your app. - -2. **Verify the provider was registered** in `.adonisrc.json`: - - ```json - { - "providers": ["./providers/AppProvider", "@ezycourse/adonis-email-guard"] - } - ``` - -3. **Verify types** in `tsconfig.json`: - - ```json - { - "compilerOptions": { - "types": ["@adonisjs/core", "@adonisjs/lucid", "@ezycourse/adonis-email-guard"] - } - } - ``` - -4. **Boot your app**. The suppression table is created automatically (default `email_suppressions`). To opt out, set `autoCreateTable: false` in `config/email-guard.ts` and create the table yourself. - -5. **Use it:** - - ```ts - import EmailGuard from '@ioc:Adonis/Addons/EmailGuard'; - - const result = await EmailGuard.check('user@example.com', {recordFailures: true}); - if (!result.valid || result.suppressed) { - // do not send - } - ``` diff --git a/instructions.ts b/instructions.ts deleted file mode 100644 index 9539e75..0000000 --- a/instructions.ts +++ /dev/null @@ -1,20 +0,0 @@ -import {join} from 'path'; -import type {ApplicationContract} from '@ioc:Adonis/Core/Application'; - -type Sink = { - installCommand: (cmd: {command: string}) => void; - publishStub: (src: string, dest: string) => Promise | void; - yellow: (s: string) => string; - green: (s: string) => string; -}; - -export default async function instructions( - projectRoot: string, - app: ApplicationContract, - sink: Sink -): Promise { - const configStub = join(__dirname, 'templates', 'config.txt'); - await sink.publishStub(configStub, join(projectRoot, 'config', 'email-guard.ts')); - // eslint-disable-next-line no-console - console.log(sink.green(' ✔ config/email-guard.ts created')); -} diff --git a/package-lock.json b/package-lock.json index 5c504d1..57456b4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,521 +1,718 @@ { - "name": "adonis-email-guard", - "version": "0.1.0", + "name": "@ezycourse/adonis-email-guard", + "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "adonis-email-guard", - "version": "0.1.0", + "name": "@ezycourse/adonis-email-guard", + "version": "1.0.0", "license": "MIT", "devDependencies": { - "@adonisjs/core": "^5.9.0", - "@adonisjs/lucid": "^18.4.0", + "@adonisjs/assembler": "^8.4.0", + "@adonisjs/core": "^7.3.4", + "@adonisjs/lucid": "^22.4.2", "@types/better-sqlite3": "^7.6.0", - "@types/node": "^20.0.0", - "better-sqlite3": "^11.0.0", + "@types/node": "^22.0.0", + "better-sqlite3": "^12.0.0", "knex": "^3.0.0", + "luxon": "^3.4.4", + "reflect-metadata": "^0.2.2", "tsx": "^4.7.0", - "typescript": "^5.0.0" + "typescript": "^5.4.0" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.6.0" }, "peerDependencies": { - "@adonisjs/core": "^5.0.0", - "@adonisjs/lucid": "^18.0.0" + "@adonisjs/core": "^7.0.0", + "@adonisjs/lucid": "^22.0.0" } }, "node_modules/@adonisjs/ace": { - "version": "11.3.1", - "resolved": "https://registry.npmjs.org/@adonisjs/ace/-/ace-11.3.1.tgz", - "integrity": "sha512-Ho3+Lk/16OSjX3CfhxsoLUTlcVG4sDlXUwHx+Zry/RLft5M6plT5ln0WkZvL7tqtb1uCZgP5YiMrMtDjSRzZLA==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@adonisjs/ace/-/ace-14.1.0.tgz", + "integrity": "sha512-8N8z1YKePBiXz7wLxHFz/HSqjCRSL/9Vzs4XQt8gk8G17u4PXwNncWt0vSgYEcDrvPAt+QOavY1vMeKOOWe29w==", "dev": true, "license": "MIT", "dependencies": { - "@poppinss/cliui": "^3.0.2", - "@poppinss/prompts": "^2.0.2", - "@poppinss/utils": "^4.0.4", - "fs-extra": "^10.1.0", - "getopts": "^2.3.0", - "leven": "^3.1.0", - "mustache": "^4.2.0", - "slash": "^3.0.0", - "term-size": "^2.2.1" + "@poppinss/cliui": "^6.8.0", + "@poppinss/hooks": "^7.3.0", + "@poppinss/macroable": "^1.1.2", + "@poppinss/prompts": "^3.1.6", + "@poppinss/utils": "^7.0.1", + "fastest-levenshtein": "^1.0.16", + "jsonschema": "^1.5.0", + "string-width": "^8.2.0", + "yargs-parser": "^22.0.0" + }, + "engines": { + "node": ">=24.0.0" }, "peerDependencies": { - "@adonisjs/application": "^5.0.0" + "youch": "^4.1.0-beta.11 || ^4.1.0" } }, - "node_modules/@adonisjs/ace/node_modules/@poppinss/utils": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-4.0.4.tgz", - "integrity": "sha512-6LS3mofSVB9IQZqofA4rX6KVVcCpdwUQuNe4efHqOTzgD/Q5HTVvDP0vKg1m994QlzJs4aLW1JwXVcNCThEh4g==", + "node_modules/@adonisjs/application": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@adonisjs/application/-/application-9.0.1.tgz", + "integrity": "sha512-bSUC8vcECEr9qvvHeMAhjvH73ngAm5c6kOnEJYNCczP6rgG7AdH03MGtrY2ewKYDyS/QepNpDKj4oVE2XtxVtw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@poppinss/file-generator": "^1.0.2", - "@types/bytes": "^3.1.1", - "@types/he": "^1.1.2", - "bytes": "^3.1.2", - "change-case": "^4.1.2", - "cuid": "^2.1.8", - "flattie": "^1.1.0", - "fs-readdir-recursive": "^1.1.0", - "he": "^1.2.0", - "kind-of": "^6.0.3", - "lodash": "^4.17.21", - "ms": "^2.1.3", - "pluralize": "^8.0.0", - "require-all": "^3.0.0", - "resolve-from": "^5.0.0", - "slugify": "^1.6.5", - "truncatise": "0.0.8" + "@poppinss/hooks": "^7.3.0", + "@poppinss/macroable": "^1.1.2", + "@poppinss/utils": "^7.0.1", + "glob-parent": "^6.0.2", + "tempura": "^0.4.1" + }, + "engines": { + "node": ">=24.0.0" + }, + "peerDependencies": { + "@adonisjs/assembler": "^8.0.0-next.23 || ^8.0.0", + "@adonisjs/config": "^6.1.0-next.0 || ^6.0.0", + "@adonisjs/fold": "^11.0.0-next.3 || ^11.0.0" + }, + "peerDependenciesMeta": { + "@adonisjs/assembler": { + "optional": true + } } }, - "node_modules/@adonisjs/application": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@adonisjs/application/-/application-5.3.0.tgz", - "integrity": "sha512-AruZZXMgOdmmRxJEHUbXoqhgRavPfhkeIR2nQtGyxbn0PCNjqlGraq8ypuLINY1J+wNuH2tt0xCS98EDeMdTOQ==", + "node_modules/@adonisjs/assembler": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@adonisjs/assembler/-/assembler-8.4.0.tgz", + "integrity": "sha512-Nxi6UU2fd/Wq8iLb+FwicK+7ePyvZcmtbJaT25RhGbgSZ2tgbxzaI7YF4TbaLKDIsF48DOcTP0dTfUIcgjBchw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@adonisjs/config": "^3.0.9", - "@adonisjs/env": "^3.0.9", - "@adonisjs/fold": "^8.2.0", - "@adonisjs/logger": "^4.1.5", - "@adonisjs/profiler": "^6.0.9", - "@poppinss/utils": "^5.0.0", - "semver": "^7.3.8" + "@adonisjs/env": "^7.0.0", + "@antfu/install-pkg": "^1.1.0", + "@ast-grep/napi": "^0.42.0", + "@poppinss/cliui": "^6.8.1", + "@poppinss/hooks": "^7.3.0", + "@poppinss/utils": "^7.0.1", + "chokidar": "^5.0.0", + "dedent": "^1.7.2", + "execa": "^9.6.1", + "fast-glob": "^3.3.3", + "fdir": "^6.5.0", + "get-port": "^7.2.0", + "get-tsconfig": "^4.13.7", + "import-meta-resolve": "^4.2.0", + "junk": "^4.0.1", + "open": "^11.0.0", + "parse-imports": "^3.0.0", + "picomatch": "^4.0.4", + "pretty-hrtime": "^1.0.3", + "tmp-cache": "^1.1.0", + "ts-morph": "^27.0.2" + }, + "engines": { + "node": ">=24.0.0" + }, + "peerDependencies": { + "typescript": "^5.0.0 || ^6.0.0" } }, "node_modules/@adonisjs/bodyparser": { - "version": "8.1.9", - "resolved": "https://registry.npmjs.org/@adonisjs/bodyparser/-/bodyparser-8.1.9.tgz", - "integrity": "sha512-enVETPmoBJhg+CP6AVlG/GSwllpW/5y22wjFpEhYZl0YOXnE7i+wsp2VeGfMtQzl4+snTuAPEfwCtG+I/s6jqQ==", + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@adonisjs/bodyparser/-/bodyparser-11.0.4.tgz", + "integrity": "sha512-amqMPVFbzxkOoCMbkFs5sC+rTu7cER2rSv+1v8dsGKszolk5lnGuyNjkha1Lqksvw1qykIIbC1fXr37B9WJTdg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@poppinss/co-body": "^1.1.3", - "@poppinss/multiparty": "^2.0.1", - "@poppinss/utils": "^5.0.0", - "bytes": "^3.1.2", - "file-type": "^16.5.4", - "fs-extra": "^10.1.0", + "@poppinss/macroable": "^1.1.2", + "@poppinss/middleware": "^3.2.7", + "@poppinss/multiparty": "^3.0.0", + "@poppinss/qs": "^6.15.0", + "@poppinss/utils": "^7.0.1", + "file-type": "^22.0.1", + "inflation": "^2.1.0", "media-typer": "^1.1.0", - "slash": "^3.0.0" + "raw-body": "^3.0.2" + }, + "engines": { + "node": ">=24.0.0" }, "peerDependencies": { - "@adonisjs/application": "^5.0.0", - "@adonisjs/drive": "^2.0.0", - "@adonisjs/http-server": "^5.0.0" + "@adonisjs/http-server": "^8.0.0-next.17 || ^8.0.0 || ^9.0.0" } }, "node_modules/@adonisjs/config": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@adonisjs/config/-/config-3.0.9.tgz", - "integrity": "sha512-f+wzrc+0HLvhJyYGEMV2QTHtyJ8sI3PKvH9h/baW/iF8UO3KF+llHH0Cf3/M5dYnpdz9rnmj0VtdTaIDfxrgGg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@adonisjs/config/-/config-6.1.0.tgz", + "integrity": "sha512-YVDRL8xHCtM6iMnAefOBaz6iXVpojwBPDQWPKxnVSucycYeNGrGitJiLy+cGaeAU7Gjm8al9SJRJt3rRPr5PKg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@poppinss/utils": "^5.0.0" + "@poppinss/utils": "^7.0.0" + }, + "engines": { + "node": ">=24.0.0" } }, "node_modules/@adonisjs/core": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@adonisjs/core/-/core-5.9.0.tgz", - "integrity": "sha512-32zG9EW0t0Ck0cMzlwD0+z3GJG7k/gZz6P0+h+s8N1N7fHxGixrKs7W7lT3OcIvk0NsuIw1tUPAU7fAWytHEqA==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@adonisjs/core/-/core-7.3.4.tgz", + "integrity": "sha512-m9X7UqF+cZbwVGUoFBadsRD4aF+zkQ056MCcitaekF4AUkWT9URUt8MoxtGNwD/vAgX96R95aDZuqCcyXsMgqA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@adonisjs/ace": "^11.3.1", - "@adonisjs/application": "^5.3.0", - "@adonisjs/bodyparser": "^8.1.7", - "@adonisjs/drive": "^2.3.0", - "@adonisjs/encryption": "^4.0.8", - "@adonisjs/events": "^7.2.1", - "@adonisjs/hash": "^7.2.2", - "@adonisjs/http-server": "^5.12.0", - "@adonisjs/validator": "^12.4.1", - "@poppinss/cliui": "^3.0.5", - "@poppinss/manager": "^5.0.2", - "@poppinss/utils": "^5.0.0", - "fs-extra": "^10.1.0", - "macroable": "^7.0.2", - "memfs": "^3.4.12", - "serve-static": "^1.15.0", - "stringify-attributes": "^2.0.0" - } - }, - "node_modules/@adonisjs/drive": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@adonisjs/drive/-/drive-2.3.0.tgz", - "integrity": "sha512-3V1kBe2qB/860KcS+dDonv8Xya2YDBdR7291pQgObJeTbV50Vy8RhwdOwtU7ybRfN2kh/svdC4238JGpbQOR9w==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@poppinss/manager": "^5.0.2", - "@poppinss/utils": "^5.0.0", - "@types/fs-extra": "^9.0.13", - "etag": "^1.8.1", - "fs-extra": "^10.1.0", - "memfs": "^3.4.7" + "@adonisjs/ace": "^14.1.0", + "@adonisjs/application": "^9.0.1", + "@adonisjs/bodyparser": "^11.0.4", + "@adonisjs/config": "^6.1.0", + "@adonisjs/env": "^7.0.0", + "@adonisjs/events": "^10.2.0", + "@adonisjs/fold": "^11.0.0", + "@adonisjs/hash": "^10.1.0", + "@adonisjs/health": "^3.1.0", + "@adonisjs/http-server": "^9.0.2", + "@adonisjs/http-transformers": "^2.3.1", + "@adonisjs/logger": "^7.1.1", + "@adonisjs/repl": "^5.0.0", + "@boringnode/encryption": "^1.0.0", + "@poppinss/colors": "^4.1.6", + "@poppinss/dumper": "^0.7.0", + "@poppinss/macroable": "^1.1.2", + "@poppinss/utils": "^7.0.1", + "@sindresorhus/is": "^8.1.0", + "@types/he": "^1.2.3", + "error-stack-parser-es": "^1.0.5", + "he": "^1.2.0", + "pretty-hrtime": "^1.0.3", + "string-width": "^8.2.1" }, - "peerDependencies": { - "@adonisjs/application": "^5.0.0", - "@adonisjs/http-server": "^5.0.0" - } - }, - "node_modules/@adonisjs/encryption": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@adonisjs/encryption/-/encryption-4.0.8.tgz", - "integrity": "sha512-zMWbIESPHXafsbiLJyON/hlRYwrTIA3PuTil7xC8W4ngC36PgWe86Ra0x0t961u1We/LaSGkT8Vn93DymqB3aA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@poppinss/utils": "^4.0.3" + "bin": { + "adonis-kit": "build/toolkit/main.js" + }, + "engines": { + "node": ">=24.0.0" }, "peerDependencies": { - "@adonisjs/application": "^5.0.0" - } - }, - "node_modules/@adonisjs/encryption/node_modules/@poppinss/utils": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-4.0.4.tgz", - "integrity": "sha512-6LS3mofSVB9IQZqofA4rX6KVVcCpdwUQuNe4efHqOTzgD/Q5HTVvDP0vKg1m994QlzJs4aLW1JwXVcNCThEh4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@poppinss/file-generator": "^1.0.2", - "@types/bytes": "^3.1.1", - "@types/he": "^1.1.2", - "bytes": "^3.1.2", - "change-case": "^4.1.2", - "cuid": "^2.1.8", - "flattie": "^1.1.0", - "fs-readdir-recursive": "^1.1.0", - "he": "^1.2.0", - "kind-of": "^6.0.3", - "lodash": "^4.17.21", - "ms": "^2.1.3", - "pluralize": "^8.0.0", - "require-all": "^3.0.0", - "resolve-from": "^5.0.0", - "slugify": "^1.6.5", - "truncatise": "0.0.8" + "@adonisjs/assembler": "^8.0.0-next.23 || ^8.0.0", + "@vinejs/vine": "^4.0.0", + "argon2": "^0.44.0", + "bcrypt": "^6.0.0", + "edge.js": "^6.2.0", + "pino-pretty": "^13.1.3", + "youch": "^4.1.0-beta.13 || ^4.1.0" + }, + "peerDependenciesMeta": { + "@adonisjs/assembler": { + "optional": true + }, + "@vinejs/vine": { + "optional": true + }, + "argon2": { + "optional": true + }, + "bcrypt": { + "optional": true + }, + "edge.js": { + "optional": true + }, + "pino-pretty": { + "optional": true + }, + "youch": { + "optional": true + } } }, "node_modules/@adonisjs/env": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@adonisjs/env/-/env-3.0.9.tgz", - "integrity": "sha512-9lxGmOQuF4FpUQ6NIwL/YQumaXG+2Wt8jQlQptplSUTasy6DHSEp7/SYvtC2RD9vxwn4gsptNCo+f8YRiqUvwQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@adonisjs/env/-/env-7.0.0.tgz", + "integrity": "sha512-9lSGONI4B1E7LxyVZiUd1yCH9BOri4Ybp4b9x3ojT9AkKfYwqvj4S2USIvFAlkE7eHUC2WMvPgMLX17342Y3ww==", "dev": true, "license": "MIT", "dependencies": { - "@poppinss/utils": "^4.0.2", - "dotenv": "^16.0.0", - "validator": "^13.7.0" + "@poppinss/utils": "^7.0.0", + "@poppinss/validator-lite": "^2.1.2", + "split-lines": "^3.0.0" + }, + "engines": { + "node": ">=24.0.0" } }, - "node_modules/@adonisjs/env/node_modules/@poppinss/utils": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-4.0.4.tgz", - "integrity": "sha512-6LS3mofSVB9IQZqofA4rX6KVVcCpdwUQuNe4efHqOTzgD/Q5HTVvDP0vKg1m994QlzJs4aLW1JwXVcNCThEh4g==", + "node_modules/@adonisjs/events": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@adonisjs/events/-/events-10.2.0.tgz", + "integrity": "sha512-SzwzbmTLsybSZd47zZMZ3df7puwhY7D8vZ5Uy79SiHjLKbr2eVzUuKjjoYB6/0pZu6IwK9Qx06dI43sl+tLoDw==", "dev": true, "license": "MIT", "dependencies": { - "@poppinss/file-generator": "^1.0.2", - "@types/bytes": "^3.1.1", - "@types/he": "^1.1.2", - "bytes": "^3.1.2", - "change-case": "^4.1.2", - "cuid": "^2.1.8", - "flattie": "^1.1.0", - "fs-readdir-recursive": "^1.1.0", - "he": "^1.2.0", - "kind-of": "^6.0.3", - "lodash": "^4.17.21", - "ms": "^2.1.3", - "pluralize": "^8.0.0", - "require-all": "^3.0.0", - "resolve-from": "^5.0.0", - "slugify": "^1.6.5", - "truncatise": "0.0.8" + "@poppinss/utils": "^7.0.0", + "@sindresorhus/is": "^7.2.0", + "emittery": "^1.2.0" + }, + "engines": { + "node": ">=24.0.0" + }, + "peerDependencies": { + "@adonisjs/application": "^9.0.0-next.14 || ^9.0.0", + "@adonisjs/fold": "^11.0.0-next.4 || ^11.0.0" } }, - "node_modules/@adonisjs/events": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/@adonisjs/events/-/events-7.2.1.tgz", - "integrity": "sha512-N+ewQ19pvdWVIRGBeio1GqlMRJpHpZ+ZHCjhObI+bqoCh5nBApumW0JYe4blyMnUbUAtA9Aq1m1QbGaE7pRMcw==", + "node_modules/@adonisjs/events/node_modules/@sindresorhus/is": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.2.0.tgz", + "integrity": "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==", "dev": true, "license": "MIT", - "dependencies": { - "emittery": "^0.10.0" + "engines": { + "node": ">=18" }, - "peerDependencies": { - "@adonisjs/application": "^5.0.0" + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" } }, "node_modules/@adonisjs/fold": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@adonisjs/fold/-/fold-8.2.0.tgz", - "integrity": "sha512-Uoo2HPp4SShIkGOF3+p3gT09W3j0zpkK+fOpPyYPTqYm7CWAunklTlowqX45b6CAVb5DCcORDUB8ia4D1ijeKg==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@adonisjs/fold/-/fold-11.0.0.tgz", + "integrity": "sha512-RnmDPWz2imVp/B74xitxCPqTdoP07bZvfJe1bh9CD9Rmia4jjDvehZF67KFyGNMZ24MuKasqs3jOcM1vGJp0GA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@poppinss/utils": "^4.0.4" + "@poppinss/utils": "^7.0.0", + "parse-imports": "^3.0.0" + }, + "engines": { + "node": ">=24.0.0" } }, - "node_modules/@adonisjs/fold/node_modules/@poppinss/utils": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-4.0.4.tgz", - "integrity": "sha512-6LS3mofSVB9IQZqofA4rX6KVVcCpdwUQuNe4efHqOTzgD/Q5HTVvDP0vKg1m994QlzJs4aLW1JwXVcNCThEh4g==", + "node_modules/@adonisjs/hash": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@adonisjs/hash/-/hash-10.1.0.tgz", + "integrity": "sha512-lW0lGwpscu9PUo3Sb3PF580jYU29I9wsPn3dIKzZbTVedqkpaNpBK3YKedwZYkDpYmiyYXi08eTTNhdWjiGLQw==", "dev": true, "license": "MIT", "dependencies": { - "@poppinss/file-generator": "^1.0.2", - "@types/bytes": "^3.1.1", - "@types/he": "^1.1.2", - "bytes": "^3.1.2", - "change-case": "^4.1.2", - "cuid": "^2.1.8", - "flattie": "^1.1.0", - "fs-readdir-recursive": "^1.1.0", - "he": "^1.2.0", - "kind-of": "^6.0.3", - "lodash": "^4.17.21", - "ms": "^2.1.3", - "pluralize": "^8.0.0", - "require-all": "^3.0.0", - "resolve-from": "^5.0.0", - "slugify": "^1.6.5", - "truncatise": "0.0.8" + "@phc/format": "^1.0.0", + "@poppinss/utils": "^7.0.0" + }, + "engines": { + "node": ">=20.6.0" + }, + "peerDependencies": { + "argon2": "^0.31.2 || ^0.41.0 || ^0.43.0 || ^0.44.0", + "bcrypt": "^5.1.1 || ^6.0.0" + }, + "peerDependenciesMeta": { + "argon2": { + "optional": true + }, + "bcrypt": { + "optional": true + } } }, - "node_modules/@adonisjs/hash": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@adonisjs/hash/-/hash-7.2.2.tgz", - "integrity": "sha512-qJxFX8jNH+5+jxckIIvz2y9pMt59ueT50a4B5kUe/68g5iC7UdwKmMos+tj5Pnm5hRFfwKXbtIQBGd+Bb87+2Q==", + "node_modules/@adonisjs/health": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@adonisjs/health/-/health-3.1.0.tgz", + "integrity": "sha512-m3doBnSwi/l9v1DO79xmjAoSPl9b2XCp+crGwF8QUlhe5CgWgtfnL0SeFNEiZGliD3c4gYdihKz4Pnydctva8A==", "dev": true, "license": "MIT", "dependencies": { - "@phc/format": "^1.0.0", - "@poppinss/manager": "^5.0.2", - "@poppinss/utils": "^5.0.0" + "@poppinss/utils": "^7.0.0", + "check-disk-space": "^3.4.0" }, - "peerDependencies": { - "@adonisjs/application": "^5.0.0" + "engines": { + "node": ">=24.0.0" } }, "node_modules/@adonisjs/http-server": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/@adonisjs/http-server/-/http-server-5.12.0.tgz", - "integrity": "sha512-+9cw/DRlLO2NSoHsccmMe3pFf6c0/8INds2yf73ZAZOmzUROb9DQaXHocJ/iwHX9EVxtDuKWDc5z0jI1SYdqEA==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@adonisjs/http-server/-/http-server-9.1.0.tgz", + "integrity": "sha512-p5Cs1fcMCZMj0Q4fMAixCgEgegaaMi2fXyhmbPZTNAK6yPhrPqXNpEdOMfnjNJf65LQyXErbjsrcPDjTKrrhCg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@poppinss/matchit": "^3.1.2", - "@poppinss/utils": "^5.0.0", - "accepts": "^1.3.8", - "co-compose": "^7.0.2", - "content-disposition": "^0.5.4", - "cookie": "^0.5.0", + "@poppinss/macroable": "^1.1.2", + "@poppinss/matchit": "^3.2.0", + "@poppinss/middleware": "^3.2.7", + "@poppinss/qs": "^6.15.0", + "@poppinss/utils": "^7.0.1", + "@sindresorhus/is": "^8.1.0", + "content-disposition": "^1.1.0", + "cookie-es": "^3.1.1", "destroy": "^1.2.0", - "encodeurl": "^1.0.2", + "encodeurl": "^2.0.0", "etag": "^1.8.1", "fresh": "^0.5.2", - "haye": "^3.0.0", - "macroable": "^7.0.2", - "mime-types": "^2.1.35", - "ms": "^2.1.3", + "mime-types": "^3.0.2", "on-finished": "^2.4.1", - "pluralize": "^8.0.0", "proxy-addr": "^2.0.7", - "qs": "^6.11.0", "tmp-cache": "^1.1.0", - "type-is": "^1.6.18", + "type-is": "^2.1.0", "vary": "^1.1.2" }, + "engines": { + "node": ">=24.0.0" + }, + "peerDependencies": { + "@adonisjs/application": "^9.0.0-next.14 || ^9.0.0", + "@adonisjs/events": "^10.1.0-next.4 || ^10.1.0", + "@adonisjs/fold": "^11.0.0-next.4 || ^11.0.0", + "@adonisjs/logger": "^7.1.0-next.3 || ^7.1.0", + "@boringnode/encryption": "^0.2.0 || ^1.0.0", + "youch": "^4.1.0-beta.13 || ^4.1.0" + }, + "peerDependenciesMeta": { + "youch": { + "optional": true + } + } + }, + "node_modules/@adonisjs/http-transformers": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@adonisjs/http-transformers/-/http-transformers-2.3.1.tgz", + "integrity": "sha512-N3gBcKyoPHDeVvVIedTzc+ARSUURwNGTPid/e3iLdM4v/myoSnXd76FL/GGzMmjfqqxegpjI2IEMibG7ylrKSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@poppinss/exception": "^1.2.3", + "@poppinss/types": "^1.2.1" + }, + "engines": { + "node": ">=24.0.0" + }, "peerDependencies": { - "@adonisjs/application": "^5.0.0", - "@adonisjs/encryption": "^4.0.0" + "@adonisjs/fold": "^11.0.0-next.2" } }, "node_modules/@adonisjs/logger": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@adonisjs/logger/-/logger-4.1.6.tgz", - "integrity": "sha512-lmnx/wGvxnlHLuUEWQ+VpUQuKBEKumdutNWZPythGP/VpBRzunypntDb7O9XfauPva6B6Z9WVjr2+v3ElTcKPQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@adonisjs/logger/-/logger-7.1.1.tgz", + "integrity": "sha512-MmUlp8xBMT6zZy0+vnQcQjHIlNfU4pUJARlINr7Bqha9BvhIn03QZgJL5QJ+kJe1tl6ZpNAryoRTJUiOk/wINQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@poppinss/utils": "^5.0.0", - "@types/pino": "^6.3.12", + "@poppinss/utils": "^7.0.0", "abstract-logging": "^2.0.1", - "pino": "^6.14.0" + "pino": "^10.3.1" + }, + "engines": { + "node": ">=24.0.0" + }, + "peerDependencies": { + "pino-pretty": "^13.1.1" + }, + "peerDependenciesMeta": { + "pino-pretty": { + "optional": true + } } }, "node_modules/@adonisjs/lucid": { - "version": "18.4.2", - "resolved": "https://registry.npmjs.org/@adonisjs/lucid/-/lucid-18.4.2.tgz", - "integrity": "sha512-4k8GOat/YQtobNqwBIU8VAuY19p+V3ucBRoZ+iwxd/qy/KE1XupPzuMZVWYt1vyBboCrBmEYYmvC851tNqoP0A==", + "version": "22.4.2", + "resolved": "https://registry.npmjs.org/@adonisjs/lucid/-/lucid-22.4.2.tgz", + "integrity": "sha512-3ztENqBQIFSGAWREHKCGbL1g4ehtsxxsuFX72Uf5bq+oSc0D6UcumjzYpU8TPyBxhmgS6HuRSfz2rG42iuz7AA==", "dev": true, "license": "MIT", "dependencies": { - "@faker-js/faker": "^8.0.1", - "@poppinss/hooks": "^5.0.3", - "@poppinss/utils": "^5.0.0", + "@adonisjs/presets": "^3.0.0", + "@faker-js/faker": "^10.4.0", + "@poppinss/hooks": "^7.3.0", + "@poppinss/macroable": "^1.1.2", + "@poppinss/qs": "^6.15.0", + "@poppinss/utils": "^7.0.1", + "deepmerge": "^4.3.1", "fast-deep-equal": "^3.1.3", "igniculus": "^1.5.0", - "knex": "^2.4.2", - "knex-dynamic-connection": "^3.0.1", - "luxon": "^3.3.0", - "macroable": "^7.0.2", + "kleur": "^4.1.5", + "knex": "^3.2.8", + "knex-dynamic-connection": "^5.0.1", "pretty-hrtime": "^1.0.3", - "qs": "^6.11.2", - "slash": "^3.0.0", + "slash": "^5.1.0", "tarn": "^3.0.2" }, "engines": { - "node": ">=14.15.4" + "node": ">=24.0.0" }, "peerDependencies": { - "@adonisjs/core": "^5.1.0" - } - }, - "node_modules/@adonisjs/lucid/node_modules/knex": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/knex/-/knex-2.5.1.tgz", - "integrity": "sha512-z78DgGKUr4SE/6cm7ku+jHvFT0X97aERh/f0MUKAKgFnwCYBEW4TFBqtHWFYiJFid7fMrtpZ/gxJthvz5mEByA==", - "dev": true, - "license": "MIT", - "dependencies": { - "colorette": "2.0.19", - "commander": "^10.0.0", - "debug": "4.3.4", - "escalade": "^3.1.1", - "esm": "^3.2.25", - "get-package-type": "^0.1.0", - "getopts": "2.3.0", - "interpret": "^2.2.0", - "lodash": "^4.17.21", - "pg-connection-string": "2.6.1", - "rechoir": "^0.8.0", - "resolve-from": "^5.0.0", - "tarn": "^3.0.2", - "tildify": "2.0.0" - }, - "bin": { - "knex": "bin/cli.js" - }, - "engines": { - "node": ">=12" + "@adonisjs/assembler": "^8.0.0-next.29 || ^8.0.0", + "@adonisjs/core": "^7.0.0-next.21 || ^7.0.0", + "@vinejs/vine": "^3.0.0 || ^4.0.0", + "luxon": "^3.4.4" }, "peerDependenciesMeta": { - "better-sqlite3": { - "optional": true - }, - "mysql": { - "optional": true - }, - "mysql2": { - "optional": true - }, - "pg": { + "@adonisjs/assembler": { "optional": true }, - "pg-native": { + "@vinejs/vine": { "optional": true }, - "sqlite3": { + "luxon": { "optional": true - }, - "tedious": { + } + } + }, + "node_modules/@adonisjs/presets": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@adonisjs/presets/-/presets-3.0.0.tgz", + "integrity": "sha512-+gVIvyEiM7jiN5Gb93200TAC8ed3vZIPfxFFo0pIVgX8k40BleuYhWxFhI6TPocVXXIIpw2JuMFV2Pqjk36W2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=24.0.0" + }, + "peerDependencies": { + "@adonisjs/assembler": "^8.0.0-next.9 || ^8.0.0", + "@adonisjs/core": "^7.0.0-next.1 || ^7.0.0" + }, + "peerDependenciesMeta": { + "@adonisjs/assembler": { "optional": true } } }, - "node_modules/@adonisjs/lucid/node_modules/pg-connection-string": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.1.tgz", - "integrity": "sha512-w6ZzNu6oMmIzEAYVw+RLK0+nqHPt8K3ZnknKi+g48Ak2pr3dtljJW3o+D/n2zzCG07Zoe9VOX3aiKpj+BN0pjg==", + "node_modules/@adonisjs/repl": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@adonisjs/repl/-/repl-5.0.0.tgz", + "integrity": "sha512-cPp0w5svYUA3M1gdxQBO2Mx5g+SZfPweqKCAxk7C1Os/Qu67JKgWqXqNnl1q0Tzv/l0L19Ms1C7ivzQxeBNajg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@poppinss/colors": "^4.1.6", + "string-width": "^8.2.0" + }, + "engines": { + "node": ">=24.0.0" + } + }, + "node_modules/@antfu/install-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz", + "integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "package-manager-detector": "^1.3.0", + "tinyexec": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@arr/every": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@arr/every/-/every-1.0.1.tgz", + "integrity": "sha512-UQFQ6SgyJ6LX42W8rHCs8KVc0JS0tzVL9ct4XYedJukskYVWTo49tNiMEK9C2HTyarbNiT/RVIRSY82vH+6sTg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@ast-grep/napi": { + "version": "0.42.3", + "resolved": "https://registry.npmjs.org/@ast-grep/napi/-/napi-0.42.3.tgz", + "integrity": "sha512-iWuH84nptrXpfrpYAsc93CD6JRnyRLYWFRzP9j1KRMK2hspVMBCbmfRyEoMd2B572dd2sSF3eXIQvY/CqIxYmQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@ast-grep/napi-darwin-arm64": "0.42.3", + "@ast-grep/napi-darwin-x64": "0.42.3", + "@ast-grep/napi-linux-arm64-gnu": "0.42.3", + "@ast-grep/napi-linux-arm64-musl": "0.42.3", + "@ast-grep/napi-linux-x64-gnu": "0.42.3", + "@ast-grep/napi-linux-x64-musl": "0.42.3", + "@ast-grep/napi-win32-arm64-msvc": "0.42.3", + "@ast-grep/napi-win32-ia32-msvc": "0.42.3", + "@ast-grep/napi-win32-x64-msvc": "0.42.3" + } + }, + "node_modules/@ast-grep/napi-darwin-arm64": { + "version": "0.42.3", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-darwin-arm64/-/napi-darwin-arm64-0.42.3.tgz", + "integrity": "sha512-pcTBI8UiNQ9xVOYfu3Ww5KXcrrHV/jJqECQ6efpJpzTGwW+mOpzgihfrq5GKjbMONhr0OaRARCMwEsvKgBXCpA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@ast-grep/napi-darwin-x64": { + "version": "0.42.3", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-darwin-x64/-/napi-darwin-x64-0.42.3.tgz", + "integrity": "sha512-mQeDYeMWUruf0oiYJejzRzG9BEXjopbhPML8rJombviX6ePmulNjh6SDX/Mxe+vqNGt0JHXgdYtsAtDu9d0LQg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@ast-grep/napi-linux-arm64-gnu": { + "version": "0.42.3", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-arm64-gnu/-/napi-linux-arm64-gnu-0.42.3.tgz", + "integrity": "sha512-T2/8eEvFTKSEXd9Dql34/bsyWogFYh7IGsuOoqYNJOcYwT+TPCLTWPZdcpGqrdYdTYT92qX+4H0dUmaZ+TuOPw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@ast-grep/napi-linux-arm64-musl": { + "version": "0.42.3", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-arm64-musl/-/napi-linux-arm64-musl-0.42.3.tgz", + "integrity": "sha512-O/K4p/GB5MiK2NE8s7pCBDpZ0EOUrMkMF0HbZKi/HIXH9HQdkoYYO+NqKumk92YNr3gUo8fkGkIG6v4wowANvQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@ast-grep/napi-linux-x64-gnu": { + "version": "0.42.3", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-x64-gnu/-/napi-linux-x64-gnu-0.42.3.tgz", + "integrity": "sha512-HnljxyLZmt7t7al46j/j/fLj7e9qG8Nlk6/vrj+AD6nRqoeu7pW4YHcQA9NXst79GBz2CU0nba1WEtjUfkNgGg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@ast-grep/napi-linux-x64-musl": { + "version": "0.42.3", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-x64-musl/-/napi-linux-x64-musl-0.42.3.tgz", + "integrity": "sha512-6WLvV3ErwWXQcpMS4BEVjD7QiTGO2Hr3LuDouQoUUBSMu9gI0bBAZGQaqGfWidI+aXYZ0eL5KmCCDB4X6Oyskg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@ast-grep/napi-win32-arm64-msvc": { + "version": "0.42.3", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-win32-arm64-msvc/-/napi-win32-arm64-msvc-0.42.3.tgz", + "integrity": "sha512-LiDOhkvBEeXi+yJomrfUYgnLvCntrWianruKXMzIK1QpxWmFSVC2uwWacMbq2v/DTk0MlQ09225yD6sAuL5pEQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } }, - "node_modules/@adonisjs/profiler": { - "version": "6.0.9", - "resolved": "https://registry.npmjs.org/@adonisjs/profiler/-/profiler-6.0.9.tgz", - "integrity": "sha512-V1bJPPDTn05NzAKUEICnYtWi9fC8NownUToaqxVkWOUovYBO6ubt06qtH1Uv9zvUjB2PKHUn+ieDAOgyHle09A==", + "node_modules/@ast-grep/napi-win32-ia32-msvc": { + "version": "0.42.3", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-win32-ia32-msvc/-/napi-win32-ia32-msvc-0.42.3.tgz", + "integrity": "sha512-DOAzKQPWQF42a9jgvCz4ajitARcMm9j2xKzcSNwkgZjrconAsRphqCTG3qkfEXX2x7KaVHAqoUp4XgPZXZ5vlA==", + "cpu": [ + "ia32" + ], "dev": true, "license": "MIT", - "dependencies": { - "@poppinss/utils": "^4.0.3", - "jest-worker": "^27.5.1" - }, - "peerDependencies": { - "@adonisjs/logger": "^4.0.0" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/@adonisjs/profiler/node_modules/@poppinss/utils": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-4.0.4.tgz", - "integrity": "sha512-6LS3mofSVB9IQZqofA4rX6KVVcCpdwUQuNe4efHqOTzgD/Q5HTVvDP0vKg1m994QlzJs4aLW1JwXVcNCThEh4g==", + "node_modules/@ast-grep/napi-win32-x64-msvc": { + "version": "0.42.3", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-win32-x64-msvc/-/napi-win32-x64-msvc-0.42.3.tgz", + "integrity": "sha512-1bl5eAbRGI5VRlKzXVPiq+sFJezh60O3ur6G+w8elA20uEZ7ik+WLQZu9T5tScFxOfCQQcjV9v4fQiaGNgHJsA==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@poppinss/file-generator": "^1.0.2", - "@types/bytes": "^3.1.1", - "@types/he": "^1.1.2", - "bytes": "^3.1.2", - "change-case": "^4.1.2", - "cuid": "^2.1.8", - "flattie": "^1.1.0", - "fs-readdir-recursive": "^1.1.0", - "he": "^1.2.0", - "kind-of": "^6.0.3", - "lodash": "^4.17.21", - "ms": "^2.1.3", - "pluralize": "^8.0.0", - "require-all": "^3.0.0", - "resolve-from": "^5.0.0", - "slugify": "^1.6.5", - "truncatise": "0.0.8" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/@adonisjs/validator": { - "version": "12.6.0", - "resolved": "https://registry.npmjs.org/@adonisjs/validator/-/validator-12.6.0.tgz", - "integrity": "sha512-0mS7msmgQpcWnxAs1hORQFOt2jWfPqEXNeq8NdCYqTUxgQObLgDlyfrMG98238EvXUhCS1kZdXM4w/EMwoiAuA==", + "node_modules/@borewit/text-codec": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.2.2.tgz", + "integrity": "sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==", "dev": true, "license": "MIT", - "dependencies": { - "@poppinss/utils": "^5.0.0", - "@types/luxon": "^3.3.1", - "@types/validator": "^13.11.1", - "luxon": "^3.4.1", - "normalize-url": "^6.1.0", - "tmp-cache": "^1.1.0", - "validator": "^13.11.0" - }, - "peerDependencies": { - "@adonisjs/application": "^5.0.0", - "@adonisjs/bodyparser": "^8.0.0", - "@adonisjs/http-server": "^5.0.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" } }, - "node_modules/@arr/every": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@arr/every/-/every-1.0.1.tgz", - "integrity": "sha512-UQFQ6SgyJ6LX42W8rHCs8KVc0JS0tzVL9ct4XYedJukskYVWTo49tNiMEK9C2HTyarbNiT/RVIRSY82vH+6sTg==", + "node_modules/@boringnode/encryption": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@boringnode/encryption/-/encryption-1.0.0.tgz", + "integrity": "sha512-wGGOE7ywA4W6KAVoVC7s1P4ULzFLIQA/JvthGAa41EA0CaH7kGGawkBB5t5tvWopgBNMhOpIg3uxvULxqf2rQw==", "dev": true, "license": "MIT", + "peer": true, + "dependencies": { + "@poppinss/utils": "^7.0.0-next.7" + }, "engines": { - "node": ">=4" + "node": ">=20.6" } }, "node_modules/@colors/colors": { @@ -972,9 +1169,9 @@ } }, "node_modules/@faker-js/faker": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.4.1.tgz", - "integrity": "sha512-XQ3cU+Q8Uqmrbf2e0cIC/QN43sTBSC8KF12u29Mb47tWrt2hAgBXSgpZMj4Ao8Uk0iJcU99QsOCaIL8934obCg==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-10.5.0.tgz", + "integrity": "sha512-bsxD8WLS5lIj7aaoCx1YJkktqYj5vlBUE6HWzu2Q51ksrGJ0H737ECCKlFU7Yf8Br45z9t99frBp/J7kzbMPAg==", "dev": true, "funding": [ { @@ -984,8 +1181,46 @@ ], "license": "MIT", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0", - "npm": ">=6.14.13" + "node": "^20.19.0 || ^22.13.0 || ^23.5.0 || >=24.0.0", + "npm": ">=10" + } + }, + "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/@phc/format": { @@ -998,76 +1233,84 @@ "node": ">=10" } }, - "node_modules/@poppinss/cliui": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@poppinss/cliui/-/cliui-3.0.5.tgz", - "integrity": "sha512-9TCwhJ6hQDAv7LWredEQL7eSA97kQ/i5Td80T7InV9z9rOXT8keywAM0pSvTUS01bwCeiZQVoT4r/G67DRiPJA==", + "node_modules/@pinojs/redact": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz", + "integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==", "dev": true, - "license": "MIT", - "dependencies": { - "@poppinss/colors": "^3.0.3", - "cli-boxes": "^3.0.0", - "cli-table3": "^0.6.3", - "color-support": "^1.1.3", - "log-update": "^4.0.0", - "pretty-hrtime": "^1.0.3", - "string-width": "^4.2.2" - } + "license": "MIT" }, - "node_modules/@poppinss/co-body": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@poppinss/co-body/-/co-body-1.2.0.tgz", - "integrity": "sha512-1aJ06XrtQ8gueo91+Vc7TTSeXECsW1pWDCKumtuGL+9xsjJvP6n567YuimwHuH99wFMIhyNW5U1g2C/4wjvXCQ==", + "node_modules/@poppinss/cliui": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@poppinss/cliui/-/cliui-6.8.1.tgz", + "integrity": "sha512-o/ssbwr+r6woG65rk9eFHnn9dVUphZr/Rk+4+05ENVMBWYpYhTJGdE9RobTG5JLFubvO4gWIyFeNlC+I4EM6eA==", "dev": true, "license": "MIT", "dependencies": { - "@poppinss/utils": "^5.0.0", - "inflation": "^2.0.0", - "qs": "^6.11.0", - "raw-body": "^2.5.1", - "type-is": "^1.6.18" + "@poppinss/colors": "^4.1.6", + "cli-boxes": "^4.0.1", + "cli-table3": "^0.6.5", + "cli-truncate": "^5.2.0", + "log-update": "^7.2.0", + "pretty-hrtime": "^1.0.3", + "string-width": "^8.2.0", + "supports-color": "^10.2.2", + "terminal-size": "^4.0.1" } }, "node_modules/@poppinss/colors": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@poppinss/colors/-/colors-3.0.3.tgz", - "integrity": "sha512-jiZcp91PvIs5s4Wz4gEVY9J2tqH6H1++mZmsrC3TmFam9gbVPUJPEubPM5j4BQYJre7bjs9nkIbYFcWMOFHIVQ==", + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@poppinss/colors/-/colors-4.1.6.tgz", + "integrity": "sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==", "dev": true, "license": "MIT", "dependencies": { - "color-support": "^1.1.3", "kleur": "^4.1.5" } }, - "node_modules/@poppinss/file-generator": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@poppinss/file-generator/-/file-generator-1.0.2.tgz", - "integrity": "sha512-rRob//4jLbUVbDSsNRihloKGgpyVsWdFQWUmONxX/gyv4koT1OlVoc3ccWgk7Y/sEa2cFxj3zrFs+wdT09iXWw==", + "node_modules/@poppinss/dumper": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@poppinss/dumper/-/dumper-0.7.0.tgz", + "integrity": "sha512-0UTYalzk2t6S4rA2uHOz5bSSW2CHdv4vggJI6Alg90yvl0UgXs6XSXpH96OH+bRkX4J/06djv29pqXJ0lq5Kag==", "dev": true, "license": "MIT", "dependencies": { - "bytes": "^3.1.2" + "@poppinss/colors": "^4.1.5", + "@sindresorhus/is": "^7.0.2", + "supports-color": "^10.0.0" } }, - "node_modules/@poppinss/hooks": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@poppinss/hooks/-/hooks-5.0.3.tgz", - "integrity": "sha512-M5a151VUl+RslVP5qwDW+u+0VmzKt5Nfplzdx2nrtXol3yVlLN3u2Jp6UADESid3DDI7IRHmFrA3sQusey3eUA==", + "node_modules/@poppinss/dumper/node_modules/@sindresorhus/is": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.2.0.tgz", + "integrity": "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==", "dev": true, "license": "MIT", - "peerDependencies": { - "@adonisjs/application": ">=4.0.0" + "engines": { + "node": ">=18" }, - "peerDependenciesMeta": { - "@adonisjs/application": { - "optional": true - } + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" } }, - "node_modules/@poppinss/manager": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@poppinss/manager/-/manager-5.0.2.tgz", - "integrity": "sha512-c5F3EKztq/iw0J+BfNu5rSI5/ji+kjts4rJaC/VvIzpTWzbRorb7UR9J32T8cLtTwjNHbmxk3BAU402lvL2JFA==", + "node_modules/@poppinss/exception": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@poppinss/exception/-/exception-1.2.3.tgz", + "integrity": "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@poppinss/hooks": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/@poppinss/hooks/-/hooks-7.3.0.tgz", + "integrity": "sha512-/H35z/bWqHg7085QOxWUDYMidx6Kl6b8kIyzIXlRYzWvsk1xm9hQOlXWdWEYch+Gmn8eL7tThx59MBj8BLxDrQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@poppinss/macroable": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@poppinss/macroable/-/macroable-1.1.2.tgz", + "integrity": "sha512-FAVBRzzWhYP5mA3lCwLH1A0fKBqq5anyjGet90Z81aRK5c/+LTGUE1zJhZrErjaenBSOOI9BVUs3WVmotneFQA==", "dev": true, "license": "MIT" }, @@ -1081,167 +1324,211 @@ "@arr/every": "^1.0.0" } }, + "node_modules/@poppinss/middleware": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/@poppinss/middleware/-/middleware-3.2.7.tgz", + "integrity": "sha512-MZC0Z97ozSz+PpfyxUPUy/ImuthpqvBbY7qku7f4Q2maHz+2uXfchfO8OggXLS6zEJ078l+jpAHZ2rDIRdjeVg==", + "dev": true, + "license": "MIT" + }, "node_modules/@poppinss/multiparty": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@poppinss/multiparty/-/multiparty-2.0.1.tgz", - "integrity": "sha512-Pf3V9PFyZDIkDBBiAOT2hdmA+1l/+hverHbUnMzNzwtwgO50s2ZPt5KxUydVA0hceg9gryo5unQ0WUF1SO9tkQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@poppinss/multiparty/-/multiparty-3.0.0.tgz", + "integrity": "sha512-z9jchUzsv7E+7sa4tWHb0+95Byx7w0ydlPGxg3nzyb7h3QlRdeW8/QkU9SexUY4lsT12do93AfNBAhSuOoVqjA==", "dev": true, "license": "MIT", "dependencies": { - "http-errors": "^2.0.0", - "safe-buffer": "5.2.1", - "uid-safe": "2.1.5" + "http-errors": "^2.0.0" } }, - "node_modules/@poppinss/prompts": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@poppinss/prompts/-/prompts-2.0.2.tgz", - "integrity": "sha512-jTrE8U5rnHTZNpBvPauFVDMQZZuEnfABbJUEXfq0uu8oGJnPaaA+y0bQbyqVf4yWqgRGldgrzAwNz739hIEnPQ==", + "node_modules/@poppinss/object-builder": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@poppinss/object-builder/-/object-builder-1.1.0.tgz", + "integrity": "sha512-FOrOq52l7u8goR5yncX14+k+Ewi5djnrt1JwXeS/FvnwAPOiveFhiczCDuvXdssAwamtrV2hp5Rw9v+n2T7hQg==", "dev": true, "license": "MIT", - "dependencies": { - "@poppinss/colors": "^3.0.2", - "enquirer": "^2.3.6" + "engines": { + "node": ">=20.6.0" } }, - "node_modules/@poppinss/utils": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-5.0.0.tgz", - "integrity": "sha512-SpJL5p4Nx3bRCpCf62KagZLUHLvJD+VDylGpXAeP2G5qb3s6SSOBlpaFmer4GxdyTqLIUt0PRCzF1TbpNU+qZw==", + "node_modules/@poppinss/prompts": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@poppinss/prompts/-/prompts-3.1.6.tgz", + "integrity": "sha512-cKHfkID6b3wl1kbHJJRC/pznQ3KnRVydyk7CE38NfTV3VS45BDYCxeZZ7bfDin71qMzITh18lKnu8iuLxBngHA==", "dev": true, "license": "MIT", "dependencies": { - "@poppinss/file-generator": "^1.0.2", - "@types/bytes": "^3.1.1", - "@types/he": "^1.1.2", - "bytes": "^3.1.2", - "change-case": "^4.1.2", - "cuid": "^2.1.8", - "flattie": "^1.1.0", - "fs-readdir-recursive": "^1.1.0", - "he": "^1.2.0", - "kind-of": "^6.0.3", - "lodash": "^4.17.21", - "ms": "^2.1.3", - "pluralize": "^8.0.0", - "require-all": "^3.0.0", - "resolve-from": "^5.0.0", - "slugify": "^1.6.5", - "truncatise": "0.0.8" + "@poppinss/colors": "^4.1.6", + "@poppinss/exception": "^1.2.2", + "@poppinss/object-builder": "^1.1.0", + "enquirer": "^2.4.1" } }, - "node_modules/@tokenizer/token": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", - "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", + "node_modules/@poppinss/qs": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@poppinss/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-QzfMhxrRB5EPeGz0l8hTwKZ5dFX6ed0aETGbuD369StCO8Ad3SW4wWBYamOK5IKeM/dfOeKaCwUZPTnGcj+jKg==", "dev": true, - "license": "MIT" + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/@types/better-sqlite3": { - "version": "7.6.13", - "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.13.tgz", - "integrity": "sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==", + "node_modules/@poppinss/string": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@poppinss/string/-/string-1.7.2.tgz", + "integrity": "sha512-A182GLDfi36iDCbhDrHB0xzrPM1fO3GHnhCDIdadf8C6eycgct4m7zusbLwEh6GPaj2Pz5BVos7XK16w7tZ7wQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*" + "@types/pluralize": "^0.0.33", + "case-anything": "^3.1.2", + "pluralize": "^8.0.0", + "slugify": "^1.6.9" } }, - "node_modules/@types/bytes": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@types/bytes/-/bytes-3.1.5.tgz", - "integrity": "sha512-VgZkrJckypj85YxEsEavcMmmSOIzkUHqWmM4CCyia5dc54YwsXzJ5uT4fYxBQNEXx+oF1krlhgCbvfubXqZYsQ==", + "node_modules/@poppinss/types": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@poppinss/types/-/types-1.2.1.tgz", + "integrity": "sha512-qUYnzl0m9HJTWsXtr8Xo7CwDx6wcjrvo14bOVbIMIlKJCzKrm3LX55dRTDr1/x4PpSvKVgmxvC6Ly2YiqXKOvQ==", "dev": true, "license": "MIT" }, - "node_modules/@types/fs-extra": { - "version": "9.0.13", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", - "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "node_modules/@poppinss/utils": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@poppinss/utils/-/utils-7.0.1.tgz", + "integrity": "sha512-mveSvLI2YPC114mK5HCuSYfUtjpClf1wHG1VCqZJCp4U2ypPhIt62Iku5urh0kPAFvnvCVHx2bXBSH14qMTOlQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*" + "@poppinss/exception": "^1.2.3", + "@poppinss/object-builder": "^1.1.0", + "@poppinss/string": "^1.7.1", + "@poppinss/types": "^1.2.1", + "flattie": "^1.1.1" } }, - "node_modules/@types/he": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@types/he/-/he-1.2.3.tgz", - "integrity": "sha512-q67/qwlxblDzEDvzHhVkwc1gzVWxaNxeyHUBF4xElrvjL11O+Ytze+1fGpBHlr/H9myiBUaUXNnNPmBHxxfAcA==", + "node_modules/@poppinss/validator-lite": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@poppinss/validator-lite/-/validator-lite-2.1.2.tgz", + "integrity": "sha512-UhSG1ouT6r67VbEFHK/8ax3EMZYHioew9PqGmEZjV41G15aPZi6cyhXtBVvF9xqkHMflA5V680k7bQzV0kfD5w==", "dev": true, "license": "MIT" }, - "node_modules/@types/luxon": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.7.2.tgz", - "integrity": "sha512-gW+Oib+vUtGJBtNC8V9Reww0oIpusw+4m81uncg9REGZAJfqOQHfo/nkabnc7w0QReXyPqjrbWMJk6NuAkiX3Q==", + "node_modules/@sec-ant/readable-stream": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", + "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", "dev": true, "license": "MIT" }, - "node_modules/@types/node": { - "version": "20.19.43", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", - "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", + "node_modules/@sindresorhus/is": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-8.1.0.tgz", + "integrity": "sha512-2SX/1jW6CIMAiebvVv5ZInoCEuWQmMyBoJXXGC6Vjakjp/fpxP5eHs7/V6WKuPEIbuK06+VpjH+vjLQhr98rDQ==", "dev": true, "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" + "engines": { + "node": ">=22" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", + "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@types/pino": { - "version": "6.3.12", - "resolved": "https://registry.npmjs.org/@types/pino/-/pino-6.3.12.tgz", - "integrity": "sha512-dsLRTq8/4UtVSpJgl9aeqHvbh6pzdmjYD3C092SYgLD2TyoCqHpTJk6vp8DvCTGGc7iowZ2MoiYiVUUCcu7muw==", + "node_modules/@speed-highlight/core": { + "version": "1.2.17", + "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.17.tgz", + "integrity": "sha512-Z92FwKpCtfaW1V0jTU/fh3QzYEZN8wDwrzRIBoADCJfn4mJCNcJN/XegifX7BDrQ8/h9Xh/JnbyMchL0FqXrkg==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/@tokenizer/inflate": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.4.1.tgz", + "integrity": "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*", - "@types/pino-pretty": "*", - "@types/pino-std-serializers": "*", - "sonic-boom": "^2.1.0" + "debug": "^4.4.3", + "token-types": "^6.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" } }, - "node_modules/@types/pino-pretty": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/@types/pino-pretty/-/pino-pretty-4.7.5.tgz", - "integrity": "sha512-rfHe6VIknk14DymxGqc9maGsRe8/HQSvM2u46EAz2XrS92qsAJnW16dpdFejBuZKD8cRJX6Aw6uVZqIQctMpAg==", + "node_modules/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@ts-morph/common": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.28.1.tgz", + "integrity": "sha512-W74iWf7ILp1ZKNYXY5qbddNaml7e9Sedv5lvU1V8lftlitkc9Pq1A+jlH23ltDgWYeZFFEqGCD1Ies9hqu3O+g==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*", - "@types/pino": "6.3" + "minimatch": "^10.0.1", + "path-browserify": "^1.0.1", + "tinyglobby": "^0.2.14" } }, - "node_modules/@types/pino-std-serializers": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/pino-std-serializers/-/pino-std-serializers-2.4.1.tgz", - "integrity": "sha512-17XcksO47M24IVTVKPeAByWUd3Oez7EbIjXpSbzMPhXVzgjGtrOa49gKBwxH9hb8dKv58OelsWQ+A1G1l9S3wQ==", + "node_modules/@types/better-sqlite3": { + "version": "7.6.13", + "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.13.tgz", + "integrity": "sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "*" } }, - "node_modules/@types/validator": { - "version": "13.15.10", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.10.tgz", - "integrity": "sha512-T8L6i7wCuyoK8A/ZeLYt1+q0ty3Zb9+qbSSvrIVitzT3YjZqkTZ40IbRsPanlB4h1QB3JVL1SYCdR6ngtFYcuA==", + "node_modules/@types/he": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@types/he/-/he-1.2.3.tgz", + "integrity": "sha512-q67/qwlxblDzEDvzHhVkwc1gzVWxaNxeyHUBF4xElrvjL11O+Ytze+1fGpBHlr/H9myiBUaUXNnNPmBHxxfAcA==", "dev": true, "license": "MIT" }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "node_modules/@types/node": { + "version": "22.20.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.0.tgz", + "integrity": "sha512-QWlFW2wf3nTjC13/DqRnBpR4ZO36VJH/JVBkA/vcnmbTBNQIlnObqyqZE1tUR7+Ni23Lda8R1BxMfbXRpCUx5g==", "dev": true, "license": "MIT", "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" + "undici-types": "~6.21.0" } }, + "node_modules/@types/pluralize": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/@types/pluralize/-/pluralize-0.0.33.tgz", + "integrity": "sha512-JOqsl+ZoCpP4e8TDke9W79FDcSgPAR0l6pixx2JHkhnRjvShyYiAYw2LVsnA7K08Y6DeOnaU6ujmENO4os/cYg==", + "dev": true, + "license": "MIT" + }, "node_modules/abstract-logging": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz", @@ -1249,20 +1536,6 @@ "dev": true, "license": "MIT" }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/ansi-colors": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", @@ -1274,16 +1547,16 @@ } }, "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", + "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", "dev": true, "license": "MIT", "dependencies": { - "type-fest": "^0.21.3" + "environment": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -1300,31 +1573,18 @@ } }, "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==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true, "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/atomic-sleep": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", @@ -1335,6 +1595,16 @@ "node": ">=8.0.0" } }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -1357,15 +1627,18 @@ "license": "MIT" }, "node_modules/better-sqlite3": { - "version": "11.10.0", - "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-11.10.0.tgz", - "integrity": "sha512-EwhOpyXiOEL/lKzHz9AW1msWFNzGc/z+LzeB3/jnFJpxu+th2yqvzsSWas1v9jgs9+xiXJcD5A8CJxAG2TaghQ==", + "version": "12.11.1", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.11.1.tgz", + "integrity": "sha512-dq9AtApgg5PGFtBzPFSBl3HZQjHok5gaQCM6zh2Yk0aSmDCs1CbnVI8/HgASQkNKsWFpseIO9beg5xxpYhbIfA==", "dev": true, "hasInstallScript": true, "license": "MIT", "dependencies": { "bindings": "^1.5.0", "prebuild-install": "^7.1.1" + }, + "engines": { + "node": "20.x || 22.x || 23.x || 24.x || 25.x || 26.x" } }, "node_modules/bindings": { @@ -1390,50 +1663,36 @@ "readable-stream": "^3.4.0" } }, - "node_modules/bl/node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "node_modules/brace-expansion": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz", + "integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==", "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": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" } }, - "node_modules/bl/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "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": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "fill-range": "^7.1.1" }, "engines": { - "node": ">= 6" + "node": ">=8" } }, "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "dev": true, "funding": [ { @@ -1452,92 +1711,72 @@ "license": "MIT", "dependencies": { "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "ieee754": "^1.1.13" } }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", "dev": true, "license": "MIT", + "dependencies": { + "run-applescript": "^7.0.0" + }, "engines": { - "node": ">= 0.8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true, "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, "engines": { - "node": ">= 0.4" + "node": ">= 0.8" } }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "node_modules/case-anything": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/case-anything/-/case-anything-3.1.2.tgz", + "integrity": "sha512-wljhAjDDIv/hM2FzgJnYQg90AWmZMNtESCjTeLH680qTzdo0nErlCxOmgzgX4ZsZAtIvqHyD87ES8QyriXB+BQ==", "dev": true, "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, "engines": { - "node": ">= 0.4" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" + "url": "https://github.com/sponsors/mesqueeb" } }, - "node_modules/capital-case": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", - "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==", + "node_modules/check-disk-space": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/check-disk-space/-/check-disk-space-3.4.0.tgz", + "integrity": "sha512-drVkSqfwA+TvuEhFipiR1OC9boEGZL5RrWvVsOthdcvQNXyCCuKkEiTOTXZ7qxSf/GLwq4GvzfrQD/Wz325hgw==", "dev": true, "license": "MIT", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case-first": "^2.0.2" + "engines": { + "node": ">=16" } }, - "node_modules/change-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz", - "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==", + "node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", "dev": true, "license": "MIT", "dependencies": { - "camel-case": "^4.1.2", - "capital-case": "^1.0.4", - "constant-case": "^3.0.4", - "dot-case": "^3.0.4", - "header-case": "^2.0.4", - "no-case": "^3.0.4", - "param-case": "^3.0.4", - "pascal-case": "^3.1.2", - "path-case": "^3.0.4", - "sentence-case": "^3.0.4", - "snake-case": "^3.0.4", - "tslib": "^2.0.3" + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, "node_modules/chownr": { @@ -1548,29 +1787,32 @@ "license": "ISC" }, "node_modules/cli-boxes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", - "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-4.0.1.tgz", + "integrity": "sha512-5IOn+jcCEHEraYolBPs/sT4BxYCe2nHg374OPiItB1O96KZFseS2gthU4twyYzeDcFew4DaUM/xwc5BQf08JJw==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": ">=18.20 <19 || >=20.10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "dev": true, "license": "MIT", "dependencies": { - "restore-cursor": "^3.1.0" + "restore-cursor": "^5.0.0" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/cli-table3": { @@ -1589,42 +1831,54 @@ "@colors/colors": "1.5.0" } }, - "node_modules/co-compose": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/co-compose/-/co-compose-7.0.3.tgz", - "integrity": "sha512-ZHLSLzeBXe5yaEyIHo9T92uVrbsBRLMXlG0G4/pSm9f6148l4mJTr1cii8Jl9ce+mbLmW5XqHURPC7gZFJNeZA==", + "node_modules/cli-table3/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "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==", + "node_modules/cli-table3/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=7.0.0" + "node": ">=8" } }, - "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==", + "node_modules/cli-truncate": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.2.0.tgz", + "integrity": "sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "slice-ansi": "^8.0.0", + "string-width": "^8.2.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "node_modules/code-block-writer": { + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-13.0.3.tgz", + "integrity": "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==", "dev": true, - "license": "ISC", - "bin": { - "color-support": "bin.js" - } + "license": "MIT" }, "node_modules/colorette": { "version": "2.0.19", @@ -1643,57 +1897,64 @@ "node": ">=14" } }, - "node_modules/constant-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz", - "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case": "^2.0.2" - } - }, "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz", + "integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==", "dev": true, "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "node_modules/content-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", + "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/cuid": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/cuid/-/cuid-2.1.8.tgz", - "integrity": "sha512-xiEMER6E7TlTPnDxrM4eRiC6TRgjNX9xzEZ5U/Se2YJKr7Mq4pJn/2XEHjl3STcSh96GmkHPcBXLES8M29wyyg==", - "deprecated": "Cuid and other k-sortable and non-cryptographic ids (Ulid, ObjectId, KSUID, all UUIDs) are all insecure. Use @paralleldrive/cuid2 instead.", + "node_modules/cookie-es": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-3.1.1.tgz", + "integrity": "sha512-UaXxwISYJPTr9hwQxMFYZ7kNhSXboMXP+Z3TRX6f1/NyaGPfuNUZOWP1pUEb75B2HjfklIYLVRfWiFZJyC6Npg==", "dev": true, "license": "MIT" }, + "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/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -1704,13 +1965,6 @@ } } }, - "node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true, - "license": "MIT" - }, "node_modules/decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", @@ -1727,6 +1981,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/dedent": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.2.tgz", + "integrity": "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -1737,6 +2006,59 @@ "node": ">=4.0.0" } }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-browser": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", + "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -1768,45 +2090,6 @@ "node": ">=8" } }, - "node_modules/dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dev": true, - "license": "MIT", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/dotenv": { - "version": "16.6.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -1815,13 +2098,13 @@ "license": "MIT" }, "node_modules/emittery": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", - "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-1.2.1.tgz", + "integrity": "sha512-sFz64DCRjirhwHLxofFqxYQm6DCp6o0Ix7jwKQvuCHPn4GMRZNuBZyLPu9Ccmk/QSCAMZt6FOUqA8JZCQvA9fw==", "dev": true, "license": "MIT", "engines": { - "node": ">=12" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sindresorhus/emittery?sponsor=1" @@ -1835,9 +2118,9 @@ "license": "MIT" }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "dev": true, "license": "MIT", "engines": { @@ -1868,14 +2151,27 @@ "node": ">=8.6" } }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/error-stack-parser-es": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz", + "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" } }, "node_modules/es-errors": { @@ -1888,18 +2184,12 @@ "node": ">= 0.4" } }, - "node_modules/es-object-atoms": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", - "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } + "license": "MIT" }, "node_modules/esbuild": { "version": "0.28.1", @@ -1953,23 +2243,6 @@ "node": ">=6" } }, - "node_modules/escape-goat": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", - "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true, - "license": "MIT" - }, "node_modules/esm": { "version": "3.2.25", "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", @@ -1990,24 +2263,31 @@ "node": ">= 0.6" } }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "node_modules/execa": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.1.tgz", + "integrity": "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==", "dev": true, "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^4.0.0", + "cross-spawn": "^7.0.6", + "figures": "^6.1.0", + "get-stream": "^9.0.0", + "human-signals": "^8.0.1", + "is-plain-obj": "^4.1.0", + "is-stream": "^4.0.1", + "npm-run-path": "^6.0.0", + "pretty-ms": "^9.2.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^4.0.0", + "yoctocolors": "^2.1.1" + }, "engines": { - "node": ">=0.8.x" + "node": "^18.19.0 || >=20.5.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, "node_modules/expand-template": { @@ -2027,36 +2307,104 @@ "dev": true, "license": "MIT" }, - "node_modules/fast-redact": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", - "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", + "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": ">=6" + "node": ">=8.6.0" } }, - "node_modules/fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "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": "MIT" + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "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/figures": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", + "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-unicode-supported": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/file-type": { - "version": "16.5.4", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz", - "integrity": "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==", + "version": "22.0.1", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-22.0.1.tgz", + "integrity": "sha512-ww5Mhre0EE+jmBvOXTmXAbEMuZE7uX4a3+oRCQFNj8w++g3ev913N6tXQz0XTXbueQ5TWQfm6BdaViEHHn8bhA==", "dev": true, "license": "MIT", "dependencies": { - "readable-web-to-node-stream": "^3.0.0", - "strtok3": "^6.2.4", - "token-types": "^4.1.1" + "@tokenizer/inflate": "^0.4.1", + "strtok3": "^10.3.5", + "token-types": "^6.1.2", + "uint8array-extras": "^1.5.0" }, "engines": { - "node": ">=10" + "node": ">=22" }, "funding": { "url": "https://github.com/sindresorhus/file-type?sponsor=1" @@ -2069,12 +2417,18 @@ "dev": true, "license": "MIT" }, - "node_modules/flatstr": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.12.tgz", - "integrity": "sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==", + "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" + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } }, "node_modules/flattie": { "version": "1.1.1", @@ -2113,35 +2467,6 @@ "dev": true, "license": "MIT" }, - "node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/fs-monkey": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.1.0.tgz", - "integrity": "sha512-QMUezzXWII9EV5aTFXW1UBVUO77wYPpjqIF8/AviUCThNeSYZykpoTixUeaNNBwmCev0AMDWMAni+f8Hxb1IFw==", - "dev": true, - "license": "Unlicense" - }, - "node_modules/fs-readdir-recursive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", - "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", - "dev": true, - "license": "MIT" - }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -2167,29 +2492,17 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "node_modules/get-east-asian-width": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", + "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==", "dev": true, "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, "engines": { - "node": ">= 0.4" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/get-package-type": { @@ -2202,18 +2515,47 @@ "node": ">=8.0.0" } }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "node_modules/get-port": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-7.2.0.tgz", + "integrity": "sha512-afP4W205ONCuMoPBqcR6PSXnzX35KTcJygfJfcp+QY+uwm3p20p1YczWXhlICIzGMCxYBQcySEcOgsJcrkyobg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-stream": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", + "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", "dev": true, "license": "MIT", "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" + "@sec-ant/readable-stream": "^0.4.1", + "is-stream": "^4.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-tsconfig": { + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz", + "integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, "node_modules/getopts": { @@ -2230,47 +2572,17 @@ "dev": true, "license": "MIT" }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "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": "MIT", - "engines": { - "node": ">= 0.4" + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC" - }, - "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/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "dev": true, - "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10.13.0" } }, "node_modules/hasown": { @@ -2286,13 +2598,6 @@ "node": ">= 0.4" } }, - "node_modules/haye": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/haye/-/haye-3.0.0.tgz", - "integrity": "sha512-yWxbPdeex78IR3x3X/DdqkZbVG4rP4UaRdUGmpClfnUh1C61mASt7Iav8vk2tXcTMSygBHDDfgoVqk68NJqzhQ==", - "dev": true, - "license": "MIT" - }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -2303,17 +2608,6 @@ "he": "bin/he" } }, - "node_modules/header-case": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz", - "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "capital-case": "^1.0.4", - "tslib": "^2.0.3" - } - }, "node_modules/http-errors": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", @@ -2335,17 +2629,31 @@ "url": "https://opencollective.com/express" } }, + "node_modules/human-signals": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz", + "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", "dev": true, "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/ieee754": { @@ -2379,6 +2687,17 @@ "node": ">=4.0.0" } }, + "node_modules/import-meta-resolve": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", + "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/inflation": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/inflation/-/inflation-2.1.0.tgz", @@ -2439,52 +2758,186 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-fullwidth-code-point": { + "node_modules/is-docker": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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": ">=8" + "node": ">=0.10.0" } }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "get-east-asian-width": "^1.3.1" }, "engines": { - "node": ">= 10.13.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jsonfile": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", - "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "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": { - "universalify": "^2.0.0" + "is-extglob": "^2.1.1" }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-in-ssh": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-in-ssh/-/is-in-ssh-1.0.0.tgz", + "integrity": "sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", + "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-wsl": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/jsonschema": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.5.0.tgz", + "integrity": "sha512-K+A9hhqbn0f3pJX17Q/7H6yQfD/5OXgdrR5UE12gMXCiN9D5Xq2o5mddV2QEcX/bjla99ASsAAQUyMCCRWAEhw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" } }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "node_modules/junk": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/junk/-/junk-4.0.1.tgz", + "integrity": "sha512-Qush0uP+G8ZScpGMZvHUiRfI0YBWuB3gVBYlI0v0vvOJt5FLicco+IkP0a50LqTTQhmts/m6tP5SWE+USyIvcQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/kleur": { @@ -2559,27 +3012,85 @@ } }, "node_modules/knex-dynamic-connection": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/knex-dynamic-connection/-/knex-dynamic-connection-3.2.0.tgz", - "integrity": "sha512-+j6KeUSim0FR8EobOqA1a/TZbN9mahjzHzJgOfQVkv6PUnSqJp70c/5n63M2YVNgNHETyBIUhV8stuQ0T/mG3g==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/knex-dynamic-connection/-/knex-dynamic-connection-5.1.0.tgz", + "integrity": "sha512-kv41rybMmUKOEAxkGytKRITAthuHFzt0l5vRT1SuTOcve4a9JMc1t/ElVOTRlBEkBexWX8A5WcO71cufrqAxkw==", "dev": true, "license": "MIT", "dependencies": { - "debug": "^4.3.5", - "knex": "^3.1.0" + "debug": "^4.4.3", + "knex": "3.2.7" }, "engines": { - "node": ">=14.0.0" + "node": ">=24.0.0" } }, - "node_modules/knex-dynamic-connection/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "node_modules/knex-dynamic-connection/node_modules/knex": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/knex/-/knex-3.2.7.tgz", + "integrity": "sha512-VxdDE72x7Tc08E5yCu8HqYoeOm0HOjAraOtYiGSAUJTYkydwfSGBOpQqYHrzM5vjLNzw2JDL2vDH8m7DjIjtgA==", "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "colorette": "2.0.19", + "commander": "^10.0.0", + "debug": "4.3.4", + "escalade": "^3.1.1", + "esm": "^3.2.25", + "get-package-type": "^0.1.0", + "getopts": "2.3.0", + "interpret": "^2.2.0", + "lodash": "^4.17.21", + "pg-connection-string": "2.6.2", + "rechoir": "^0.8.0", + "resolve-from": "^5.0.0", + "tarn": "^3.0.2", + "tildify": "2.0.0" + }, + "bin": { + "knex": "bin/cli.js" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "pg-query-stream": "^4.14.0" + }, + "peerDependenciesMeta": { + "better-sqlite3": { + "optional": true + }, + "mysql": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-native": { + "optional": true + }, + "pg-query-stream": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "tedious": { + "optional": true + } + } + }, + "node_modules/knex-dynamic-connection/node_modules/knex/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" }, "engines": { "node": ">=6.0" @@ -2590,16 +3101,38 @@ } } }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "node_modules/knex-dynamic-connection/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/knex/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, "engines": { - "node": ">=6" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, + "node_modules/knex/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash": { "version": "4.18.1", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", @@ -2608,32 +3141,52 @@ "license": "MIT" }, "node_modules/log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-7.2.0.tgz", + "integrity": "sha512-iLs7dGSyjZiUgvrUvuD3FndAxVJk+TywBkkkwUSm9HdYoskJalWg5qVsEiXeufPvRVPbCUmNQewg798rx+sPXg==", "dev": true, "license": "MIT", "dependencies": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" + "ansi-escapes": "^7.3.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^8.0.0", + "strip-ansi": "^7.2.0", + "wrap-ansi": "^10.0.0" }, "engines": { - "node": ">=10" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "dev": true, "license": "MIT", "dependencies": { - "tslib": "^2.0.3" + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/luxon": { @@ -2642,74 +3195,62 @@ "integrity": "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" } }, - "node_modules/macroable": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/macroable/-/macroable-7.0.2.tgz", - "integrity": "sha512-QS9p+Q20YBxpE0dJBnF6CPURP7p1GUsxnhTxTWH5nG3A1F5w8Rg3T4Xyh5UlrFSbHp88oOciVP/0agsNLhkHdQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/math-intrinsics": { + "node_modules/media-typer": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">= 0.8" } }, - "node_modules/media-typer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "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": ">= 0.8" + "node": ">= 8" } }, - "node_modules/memfs": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", - "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "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": "Unlicense", + "license": "MIT", "dependencies": { - "fs-monkey": "^1.0.4" + "braces": "^3.0.3", + "picomatch": "^2.3.1" }, "engines": { - "node": ">= 4.0.0" + "node": ">=8.6" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, - "license": "MIT" - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", - "bin": { - "mime": "cli.js" - }, "engines": { - "node": ">=4" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "dev": true, "license": "MIT", "engines": { @@ -2717,26 +3258,33 @@ } }, "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", "dev": true, "license": "MIT", "dependencies": { - "mime-db": "1.52.0" + "mime-db": "^1.54.0" }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/mimic-response": { @@ -2752,6 +3300,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", @@ -2776,16 +3340,6 @@ "dev": true, "license": "MIT" }, - "node_modules/mustache": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", - "dev": true, - "license": "MIT", - "bin": { - "mustache": "bin/mustache" - } - }, "node_modules/napi-build-utils": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", @@ -2793,27 +3347,6 @@ "dev": true, "license": "MIT" }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dev": true, - "license": "MIT", - "dependencies": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, "node_modules/node-abi": { "version": "3.92.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.92.0.tgz", @@ -2827,30 +3360,44 @@ "node": ">=10" } }, - "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "node_modules/npm-run-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", + "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", "dev": true, "license": "MIT", + "dependencies": { + "path-key": "^4.0.0", + "unicorn-magic": "^0.3.0" + }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" } }, "node_modules/on-finished": { @@ -2877,85 +3424,103 @@ } }, "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", "dev": true, "license": "MIT", "dependencies": { - "mimic-fn": "^2.1.0" + "mimic-function": "^5.0.0" }, "engines": { - "node": ">=6" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "node_modules/open": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/open/-/open-11.0.0.tgz", + "integrity": "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==", "dev": true, "license": "MIT", "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" + "default-browser": "^5.4.0", + "define-lazy-prop": "^3.0.0", + "is-in-ssh": "^1.0.0", + "is-inside-container": "^1.0.0", + "powershell-utils": "^0.1.0", + "wsl-utils": "^0.3.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "node_modules/package-manager-detector": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz", + "integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } + "license": "MIT" }, - "node_modules/pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "node_modules/parse-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/parse-imports/-/parse-imports-3.0.0.tgz", + "integrity": "sha512-IwiqoJANa4O6M76LBWEvoS2iPIUqBOnKG1lV3/J0oVM6V2XjED+mYAXedEMX5xUglVjfGpZOfaEyuOUjBuUE4g==", "dev": true, - "license": "MIT", + "license": "Apache-2.0 AND MIT", "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" + "es-module-lexer": "^1.7.0", + "slashes": "^3.0.12" + }, + "engines": { + "node": ">= 22" + }, + "funding": { + "url": "https://github.com/sponsors/TomerAberbach" } }, - "node_modules/path-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz", - "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==", + "node_modules/parse-ms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", + "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", "dev": true, "license": "MIT", - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", "dev": true, "license": "MIT" }, - "node_modules/peek-readable": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz", - "integrity": "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==", + "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" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" } }, + "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/pg-connection-string": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", @@ -2963,43 +3528,60 @@ "dev": true, "license": "MIT" }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/pino": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-6.14.0.tgz", - "integrity": "sha512-iuhEDel3Z3hF9Jfe44DPXR8l07bhjuFY3GMHIXbjnY9XcafbyDDwl2sN2vw2GjMPf5Nkoe+OFao7ffn9SXaKDg==", + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/pino/-/pino-10.3.1.tgz", + "integrity": "sha512-r34yH/GlQpKZbU1BvFFqOjhISRo1MNx1tWYsYvmj6KIRHSPMT2+yHOEb1SG6NMvRoHRF0a07kCOox/9yakl1vg==", "dev": true, "license": "MIT", "dependencies": { - "fast-redact": "^3.0.0", - "fast-safe-stringify": "^2.0.8", - "flatstr": "^1.0.12", - "pino-std-serializers": "^3.1.0", - "process-warning": "^1.0.0", + "@pinojs/redact": "^0.4.0", + "atomic-sleep": "^1.0.0", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^3.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^5.0.0", "quick-format-unescaped": "^4.0.3", - "sonic-boom": "^1.0.2" + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^4.0.0" }, "bin": { "pino": "bin.js" } }, - "node_modules/pino-std-serializers": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-3.2.0.tgz", - "integrity": "sha512-EqX4pwDPrt3MuOAAUBMU0Tk5kR/YcCM5fNPEzgCO2zJ5HfX0vbiH9HbJglnyeQsN96Kznae6MWD47pZB5avTrg==", - "dev": true, - "license": "MIT" - }, - "node_modules/pino/node_modules/sonic-boom": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.4.1.tgz", - "integrity": "sha512-LRHh/A8tpW7ru89lrlkU4AszXt1dbwSjVWguGrmlxE7tawVmDBlI1PILMkXAxJTwqhgsEeTHzj36D5CmHgQmNg==", + "node_modules/pino-abstract-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz", + "integrity": "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==", "dev": true, "license": "MIT", "dependencies": { - "atomic-sleep": "^1.0.0", - "flatstr": "^1.0.12" + "split2": "^4.0.0" } }, + "node_modules/pino-std-serializers": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.1.0.tgz", + "integrity": "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==", + "dev": true, + "license": "MIT" + }, "node_modules/pluralize": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", @@ -3010,6 +3592,19 @@ "node": ">=4" } }, + "node_modules/powershell-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/powershell-utils/-/powershell-utils-0.1.0.tgz", + "integrity": "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/prebuild-install": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", @@ -3048,21 +3643,37 @@ "node": ">= 0.8" } }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "node_modules/pretty-ms": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz", + "integrity": "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==", "dev": true, "license": "MIT", + "dependencies": { + "parse-ms": "^4.0.0" + }, "engines": { - "node": ">= 0.6.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/process-warning": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-1.0.0.tgz", - "integrity": "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz", + "integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], "license": "MIT" }, "node_modules/proxy-addr": { @@ -3090,22 +3701,26 @@ "once": "^1.3.1" } }, - "node_modules/qs": { - "version": "6.15.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz", - "integrity": "sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==", + "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, - "license": "BSD-3-Clause", - "dependencies": { - "es-define-property": "^1.0.1", - "side-channel": "^1.1.1" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "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/quick-format-unescaped": { "version": "4.0.4", @@ -3114,40 +3729,20 @@ "dev": true, "license": "MIT" }, - "node_modules/random-bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/raw-body": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", - "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", "dev": true, "license": "MIT", "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", + "iconv-lite": "~0.7.0", "unpipe": "~1.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.10" } }, "node_modules/rc": { @@ -3167,37 +3762,42 @@ } }, "node_modules/readable-stream": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", - "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "license": "MIT", "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 6" } }, - "node_modules/readable-web-to-node-stream": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.4.tgz", - "integrity": "sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw==", + "node_modules/readdirp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", "dev": true, "license": "MIT", - "dependencies": { - "readable-stream": "^4.7.0" - }, "engines": { - "node": ">=8" + "node": ">= 20.19.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12.13.0" } }, "node_modules/rechoir": { @@ -3213,15 +3813,12 @@ "node": ">= 10.13.0" } }, - "node_modules/require-all": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/require-all/-/require-all-3.0.0.tgz", - "integrity": "sha512-jPGN876lc5exWYrMcgZSd7U42P0PmVQzxnQB13fCSzmyGnqQWW4WUz5DosZ/qe24hz+5o9lSvW2epBNZ1xa6Fw==", + "node_modules/reflect-metadata": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } + "license": "Apache-2.0" }, "node_modules/resolve": { "version": "1.22.12", @@ -3255,18 +3852,79 @@ "node": ">=8" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, "license": "MIT", "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/run-applescript": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/safe-buffer": { @@ -3290,6 +3948,16 @@ ], "license": "MIT" }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -3310,96 +3978,6 @@ "node": ">=10" } }, - "node_modules/send": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", - "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.1", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "~2.4.1", - "range-parser": "~1.2.1", - "statuses": "~2.0.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, - "license": "MIT" - }, - "node_modules/send/node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/sentence-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz", - "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case-first": "^2.0.2" - } - }, - "node_modules/serve-static": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", - "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "~0.19.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-static/node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -3407,89 +3985,42 @@ "dev": true, "license": "ISC" }, - "node_modules/side-channel": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", - "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.4", - "side-channel-list": "^1.0.1", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", - "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "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": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.4" + "shebang-regex": "^3.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "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", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, + "license": "ISC", "engines": { - "node": ">= 0.4" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, "node_modules/simple-concat": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", @@ -3538,28 +4069,37 @@ } }, "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/slashes": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/slashes/-/slashes-3.0.12.tgz", + "integrity": "sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA==", + "dev": true, + "license": "ISC" + }, "node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-8.0.0.tgz", + "integrity": "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" + "ansi-styles": "^6.2.3", + "is-fullwidth-code-point": "^5.1.0" }, "engines": { - "node": ">=10" + "node": ">=20" }, "funding": { "url": "https://github.com/chalk/slice-ansi?sponsor=1" @@ -3575,25 +4115,37 @@ "node": ">=8.0.0" } }, - "node_modules/snake-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", - "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "node_modules/sonic-boom": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.1.tgz", + "integrity": "sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==", "dev": true, "license": "MIT", "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" + "atomic-sleep": "^1.0.0" } }, - "node_modules/sonic-boom": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-2.8.0.tgz", - "integrity": "sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg==", + "node_modules/split-lines": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/split-lines/-/split-lines-3.0.0.tgz", + "integrity": "sha512-d0TpRBL/VfKDXsk8JxPF7zgF5pCUDdBMSlEL36xBgVeaX448t+yGXcJaikUyzkoKOJ0l6KpMfygzJU9naIuivw==", "dev": true, "license": "MIT", - "dependencies": { - "atomic-sleep": "^1.0.0" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 10.x" } }, "node_modules/statuses": { @@ -3617,31 +4169,49 @@ } }, "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.1.tgz", + "integrity": "sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "get-east-asian-width": "^1.5.0", + "strip-ansi": "^7.1.2" }, "engines": { - "node": ">=8" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/stringify-attributes": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/stringify-attributes/-/stringify-attributes-2.0.0.tgz", - "integrity": "sha512-wrVfRV6sCCB6wr3gx8OgKsp/9dSWWbKr8ifLfOxEcd/BBoa8d5pAf4BZb/jQW1JZnoZImjvUdxdo3ikYHZmYiw==", + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "dev": true, "license": "MIT", "dependencies": { - "escape-goat": "^2.0.0" + "ansi-regex": "^6.2.2" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/strip-ansi": { @@ -3657,6 +4227,19 @@ "node": ">=8" } }, + "node_modules/strip-final-newline": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", + "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -3668,17 +4251,16 @@ } }, "node_modules/strtok3": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz", - "integrity": "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==", + "version": "10.3.5", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.5.tgz", + "integrity": "sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA==", "dev": true, "license": "MIT", "dependencies": { - "@tokenizer/token": "^0.3.0", - "peek-readable": "^4.1.0" + "@tokenizer/token": "^0.3.0" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "type": "github", @@ -3686,16 +4268,13 @@ } }, "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", + "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", "dev": true, "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/chalk/supports-color?sponsor=1" @@ -3744,21 +4323,6 @@ "node": ">=6" } }, - "node_modules/tar-stream/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/tarn": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/tarn/-/tarn-3.1.0.tgz", @@ -3769,19 +4333,49 @@ "node": ">=8.0.0" } }, - "node_modules/term-size": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", - "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", + "node_modules/tempura": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/tempura/-/tempura-0.4.1.tgz", + "integrity": "sha512-NQ4Cs23jM6UUp3CcS5vjmyjTC6dtA5EsflBG2cyG0wZvP65AV26tJ920MGvTRYIImCY13RBpOhc7q4/pu+FG5A==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=10" + } + }, + "node_modules/terminal-size": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/terminal-size/-/terminal-size-4.0.1.tgz", + "integrity": "sha512-avMLDQpUI9I5XFrklECw1ZEUPJhqzcwSWsyyI8blhRLT+8N1jLJWLWWYQpB2q2xthq8xDvjZPISVh53T/+CLYQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/thread-stream": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-4.2.0.tgz", + "integrity": "sha512-e2zZ96wSChazBsbENf/Pcm/4swHt2cEKQ92rhUjkL9GCKiTDJIaTBenjE/m9DXi0QBmTMDkFDdOomUy20A1tDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "real-require": "^1.0.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/thread-stream/node_modules/real-require": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-1.0.0.tgz", + "integrity": "sha512-P4nbQYQfePJxRSmY+v/KINxVucm4NF3p3s7pJveMTtom52FR4YGltUQLB8idDXwDDWW+eYrWDFbuzUnjoWHF7g==", + "dev": true, + "license": "MIT" + }, "node_modules/tildify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/tildify/-/tildify-2.0.0.tgz", @@ -3792,6 +4386,33 @@ "node": ">=8" } }, + "node_modules/tinyexec": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz", + "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, "node_modules/tmp-cache": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/tmp-cache/-/tmp-cache-1.1.0.tgz", @@ -3802,6 +4423,19 @@ "node": ">=6" } }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -3813,36 +4447,34 @@ } }, "node_modules/token-types": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz", - "integrity": "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.1.2.tgz", + "integrity": "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==", "dev": true, "license": "MIT", "dependencies": { + "@borewit/text-codec": "^0.2.1", "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" }, "engines": { - "node": ">=10" + "node": ">=14.16" }, "funding": { "type": "github", "url": "https://github.com/sponsors/Borewit" } }, - "node_modules/truncatise": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/truncatise/-/truncatise-0.0.8.tgz", - "integrity": "sha512-cXzueh9pzBCsLzhToB4X4gZCb3KYkrsAcBAX97JnazE74HOl3cpBJYEV7nabHeG/6/WXCU5Yujlde/WPBUwnsg==", - "dev": true, - "license": "MIT" - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "node_modules/ts-morph": { + "version": "27.0.2", + "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-27.0.2.tgz", + "integrity": "sha512-fhUhgeljcrdZ+9DZND1De1029PrE+cMkIP7ooqkLRTrRLTqcki2AstsyJm0vRNbTbVCNJ0idGlbBrfqc7/nA8w==", "dev": true, - "license": "0BSD" + "license": "MIT", + "dependencies": { + "@ts-morph/common": "~0.28.1", + "code-block-writer": "^13.0.3" + } }, "node_modules/tsx": { "version": "4.22.4", @@ -3876,41 +4508,23 @@ "node": "*" } }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz", + "integrity": "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==", "dev": true, "license": "MIT", "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "content-type": "^2.0.0", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" }, "engines": { - "node": ">= 0.6" - } - }, - "node_modules/type-is/node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/typescript": { @@ -3919,6 +4533,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3927,17 +4542,17 @@ "node": ">=14.17" } }, - "node_modules/uid-safe": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", - "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "node_modules/uint8array-extras": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz", + "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==", "dev": true, "license": "MIT", - "dependencies": { - "random-bytes": "~1.0.0" - }, "engines": { - "node": ">= 0.8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/undici-types": { @@ -3947,14 +4562,17 @@ "dev": true, "license": "MIT" }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", "dev": true, "license": "MIT", "engines": { - "node": ">= 10.0.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/unpipe": { @@ -3967,66 +4585,84 @@ "node": ">= 0.8" } }, - "node_modules/upper-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz", - "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==", + "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/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "dev": true, "license": "MIT", - "dependencies": { - "tslib": "^2.0.3" + "engines": { + "node": ">= 0.8" } }, - "node_modules/upper-case-first": { + "node_modules/which": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz", - "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "tslib": "^2.0.3" + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" } }, - "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/validator": { - "version": "13.15.35", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.35.tgz", - "integrity": "sha512-TQ5pAGhd5whStmqWvYF4OjQROlmv9SMFVt37qoCBdqRffuuklWYQlCNnEs2ZaIBD1kZRNnikiZOS1eqgkar0iw==", + "node_modules/wrap-ansi": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-10.0.0.tgz", + "integrity": "sha512-SGcvg80f0wUy2/fXES19feHMz8E0JoXv2uNgHOu4Dgi2OrCy1lqwFYEJz1BLbDI0exjPMe/ZdzZ/YpGECBG/aQ==", "dev": true, "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.3", + "string-width": "^8.2.0", + "strip-ansi": "^7.1.2" + }, "engines": { - "node": ">= 0.10" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "ansi-regex": "^6.2.2" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/wrappy": { @@ -4035,6 +4671,72 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true, "license": "ISC" + }, + "node_modules/wsl-utils": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.3.1.tgz", + "integrity": "sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0", + "powershell-utils": "^0.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs-parser": { + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" + } + }, + "node_modules/yoctocolors": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz", + "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/youch": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/youch/-/youch-4.1.1.tgz", + "integrity": "sha512-mxW3qiSnl+GRxXsaUMzv2Mbada1Y8CDltET9UxejDQe6DBYlSekghl5U5K0ReAikcHDi0G1vKZEmmo/NWAGKLA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@poppinss/colors": "^4.1.6", + "@poppinss/dumper": "^0.7.0", + "@speed-highlight/core": "^1.2.14", + "cookie-es": "^3.0.1", + "youch-core": "^0.3.3" + } + }, + "node_modules/youch-core": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/youch-core/-/youch-core-0.3.3.tgz", + "integrity": "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@poppinss/exception": "^1.2.2", + "error-stack-parser-es": "^1.0.5" + } } } } diff --git a/package.json b/package.json index fa7852e..02ddc32 100644 --- a/package.json +++ b/package.json @@ -1,30 +1,36 @@ { "name": "@ezycourse/adonis-email-guard", - "version": "0.1.0", - "description": "AdonisJS v5 package: email validation (syntax, MX, SMTP, disposable, spam-trap) + DB-backed suppression list with configurable table and auto-create.", - "main": "build/providers/EmailGuardProvider.js", - "types": "build/adonis-typings/index.d.ts", + "version": "1.0.0", + "description": "AdonisJS v7 package: email validation (syntax, MX, SMTP, disposable, spam-trap) + DB-backed suppression list with configurable table and auto-create.", + "type": "module", + "main": "./build/index.js", + "types": "./build/index.d.ts", "files": [ - "build/adonis-typings", - "build/providers", - "build/src", - "build/instructions.js", - "build/instructions.md", - "build/templates" + "build", + "!build/bin", + "!build/tests" ], + "exports": { + ".": "./build/index.js", + "./email_guard_provider": "./build/providers/email_guard_provider.js", + "./services/main": "./build/services/main.js", + "./types": "./build/src/types.js" + }, "scripts": { + "clean": "rm -rf build", + "copy:stubs": "mkdir -p build/stubs/config && cp stubs/config/email_guard.stub build/stubs/config/email_guard.stub", + "compile": "npm run clean && tsc && npm run copy:stubs", "build": "npm run compile", - "compile": "rm -rf build && tsc && npm run copy:assets", - "copy:assets": "cp instructions.md build/ && mkdir -p build/templates && cp templates/config.txt build/templates/", "prepublishOnly": "npm run build && npm test", - "lint": "eslint . --ext=.ts", + "test": "node --import=tsx --test tests/*.spec.ts", + "typecheck": "tsc --noEmit", "format": "prettier --write .", - "test": "tsx --test test/*.spec.ts" + "lint": "eslint . --ext=.ts" }, "keywords": [ "adonisjs", "adonis", - "adonis5", + "adonis7", "email", "email-validation", "suppression-list", @@ -44,36 +50,24 @@ }, "homepage": "https://github.com/shakilhossain-cse/adonis-email-guard#readme", "peerDependencies": { - "@adonisjs/core": "^5.0.0", - "@adonisjs/lucid": "^18.0.0" + "@adonisjs/core": "^7.0.0", + "@adonisjs/lucid": "^22.0.0" }, "devDependencies": { - "@adonisjs/core": "^5.9.0", - "@adonisjs/lucid": "^18.4.0", + "@adonisjs/assembler": "^8.4.0", + "@adonisjs/core": "^7.3.4", + "@adonisjs/lucid": "^22.4.2", "@types/better-sqlite3": "^7.6.0", - "@types/node": "^20.0.0", - "better-sqlite3": "^11.0.0", + "@types/node": "^22.0.0", + "better-sqlite3": "^12.0.0", "knex": "^3.0.0", + "luxon": "^3.4.4", + "reflect-metadata": "^0.2.2", "tsx": "^4.7.0", - "typescript": "^5.0.0" + "typescript": "^5.4.0" }, "engines": { - "node": ">=18.0.0" - }, - "adonisjs": { - "instructionsMd": "./build/instructions.md", - "types": "@ezycourse/adonis-email-guard", - "providers": [ - "@ezycourse/adonis-email-guard" - ], - "templates": { - "config": [ - { - "src": "config/email-guard.txt", - "dest": "email-guard" - } - ] - } + "node": ">=20.6.0" }, "publishConfig": { "access": "restricted", diff --git a/providers/EmailGuardProvider.ts b/providers/EmailGuardProvider.ts deleted file mode 100644 index 5207dac..0000000 --- a/providers/EmailGuardProvider.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type {ApplicationContract} from '@ioc:Adonis/Core/Application'; - -export default class EmailGuardProvider { - public static needsApplication = true; - - constructor(protected app: ApplicationContract) {} - - public register(): void { - this.app.container.singleton('Adonis/Addons/EmailGuard', () => { - const config = this.app.config.get('email-guard', {}); - const db = this.app.container.use('Adonis/Lucid/Database'); - const logger = this.app.container.use('Adonis/Core/Logger'); - - const {EmailGuard} = require('../src/EmailGuard'); - return new EmailGuard(config, db, logger); - }); - } - - public async boot(): Promise { - const config = this.app.config.get('email-guard', {}); - if (config.autoCreateTable === false) return; - - const guard = this.app.container.use('Adonis/Addons/EmailGuard'); - const logger = this.app.container.use('Adonis/Core/Logger'); - - try { - await guard.ensureTable(); - } catch (err) { - logger.error( - {err}, - 'adonis-email-guard: failed to ensure suppression table exists. Disable autoCreateTable or create the table manually.' - ); - } - } -} diff --git a/providers/email_guard_provider.ts b/providers/email_guard_provider.ts new file mode 100644 index 0000000..2f39720 --- /dev/null +++ b/providers/email_guard_provider.ts @@ -0,0 +1,40 @@ +import type { ApplicationService } from '@adonisjs/core/types' + +import { EmailGuard } from '../src/email_guard.js' +import type { EmailGuardConfig } from '../src/types.js' + +declare module '@adonisjs/core/types' { + export interface ContainerBindings { + emailGuard: EmailGuard + } +} + +export default class EmailGuardProvider { + constructor(protected app: ApplicationService) {} + + register(): void { + this.app.container.singleton('emailGuard', async (resolver) => { + const config = this.app.config.get('email_guard', {}) + const db = await resolver.make('lucid.db') + const logger = await resolver.make('logger') + return new EmailGuard(config, db, logger) + }) + } + + async boot(): Promise { + const config = this.app.config.get('email_guard', {}) + if (config.autoCreateTable === false) return + + const guard = await this.app.container.make('emailGuard') + const logger = await this.app.container.make('logger') + + try { + await guard.ensureTable() + } catch (err) { + logger.error( + { err }, + 'adonis-email-guard: failed to ensure suppression table exists. Disable autoCreateTable or create the table manually.' + ) + } + } +} diff --git a/services/main.ts b/services/main.ts new file mode 100644 index 0000000..9d934f4 --- /dev/null +++ b/services/main.ts @@ -0,0 +1,10 @@ +import app from '@adonisjs/core/services/app' +import type { EmailGuard } from '../src/email_guard.js' + +let emailGuard: EmailGuard + +await app.booted(async () => { + emailGuard = await app.container.make('emailGuard') +}) + +export { emailGuard as default } diff --git a/src/Validator/index.ts b/src/Validator/index.ts deleted file mode 100644 index 9263ebd..0000000 --- a/src/Validator/index.ts +++ /dev/null @@ -1,228 +0,0 @@ -import * as dns from 'dns/promises'; -import * as net from 'net'; - -import type { - EmailValidationResult, - ValidateEmailOptions, -} from '@ioc:Adonis/Addons/EmailGuard'; - -import { - DISPOSABLE_DOMAINS, - POPULAR_DOMAINS, - SPAM_TRAP_DOMAINS, - SPAM_TRAP_LOCALPARTS, -} from './disposable-domains'; - -const SYNTAX_RE = - /^(?=.{1,254}$)(?=.{1,64}@)[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.)+[A-Za-z]{2,}$/; - -export type ValidatorConstructorOptions = { - checkSmtp?: boolean; - fromAddress?: string; - smtpTimeoutMs?: number; - extraDisposableDomains?: string[]; - extraSpamTrapDomains?: string[]; -}; - -export class EmailValidator { - private readonly disposable: Set; - private readonly spamTrap: Set; - private readonly defaultOptions: Required< - Pick - > & {fromAddress?: string}; - - constructor(opts: ValidatorConstructorOptions = {}) { - this.disposable = new Set([ - ...DISPOSABLE_DOMAINS, - ...(opts.extraDisposableDomains ?? []).map(d => d.toLowerCase()), - ]); - this.spamTrap = new Set([ - ...SPAM_TRAP_DOMAINS, - ...(opts.extraSpamTrapDomains ?? []).map(d => d.toLowerCase()), - ]); - this.defaultOptions = { - checkSmtp: opts.checkSmtp ?? false, - smtpTimeoutMs: opts.smtpTimeoutMs ?? 5000, - fromAddress: opts.fromAddress, - }; - } - - public checkSyntax(email: string): boolean { - return typeof email === 'string' && SYNTAX_RE.test(email); - } - - public isDisposableDomain(domain: string): boolean { - return this.disposable.has(domain.toLowerCase()); - } - - public isSpamTrap(email: string): boolean { - const [local, domain] = email.toLowerCase().split('@'); - if (!domain) return false; - if (this.spamTrap.has(domain)) return true; - if (SPAM_TRAP_LOCALPARTS.includes(local)) return true; - return false; - } - - public suggestDomain(domain: string): string | undefined { - const d = domain.toLowerCase(); - if (POPULAR_DOMAINS.includes(d)) return undefined; - - let best: {domain: string; dist: number} | undefined; - for (const candidate of POPULAR_DOMAINS) { - const dist = levenshtein(d, candidate); - if (dist === 0) return undefined; - if (!best || dist < best.dist) best = {domain: candidate, dist}; - } - if (best && best.dist <= 2 && best.dist / best.domain.length <= 0.3) { - return best.domain; - } - return undefined; - } - - public async resolveMxHost(domain: string): Promise { - try { - const records = await dns.resolveMx(domain); - if (!records.length) return undefined; - records.sort((a, b) => a.priority - b.priority); - return records[0].exchange; - } catch { - return undefined; - } - } - - public async validate( - email: string, - options: ValidateEmailOptions = {} - ): Promise { - const merged = {...this.defaultOptions, ...options}; - - const result: EmailValidationResult = { - valid: false, - email, - checks: {syntax: false, mx: false, smtp: null, disposable: false, spamTrap: false}, - }; - - if (!this.checkSyntax(email)) { - result.reason = 'Invalid email syntax'; - return result; - } - result.checks.syntax = true; - - const domain = email.split('@')[1].toLowerCase(); - - const suggestion = this.suggestDomain(domain); - if (suggestion) result.suggestion = `${email.split('@')[0]}@${suggestion}`; - - if (this.isDisposableDomain(domain)) { - result.checks.disposable = true; - result.reason = 'Disposable email domain'; - return result; - } - - if (this.isSpamTrap(email)) { - result.checks.spamTrap = true; - result.reason = 'Known spam trap address'; - return result; - } - - const mxHost = await this.resolveMxHost(domain); - if (!mxHost) { - result.reason = 'No MX records found for domain'; - return result; - } - result.checks.mx = true; - result.mxHost = mxHost; - - if (merged.checkSmtp) { - const probe = await smtpProbe( - mxHost, - email, - merged.fromAddress || `verify@${domain}`, - merged.smtpTimeoutMs - ); - result.checks.smtp = probe.ok; - if (!probe.ok) { - result.reason = probe.reason || 'SMTP handshake failed'; - return result; - } - } - - result.valid = true; - return result; - } -} - -async function smtpProbe( - mxHost: string, - email: string, - fromAddress: string, - timeoutMs: number -): Promise<{ok: boolean; reason?: string}> { - return new Promise(resolve => { - const socket = net.createConnection(25, mxHost); - let stage = 0; - let buffer = ''; - let settled = false; - - const finish = (ok: boolean, reason?: string) => { - if (settled) return; - settled = true; - try { - socket.write('QUIT\r\n'); - } catch { - /* noop */ - } - socket.destroy(); - resolve({ok, reason}); - }; - - socket.setTimeout(timeoutMs); - socket.on('timeout', () => finish(false, 'SMTP timeout')); - socket.on('error', err => finish(false, `SMTP error: ${err.message}`)); - - socket.on('data', chunk => { - buffer += chunk.toString('utf8'); - if (!buffer.endsWith('\r\n')) return; - const line = buffer.trim().split('\r\n').pop() || ''; - const code = parseInt(line.slice(0, 3), 10); - buffer = ''; - - if (stage === 0) { - if (code !== 220) return finish(false, `Bad greeting: ${line}`); - stage = 1; - socket.write(`EHLO ${fromAddress.split('@')[1] || 'localhost'}\r\n`); - } else if (stage === 1) { - if (code !== 250) return finish(false, `EHLO rejected: ${line}`); - stage = 2; - socket.write(`MAIL FROM:<${fromAddress}>\r\n`); - } else if (stage === 2) { - if (code !== 250) return finish(false, `MAIL FROM rejected: ${line}`); - stage = 3; - socket.write(`RCPT TO:<${email}>\r\n`); - } else if (stage === 3) { - if (code === 250 || code === 251) return finish(true); - return finish(false, `RCPT TO rejected (${code}): ${line}`); - } - }); - }); -} - -function levenshtein(a: string, b: string): number { - if (a === b) return 0; - if (!a.length) return b.length; - if (!b.length) return a.length; - - const prev = new Array(b.length + 1); - const curr = new Array(b.length + 1); - for (let j = 0; j <= b.length; j++) prev[j] = j; - - for (let i = 1; i <= a.length; i++) { - curr[0] = i; - for (let j = 1; j <= b.length; j++) { - const cost = a.charCodeAt(i - 1) === b.charCodeAt(j - 1) ? 0 : 1; - curr[j] = Math.min(curr[j - 1] + 1, prev[j] + 1, prev[j - 1] + cost); - } - for (let j = 0; j <= b.length; j++) prev[j] = curr[j]; - } - return prev[b.length]; -} diff --git a/src/define_config.ts b/src/define_config.ts new file mode 100644 index 0000000..35d1cbd --- /dev/null +++ b/src/define_config.ts @@ -0,0 +1,5 @@ +import type { EmailGuardConfig } from './types.js' + +export function defineConfig(config: EmailGuardConfig): EmailGuardConfig { + return config +} diff --git a/src/Validator/disposable-domains.ts b/src/disposable_domains.ts similarity index 100% rename from src/Validator/disposable-domains.ts rename to src/disposable_domains.ts diff --git a/src/EmailGuard.ts b/src/email_guard.ts similarity index 56% rename from src/EmailGuard.ts rename to src/email_guard.ts index f8fb2c6..630fcd6 100644 --- a/src/EmailGuard.ts +++ b/src/email_guard.ts @@ -1,26 +1,27 @@ -import type {DatabaseContract} from '@ioc:Adonis/Lucid/Database'; -import type {LoggerContract} from '@ioc:Adonis/Core/Logger'; +import type { Database } from '@adonisjs/lucid/database' +import type { Logger } from '@adonisjs/core/logger' + import type { EmailGuardConfig, - EmailGuardContract, + EmailGuardService, EmailValidationResult, SuppressionReason, SuppressionRow, SuppressionSource, ValidateEmailOptions, -} from '@ioc:Adonis/Addons/EmailGuard'; +} from './types.js' -import {EmailValidator} from './Validator'; -import {SuppressionService} from './Suppression'; +import { EmailValidator } from './validator.js' +import { SuppressionService } from './suppression.js' -export class EmailGuard implements EmailGuardContract { - private readonly validator: EmailValidator; - private readonly suppression: SuppressionService; +export class EmailGuard implements EmailGuardService { + private readonly validator: EmailValidator + private readonly suppression: SuppressionService constructor( config: EmailGuardConfig, - db: DatabaseContract, - private readonly logger?: LoggerContract + db: Database, + private readonly logger?: Logger ) { this.validator = new EmailValidator({ checkSmtp: config.validator?.checkSmtp, @@ -28,27 +29,27 @@ export class EmailGuard implements EmailGuardContract { smtpTimeoutMs: config.validator?.smtpTimeoutMs, extraDisposableDomains: config.extraDisposableDomains, extraSpamTrapDomains: config.extraSpamTrapDomains, - }); + }) this.suppression = new SuppressionService(db, { tableName: config.tableName ?? 'email_suppressions', connection: config.connection, - }); + }) } public validate( email: string, options: ValidateEmailOptions = {} ): Promise { - return this.validator.validate(email, options); + return this.validator.validate(email, options) } public isSuppressed(email: string): Promise { - return this.suppression.isSuppressed(email); + return this.suppression.isSuppressed(email) } public find(email: string): Promise { - return this.suppression.find(email); + return this.suppression.find(email) } public suppress( @@ -57,53 +58,53 @@ export class EmailGuard implements EmailGuardContract { source: SuppressionSource = 'manual', metadata?: Record ): Promise { - return this.suppression.suppress(email, reason, source, metadata ?? null); + return this.suppression.suppress(email, reason, source, metadata ?? null) } public unsuppress(email: string): Promise { - return this.suppression.unsuppress(email); + return this.suppression.unsuppress(email) } public ensureTable(): Promise { - return this.suppression.ensureTable(); + return this.suppression.ensureTable() } public async check( email: string, - options: ValidateEmailOptions & {recordFailures?: boolean} = {} - ): Promise { - let suppressed = false; + options: ValidateEmailOptions & { recordFailures?: boolean } = {} + ): Promise { + let suppressed = false if (!options.skipSuppressionCheck) { - suppressed = await this.suppression.isSuppressed(email); + suppressed = await this.suppression.isSuppressed(email) } - const validation = await this.validator.validate(email, options); + const validation = await this.validator.validate(email, options) if (options.recordFailures && !validation.valid && !suppressed) { - const reason = mapReason(validation); + const reason = mapReason(validation) try { await this.suppression.suppress(email, reason, 'validator', { checks: validation.checks, reasonText: validation.reason, - }); - suppressed = true; + }) + suppressed = true } catch (err) { this.logger?.warn( - {err, email}, + { err, email }, 'adonis-email-guard: failed to record validation failure to suppression list' - ); + ) } } - return {...validation, suppressed}; + return { ...validation, suppressed } } } function mapReason(validation: EmailValidationResult): SuppressionReason { - if (!validation.checks.syntax) return 'invalid-syntax'; - if (validation.checks.disposable) return 'disposable'; - if (validation.checks.spamTrap) return 'spam-trap'; - if (!validation.checks.mx) return 'no-mx'; - if (validation.checks.smtp === false) return 'smtp-failed'; - return 'invalid-syntax'; + if (!validation.checks.syntax) return 'invalid-syntax' + if (validation.checks.disposable) return 'disposable' + if (validation.checks.spamTrap) return 'spam-trap' + if (!validation.checks.mx) return 'no-mx' + if (validation.checks.smtp === false) return 'smtp-failed' + return 'invalid-syntax' } diff --git a/src/Suppression/index.ts b/src/suppression.ts similarity index 54% rename from src/Suppression/index.ts rename to src/suppression.ts index 4777d79..1652fa1 100644 --- a/src/Suppression/index.ts +++ b/src/suppression.ts @@ -1,48 +1,49 @@ -import type {DatabaseContract, QueryClientContract} from '@ioc:Adonis/Lucid/Database'; -import type { - SuppressionReason, - SuppressionRow, - SuppressionSource, -} from '@ioc:Adonis/Addons/EmailGuard'; +import type { Database } from '@adonisjs/lucid/database' +import type { QueryClientContract } from '@adonisjs/lucid/types/database' + +import type { SuppressionReason, SuppressionRow, SuppressionSource } from './types.js' export type SuppressionServiceOptions = { - tableName: string; - connection?: string; -}; + tableName: string + connection?: string +} export class SuppressionService { - private readonly tableName: string; - private readonly connection?: string; - - constructor(private readonly db: DatabaseContract, opts: SuppressionServiceOptions) { - this.tableName = opts.tableName; - this.connection = opts.connection; + private readonly tableName: string + private readonly connection?: string + + constructor( + private readonly db: Database, + opts: SuppressionServiceOptions + ) { + this.tableName = opts.tableName + this.connection = opts.connection } private client(): QueryClientContract { - return this.connection ? this.db.connection(this.connection) : this.db.connection(); + return this.connection ? this.db.connection(this.connection) : this.db.connection() } private normalize(email: string): string { - return email.trim().toLowerCase(); + return email.trim().toLowerCase() } public async ensureTable(): Promise { - const client = this.client(); - const exists = await client.schema.hasTable(this.tableName); - if (exists) return; - - await client.schema.createTable(this.tableName, (table: any) => { - table.bigIncrements('id').primary(); - table.string('email', 320).notNullable().unique(); - table.string('reason', 64).nullable(); - table.string('source', 64).nullable(); - table.json('metadata').nullable(); - table.timestamp('created_at', {useTz: true}).notNullable(); - table.timestamp('updated_at', {useTz: true}).notNullable(); - table.index(['reason']); - table.index(['source']); - }); + const client = this.client() + const exists = await client.schema.hasTable(this.tableName) + if (exists) return + + await client.schema.createTable(this.tableName, (table) => { + table.bigIncrements('id').primary() + table.string('email', 320).notNullable().unique() + table.string('reason', 64).nullable() + table.string('source', 64).nullable() + table.json('metadata').nullable() + table.timestamp('created_at', { useTz: true }).notNullable() + table.timestamp('updated_at', { useTz: true }).notNullable() + table.index(['reason']) + table.index(['source']) + }) } public async isSuppressed(email: string): Promise { @@ -50,16 +51,16 @@ export class SuppressionService { .from(this.tableName) .where('email', this.normalize(email)) .select('id') - .first(); - return !!row; + .first() + return !!row } public async find(email: string): Promise { const row = await this.client() .from(this.tableName) .where('email', this.normalize(email)) - .first(); - return row ? this.hydrate(row) : null; + .first() + return row ? this.hydrate(row) : null } public async suppress( @@ -68,18 +69,18 @@ export class SuppressionService { source: SuppressionSource | null = 'manual', metadata: Record | null = null ): Promise { - const normalized = this.normalize(email); - const now = new Date(); - const client = this.client(); + const normalized = this.normalize(email) + const now = new Date() + const client = this.client() - const existing = await client.from(this.tableName).where('email', normalized).first(); - const meta = metadata !== null ? JSON.stringify(metadata) : null; + const existing = await client.from(this.tableName).where('email', normalized).first() + const meta = metadata !== null ? JSON.stringify(metadata) : null if (existing) { await client .from(this.tableName) .where('email', normalized) - .update({reason, source, metadata: meta, updated_at: now}); + .update({ reason, source, metadata: meta, updated_at: now }) } else { await client.table(this.tableName).insert({ email: normalized, @@ -88,26 +89,28 @@ export class SuppressionService { metadata: meta, created_at: now, updated_at: now, - }); + }) } - const row = await client.from(this.tableName).where('email', normalized).first(); - return this.hydrate(row); + const row = await client.from(this.tableName).where('email', normalized).first() + return this.hydrate(row) } public async unsuppress(email: string): Promise { const count = await this.client() .from(this.tableName) .where('email', this.normalize(email)) - .delete(); - return Number(count) > 0; + .delete() + return Number(count) > 0 } private hydrate(row: any): SuppressionRow { - let metadata: Record | null = null; + let metadata: Record | null = null if (row.metadata !== null && row.metadata !== undefined) { metadata = - typeof row.metadata === 'string' ? safeParseJson(row.metadata) : (row.metadata as Record); + typeof row.metadata === 'string' + ? safeParseJson(row.metadata) + : (row.metadata as Record) } return { id: Number(row.id), @@ -117,14 +120,14 @@ export class SuppressionService { metadata, created_at: row.created_at instanceof Date ? row.created_at : new Date(row.created_at), updated_at: row.updated_at instanceof Date ? row.updated_at : new Date(row.updated_at), - }; + } } } function safeParseJson(value: string): Record | null { try { - return JSON.parse(value); + return JSON.parse(value) } catch { - return null; + return null } } diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..26d8b1a --- /dev/null +++ b/src/types.ts @@ -0,0 +1,76 @@ +export type SuppressionReason = + | 'bounce' + | 'complaint' + | 'manual' + | 'invalid-syntax' + | 'no-mx' + | 'smtp-failed' + | 'disposable' + | 'spam-trap' + | 'unsubscribe' + | (string & {}) + +export type SuppressionSource = 'manual' | 'validator' | 'webhook' | (string & {}) + +export type ValidateEmailOptions = { + checkSmtp?: boolean + fromAddress?: string + smtpTimeoutMs?: number + skipSuppressionCheck?: boolean +} + +export type EmailValidationResult = { + valid: boolean + email: string + reason?: string + checks: { + syntax: boolean + mx: boolean + smtp: boolean | null + disposable: boolean + spamTrap: boolean + } + suggestion?: string + mxHost?: string +} + +export type SuppressionRow = { + id: number + email: string + reason: SuppressionReason | null + source: SuppressionSource | null + metadata: Record | null + created_at: Date + updated_at: Date +} + +export type EmailGuardConfig = { + tableName?: string + autoCreateTable?: boolean + connection?: string + validator?: { + checkSmtp?: boolean + fromAddress?: string + smtpTimeoutMs?: number + } + extraDisposableDomains?: string[] + extraSpamTrapDomains?: string[] +} + +export interface EmailGuardService { + validate(email: string, options?: ValidateEmailOptions): Promise + isSuppressed(email: string): Promise + suppress( + email: string, + reason?: SuppressionReason, + source?: SuppressionSource, + metadata?: Record + ): Promise + unsuppress(email: string): Promise + find(email: string): Promise + check( + email: string, + options?: ValidateEmailOptions & { recordFailures?: boolean } + ): Promise + ensureTable(): Promise +} diff --git a/src/validator.ts b/src/validator.ts new file mode 100644 index 0000000..ac6521d --- /dev/null +++ b/src/validator.ts @@ -0,0 +1,224 @@ +import * as dns from 'node:dns/promises' +import * as net from 'node:net' + +import type { EmailValidationResult, ValidateEmailOptions } from './types.js' +import { + DISPOSABLE_DOMAINS, + POPULAR_DOMAINS, + SPAM_TRAP_DOMAINS, + SPAM_TRAP_LOCALPARTS, +} from './disposable_domains.js' + +const SYNTAX_RE = + /^(?=.{1,254}$)(?=.{1,64}@)[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.)+[A-Za-z]{2,}$/ + +export type ValidatorConstructorOptions = { + checkSmtp?: boolean + fromAddress?: string + smtpTimeoutMs?: number + extraDisposableDomains?: string[] + extraSpamTrapDomains?: string[] +} + +export class EmailValidator { + private readonly disposable: Set + private readonly spamTrap: Set + private readonly defaultOptions: Required< + Pick + > & { fromAddress?: string } + + constructor(opts: ValidatorConstructorOptions = {}) { + this.disposable = new Set([ + ...DISPOSABLE_DOMAINS, + ...(opts.extraDisposableDomains ?? []).map((d) => d.toLowerCase()), + ]) + this.spamTrap = new Set([ + ...SPAM_TRAP_DOMAINS, + ...(opts.extraSpamTrapDomains ?? []).map((d) => d.toLowerCase()), + ]) + this.defaultOptions = { + checkSmtp: opts.checkSmtp ?? false, + smtpTimeoutMs: opts.smtpTimeoutMs ?? 5000, + fromAddress: opts.fromAddress, + } + } + + public checkSyntax(email: string): boolean { + return typeof email === 'string' && SYNTAX_RE.test(email) + } + + public isDisposableDomain(domain: string): boolean { + return this.disposable.has(domain.toLowerCase()) + } + + public isSpamTrap(email: string): boolean { + const [local, domain] = email.toLowerCase().split('@') + if (!domain) return false + if (this.spamTrap.has(domain)) return true + if (SPAM_TRAP_LOCALPARTS.includes(local)) return true + return false + } + + public suggestDomain(domain: string): string | undefined { + const d = domain.toLowerCase() + if (POPULAR_DOMAINS.includes(d)) return undefined + + let best: { domain: string; dist: number } | undefined + for (const candidate of POPULAR_DOMAINS) { + const dist = levenshtein(d, candidate) + if (dist === 0) return undefined + if (!best || dist < best.dist) best = { domain: candidate, dist } + } + if (best && best.dist <= 2 && best.dist / best.domain.length <= 0.3) { + return best.domain + } + return undefined + } + + public async resolveMxHost(domain: string): Promise { + try { + const records = await dns.resolveMx(domain) + if (!records.length) return undefined + records.sort((a, b) => a.priority - b.priority) + return records[0].exchange + } catch { + return undefined + } + } + + public async validate( + email: string, + options: ValidateEmailOptions = {} + ): Promise { + const merged = { ...this.defaultOptions, ...options } + + const result: EmailValidationResult = { + valid: false, + email, + checks: { syntax: false, mx: false, smtp: null, disposable: false, spamTrap: false }, + } + + if (!this.checkSyntax(email)) { + result.reason = 'Invalid email syntax' + return result + } + result.checks.syntax = true + + const domain = email.split('@')[1].toLowerCase() + + const suggestion = this.suggestDomain(domain) + if (suggestion) result.suggestion = `${email.split('@')[0]}@${suggestion}` + + if (this.isDisposableDomain(domain)) { + result.checks.disposable = true + result.reason = 'Disposable email domain' + return result + } + + if (this.isSpamTrap(email)) { + result.checks.spamTrap = true + result.reason = 'Known spam trap address' + return result + } + + const mxHost = await this.resolveMxHost(domain) + if (!mxHost) { + result.reason = 'No MX records found for domain' + return result + } + result.checks.mx = true + result.mxHost = mxHost + + if (merged.checkSmtp) { + const probe = await smtpProbe( + mxHost, + email, + merged.fromAddress || `verify@${domain}`, + merged.smtpTimeoutMs + ) + result.checks.smtp = probe.ok + if (!probe.ok) { + result.reason = probe.reason || 'SMTP handshake failed' + return result + } + } + + result.valid = true + return result + } +} + +async function smtpProbe( + mxHost: string, + email: string, + fromAddress: string, + timeoutMs: number +): Promise<{ ok: boolean; reason?: string }> { + return new Promise((resolve) => { + const socket = net.createConnection(25, mxHost) + let stage = 0 + let buffer = '' + let settled = false + + const finish = (ok: boolean, reason?: string) => { + if (settled) return + settled = true + try { + socket.write('QUIT\r\n') + } catch { + /* noop */ + } + socket.destroy() + resolve({ ok, reason }) + } + + socket.setTimeout(timeoutMs) + socket.on('timeout', () => finish(false, 'SMTP timeout')) + socket.on('error', (err) => finish(false, `SMTP error: ${err.message}`)) + + socket.on('data', (chunk) => { + buffer += chunk.toString('utf8') + if (!buffer.endsWith('\r\n')) return + const line = buffer.trim().split('\r\n').pop() || '' + const code = Number.parseInt(line.slice(0, 3), 10) + buffer = '' + + if (stage === 0) { + if (code !== 220) return finish(false, `Bad greeting: ${line}`) + stage = 1 + socket.write(`EHLO ${fromAddress.split('@')[1] || 'localhost'}\r\n`) + } else if (stage === 1) { + if (code !== 250) return finish(false, `EHLO rejected: ${line}`) + stage = 2 + socket.write(`MAIL FROM:<${fromAddress}>\r\n`) + } else if (stage === 2) { + if (code !== 250) return finish(false, `MAIL FROM rejected: ${line}`) + stage = 3 + socket.write(`RCPT TO:<${email}>\r\n`) + } else if (stage === 3) { + if (code === 250 || code === 251) return finish(true) + return finish(false, `RCPT TO rejected (${code}): ${line}`) + } + }) + }) +} + +function levenshtein(a: string, b: string): number { + if (a === b) return 0 + if (!a.length) return b.length + if (!b.length) return a.length + + const prev = new Array(b.length + 1) + const curr = new Array(b.length + 1) + for (let j = 0; j <= b.length; j++) prev[j] = j + + for (let i = 1; i <= a.length; i++) { + curr[0] = i + for (let j = 1; j <= b.length; j++) { + const cost = a.charCodeAt(i - 1) === b.charCodeAt(j - 1) ? 0 : 1 + curr[j] = Math.min(curr[j - 1] + 1, prev[j] + 1, prev[j - 1] + cost) + } + for (let j = 0; j <= b.length; j++) prev[j] = curr[j] + } + return prev[b.length] +} diff --git a/templates/config.txt b/stubs/config/email_guard.stub similarity index 87% rename from templates/config.txt rename to stubs/config/email_guard.stub index b4edf4f..d37ba9c 100644 --- a/templates/config.txt +++ b/stubs/config/email_guard.stub @@ -1,6 +1,9 @@ -import {EmailGuardConfig} from '@ioc:Adonis/Addons/EmailGuard'; +{{{ + exports({ to: app.configPath('email_guard.ts') }) +}}} +import { defineConfig } from '@ezycourse/adonis-email-guard' -const emailGuardConfig: EmailGuardConfig = { +const emailGuardConfig = defineConfig({ /* |-------------------------------------------------------------------------- | Suppression table @@ -48,6 +51,6 @@ const emailGuardConfig: EmailGuardConfig = { */ extraDisposableDomains: [], extraSpamTrapDomains: [], -}; +}) -export default emailGuardConfig; +export default emailGuardConfig diff --git a/stubs/main.ts b/stubs/main.ts new file mode 100644 index 0000000..48a6046 --- /dev/null +++ b/stubs/main.ts @@ -0,0 +1,3 @@ +import { fileURLToPath } from 'node:url' + +export const stubsRoot = fileURLToPath(new URL('./', import.meta.url)) diff --git a/test/email-guard.spec.ts b/test/email-guard.spec.ts deleted file mode 100644 index 9839b87..0000000 --- a/test/email-guard.spec.ts +++ /dev/null @@ -1,81 +0,0 @@ -import {after, beforeEach, describe, it} from 'node:test'; -import assert from 'node:assert/strict'; - -import {EmailGuard} from '../src/EmailGuard'; -import {makeFakeDatabase, makeKnex} from './helpers'; - -describe('EmailGuard facade', () => { - const k = makeKnex(); - const db = makeFakeDatabase(k); - let guard: EmailGuard; - - beforeEach(async () => { - await k.schema.dropTableIfExists('email_suppressions'); - guard = new EmailGuard({tableName: 'email_suppressions'}, db); - await guard.ensureTable(); - }); - - after(async () => { - await k.destroy(); - }); - - describe('check()', () => { - it('reports suppressed=true when email is in the suppression list', async () => { - await guard.suppress('blocked@mailinator.com', 'manual'); - const r = await guard.check('blocked@mailinator.com'); - assert.equal(r.suppressed, true); - }); - - it('skips suppression lookup when skipSuppressionCheck is true', async () => { - await guard.suppress('blocked@mailinator.com', 'manual'); - const r = await guard.check('blocked@mailinator.com', {skipSuppressionCheck: true}); - assert.equal(r.suppressed, false); - }); - - it('records validation failures when recordFailures=true', async () => { - const r = await guard.check('user@mailinator.com', {recordFailures: true}); - assert.equal(r.valid, false); - assert.equal(r.checks.disposable, true); - assert.equal(r.suppressed, true); - - const row = await guard.find('user@mailinator.com'); - assert.ok(row); - assert.equal(row?.reason, 'disposable'); - assert.equal(row?.source, 'validator'); - }); - - it('does not record when recordFailures is omitted', async () => { - const r = await guard.check('user@mailinator.com'); - assert.equal(r.valid, false); - assert.equal(r.suppressed, false); - assert.equal(await guard.find('user@mailinator.com'), null); - }); - - it('records bad syntax with reason=invalid-syntax', async () => { - const r = await guard.check('not-an-email', {recordFailures: true}); - assert.equal(r.valid, false); - assert.equal(r.suppressed, true); - const row = await guard.find('not-an-email'); - assert.equal(row?.reason, 'invalid-syntax'); - }); - - it('records spam-trap addresses', async () => { - const r = await guard.check('abuse@anywhere.com', {recordFailures: true}); - assert.equal(r.suppressed, true); - const row = await guard.find('abuse@anywhere.com'); - assert.equal(row?.reason, 'spam-trap'); - }); - }); - - describe('extra block lists merge into validator', () => { - it('accepts custom disposable domains via config', async () => { - const g = new EmailGuard( - {tableName: 'email_suppressions', extraDisposableDomains: ['my-tmp.test']}, - db - ); - const r = await g.validate('foo@my-tmp.test'); - assert.equal(r.valid, false); - assert.equal(r.checks.disposable, true); - }); - }); -}); diff --git a/test/helpers.ts b/test/helpers.ts deleted file mode 100644 index a992696..0000000 --- a/test/helpers.ts +++ /dev/null @@ -1,26 +0,0 @@ -import knex, {Knex} from 'knex'; - -/** - * Minimal DatabaseContract-shaped facade over a knex instance. - * Just enough surface for SuppressionService to work against SQLite in tests. - */ -export function makeFakeDatabase(k: Knex) { - const client = { - get schema() { - return k.schema; - }, - from: (t: string) => k.from(t), - table: (t: string) => k.table(t), - }; - return { - connection: (_name?: string) => client, - } as any; -} - -export function makeKnex(): Knex { - return knex({ - client: 'better-sqlite3', - connection: {filename: ':memory:'}, - useNullAsDefault: true, - }); -} diff --git a/test/suppression.spec.ts b/test/suppression.spec.ts deleted file mode 100644 index 2defa63..0000000 --- a/test/suppression.spec.ts +++ /dev/null @@ -1,85 +0,0 @@ -import {after, beforeEach, describe, it} from 'node:test'; -import assert from 'node:assert/strict'; - -import {SuppressionService} from '../src/Suppression'; -import {makeFakeDatabase, makeKnex} from './helpers'; - -describe('SuppressionService', () => { - const k = makeKnex(); - const db = makeFakeDatabase(k); - const TABLE = 'email_suppressions'; - let service: SuppressionService; - - beforeEach(async () => { - await k.schema.dropTableIfExists(TABLE); - service = new SuppressionService(db, {tableName: TABLE}); - await service.ensureTable(); - }); - - after(async () => { - await k.destroy(); - }); - - describe('ensureTable', () => { - it('is idempotent', async () => { - await service.ensureTable(); - await service.ensureTable(); - assert.equal(await k.schema.hasTable(TABLE), true); - }); - }); - - describe('suppress', () => { - it('inserts a new row', async () => { - const row = await service.suppress('a@x.com', 'bounce', 'webhook', {provider: 'postmark'}); - assert.equal(row.email, 'a@x.com'); - assert.equal(row.reason, 'bounce'); - assert.equal(row.source, 'webhook'); - assert.deepEqual(row.metadata, {provider: 'postmark'}); - assert.equal(typeof row.id, 'number'); - }); - - it('normalizes email to lowercase + trim', async () => { - const row = await service.suppress(' Foo@Example.COM '); - assert.equal(row.email, 'foo@example.com'); - assert.equal(await service.isSuppressed('FOO@example.com'), true); - }); - - it('upserts on conflicting email', async () => { - await service.suppress('dup@x.com', 'bounce', 'webhook'); - const updated = await service.suppress('dup@x.com', 'complaint', 'manual', {note: 'updated'}); - assert.equal(updated.reason, 'complaint'); - assert.equal(updated.source, 'manual'); - assert.deepEqual(updated.metadata, {note: 'updated'}); - - const rows = await k(TABLE).select('id'); - assert.equal(rows.length, 1); - }); - - it('handles null metadata', async () => { - const row = await service.suppress('null-meta@x.com', 'manual', 'manual'); - assert.equal(row.metadata, null); - }); - }); - - describe('isSuppressed / find / unsuppress', () => { - it('returns false for unknown emails', async () => { - assert.equal(await service.isSuppressed('unknown@x.com'), false); - assert.equal(await service.find('unknown@x.com'), null); - }); - - it('returns true for suppressed emails', async () => { - await service.suppress('known@x.com', 'bounce'); - assert.equal(await service.isSuppressed('known@x.com'), true); - const row = await service.find('known@x.com'); - assert.ok(row); - assert.equal(row?.email, 'known@x.com'); - }); - - it('deletes via unsuppress', async () => { - await service.suppress('gone@x.com'); - assert.equal(await service.unsuppress('gone@x.com'), true); - assert.equal(await service.unsuppress('gone@x.com'), false); - assert.equal(await service.isSuppressed('gone@x.com'), false); - }); - }); -}); diff --git a/tests/email_guard.spec.ts b/tests/email_guard.spec.ts new file mode 100644 index 0000000..46b026f --- /dev/null +++ b/tests/email_guard.spec.ts @@ -0,0 +1,81 @@ +import { after, beforeEach, describe, it } from 'node:test' +import assert from 'node:assert/strict' + +import { EmailGuard } from '../src/email_guard.js' +import { makeFakeDatabase, makeKnex } from './helpers.js' + +describe('EmailGuard facade', () => { + const k = makeKnex() + const db = makeFakeDatabase(k) + let guard: EmailGuard + + beforeEach(async () => { + await k.schema.dropTableIfExists('email_suppressions') + guard = new EmailGuard({ tableName: 'email_suppressions' }, db) + await guard.ensureTable() + }) + + after(async () => { + await k.destroy() + }) + + describe('check()', () => { + it('reports suppressed=true when email is in the suppression list', async () => { + await guard.suppress('blocked@mailinator.com', 'manual') + const r = await guard.check('blocked@mailinator.com') + assert.equal(r.suppressed, true) + }) + + it('skips suppression lookup when skipSuppressionCheck is true', async () => { + await guard.suppress('blocked@mailinator.com', 'manual') + const r = await guard.check('blocked@mailinator.com', { skipSuppressionCheck: true }) + assert.equal(r.suppressed, false) + }) + + it('records validation failures when recordFailures=true', async () => { + const r = await guard.check('user@mailinator.com', { recordFailures: true }) + assert.equal(r.valid, false) + assert.equal(r.checks.disposable, true) + assert.equal(r.suppressed, true) + + const row = await guard.find('user@mailinator.com') + assert.ok(row) + assert.equal(row?.reason, 'disposable') + assert.equal(row?.source, 'validator') + }) + + it('does not record when recordFailures is omitted', async () => { + const r = await guard.check('user@mailinator.com') + assert.equal(r.valid, false) + assert.equal(r.suppressed, false) + assert.equal(await guard.find('user@mailinator.com'), null) + }) + + it('records bad syntax with reason=invalid-syntax', async () => { + const r = await guard.check('not-an-email', { recordFailures: true }) + assert.equal(r.valid, false) + assert.equal(r.suppressed, true) + const row = await guard.find('not-an-email') + assert.equal(row?.reason, 'invalid-syntax') + }) + + it('records spam-trap addresses', async () => { + const r = await guard.check('abuse@anywhere.com', { recordFailures: true }) + assert.equal(r.suppressed, true) + const row = await guard.find('abuse@anywhere.com') + assert.equal(row?.reason, 'spam-trap') + }) + }) + + describe('extra block lists merge into validator', () => { + it('accepts custom disposable domains via config', async () => { + const g = new EmailGuard( + { tableName: 'email_suppressions', extraDisposableDomains: ['my-tmp.test'] }, + db + ) + const r = await g.validate('foo@my-tmp.test') + assert.equal(r.valid, false) + assert.equal(r.checks.disposable, true) + }) + }) +}) diff --git a/tests/helpers.ts b/tests/helpers.ts new file mode 100644 index 0000000..bc06c30 --- /dev/null +++ b/tests/helpers.ts @@ -0,0 +1,27 @@ +import knex, { type Knex } from 'knex' + +/** + * Minimal Database-shaped facade over a knex instance. Just enough surface + * for SuppressionService to work against SQLite in tests, without booting + * a real AdonisJS application. + */ +export function makeFakeDatabase(k: Knex): any { + const client = { + get schema() { + return k.schema + }, + from: (t: string) => k.from(t), + table: (t: string) => k.table(t), + } + return { + connection: (_name?: string) => client, + } +} + +export function makeKnex(): Knex { + return knex({ + client: 'better-sqlite3', + connection: { filename: ':memory:' }, + useNullAsDefault: true, + }) +} diff --git a/tests/suppression.spec.ts b/tests/suppression.spec.ts new file mode 100644 index 0000000..72f32f7 --- /dev/null +++ b/tests/suppression.spec.ts @@ -0,0 +1,87 @@ +import { after, beforeEach, describe, it } from 'node:test' +import assert from 'node:assert/strict' + +import { SuppressionService } from '../src/suppression.js' +import { makeFakeDatabase, makeKnex } from './helpers.js' + +describe('SuppressionService', () => { + const k = makeKnex() + const db = makeFakeDatabase(k) + const TABLE = 'email_suppressions' + let service: SuppressionService + + beforeEach(async () => { + await k.schema.dropTableIfExists(TABLE) + service = new SuppressionService(db, { tableName: TABLE }) + await service.ensureTable() + }) + + after(async () => { + await k.destroy() + }) + + describe('ensureTable', () => { + it('is idempotent', async () => { + await service.ensureTable() + await service.ensureTable() + assert.equal(await k.schema.hasTable(TABLE), true) + }) + }) + + describe('suppress', () => { + it('inserts a new row', async () => { + const row = await service.suppress('a@x.com', 'bounce', 'webhook', { provider: 'postmark' }) + assert.equal(row.email, 'a@x.com') + assert.equal(row.reason, 'bounce') + assert.equal(row.source, 'webhook') + assert.deepEqual(row.metadata, { provider: 'postmark' }) + assert.equal(typeof row.id, 'number') + }) + + it('normalizes email to lowercase + trim', async () => { + const row = await service.suppress(' Foo@Example.COM ') + assert.equal(row.email, 'foo@example.com') + assert.equal(await service.isSuppressed('FOO@example.com'), true) + }) + + it('upserts on conflicting email', async () => { + await service.suppress('dup@x.com', 'bounce', 'webhook') + const updated = await service.suppress('dup@x.com', 'complaint', 'manual', { + note: 'updated', + }) + assert.equal(updated.reason, 'complaint') + assert.equal(updated.source, 'manual') + assert.deepEqual(updated.metadata, { note: 'updated' }) + + const rows = await k(TABLE).select('id') + assert.equal(rows.length, 1) + }) + + it('handles null metadata', async () => { + const row = await service.suppress('null-meta@x.com', 'manual', 'manual') + assert.equal(row.metadata, null) + }) + }) + + describe('isSuppressed / find / unsuppress', () => { + it('returns false for unknown emails', async () => { + assert.equal(await service.isSuppressed('unknown@x.com'), false) + assert.equal(await service.find('unknown@x.com'), null) + }) + + it('returns true for suppressed emails', async () => { + await service.suppress('known@x.com', 'bounce') + assert.equal(await service.isSuppressed('known@x.com'), true) + const row = await service.find('known@x.com') + assert.ok(row) + assert.equal(row?.email, 'known@x.com') + }) + + it('deletes via unsuppress', async () => { + await service.suppress('gone@x.com') + assert.equal(await service.unsuppress('gone@x.com'), true) + assert.equal(await service.unsuppress('gone@x.com'), false) + assert.equal(await service.isSuppressed('gone@x.com'), false) + }) + }) +}) diff --git a/test/validator.spec.ts b/tests/validator.spec.ts similarity index 59% rename from test/validator.spec.ts rename to tests/validator.spec.ts index eecce65..c8e071e 100644 --- a/test/validator.spec.ts +++ b/tests/validator.spec.ts @@ -1,114 +1,113 @@ -import {describe, it} from 'node:test'; -import assert from 'node:assert/strict'; +import { describe, it } from 'node:test' +import assert from 'node:assert/strict' -import {EmailValidator} from '../src/Validator'; +import { EmailValidator } from '../src/validator.js' describe('EmailValidator', () => { const validator = new EmailValidator({ extraDisposableDomains: ['custom-disposable.test'], extraSpamTrapDomains: ['custom-trap.test'], - }); + }) describe('checkSyntax', () => { it('accepts well-formed addresses', () => { - assert.equal(validator.checkSyntax('user@example.com'), true); - assert.equal(validator.checkSyntax('first.last+tag@sub.example.co.uk'), true); - }); + assert.equal(validator.checkSyntax('user@example.com'), true) + assert.equal(validator.checkSyntax('first.last+tag@sub.example.co.uk'), true) + }) it('rejects malformed addresses', () => { - assert.equal(validator.checkSyntax(''), false); - assert.equal(validator.checkSyntax('no-at-sign'), false); - assert.equal(validator.checkSyntax('user@'), false); - assert.equal(validator.checkSyntax('@example.com'), false); - assert.equal(validator.checkSyntax('user@@example.com'), false); - assert.equal(validator.checkSyntax('user@example'), false); - }); + assert.equal(validator.checkSyntax(''), false) + assert.equal(validator.checkSyntax('no-at-sign'), false) + assert.equal(validator.checkSyntax('user@'), false) + assert.equal(validator.checkSyntax('@example.com'), false) + assert.equal(validator.checkSyntax('user@@example.com'), false) + assert.equal(validator.checkSyntax('user@example'), false) + }) it('rejects local-parts over 64 chars', () => { - const long = 'a'.repeat(65) + '@example.com'; - assert.equal(validator.checkSyntax(long), false); - }); - }); + const long = 'a'.repeat(65) + '@example.com' + assert.equal(validator.checkSyntax(long), false) + }) + }) describe('disposable / spam-trap detection', () => { it('flags built-in disposable domains', () => { - assert.equal(validator.isDisposableDomain('mailinator.com'), true); - assert.equal(validator.isDisposableDomain('yopmail.com'), true); - }); + assert.equal(validator.isDisposableDomain('mailinator.com'), true) + assert.equal(validator.isDisposableDomain('yopmail.com'), true) + }) it('honors extraDisposableDomains', () => { - assert.equal(validator.isDisposableDomain('custom-disposable.test'), true); - }); + assert.equal(validator.isDisposableDomain('custom-disposable.test'), true) + }) it('does not flag normal providers', () => { - assert.equal(validator.isDisposableDomain('gmail.com'), false); - }); + assert.equal(validator.isDisposableDomain('gmail.com'), false) + }) it('flags spam-trap by domain', () => { - assert.equal(validator.isSpamTrap('anything@example.com'), true); - assert.equal(validator.isSpamTrap('anything@custom-trap.test'), true); - }); + assert.equal(validator.isSpamTrap('anything@example.com'), true) + assert.equal(validator.isSpamTrap('anything@custom-trap.test'), true) + }) it('flags spam-trap by local-part', () => { - assert.equal(validator.isSpamTrap('abuse@somewhere.com'), true); - assert.equal(validator.isSpamTrap('postmaster@somewhere.com'), true); - assert.equal(validator.isSpamTrap('no-reply@somewhere.com'), true); - }); + assert.equal(validator.isSpamTrap('abuse@somewhere.com'), true) + assert.equal(validator.isSpamTrap('postmaster@somewhere.com'), true) + assert.equal(validator.isSpamTrap('no-reply@somewhere.com'), true) + }) it('returns false for clean addresses', () => { - assert.equal(validator.isSpamTrap('hi@somewhere.com'), false); - }); - }); + assert.equal(validator.isSpamTrap('hi@somewhere.com'), false) + }) + }) describe('suggestDomain', () => { it('suggests fixes for close typos', () => { - assert.equal(validator.suggestDomain('gmial.com'), 'gmail.com'); - assert.equal(validator.suggestDomain('hotnail.com'), 'hotmail.com'); - }); + assert.equal(validator.suggestDomain('gmial.com'), 'gmail.com') + assert.equal(validator.suggestDomain('hotnail.com'), 'hotmail.com') + }) it('returns undefined for popular domains', () => { - assert.equal(validator.suggestDomain('gmail.com'), undefined); - }); + assert.equal(validator.suggestDomain('gmail.com'), undefined) + }) it('returns undefined when no close match', () => { - assert.equal(validator.suggestDomain('totally-unrelated-domain.io'), undefined); - }); - }); + assert.equal(validator.suggestDomain('totally-unrelated-domain.io'), undefined) + }) + }) describe('validate', () => { it('rejects invalid syntax without DNS', async () => { - const r = await validator.validate('not-an-email'); - assert.equal(r.valid, false); - assert.equal(r.checks.syntax, false); - assert.equal(r.reason, 'Invalid email syntax'); - }); + const r = await validator.validate('not-an-email') + assert.equal(r.valid, false) + assert.equal(r.checks.syntax, false) + assert.equal(r.reason, 'Invalid email syntax') + }) it('rejects disposable domains before doing MX lookup', async () => { - const r = await validator.validate('user@mailinator.com'); - assert.equal(r.valid, false); - assert.equal(r.checks.syntax, true); - assert.equal(r.checks.disposable, true); - assert.equal(r.checks.mx, false); - }); + const r = await validator.validate('user@mailinator.com') + assert.equal(r.valid, false) + assert.equal(r.checks.syntax, true) + assert.equal(r.checks.disposable, true) + assert.equal(r.checks.mx, false) + }) it('rejects spam-trap before doing MX lookup', async () => { - const r = await validator.validate('abuse@somewhere.com'); - assert.equal(r.valid, false); - assert.equal(r.checks.spamTrap, true); - assert.equal(r.checks.mx, false); - }); + const r = await validator.validate('abuse@somewhere.com') + assert.equal(r.valid, false) + assert.equal(r.checks.spamTrap, true) + assert.equal(r.checks.mx, false) + }) it('attaches a typo suggestion when available', async () => { - const r = await validator.validate('user@gmial.com'); - assert.equal(r.suggestion, 'user@gmail.com'); - }); + const r = await validator.validate('user@gmial.com') + assert.equal(r.suggestion, 'user@gmail.com') + }) it('fails when domain has no MX records', async () => { - // Use a domain that is guaranteed not to have MX records. - const r = await validator.validate('user@this-domain-should-never-exist-abc123.invalid'); - assert.equal(r.valid, false); - assert.equal(r.checks.mx, false); - assert.equal(r.reason, 'No MX records found for domain'); - }); - }); -}); + const r = await validator.validate('user@this-domain-should-never-exist-abc123.invalid') + assert.equal(r.valid, false) + assert.equal(r.checks.mx, false) + assert.equal(r.reason, 'No MX records found for domain') + }) + }) +}) diff --git a/tsconfig.json b/tsconfig.json index a822200..f04ff6b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,8 +1,9 @@ { "compilerOptions": { - "target": "ES2020", - "module": "CommonJS", - "lib": ["ES2020"], + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "lib": ["ES2022"], "declaration": true, "outDir": "./build", "rootDir": "./", @@ -10,17 +11,15 @@ "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, - "moduleResolution": "node", - "resolveJsonModule": true, - "experimentalDecorators": true, - "emitDecoratorMetadata": true + "resolveJsonModule": true }, "include": [ - "src/**/*", - "providers/**/*", - "adonis-typings/**/*", - "instructions.ts" + "index.ts", + "configure.ts", + "providers/**/*.ts", + "services/**/*.ts", + "src/**/*.ts", + "stubs/main.ts" ], - "files": ["adonis-typings/index.ts"], - "exclude": ["node_modules", "build", "test"] + "exclude": ["node_modules", "build", "tests"] }