diff --git a/.ai/ai-agents.md b/.ai/ai-agents.md new file mode 100644 index 0000000..f8ed1a3 --- /dev/null +++ b/.ai/ai-agents.md @@ -0,0 +1,29 @@ +# AI Agents + +We have a custom package for making AI Agents that uses the OpenAI Agents SDK (`packages/agentic-workflows`). + +## Agent Service + +The core is an agent service (`packages/agentic-workflows/src/service/ai-agent-service.ts`) with multiple +implementations: + +- `ai-agent-service-openai`: production implementation using the OpenAI API +- `ai-agent-service-local`: mocked implementation for testing non-AI portions of workflows (orchestration, task + management, error handling, etc) +- `ai-agent-service-ollama`: hits a local ollama deployment for development/testing with local models + +## Tools + +Tools can be passed into `AgentConfig` to give agents access to external capabilities: + +```ts +tools: [getWebContentTool({ tavilyService: this.tavilyService })], +``` + +Tool definitions live in `packages/tavily-utils/src/tools/`. + +## Update Checklist + +Every time you update an agent, you must also update: +- Any fixtures +- Any tests that assume a certain agent structure diff --git a/.ai/bull-queues.md b/.ai/bull-queues.md new file mode 100644 index 0000000..df01626 --- /dev/null +++ b/.ai/bull-queues.md @@ -0,0 +1,92 @@ +# BullMQ Crons & Async Workers + +We use "bullmq" to run cron jobs and async workflows. Bull uses Redis under the hood. + +## Prerequisites + +The consuming service must have a configured redis instance. +For testing, boot a redis container: + +```ts +const redisContainer = new RedisContainer(); +await redisContainer.start(); +``` + +Our utilities for interacting with Bull: `packages/commons/src/bull`. + +## Queue + Worker Pattern + +Every bull queue must have a `*-queue` and a `*-worker`. + +### Queue + +A queue wraps a BullMQ `Queue` and exposes an `addAndAwait()` method for enqueuing jobs: + +```ts +@Injectable() +export class ExampleQueue { + private queue: Queue; + + constructor(private redisConnectionConfig: RedisConnectionConfig) { + this.queue = new Queue("example-queue", { + connection: redisConnectionConfig.getConnection() + }); + } + + async addAndAwait(data: ExampleRequest): Promise { + return await this.queue.add("example-job", data as any); + } +} +``` + +### Worker + +A worker processes jobs from the queue: + +```ts +@Injectable() +export class ExampleWorker { + private worker: Worker; + + constructor(private redisConnectionConfig: RedisConnectionConfig) {} + + start(): void { + this.worker = new Worker("example-queue", async (job) => { + // process job.data + }, { + connection: this.redisConnectionConfig.getConnection() + }); + } +} +``` + +## Cron Jobs + +The queue is injected and launched via `CronLauncher`: + +```ts +this.cronLauncher = new CronLauncher([ + { + queue: exampleCronQueue, + pattern: config.cronPattern, + interval: config.interval, + jobId: EXAMPLE_CRON_JOB_ID + } +]); +this.cronLauncher.launchCrons(); +``` + +**All queues must have globally unique names in the codebase.** + +## Async Processes + +Bull is also used for general async processing of multi-stage workflows with retries. + +Trigger an async task: + +```ts +await this.exampleQueue.addAndAwait(request); +``` + +This adds an item to the queue, triggers the worker, and returns a response. There are default retry mechanisms on any +bull worker set up like this. diff --git a/.ai/configuration.md b/.ai/configuration.md new file mode 100644 index 0000000..d224415 --- /dev/null +++ b/.ai/configuration.md @@ -0,0 +1,45 @@ +# Configuration + +## Configuration Loading + +Configuration is read via `packages/commons/src/config/config-utils.ts`. This defaults to reading from a YAML file at +the application root (e.g., `assets/config.yaml`). + +Overrides can be set as environment variables with the `app_` prefix: + +```json +{ + "name": "app_remoteClient___port", + "value": "8080" +}, +{ + "name": "app_remoteClient___address", + "value": "localhost" +} +``` + +### Type Suffixes + +Env vars are parsed as strings. For typed values, use suffixes: +- `_numeric`: `"app_defaultTokenExpirySeconds_numeric"` → `600` +- `_boolean`: `"app_someFeatureEnabled_boolean"` → `true` + +## Dynamic Configuration + +`*DynamicConfig` classes are simple, injectable config holders that: + +- Load initial values from YAML at startup via `loadConfig(...)`. +- Expose **getter** methods for production code. +- Expose **setter** methods so tests can override values at runtime. + +Typical structure: +- Static `CONFIG_KEY` field pointing to the YAML section +- Private fields for each config value +- Constructor: `loadConfig` using `ApplicationConfig.applicationRoot` and `CONFIG_KEY` +- Public getters and setters mirroring those fields + +Best practices: +- Always save and restore original values (use `try/finally`) in tests. +- Keep fields private, exposed only via getters/setters. +- Use consistent naming: `getX()` / `setX(...)`. +- Always mark these classes as `@Injectable()`. diff --git a/.ai/dependency-injection.md b/.ai/dependency-injection.md new file mode 100644 index 0000000..39109e1 --- /dev/null +++ b/.ai/dependency-injection.md @@ -0,0 +1,74 @@ +# NestJS Dependency Injection + +All dependencies in our object graph are managed via NestJS. +We add the `@Injectable()` tag to all classes that are created/managed via DI. + +## Module Structure + +We create a `Module` for each logical group of functionality: + +```ts +import { Closer, ConfigModule, PostgresConnectionModule } from "@zeroshotbuilders/commons"; +import { Module } from "@nestjs/common"; +import { ExampleConfig } from "./config/example-config"; +import { ExampleDao } from "./repository/example-dao"; +import { ExampleRepository } from "./repository/example-repository"; +import { ExampleServiceImpl } from "./service/example-service-impl"; + +@Module({ + providers: [ + ExampleServiceImpl, + ExampleConfig, + Closer, + ExampleDao, + ExampleRepository + ], + imports: [ + ConfigModule.forApplicationRoot(__dirname), + PostgresConnectionModule.forApplicationRoot(__dirname) + ] +}) +export class ExampleModule {} +``` + +## Provider Registration + +All classes that participate in DI must be: +1. Decorated with `@Injectable()` +2. Listed in the `providers` array of their module +3. Constructor-injected with their dependencies + +```ts +@Injectable() +export class ExampleRepository { + constructor( + private readonly exampleDao: ExampleDao, + private readonly config: ExampleConfig + ) {} +} +``` + +## Cron Job Wiring + +Services that need cron jobs wire them up via `CronLauncher`: + +```ts +@Injectable() +export class ServiceComponent { + constructor( + private readonly cronQueue: ExampleCronQueue, + private readonly config: ExampleConfig, + private readonly closer: Closer + ) { + this.cronLauncher = new CronLauncher([ + { + queue: cronQueue, + pattern: config.cronPattern, + interval: config.interval, + jobId: EXAMPLE_CRON_JOB_ID + } + ]); + this.cronLauncher.launchCrons(); + } +} +``` diff --git a/.ai/skills/testing-guide.md b/.ai/skills/testing-guide.md new file mode 100644 index 0000000..a65ee55 --- /dev/null +++ b/.ai/skills/testing-guide.md @@ -0,0 +1,57 @@ +--- +name: testing-guide +description: Reference guide for writing integration and unit tests +--- + +Reference guide for writing integration and unit tests. + +Read these docs for full details: +- `.ai/testing.md` for integration test structure, unit tests, and testcontainers +- `.ai/configuration.md` for dynamic config and overriding config in tests + +## Quick Reference + +### Integration Test Structure +- Boot dependencies via testcontainers (`PostgresContainer`, `RedisContainer` from `@zeroshotbuilders/commons-testing`) +- Wire into a NestJS test module using `.overrideProvider()` +- Run assertions against the real stack + +### Testcontainers +```ts +import { PostgresContainer, RedisContainer } from "@zeroshotbuilders/commons-testing"; + +const postgresContainer = new PostgresContainer(); +await postgresContainer.start(); + +const redisContainer = new RedisContainer(); +await redisContainer.start(); +``` + +### Overriding Config in Tests +```ts +const testModule = await Test.createTestingModule({ + imports: [ServiceModule], +}) + .overrideProvider(RedisConnectionConfig) + .useValue(redisContainer.getConnectionConfig()) + .overrideProvider(PostgresConnectionConfig) + .useValue(postgresContainer.getConnectionConfig()) + .compile(); +``` + +### Dynamic Config in Tests +```ts +const original = dynamicConfig.getX(); +try { + dynamicConfig.setX(testValue); + // test logic +} finally { + dynamicConfig.setX(original); +} +``` + +### Unit Tests +Required for all utility functions, especially in `packages/commons`. +Good example: `packages/commons/test/port/port-utils.spec.ts`. + +$ARGUMENTS diff --git a/.ai/sql-decorators.md b/.ai/sql-decorators.md new file mode 100644 index 0000000..c0d1969 --- /dev/null +++ b/.ai/sql-decorators.md @@ -0,0 +1,87 @@ +# sql-decorators Framework + +We have built a custom in-house framework for interacting with the SQL database. It allows us to use actual SQL queries. +The logic lives in the `sql-decorators` package. **100% of DML must use this `sql-decorators` construct.** The queries should all live +in a DAO. + +The framework uses "sequelize" to actually execute the queries. + +## Implementation Details + +For implementation details, look at `packages/sql-decorators/src/decorators.ts`. This is where our main decorators live that +contain the logic for translating TypeScript functions on the DAO into actual SQL calls. It is also responsible for +running the actual underlying query and managing parameterized replacements. + +For examples of how to use each decorator, look in `packages/sql-decorators/test`. + +## Data Access Objects (DAOs) + +A DAO encapsulates all interaction with a data source behind a clean interface. DAOs handle queries, inserts, updates, +deletes, and data-mapping so the rest of the application never deals directly with SQL, ORMs, or database drivers. + +In a well-structured backend, services depend on DAOs rather than on raw database primitives. + +## DAO Structure + +```ts +@Dao({ + queryDirectory: `${__dirname}/queries` +}) +export class NoteDao extends DaoBase { + @SqlQuery({ + queryType: QueryTypes.SELECT, + clazz: NoteModel, + returnList: true + }) + getNotes( + noteIds: string[] | undefined, + customerIds: string[] | undefined + ): Promise> { + return null; + } +} +``` + +## Transactions + +When you need to perform multiple inserts, mutations, or anything that would require a SQL Transaction, we have a +`@SqlTransaction` decorator. This generates a `Transaction` object that must be passed into each of the methods that +must be part of the same transaction. + +Look in `packages/sql-decorators/test/repository/enum-dao.ts` for an example on how to do this. + +## Streaming with @StreamSelect + +The `@StreamSelect` decorator handles paginating through a database table for large result sets: + +```typescript +@StreamSelect({ + clazz: TreatmentModel, + batchSize: 1000 +}) +streamTreatments( + createdSince?: number | undefined +): StreamIterator { + return null; // Implementation is injected by the decorator +} +``` + +### How StreamSelect Works + +- **Batching**: Executes the SQL query multiple times with `LIMIT` and `OFFSET` clauses. +- **Lazy Fetching**: Fetches the first `batchSize` records, then auto-fetches the next batch when consumed. +- **Termination**: Stops when a batch returns fewer records than `batchSize`. + +### CRITICAL: Sort Order + +Because `StreamSelect` relies on `LIMIT` and `OFFSET`, **the underlying SQL query MUST have a deterministic `ORDER BY` +clause.** Without it, records may be duplicated or skipped between batches. + +**Always use a unique, immutable column (like `created_at`) in your `ORDER BY` clause for streaming.** + +```sql +SELECT * +FROM treatments +WHERE (:createdSince IS NULL OR created_at > :createdSince) +ORDER BY created_at +``` diff --git a/.ai/testing.md b/.ai/testing.md new file mode 100644 index 0000000..3442b73 --- /dev/null +++ b/.ai/testing.md @@ -0,0 +1,74 @@ +# Testing + +## Integration Tests + +Integration tests in build-kit use testcontainers to boot real dependencies (Postgres, Redis) and validate packages +end-to-end. + +Test structure: +- Boot dependencies via testcontainers +- Wire them into a NestJS test module +- Run assertions against the real stack + +## Unit Tests + +We use unit tests for testing smaller units of code. If we ever create a utility function, especially one that lives in +a common place (like `commons`), then we must have unit tests. + +A good example: `packages/commons/test/port/port-utils.spec.ts`. + +## Testcontainers + +`packages/commons-testing` provides testcontainer utilities for spinning up real Postgres and Redis instances in tests: + +```ts +const postgresContainer = new PostgresContainer(); +await postgresContainer.start(); + +const redisContainer = new RedisContainer(); +await redisContainer.start(); +``` + +These containers provide connection configs that can be injected into NestJS test modules. + +## Overriding Configuration in Tests + +Override configuration by injecting values into NestJS test modules: + +```ts +const testModule = await Test.createTestingModule({ + imports: [ServiceModule], +}) + .overrideProvider(RedisConnectionConfig) + .useValue(redisContainer.getConnectionConfig()) + .overrideProvider(PostgresConnectionConfig) + .useValue(postgresContainer.getConnectionConfig()) + .compile(); +await testModule.init(); +``` + +This skips `loadConfig` entirely and injects specific objects into the NestJS dependency graph. + +## Dynamic Configuration in Tests + +`*DynamicConfig` classes expose getter/setter methods so tests can override values at runtime: + +1. Fetch the dynamic config from the test module +2. Override in tests with cleanup: + - Read original value via getter + - Set temporary test value via setter + - In `finally`, restore the original value + +Always save and restore original values using `try/finally`. + +## Third-Party API Mocking + +Third-party `*-utils` packages can have local implementations for testing. The local implementation exposes `static` +methods so tests can change or access mock state: + +```ts +await ExampleServiceLocal.updateStatus(id, "Active"); +await eventually(async () => { + // assert the service synced the change +}); +``` diff --git a/.aiassistant/rules/rules.md b/.aiassistant/rules/rules.md new file mode 120000 index 0000000..3fcdf10 --- /dev/null +++ b/.aiassistant/rules/rules.md @@ -0,0 +1 @@ +../../.junie/guidelines.md \ No newline at end of file diff --git a/.claude/commands/testing-guide.md b/.claude/commands/testing-guide.md new file mode 120000 index 0000000..53fce2b --- /dev/null +++ b/.claude/commands/testing-guide.md @@ -0,0 +1 @@ +../../.ai/skills/testing-guide.md \ No newline at end of file diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..50cb6fb --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,44 @@ +{ + "$schema": "https://json.schemastore.org/claude-code-settings.json", + "permissions": { + "allow": [ + "Bash(git add:*)", + "Bash(git commit:*)", + "Bash(git diff:*)", + "Bash(git log:*)", + "Bash(git status:*)", + "Bash(git checkout:*)", + "Bash(git branch:*)", + "Bash(git stash:*)", + "Bash(git merge:*)", + "Bash(git rebase:*)", + "Bash(git fetch:*)", + "Bash(git push:*)", + "Bash(git pull:*)", + "Bash(yarn nx:*)", + "Bash(yarn install:*)", + "Bash(grep:*)", + "Bash(rg:*)", + "Bash(ls:*)", + "Bash(find:*)", + "Bash(wc:*)", + "Bash(cat:*)", + "Bash(head:*)", + "Bash(tail:*)", + "Bash(sort:*)", + "Bash(uniq:*)", + "Bash(xargs:*)", + "Bash(awk:*)", + "Bash(sed:*)", + "Bash(jq:*)", + "Bash(tree:*)", + "Bash(which:*)", + "Bash(gh:*)", + "Bash(gh pr:*)", + "Bash(gh run:*)", + "Bash(gh workflow:*)", + "Bash(git -c:*)" + ] + }, + "hooks": {} +} diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..025dd8c --- /dev/null +++ b/.editorconfig @@ -0,0 +1,8 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..edabdb0 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,18 @@ +{ + "root": true, + "ignorePatterns": ["**/*"], + "plugins": ["@typescript-eslint"], + "overrides": [ + { + "files": ["*.ts", "*.tsx"], + "extends": [ + "plugin:@typescript-eslint/recommended", + "prettier" + ], + "rules": { + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-unused-vars": "warn" + } + } + ] +} diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..af3ad12 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +/.yarn/** linguist-vendored +/.yarn/releases/* binary +/.yarn/plugins/**/* binary +/.pnp.* binary linguist-generated diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml new file mode 100644 index 0000000..f38af1d --- /dev/null +++ b/.github/workflows/main.yaml @@ -0,0 +1,60 @@ +name: build-kit main + +on: + workflow_dispatch: + push: + branches: + - main + +concurrency: + group: main-build + cancel-in-progress: false + +permissions: + contents: write + +jobs: + release: + runs-on: ubuntu-latest + if: ${{ !contains(github.event.head_commit.message, 'v0') }} + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + token: ${{ secrets.GH_TOKEN }} + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version-file: '.nvmrc' + registry-url: 'https://registry.npmjs.org' + + - name: Enable Corepack + run: corepack enable + + - name: Set git user + run: | + git config user.name 'github-actions[bot]' + git config user.email 'github-actions[bot]@users.noreply.github.com' + + - name: Install dependencies + run: yarn install + + - name: Fast-forward to latest main + run: | + git fetch origin main + git reset --hard origin/main + + - name: Bump version + run: yarn lerna version -y 'patch' --force-publish + + - name: Build + run: yarn nx run-many --target=build + + - name: Publish to npm + run: | + for pkg in commons commons-testing sql-decorators openai-utils tavily-utils agentic-workflows; do + npm publish "dist/packages/$pkg" --access public || true + done + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml new file mode 100644 index 0000000..7992eb1 --- /dev/null +++ b/.github/workflows/pr.yaml @@ -0,0 +1,32 @@ +name: build-kit PR + +on: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + ci: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version-file: '.nvmrc' + + - name: Enable Corepack + run: corepack enable + + - name: Install dependencies + run: yarn install --immutable + + - name: Fetch main branch + run: git fetch origin main --depth=1 + + - name: Lint + run: yarn nx affected --target=lint --base=remotes/origin/main + + - name: Test + run: yarn nx affected --target=test --base=remotes/origin/main diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bb61800 --- /dev/null +++ b/.gitignore @@ -0,0 +1,56 @@ +# compiled output +dist +node_modules/ +ctrf +*.tsbuildinfo + +# Generated OpenAPI Compilation Outputs +**/src/generated + +# generated outputs +*package.json.lerna_backup +tmp + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +signature.js + +# OS +.DS_Store + +# npm +.npmrc + +# ENV +.env + +# Tests +coverage +/.nyc_output + +# IDEs and editors +/.idea +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# IDE - VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +.yarn/install-state.gz +.yarn/cache + +# nx +.nx diff --git a/.junie/guidelines.md b/.junie/guidelines.md new file mode 120000 index 0000000..9cea43b --- /dev/null +++ b/.junie/guidelines.md @@ -0,0 +1 @@ +../AI.md \ No newline at end of file diff --git a/.junie/skills/testing-guide/SKILL.md b/.junie/skills/testing-guide/SKILL.md new file mode 120000 index 0000000..b94d558 --- /dev/null +++ b/.junie/skills/testing-guide/SKILL.md @@ -0,0 +1 @@ +../../../.ai/skills/testing-guide.md \ No newline at end of file diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..53d1c14 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v22 diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..75df8d4 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,7 @@ +{ + "singleQuote": false, + "tabWidth": 2, + "trailingComma": "none", + "semi": true, + "printWidth": 80 +} diff --git a/.yarnrc.yml b/.yarnrc.yml new file mode 100644 index 0000000..3186f3f --- /dev/null +++ b/.yarnrc.yml @@ -0,0 +1 @@ +nodeLinker: node-modules diff --git a/AGENTS.md b/AGENTS.md new file mode 120000 index 0000000..269ff5e --- /dev/null +++ b/AGENTS.md @@ -0,0 +1 @@ +AI.md \ No newline at end of file diff --git a/AI.md b/AI.md new file mode 100644 index 0000000..755b1df --- /dev/null +++ b/AI.md @@ -0,0 +1,64 @@ +--- +apply: always +--- + +# Coding Agent Guidelines + +## build-kit + +build-kit is an NX monorepo of reusable TypeScript infrastructure libraries published under the `@zeroshotbuilders/*` +scope. These packages provide shared utilities for NestJS-based backend services — configuration, database access, +job queues, AI agent orchestration, and testing infrastructure. + +## Build and Test + +```bash +yarn nx run :build # compile a single package (+ deps) +yarn nx run :lint # lint a single package +yarn nx run :test # test a single package +yarn nx run-many --target=build # build everything +yarn install # only if deps change +``` + +**IMPORTANT: You MUST run tests for every package you modify.** Do not skip tests. Tests are the final validation. +Never run all tests — only for changed packages. Fix any failures before moving on. + +## Key Rules + +- **Errors**: Always throw `ServerError` from "nice-grpc". Never throw `Error`. +- **Logging**: Always use `winston` (`createLogger`). Never use `console`. +- **100% of DML** must use the `sql-decorators` framework. All queries live in DAOs. +- **DI**: All classes managed via NestJS. Use `@Injectable()`. +- Keep logging and error handling focused and minimal. + +## Packages + +| Package | Purpose | +|---|---| +| `commons` | Core utilities — config, redis, postgres, bull, logging, crypto | +| `commons-testing` | Test utilities — testcontainers for postgres/redis, ollama fixture | +| `sql-decorators` | Sequelize decorators and query utilities | +| `openai-utils` | OpenAI client factory and service | +| `tavily-utils` | Tavily search client + tool definitions | +| `agentic-workflows` | AI agent orchestration — @Agent decorator, session management | + +## Detailed Documentation + +Canonical deep-dive docs live in `.ai/`: + +| Topic | File | +|---|---| +| sql-decorators framework & queries | `.ai/sql-decorators.md` | +| Testing (integration, unit, testcontainers) | `.ai/testing.md` | +| Configuration loading | `.ai/configuration.md` | +| NestJS dependency injection | `.ai/dependency-injection.md` | +| BullMQ crons & async workers | `.ai/bull-queues.md` | +| AI agents (OpenAI SDK) | `.ai/ai-agents.md` | + +## On-Demand Skills + +Canonical skill guides live in `.ai/skills/`: + +- `testing-guide` + +When a task matches a skill, open the relevant `.ai/skills/.md` and follow it. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 120000 index 0000000..269ff5e --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +AI.md \ No newline at end of file diff --git a/README.md b/README.md index 71e73e1..44f65bc 100644 --- a/README.md +++ b/README.md @@ -1 +1,32 @@ -# build-kit \ No newline at end of file +# build-kit + +Reusable TypeScript infrastructure libraries by [Zeroshot Builders](https://www.zeroshotbuilders.com/). + +## Packages + +| Package | Description | +|---|---| +| `@zeroshotbuilders/commons` | Core utilities — config loading, Redis, Postgres, BullMQ, logging, crypto | +| `@zeroshotbuilders/commons-testing` | Test utilities — testcontainers for Postgres/Redis, test fixtures | +| `@zeroshotbuilders/sql-decorators` | Sequelize decorators and query utilities | +| `@zeroshotbuilders/openai-utils` | OpenAI client factory and service | +| `@zeroshotbuilders/tavily-utils` | Tavily search client and tool definitions | +| `@zeroshotbuilders/agentic-workflows` | AI agent orchestration — @Agent decorator, session management | + +## Prerequisites + +- Node 22 +- Yarn 4 +- Docker (for integration tests) + +## Getting Started + +```bash +yarn install +yarn nx run-many --target=build +yarn nx run-many --target=test +``` + +## License + +MIT diff --git a/jest.config.ts b/jest.config.ts new file mode 100644 index 0000000..0ab4929 --- /dev/null +++ b/jest.config.ts @@ -0,0 +1,2 @@ +import { getJestProjects } from "@nx/jest"; +export default { projects: getJestProjects() }; diff --git a/jest.preset.js b/jest.preset.js new file mode 100644 index 0000000..327ab25 --- /dev/null +++ b/jest.preset.js @@ -0,0 +1,2 @@ +const nxPreset = require("@nx/jest/preset").default; +module.exports = { ...nxPreset }; diff --git a/lerna.json b/lerna.json new file mode 100644 index 0000000..d2411ee --- /dev/null +++ b/lerna.json @@ -0,0 +1,6 @@ +{ + "packages": ["packages/*"], + "version": "0.0.1", + "$schema": "node_modules/lerna/schemas/lerna-schema.json", + "useWorkspaces": true +} diff --git a/nx.json b/nx.json new file mode 100644 index 0000000..13d5fd7 --- /dev/null +++ b/nx.json @@ -0,0 +1,33 @@ +{ + "$schema": "./node_modules/nx/schemas/nx-schema.json", + "namedInputs": { + "default": ["{projectRoot}/**/*", "sharedGlobals"], + "production": [ + "default", + "!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)", + "!{projectRoot}/tsconfig.spec.json", + "!{projectRoot}/jest.config.[jt]s" + ], + "sharedGlobals": [] + }, + "targetDefaults": { + "build": { + "dependsOn": ["^build"], + "inputs": ["production", "^production"], + "cache": true + }, + "test": { + "inputs": ["default", "^production", "{workspaceRoot}/jest.preset.js"], + "cache": true + }, + "lint": { + "inputs": ["default", "{workspaceRoot}/.eslintrc.json"], + "cache": true + } + }, + "workspaceLayout": { + "appsDir": "packages", + "libsDir": "packages" + }, + "analytics": false +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..69735df --- /dev/null +++ b/package.json @@ -0,0 +1,47 @@ +{ + "name": "build-kit", + "version": "0.0.1", + "private": true, + "packageManager": "yarn@4.13.0", + "workspaces": [ + "packages/*" + ], + "scripts": { + "build": "nx run-many --target=build", + "test": "nx run-many --target=test", + "lint": "nx run-many --target=lint" + }, + "devDependencies": { + "@grpc/grpc-js": "^1.9", + "@nestjs/common": "^10", + "@nestjs/core": "^10", + "@nestjs/platform-express": "^10", + "@nestjs/testing": "^11.1.18", + "@nx/eslint": "^22.6.4", + "@nx/jest": "^22.6.4", + "@nx/js": "^22.6.4", + "@types/bcrypt": "^6.0.0", + "@types/jest": "^29", + "@types/js-yaml": "^4.0.9", + "@types/luxon": "^3.7.1", + "@types/node": "^22", + "@types/randomstring": "^1.3.0", + "@typescript-eslint/eslint-plugin": "^8", + "@typescript-eslint/parser": "^8", + "bcrypt": "^6.0.0", + "eslint": "^9", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-prettier": "^5.5.5", + "jest": "^29", + "jest-environment-node": "^29", + "lerna": "^9.0.7", + "nx": "^22.6.4", + "pg": "^8.20.0", + "prettier": "^3.8.1", + "rxjs": "^7.8.2", + "testcontainers": "^11.13.0", + "ts-jest": "^29", + "ts-node": "^10.9.2", + "typescript": "~5.8" + } +} diff --git a/packages/agentic-workflows/.eslintrc.json b/packages/agentic-workflows/.eslintrc.json new file mode 100644 index 0000000..f1ff0d9 --- /dev/null +++ b/packages/agentic-workflows/.eslintrc.json @@ -0,0 +1,10 @@ +{ + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "rules": {} + } + ] +} diff --git a/packages/agentic-workflows/index.ts b/packages/agentic-workflows/index.ts new file mode 100644 index 0000000..845bd88 --- /dev/null +++ b/packages/agentic-workflows/index.ts @@ -0,0 +1,16 @@ +export const AI_AGENT_APPLICATION_ROOT = "AiAgentApplicationRoot"; +export * from "./src/ai-agent-module"; +export * from "./src/ai-agent-factory"; +export * from "./src/config/ai-agent-config"; +export * from "./src/service/ai-agent-service"; +export * from "./src/service/ai-agent-service-local"; +export * from "./src/service/ai-agent-service-openai"; +export * from "./src/service/ai-agent-service-ollama"; +export * from "./src/service/decorators"; +export * from "./src/service/prompt-utils"; +export * from "./src/service/agent-parameter-mapper"; +export * from "./src/repository/session/conversation-session-model"; +export * from "./src/repository/session/conversation-session-repository"; +export * from "./src/repository/session/in-memory-conversation-session-repository"; +export * from "./src/repository/session/repository-session"; +export * from "./src/service/ai-session-factory"; diff --git a/packages/agentic-workflows/jest.config.ts b/packages/agentic-workflows/jest.config.ts new file mode 100644 index 0000000..9b25b3e --- /dev/null +++ b/packages/agentic-workflows/jest.config.ts @@ -0,0 +1,10 @@ +export default { + displayName: "agentic-workflows", + preset: "../../jest.preset.js", + testEnvironment: "node", + transform: { + "^.+\\.[tj]s$": ["ts-jest", { tsconfig: "/tsconfig.spec.json" }] + }, + moduleFileExtensions: ["ts", "js", "html"], + coverageDirectory: "../../coverage/packages/agentic-workflows" +}; diff --git a/packages/agentic-workflows/package.json b/packages/agentic-workflows/package.json new file mode 100644 index 0000000..2042ce5 --- /dev/null +++ b/packages/agentic-workflows/package.json @@ -0,0 +1,20 @@ +{ + "name": "@zeroshotbuilders/agentic-workflows", + "version": "0.0.1", + "type": "commonjs", + "main": "./src/index.ts", + "publishConfig": { + "main": "./index.js", + "types": "./index.d.ts", + "access": "public" + }, + "dependencies": { + "@openai/agents": "^0.3.0", + "openai": "^4.77.0" + }, + "peerDependencies": { + "@nestjs/common": ">=10.0.0", + "@nestjs/core": ">=10.0.0", + "@zeroshotbuilders/commons": ">=0.0.1" + } +} diff --git a/packages/agentic-workflows/project.json b/packages/agentic-workflows/project.json new file mode 100644 index 0000000..f1c811c --- /dev/null +++ b/packages/agentic-workflows/project.json @@ -0,0 +1,29 @@ +{ + "name": "agentic-workflows", + "sourceRoot": "packages/agentic-workflows/src", + "projectType": "library", + "targets": { + "build": { + "executor": "@nx/js:tsc", + "options": { + "outputPath": "dist/packages/agentic-workflows", + "main": "packages/agentic-workflows/src/index.ts", + "tsConfig": "packages/agentic-workflows/tsconfig.lib.json" + } + }, + "test": { + "executor": "@nx/jest:jest", + "options": { + "jestConfig": "packages/agentic-workflows/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": ["packages/agentic-workflows/**/*.ts"] + } + } + }, + "tags": [] +} diff --git a/packages/agentic-workflows/src/ai-agent-factory.ts b/packages/agentic-workflows/src/ai-agent-factory.ts new file mode 100644 index 0000000..81bff27 --- /dev/null +++ b/packages/agentic-workflows/src/ai-agent-factory.ts @@ -0,0 +1,98 @@ +import { Injectable } from "@nestjs/common"; +import { AiAgentConfig, AiAgentProvider } from "./config/ai-agent-config"; +import { AiAgentService } from "./service/ai-agent-service"; +import { AiAgentServiceLocal } from "./service/ai-agent-service-local"; +import { AiAgentServiceOllama } from "./service/ai-agent-service-ollama"; +import { AiAgentServiceOpenai } from "./service/ai-agent-service-openai"; + +/** + * Factory for creating AI agent service instances. + * Automatically selects the appropriate implementation based on configuration. + */ +@Injectable() +export class AiAgentFactory { + constructor(private readonly config: AiAgentConfig) {} + + /** + * Creates an AI agent service based on the configured provider. + * In local/test mode, returns the local mock implementation. + * + * @returns An AiAgentService implementation (Local, OpenAI, or Ollama) + * @throws Error if the provider is not supported or required configuration is missing + */ + public makeAiAgentService(): AiAgentService { + // Use local mock implementation in test mode + if (this.config.local) { + return AiAgentServiceLocal.getInstance(); + } + + switch (this.config.provider) { + case AiAgentProvider.OPENAI: + return this.makeOpenaiService(); + case AiAgentProvider.OLLAMA: + return this.makeOllamaService(); + default: + throw new Error( + `Unsupported AI agent provider: ${this.config.provider}` + ); + } + } + + /** + * Creates an OpenAI-based AI agent service. + * + * @returns An AiAgentServiceOpenai instance + * @throws Error if the OpenAI API token is not configured + */ + public makeOpenaiService(): AiAgentServiceOpenai { + if (!this.config.openaiApiToken) { + throw new Error("OpenAI API token is required for OpenAI provider"); + } + return new AiAgentServiceOpenai( + this.config.openaiApiToken, + this.config.defaultModel + ); + } + + /** + * Creates an Ollama-based AI agent service. + * + * @returns An AiAgentServiceOllama instance + */ + public makeOllamaService(): AiAgentServiceOllama { + return new AiAgentServiceOllama( + this.config.ollamaBaseUrl ?? "http://localhost:11434", + this.config.defaultModel + ); + } + + /** + * Creates an Ollama-based AI agent service with a custom base URL. + * Useful for testing with OllamaFixture. + * + * @param baseUrl - The base URL of the Ollama instance + * @param defaultModel - Optional default model to use + * @returns An AiAgentServiceOllama instance + */ + public static makeOllamaServiceForUrl( + baseUrl: string, + defaultModel?: string + ): AiAgentServiceOllama { + return new AiAgentServiceOllama(baseUrl, defaultModel); + } + + /** + * Creates an OpenAI-based AI agent service with explicit credentials. + * Useful for testing or when not using dependency injection. + * + * @param apiKey - The OpenAI API key + * @param defaultModel - Optional default model to use + * @returns An AiAgentServiceOpenai instance + */ + public static makeOpenaiServiceForKey( + apiKey: string, + defaultModel?: string + ): AiAgentServiceOpenai { + return new AiAgentServiceOpenai(apiKey, defaultModel); + } +} diff --git a/packages/agentic-workflows/src/ai-agent-module.ts b/packages/agentic-workflows/src/ai-agent-module.ts new file mode 100644 index 0000000..145804f --- /dev/null +++ b/packages/agentic-workflows/src/ai-agent-module.ts @@ -0,0 +1,66 @@ +import { + ApplicationConfig, + ConfigModule +} from "@zeroshotbuilders/commons"; +import { DynamicModule, Module } from "@nestjs/common"; +import { AiAgentFactory } from "./ai-agent-factory"; +import { AiAgentConfig } from "./config/ai-agent-config"; +import { CONVERSATION_SESSION_REPOSITORY } from "./repository/session/conversation-session-repository"; +import { InMemoryConversationSessionRepository } from "./repository/session/in-memory-conversation-session-repository"; +import { AiSessionFactory } from "./service/ai-session-factory"; + +export const AI_AGENT_APPLICATION_ROOT = "AiAgentApplicationRoot"; +export const AI_AGENT_SERVICE = "AI_AGENT_SERVICE"; + +@Module({}) +export class AiAgentModule { + /** + * Creates a module configured for the given application root. + * Uses the configuration from the application's config.yaml to determine + * which provider (OpenAI or Ollama) to use. + * + * @param applicationRoot - The root directory of the application + * @returns A configured DynamicModule + */ + public static forApplicationRoot(applicationRoot: string): DynamicModule { + return { + module: AiAgentModule, + imports: [ + ConfigModule.forApplicationRoot(applicationRoot) + ], + providers: [ + { + provide: AI_AGENT_APPLICATION_ROOT, + useValue: applicationRoot + }, + { + provide: AiAgentConfig, + useFactory: (applicationConfig: ApplicationConfig) => { + return AiAgentConfig.create(applicationConfig); + }, + inject: [ApplicationConfig] + }, + AiAgentFactory, + { + provide: AI_AGENT_SERVICE, + useFactory: (aiAgentFactory: AiAgentFactory) => + aiAgentFactory.makeAiAgentService(), + inject: [AiAgentFactory] + }, + InMemoryConversationSessionRepository, + { + provide: CONVERSATION_SESSION_REPOSITORY, + useExisting: InMemoryConversationSessionRepository + }, + AiSessionFactory + ], + exports: [ + AI_AGENT_SERVICE, + AiAgentFactory, + AiAgentConfig, + CONVERSATION_SESSION_REPOSITORY, + AiSessionFactory + ] + }; + } +} diff --git a/packages/agentic-workflows/src/config/ai-agent-config.ts b/packages/agentic-workflows/src/config/ai-agent-config.ts new file mode 100644 index 0000000..7d98316 --- /dev/null +++ b/packages/agentic-workflows/src/config/ai-agent-config.ts @@ -0,0 +1,51 @@ +import { ApplicationConfig, loadConfig } from "@zeroshotbuilders/commons"; +import { Injectable } from "@nestjs/common"; + +/** + * Provider type for the AI agent service + */ +export enum AiAgentProvider { + OPENAI = "openai", + OLLAMA = "ollama" +} + +/** + * Configuration for the AI agent service. + * Supports both OpenAI and Ollama providers. + */ +@Injectable() +export class AiAgentConfig { + private static readonly CONFIG_KEY = "aiAgent"; + + /** Whether running in local/test mode */ + readonly local: boolean; + + /** The provider to use (openai or ollama) */ + readonly provider: AiAgentProvider; + + /** OpenAI API token (required for OpenAI provider) */ + readonly openaiApiToken?: string; + + /** Ollama base URL (required for Ollama provider, defaults to localhost:11434) */ + readonly ollamaBaseUrl?: string; + + /** Default model to use */ + readonly defaultModel?: string; + + static create( + applicationConfig: ApplicationConfig + ): AiAgentConfig { + const config = loadConfig( + applicationConfig.applicationRoot, + AiAgentConfig.CONFIG_KEY + ); + return { + local: applicationConfig.local, + provider: config.provider ?? AiAgentProvider.OPENAI, + openaiApiToken: + config.openaiApiToken ?? process.env.OPENAI_API_KEY, + ollamaBaseUrl: config.ollamaBaseUrl ?? "http://localhost:11434", + defaultModel: config.defaultModel + }; + } +} diff --git a/packages/agentic-workflows/src/repository/session/conversation-session-model.ts b/packages/agentic-workflows/src/repository/session/conversation-session-model.ts new file mode 100644 index 0000000..9d79bb6 --- /dev/null +++ b/packages/agentic-workflows/src/repository/session/conversation-session-model.ts @@ -0,0 +1,17 @@ +export class ConversationSessionModel { + sessionId: string; + clientId: string; + createdAt: number; + updatedAt: number; +} + +export class ConversationItemModel { + itemId: string; + sessionId: string; + sequenceNumber: number; + role: string; + content: string; + metadata: string | undefined; + createdAt: number; + deletedAt: number | undefined; +} diff --git a/packages/agentic-workflows/src/repository/session/conversation-session-repository.ts b/packages/agentic-workflows/src/repository/session/conversation-session-repository.ts new file mode 100644 index 0000000..5dd8e86 --- /dev/null +++ b/packages/agentic-workflows/src/repository/session/conversation-session-repository.ts @@ -0,0 +1,27 @@ +import { + ConversationItemModel, + ConversationSessionModel +} from "./conversation-session-model"; + +export const CONVERSATION_SESSION_REPOSITORY = + "CONVERSATION_SESSION_REPOSITORY"; + +export interface ConversationSessionRepository { + createSession(clientId: string): Promise; + + getSession(sessionId: string): Promise; + + getConversationItems( + sessionId: string, + limit?: number + ): Promise; + + addConversationItems( + sessionId: string, + items: { role: string; content: string; metadata?: Record }[] + ): Promise; + + clearConversation(sessionId: string): Promise; + + popLastItem(sessionId: string): Promise; +} diff --git a/packages/agentic-workflows/src/repository/session/in-memory-conversation-session-repository.ts b/packages/agentic-workflows/src/repository/session/in-memory-conversation-session-repository.ts new file mode 100644 index 0000000..b11c8b8 --- /dev/null +++ b/packages/agentic-workflows/src/repository/session/in-memory-conversation-session-repository.ts @@ -0,0 +1,117 @@ +import { Injectable } from "@nestjs/common"; +import { ServerError, Status } from "nice-grpc"; +import { v4 as uuidv4 } from "uuid"; +import { + ConversationItemModel, + ConversationSessionModel +} from "./conversation-session-model"; +import { ConversationSessionRepository } from "./conversation-session-repository"; + +@Injectable() +export class InMemoryConversationSessionRepository + implements ConversationSessionRepository +{ + private sessions: Map = new Map(); + private items: Map = new Map(); + + async createSession(clientId: string): Promise { + const sessionId = uuidv4(); + const now = Date.now(); + const session: ConversationSessionModel = { + sessionId, + clientId, + createdAt: now, + updatedAt: now + }; + this.sessions.set(sessionId, session); + this.items.set(sessionId, []); + return session; + } + + async getSession(sessionId: string): Promise { + const session = this.sessions.get(sessionId); + if (!session) { + throw new ServerError( + Status.NOT_FOUND, + `Session not found: ${sessionId}` + ); + } + return session; + } + + async getConversationItems( + sessionId: string, + limit?: number + ): Promise { + const sessionItems = this.items.get(sessionId) || []; + const activeItems = sessionItems.filter((item) => !item.deletedAt); + if (limit) { + return activeItems.slice(-limit); + } + return activeItems; + } + + async addConversationItems( + sessionId: string, + items: { role: string; content: string; metadata?: Record }[] + ): Promise { + const session = await this.getSession(sessionId); + const sessionItems = this.items.get(sessionId) || []; + + const now = Date.now(); + let sequenceNumber = + sessionItems.length > 0 + ? Math.max(...sessionItems.map((i) => i.sequenceNumber)) + 1 + : 0; + + for (const item of items) { + const newItem: ConversationItemModel = { + itemId: uuidv4(), + sessionId, + sequenceNumber: sequenceNumber++, + role: item.role, + content: item.content, + metadata: item.metadata ? JSON.stringify(item.metadata) : undefined, + createdAt: now, + deletedAt: undefined + }; + sessionItems.push(newItem); + } + + this.items.set(sessionId, sessionItems); + session.updatedAt = now; + } + + async clearConversation(sessionId: string): Promise { + const session = await this.getSession(sessionId); + const sessionItems = this.items.get(sessionId) || []; + const now = Date.now(); + + for (const item of sessionItems) { + if (!item.deletedAt) { + item.deletedAt = now; + } + } + + session.updatedAt = now; + } + + async popLastItem( + sessionId: string + ): Promise { + const session = await this.getSession(sessionId); + const sessionItems = this.items.get(sessionId) || []; + const activeItems = sessionItems.filter((item) => !item.deletedAt); + + if (activeItems.length === 0) { + return undefined; + } + + const lastItem = activeItems[activeItems.length - 1]; + const now = Date.now(); + lastItem.deletedAt = now; + session.updatedAt = now; + + return lastItem; + } +} diff --git a/packages/agentic-workflows/src/repository/session/repository-session.ts b/packages/agentic-workflows/src/repository/session/repository-session.ts new file mode 100644 index 0000000..90ae7cc --- /dev/null +++ b/packages/agentic-workflows/src/repository/session/repository-session.ts @@ -0,0 +1,123 @@ +import type { AgentInputItem, Session } from "@openai/agents"; +import { ConversationSessionRepository } from "./conversation-session-repository"; + +/** + * Repository-backed session implementation for OpenAI Agents SDK. + * Stores conversation history in our database instead of in-memory or OpenAI's servers. + * + * IMPORTANT: This session only stores plain chat messages, not execution artifacts. + */ +export class RepositorySession implements Session { + private sessionId: string; + private repository: ConversationSessionRepository; + private cachedItems: AgentInputItem[] | undefined = undefined; + + constructor(sessionId: string, repository: ConversationSessionRepository) { + this.sessionId = sessionId; + this.repository = repository; + } + + async getSessionId(): Promise { + return this.sessionId; + } + + /** + * Converts stored string content to the array of content parts expected by the Agents SDK. + * The SDK requires content to be an array, not a string. + */ + private toContentParts( + role: "user" | "assistant" | "system", + content: string + ): { type: string; text: string }[] { + if (role === "user") { + return [{ type: "input_text", text: content }]; + } + + // assistant + system + return [{ type: "output_text", text: content }]; + } + + /** + * Returns conversation items as plain chat messages. + * Does NOT restore metadata, IDs, or any execution artifacts. + */ + async getItems(limit?: number): Promise { + if (!limit && this.cachedItems) { + return this.cachedItems; + } + + const dbItems = await this.repository.getConversationItems( + this.sessionId, + limit + ); + + const items: AgentInputItem[] = dbItems.map((item) => ({ + role: item.role as "user" | "assistant" | "system", + content: this.toContentParts( + item.role as "user" | "assistant" | "system", + item.content + ) + })); + + if (!limit) { + this.cachedItems = items; + } + + return items; + } + + /** + * Adds items to the session, down-projecting to plain chat messages. + * Only persists user, assistant, and system messages. + * Filters out all execution artifacts (tool_call, tool_result, reasoning, etc.) + */ + async addItems(items: AgentInputItem[]): Promise { + // Down-project aggressively: only keep human-visible chat turns + const messages = items + .filter( + (item) => + item.role === "user" || + item.role === "assistant" || + item.role === "system" + ) + .map((item) => ({ + role: item.role as string, + content: + typeof item.content === "string" + ? item.content + : JSON.stringify(item.content) + })); + + if (messages.length > 0) { + await this.repository.addConversationItems(this.sessionId, messages); + } + + this.cachedItems = undefined; + } + + async clearSession(): Promise { + await this.repository.clearConversation(this.sessionId); + this.cachedItems = undefined; + } + + /** + * Pops the last item from the session. + * Returns only plain chat message - no metadata. + */ + async popItem(): Promise { + const poppedItem = await this.repository.popLastItem(this.sessionId); + this.cachedItems = undefined; + + if (!poppedItem) { + return undefined; + } + + return { + role: poppedItem.role as "user" | "assistant" | "system", + content: this.toContentParts( + poppedItem.role as "user" | "assistant" | "system", + poppedItem.content + ) + }; + } +} diff --git a/packages/agentic-workflows/src/service/agent-parameter-mapper.ts b/packages/agentic-workflows/src/service/agent-parameter-mapper.ts new file mode 100644 index 0000000..67a6855 --- /dev/null +++ b/packages/agentic-workflows/src/service/agent-parameter-mapper.ts @@ -0,0 +1,72 @@ +import { RepositorySession } from "../repository/session/repository-session"; + +export class AgentParameterMapper { + private readonly parameterNames: string[]; + + public static create(func: (...args: any[]) => any): AgentParameterMapper { + return new AgentParameterMapper(func); + } + + private constructor(func: (...args: any[]) => any) { + this.parameterNames = this.extractParameterNames(func); + } + + /** + * Maps arguments to an object where keys are parameter names. + * Special case: if a parameter is named 'context', it is excluded from the input object + * and returned separately. + */ + public mapArguments(args: any[]): { + input: string; + context?: Record; + } { + const inputObj: Record = {}; + let context: Record | undefined; + + for (let i = 0; i < this.parameterNames.length; i++) { + const name = this.parameterNames[i]; + const value = args[i]; + + if (name === "context") { + context = value; + } else if (value instanceof RepositorySession) { + // Skip session objects + } else { + inputObj[name] = value; + } + } + + // If there is only one input parameter and it's not 'context', and it's a string, + // we could potentially just use it as the input string directly to remain backward compatible + // or if the user wants it that way. + // However, the issue description says "cast into a json string". + // If we have multiple arguments, we definitely want JSON. + // If we have one argument, JSON is also fine and more consistent. + + return { + input: JSON.stringify(inputObj, null, 2), + context + }; + } + + public getParameterNames(): string[] { + return this.parameterNames; + } + + private extractParameterNames(func: (...args: any[]) => any): string[] { + const STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm; + const ARGUMENT_NAMES = /([^\s,]+)/g; + const fnStr = func.toString().replace(STRIP_COMMENTS, ""); + const result = fnStr + .slice(fnStr.indexOf("(") + 1, fnStr.indexOf(")")) + .match(ARGUMENT_NAMES); + + if (result === null) { + return []; + } + + // Filter out potential artifacts like default values or destructured patterns if simple regex isn't enough + // But for basic usage like `(arg1, arg2)` it works fine. + return result; + } +} diff --git a/packages/agentic-workflows/src/service/ai-agent-service-local.ts b/packages/agentic-workflows/src/service/ai-agent-service-local.ts new file mode 100644 index 0000000..895468a --- /dev/null +++ b/packages/agentic-workflows/src/service/ai-agent-service-local.ts @@ -0,0 +1,206 @@ +import { + AgentConfig, + AgentRunConfig, + AgentRunResult, + AiAgentService, + AgentType +} from "./ai-agent-service"; + +/** + * Local/mock implementation of AiAgentService for testing. + * Follows the pattern of OpenaiServiceLocal and TavilyServiceLocal. + * + * Usage in tests: + * ```typescript + * // Mock Phase 1: Link Extraction + * AiAgentServiceLocal.setResponse("ProgramNextStepsAgent:extractLinks", { + * links: ["https://example.com/apply"] + * }); + * + * // Mock Phase 2: Link Summaries (multiple responses for loops) + * AiAgentServiceLocal.setResponses("ProgramNextStepsAgent:summarizeLink", [ + * "Summary for first link", + * "Summary for second link" + * ]); + * + * // Mock errors + * AiAgentServiceLocal.setError("ProgramNextStepsAgent:searchWeb", "Failed to fetch"); + * + * // Cleanup + * AiAgentServiceLocal.clearResponses(); + * AiAgentServiceLocal.clearErrors(); + * ``` + */ +export class AiAgentServiceLocal implements AiAgentService { + private static instance: AiAgentServiceLocal = new AiAgentServiceLocal(); + private static responsesByAgentName: Map = new Map(); + private static errorsByAgentName: Map = new Map(); + private static mockWorkingDir: string | undefined; + + public static getInstance(): AiAgentServiceLocal { + return AiAgentServiceLocal.instance; + } + + /** + * Set a single response for an agent. + * If called multiple times for the same agent, responses will be queued. + */ + public static setResponse(agentName: string, output: T): void { + const existing = this.responsesByAgentName.get(agentName) || []; + existing.push(output); + this.responsesByAgentName.set(agentName, existing); + } + + /** + * Set multiple responses for an agent (useful for agents called in loops). + * Responses will be returned in order, one per call. + */ + public static setResponses(agentName: string, outputs: T[]): void { + const existing = this.responsesByAgentName.get(agentName) || []; + existing.push(...outputs); + this.responsesByAgentName.set(agentName, existing); + } + + /** + * Set a mock working directory to return with successful responses. + * Used to test flows where the caller needs a workingDir (e.g., Codex CLI agent). + */ + public static setMockWorkingDir(dir: string | undefined): void { + this.mockWorkingDir = dir; + } + + /** + * Set an error message for an agent. + * When this agent is called, it will return a failed result with this error. + */ + public static setError(agentName: string, errorMessage: string): void { + this.errorsByAgentName.set(agentName, errorMessage); + } + + /** + * Clear all response overrides + */ + public static clearResponses(): void { + this.responsesByAgentName.clear(); + } + + /** + * Clear all error overrides + */ + public static clearErrors(): void { + this.errorsByAgentName.clear(); + } + + /** + * Clear all overrides (both responses and errors) + */ + public static clearAllOverrides(): void { + this.responsesByAgentName.clear(); + this.errorsByAgentName.clear(); + this.mockWorkingDir = undefined; + } + + /** + * Creates a mock agent. In local mode, we don't actually create real agents, + * but we return a placeholder that can be used with runAgent. + */ + createAgent(config: AgentConfig): AgentType { + // Return a mock agent object that contains the config + // This is just a placeholder since we don't actually use it in local mode + return { config } as unknown as AgentType; + } + + /** + * Runs a mock agent. Returns the next queued response for the agent's name, + * or an error if one is configured, or a default response. + */ + async runAgent( + agent: AgentType, + config: AgentRunConfig + ): Promise> { + const agentConfig = (agent as any).config as AgentConfig; + return this.executeAgent(agentConfig, config); + } + + /** + * Convenience method to create and run an agent in one call. + * This is the primary method used in production code. + */ + async createAndRun( + agentConfig: AgentConfig, + runConfig: AgentRunConfig + ): Promise> { + return this.executeAgent(agentConfig, runConfig); + } + + /** + * Internal method that handles the actual mock execution logic + */ + private async executeAgent( + agentConfig: AgentConfig, + runConfig: AgentRunConfig + ): Promise> { + const result = await this.getAgentResult(agentConfig); + + if (runConfig.session && result.success) { + await runConfig.session.addItems([ + { role: "user", content: runConfig.input }, + { + role: "assistant", + content: + typeof result.output === "string" + ? result.output + : JSON.stringify(result.output) + } + ]); + } + + return result; + } + + private async getAgentResult( + agentConfig: AgentConfig + ): Promise> { + // Check for error override + const error = AiAgentServiceLocal.errorsByAgentName.get(agentConfig.name); + if (error) { + return { + success: false, + error, + output: undefined as any + }; + } + + // Check for response override + const responses = AiAgentServiceLocal.responsesByAgentName.get( + agentConfig.name + ); + if (responses && responses.length > 0) { + const response = responses.shift(); // Pop first response from queue + return { + success: true, + output: response, + workingDir: AiAgentServiceLocal.mockWorkingDir + }; + } + + // Default mock response + return { + success: true, + output: this.generateDefaultResponse(agentConfig), + workingDir: AiAgentServiceLocal.mockWorkingDir + }; + } + + /** + * Generate a reasonable default response based on the agent's output schema + */ + private generateDefaultResponse(config: AgentConfig): T { + // For structured outputs with a schema, return an empty object + if (config.outputSchema) { + return {} as T; + } + // For string outputs (no schema), return a mock string + return `Mock response for ${config.name}` as T; + } +} diff --git a/packages/agentic-workflows/src/service/ai-agent-service-ollama.ts b/packages/agentic-workflows/src/service/ai-agent-service-ollama.ts new file mode 100644 index 0000000..a670d8e --- /dev/null +++ b/packages/agentic-workflows/src/service/ai-agent-service-ollama.ts @@ -0,0 +1,100 @@ +import { Agent, OpenAIProvider, Runner } from "@openai/agents"; +import { createLogger, transports } from "winston"; +import { + AgentConfig, + AgentRunConfig, + AgentRunResult, + AgentType, + AiAgentService +} from "./ai-agent-service"; + +/** + * Ollama-based implementation of the AI agent service. + * Uses Ollama's OpenAI-compatible API endpoint via the @openai/agents SDK. + * + * Ollama provides an OpenAI-compatible API at /v1, which allows us to use + * the same OpenAI SDK with a different base URL pointing to the local + * Ollama instance. + */ +export class AiAgentServiceOllama implements AiAgentService { + private readonly logger = createLogger({ + transports: [new transports.Console()] + }); + + private readonly defaultModel: string; + private readonly runner: Runner; + + /** + * Creates an Ollama-based AI agent service. + * + * @param baseUrl - The base URL of the Ollama instance (e.g., "http://localhost:11434") + * @param defaultModel - The default model to use (e.g., "llama2", "mistral", "codellama") + */ + constructor(baseUrl: string, defaultModel = "qwen2.5:14b") { + this.defaultModel = defaultModel; + // Ollama exposes an OpenAI-compatible API at /v1 + const provider = new OpenAIProvider({ + baseURL: `${baseUrl}/v1`, + apiKey: "ollama", // Ollama doesn't require an API key, but the SDK requires a non-empty value + useResponses: false // Use chat completions API for Ollama compatibility + }); + this.runner = new Runner({ + modelProvider: provider + }); + } + + public createAgent(config: AgentConfig): AgentType { + return new Agent({ + name: config.name, + instructions: config.instructions, + model: config.model ?? this.defaultModel, + tools: config.tools ?? [], + outputType: config.outputSchema, + modelSettings: config.modelSettings, + inputGuardrails: config.inputGuardrails ?? undefined + }) as AgentType; + } + + public async runAgent( + agent: AgentType, + config: AgentRunConfig + ): Promise> { + try { + const runOptions: Record = {}; + if (config.session) { + runOptions["session"] = config.session; + } + if (config.maxTurns !== undefined) { + runOptions["maxTurns"] = config.maxTurns; + } + const result = + Object.keys(runOptions).length > 0 + ? await this.runner.run(agent, config.input, runOptions) + : await this.runner.run(agent, config.input); + return { + output: result.finalOutput as T, + success: true, + rawResult: result + }; + } catch (error) { + this.logger.error( + `Error running Ollama agent ${ + error instanceof Error ? error.message : String(error) + }` + ); + return { + output: "" as unknown as T, + success: false, + error: error instanceof Error ? error.message : String(error) + }; + } + } + + public async createAndRun( + agentConfig: AgentConfig, + runConfig: AgentRunConfig + ): Promise> { + const agent = this.createAgent(agentConfig); + return this.runAgent(agent, runConfig); + } +} diff --git a/packages/agentic-workflows/src/service/ai-agent-service-openai.ts b/packages/agentic-workflows/src/service/ai-agent-service-openai.ts new file mode 100644 index 0000000..936bb72 --- /dev/null +++ b/packages/agentic-workflows/src/service/ai-agent-service-openai.ts @@ -0,0 +1,89 @@ +import { Agent, run, setDefaultOpenAIKey } from "@openai/agents"; +import { createLogger, transports } from "winston"; +import { + AgentConfig, + AgentRunConfig, + AgentRunResult, + AgentType, + AiAgentService +} from "./ai-agent-service"; + +/** + * OpenAI-based implementation of the AI agent service. + * Uses the OpenAI API directly via the @openai/agents SDK. + */ +export class AiAgentServiceOpenai implements AiAgentService { + private readonly logger = createLogger({ + transports: [new transports.Console()] + }); + + private readonly defaultModel: string; + + constructor(apiKey: string, defaultModel = "gpt-4o") { + this.defaultModel = defaultModel; + setDefaultOpenAIKey(apiKey); + } + + public createAgent(config: AgentConfig): AgentType { + return new Agent({ + name: config.name, + instructions: config.instructions, + model: config.model ?? this.defaultModel, + tools: config.tools ?? [], + outputType: config.outputSchema, + modelSettings: config.modelSettings, + inputGuardrails: config.inputGuardrails ?? [] + }) as AgentType; + } + + public async runAgent( + agent: AgentType, + config: AgentRunConfig + ): Promise> { + try { + const runOptions: Record = {}; + if (config.session) { + runOptions["session"] = config.session; + } + if (config.maxTurns !== undefined) { + runOptions["maxTurns"] = config.maxTurns; + } + const result = + Object.keys(runOptions).length > 0 + ? await run(agent, config.input, runOptions) + : await run(agent, config.input); + + return { + output: result.finalOutput as T, + success: true, + rawResult: result + }; + } catch (error) { + const errorMessage = + error instanceof Error ? error.message : String(error); + const logMessage = `Error running OpenAI agent ${errorMessage}`; + if (this.isMaxTurnsExceededError(errorMessage)) { + this.logger.warn(logMessage); + } else { + this.logger.error(logMessage); + } + return { + output: "" as unknown as T, + success: false, + error: errorMessage + }; + } + } + + public async createAndRun( + agentConfig: AgentConfig, + runConfig: AgentRunConfig + ): Promise> { + const agent = this.createAgent(agentConfig); + return this.runAgent(agent, runConfig); + } + + private isMaxTurnsExceededError(errorMessage: string): boolean { + return /max turns \(\d+\) exceeded/i.test(errorMessage); + } +} diff --git a/packages/agentic-workflows/src/service/ai-agent-service.ts b/packages/agentic-workflows/src/service/ai-agent-service.ts new file mode 100644 index 0000000..bb70fa4 --- /dev/null +++ b/packages/agentic-workflows/src/service/ai-agent-service.ts @@ -0,0 +1,95 @@ +import type { + InputGuardrail, + ModelSettings, + Session, + UnknownContext +} from "@openai/agents"; +import { Agent, Tool } from "@openai/agents"; +import { z } from "zod"; + +/** + * Configuration for an AI agent run + */ +export interface AgentRunConfig { + /** The input message/prompt to send to the agent */ + input: string; + /** Optional context to provide to the agent */ + context?: Record; + /** Optional session for conversation history */ + session?: Session; + /** Maximum number of agentic turns before stopping. Defaults to 10 in the SDK. */ + maxTurns?: number; + /** Optional git branch to fetch and checkout after cloning. Used by Codex CLI service. */ + branch?: string; +} + +/** + * Result from an AI agent run + */ +export interface AgentRunResult { + /** The final output from the agent */ + output: T; + /** Whether the run completed successfully */ + success: boolean; + /** Any error message if the run failed */ + error?: string; + /** The raw result from the underlying SDK (for advanced use cases) */ + rawResult?: unknown; + /** Path to the git repo working directory. When set, the caller is responsible for cleanup. */ + workingDir?: string; +} + +/** + * Configuration for creating an AI agent + */ +export interface AgentConfig { + /** Name of the agent */ + name: string; + /** Instructions/system prompt for the agent */ + instructions: string; + /** Model to use (e.g., "gpt-4o", "llama2") */ + model?: string; + /** Tools available to the agent */ + tools?: Tool[]; + /** Output schema for the agent */ + outputSchema?: T extends string ? undefined : z.ZodType; + /** Model settings (e.g., toolChoice, temperature) */ + modelSettings?: ModelSettings; + /** Input guardrails that run checks on the input before the agent processes it */ + inputGuardrails?: InputGuardrail[]; +} + +/** + * Helper type for Agent with Zod output type + */ +export type AgentType = Agent< + UnknownContext, + T extends string ? undefined : z.ZodType +>; + +/** + * Interface for AI agent services that abstracts the underlying provider. + * Implementations can use OpenAI, Ollama, or other providers. + */ +export interface AiAgentService { + /** + * Creates an agent with the given configuration + */ + createAgent(config: AgentConfig): AgentType; + + /** + * Runs an agent with the given input and returns the result + */ + runAgent( + agent: AgentType, + config: AgentRunConfig + ): Promise>; + + /** + * Convenience method to create and run an agent in one call + */ + createAndRun( + agentConfig: AgentConfig, + runConfig: AgentRunConfig + ): Promise>; +} diff --git a/packages/agentic-workflows/src/service/ai-session-factory.ts b/packages/agentic-workflows/src/service/ai-session-factory.ts new file mode 100644 index 0000000..6c829e5 --- /dev/null +++ b/packages/agentic-workflows/src/service/ai-session-factory.ts @@ -0,0 +1,33 @@ +import { Inject, Injectable } from "@nestjs/common"; +import { ConversationSessionModel } from "../repository/session/conversation-session-model"; +import { + CONVERSATION_SESSION_REPOSITORY, + ConversationSessionRepository +} from "../repository/session/conversation-session-repository"; +import { RepositorySession } from "../repository/session/repository-session"; + +@Injectable() +export class AiSessionFactory { + constructor( + @Inject(CONVERSATION_SESSION_REPOSITORY) + private readonly conversationSessionRepository: ConversationSessionRepository + ) {} + + public async getOrCreateSession( + clientId: string, + sessionId?: string + ): Promise { + let session: ConversationSessionModel; + if (sessionId) { + session = await this.conversationSessionRepository.getSession(sessionId); + } else { + session = await this.conversationSessionRepository.createSession( + clientId + ); + } + return new RepositorySession( + session.sessionId, + this.conversationSessionRepository + ); + } +} diff --git a/packages/agentic-workflows/src/service/decorators.ts b/packages/agentic-workflows/src/service/decorators.ts new file mode 100644 index 0000000..ff25668 --- /dev/null +++ b/packages/agentic-workflows/src/service/decorators.ts @@ -0,0 +1,183 @@ +import { timeFunction } from "@zeroshotbuilders/commons"; +import { ModelSettings, Tool } from "@openai/agents"; +import fs from "fs"; +import path from "path"; +import { z } from "zod"; +import { RepositorySession } from "../repository/session/repository-session"; +import { AgentParameterMapper } from "./agent-parameter-mapper"; +import { + AgentConfig, + AgentRunConfig, + AgentRunResult, + AiAgentService +} from "./ai-agent-service"; +import { + generateToolsReference, + mapToolKeys, + parsePromptFrontmatter, + validateToolsMatch +} from "./prompt-utils"; + +/** + * Customizable options for specifying Agentic Workflows + * - promptsDirectory (optional): the directory to look for prompts in. If not specified, then each individual method + * must specify the prompt to execute. Should use `__dirname` to specify the directory so that it's relative to + * the workflow class. + * - toolRegistry (optional): a registry mapping tool keys to tool names for use in frontmatter. If provided, + * prompts can declare tools using friendly keys instead of raw tool names. + */ +export type AgenticWorkflowOptions = { + promptsDirectory?: string; + toolRegistry?: Record; +}; + +/** + * Decorator for an Agentic Workflow class that contains AI agents + * @param options the class-namespaced options for the workflow + * @constructor + */ +export function AgenticWorkflow( + options?: AgenticWorkflowOptions +): ClassDecorator { + return function (target: any) { + target.prototype.agenticWorkflowOptions = options; + }; +} + +/** + * Customizable options for specifying AI agents: + * - name (optional): the name of the agent. If not specified, it will be derived from the class and method name (e.g. "ClassName:methodName") + * - tools (optional): the tools available to the agent. Can be an array of tools or a function that returns an array of tools given the instance. + * - model (optional): the model to use for the agent + * - modelSettings (optional): the model settings for the agent + * - outputSchema (optional): the output schema for the agent + * - maxTurns (optional): maximum number of agentic turns. If not specified, defaults to 1 for agents + * without tools (since they should always complete in a single turn) or 5 for agents with tools. + */ +export type AgentOptions = { + name?: string; + tools?: Tool[] | ((instance: any) => Tool[]); + model?: string; + modelSettings?: ModelSettings; + outputSchema?: T extends string ? undefined : z.ZodType; + maxTurns?: number; + /** Name of the method parameter that contains the git branch to checkout before running. */ + branchParam?: string; +}; + +/** + * Decorator for a class method that executes an AI agent + * @param options + * @constructor + */ +export function Agent(options: AgentOptions): MethodDecorator { + return function ( + target: any, + propertyKey: string | symbol, + descriptor: PropertyDescriptor + ) { + const originalMethod = descriptor.value; + const parameterMapper = AgentParameterMapper.create(originalMethod); + + descriptor.value = async function ( + ...args: any[] + ): Promise> { + const parentInstance = this as any; + const aiAgentService: AiAgentService = parentInstance.aiAgentService; + + if (!aiAgentService) { + throw new Error( + "aiAgentService not found on the class instance. Make sure it is injected as 'aiAgentService'." + ); + } + + const promptsDirectory = + parentInstance.agenticWorkflowOptions?.promptsDirectory; + if (!promptsDirectory) { + throw new Error("promptsDirectory not specified in @AgenticWorkflow"); + } + + const filePath = path.join( + promptsDirectory, + `${propertyKey.toString()}.md` + ); + if (!fs.existsSync(filePath)) { + throw new Error(`Prompt file not found: ${filePath}`); + } + const rawMarkdown = fs.readFileSync(filePath, "utf-8"); + + // Parse frontmatter from the markdown file + const { frontmatter, content } = parsePromptFrontmatter(rawMarkdown); + + const tools = + typeof options.tools === "function" + ? options.tools(parentInstance) + : options.tools; + + // If frontmatter declares tools and a registry is provided, validate + const toolRegistry = parentInstance.agenticWorkflowOptions?.toolRegistry; + if (frontmatter.tools && frontmatter.tools.length > 0) { + if (toolRegistry) { + // Map tool keys to tool names and validate + const declaredToolNames = mapToolKeys( + frontmatter.tools, + toolRegistry + ); + if (tools) { + validateToolsMatch(declaredToolNames, tools); + } + } + } + + // Generate tools reference documentation and inject it into instructions + const toolsReference = tools ? generateToolsReference(tools) : ""; + const instructions = toolsReference + content; + + const agentName = + options.name ?? `${target.constructor.name}:${propertyKey.toString()}`; + + const agentConfig: AgentConfig = { + name: agentName, + instructions, + tools, + model: options.model, + modelSettings: options.modelSettings, + outputSchema: options.outputSchema + }; + + const { input, context } = parameterMapper.mapArguments(args); + + const maybeSession: RepositorySession = args.find( + (arg) => arg instanceof RepositorySession + ); + + // Extract branch from the named parameter if branchParam is specified + let branch: string | undefined; + if (options.branchParam) { + const paramNames = parameterMapper.getParameterNames(); + const branchIdx = paramNames.indexOf(options.branchParam); + if (branchIdx >= 0 && typeof args[branchIdx] === "string") { + branch = args[branchIdx]; + } + } + + // Default maxTurns: 1 for agents without tools (they complete in a single turn), + // 8 for agents with tools (to allow for multi-step tool call + response cycles) + const hasTools = tools && tools.length > 0; + const maxTurns = options.maxTurns ?? (hasTools ? 8 : 1); + + const runConfig: AgentRunConfig = { + input, + context, + session: maybeSession, + maxTurns, + branch + }; + + return timeFunction( + () => aiAgentService.createAndRun(agentConfig, runConfig), + agentConfig.name + ); + }; + }; +} diff --git a/packages/agentic-workflows/src/service/prompt-utils.ts b/packages/agentic-workflows/src/service/prompt-utils.ts new file mode 100644 index 0000000..4060864 --- /dev/null +++ b/packages/agentic-workflows/src/service/prompt-utils.ts @@ -0,0 +1,150 @@ +import { Tool } from "@openai/agents"; + +export type PromptFrontmatter = { + tools?: string[]; +}; + +export type ParsedPrompt = { + frontmatter: PromptFrontmatter; + content: string; +}; + +/** + * Parses frontmatter from a markdown file. + * Expects YAML frontmatter delimited by --- at the start of the file. + */ +export function parsePromptFrontmatter(markdown: string): ParsedPrompt { + const frontmatterRegex = /^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/; + const match = markdown.match(frontmatterRegex); + + if (!match) { + return { + frontmatter: {}, + content: markdown + }; + } + + const frontmatterText = match[1]; + const content = match[2]; + + // Simple YAML parser for our specific use case (tools array) + const frontmatter: PromptFrontmatter = {}; + + // Parse tools array + const toolsMatch = frontmatterText.match(/tools:\s*\n((?:\s+-\s+.+\n?)*)/); + if (toolsMatch) { + const toolsText = toolsMatch[1]; + const tools = toolsText + .split("\n") + .map((line) => line.trim()) + .filter((line) => line.startsWith("-")) + .map((line) => line.substring(1).trim()) + .filter(Boolean); + frontmatter.tools = tools; + } + + return { + frontmatter, + content + }; +} + +/** + * Generates a tools reference section to be injected into the prompt. + * This documents the available tools and their usage for the agent. + */ +export function generateToolsReference(tools: Tool[]): string { + if (!tools || tools.length === 0) { + return ""; + } + + const toolDocs = tools + .map((tool) => { + const anyTool = tool as any; + const params = (tool as any).parameters; + let paramsDoc = ""; + + if (params && params._def && params._def.shape) { + const shape = params._def.shape(); + const paramNames = Object.keys(shape); + if (paramNames.length > 0) { + const paramsList = paramNames + .map((name) => { + const field = shape[name]; + const desc = field._def.description; + return ` - ${name}: ${desc || "parameter"}`; + }) + .join("\n"); + paramsDoc = `\nParameters:\n${paramsList}`; + } + } + + return `## ${anyTool.name}\n${anyTool.description || ""}${paramsDoc}`; + }) + .join("\n\n"); + + return `# Available Tools\n\nYou have access to the following tools:\n\n${toolDocs}\n\n---\n\n`; +} + +/** + * Maps tool keys from frontmatter to actual tool names using a registry. + * Validates that all referenced tool keys exist in the registry. + */ +export function mapToolKeys( + toolKeys: string[], + registry: Record +): string[] { + const toolNames: string[] = []; + const invalidKeys: string[] = []; + + for (const key of toolKeys) { + if (key in registry) { + toolNames.push(registry[key]); + } else { + invalidKeys.push(key); + } + } + + if (invalidKeys.length > 0) { + throw new Error( + `Invalid tool keys in frontmatter: ${invalidKeys.join(", ")}. ` + + `Available keys: ${Object.keys(registry).join(", ")}` + ); + } + + return toolNames; +} + +/** + * Validates that tools provided to the agent match the tools declared in frontmatter. + */ +export function validateToolsMatch( + declaredToolNames: string[], + actualTools: Tool[] +): void { + const actualToolNames = actualTools.map((t) => t.name); + + // Check that all declared tools are provided + const missingTools = declaredToolNames.filter( + (name) => !actualToolNames.includes(name) + ); + if (missingTools.length > 0) { + throw new Error( + `Tools declared in frontmatter but not provided to agent: ${missingTools.join( + ", " + )}` + ); + } + + // Check that all provided tools are declared + const extraTools = actualToolNames.filter( + (name) => !declaredToolNames.includes(name) + ); + if (extraTools.length > 0) { + throw new Error( + `Tools provided to agent but not declared in frontmatter: ${extraTools.join( + ", " + )}. ` + `Add these to the frontmatter 'tools' list.` + ); + } +} diff --git a/packages/agentic-workflows/test/ai-agent-service-local.spec.ts b/packages/agentic-workflows/test/ai-agent-service-local.spec.ts new file mode 100644 index 0000000..95359a5 --- /dev/null +++ b/packages/agentic-workflows/test/ai-agent-service-local.spec.ts @@ -0,0 +1,256 @@ +import { z } from "zod"; +import { AgentConfig } from "@zeroshotbuilders/agentic-workflows"; +import { AiAgentServiceLocal } from "@zeroshotbuilders/agentic-workflows"; + +describe("AiAgentServiceLocal", () => { + let service: AiAgentServiceLocal; + + beforeEach(() => { + service = AiAgentServiceLocal.getInstance(); + AiAgentServiceLocal.clearAllOverrides(); + }); + + afterEach(() => { + AiAgentServiceLocal.clearAllOverrides(); + }); + + describe("Single Agent Execution", () => { + it("should return a mocked response for a string output agent", async () => { + const agentConfig: AgentConfig = { + name: "TestStringAgent", + instructions: "You are a test agent that returns strings", + tools: [] + }; + const mockResponse = "This is a test response"; + AiAgentServiceLocal.setResponse("TestStringAgent", mockResponse); + const result = await service.createAndRun(agentConfig, { input: "Test input" }); + expect(result.success).toBe(true); + expect(result.output).toBe(mockResponse); + expect(result.error).toBeUndefined(); + }); + + it("should return a mocked response for a structured output agent", async () => { + const outputSchema = z.object({ links: z.array(z.string()) }); + type LinksOutput = z.infer; + const agentConfig: AgentConfig = { + name: "TestAgent:extractLinks", + instructions: "You extract links from web pages", + outputSchema, + tools: [] + }; + const mockResponse: LinksOutput = { + links: ["https://example.com/page1", "https://example.com/page2"] + }; + AiAgentServiceLocal.setResponse("TestAgent:extractLinks", mockResponse); + const result = await service.createAndRun(agentConfig, { input: "Extract links from this page" }); + expect(result.success).toBe(true); + expect(result.output).toEqual(mockResponse); + expect(result.output.links).toHaveLength(2); + }); + }); + + describe("Multiple Responses for Same Agent (Loop Scenario)", () => { + it("should return responses in order when agent is called multiple times", async () => { + const agentConfig: AgentConfig = { + name: "TestAgent:summarizeLink", + instructions: "You summarize web page content", + tools: [] + }; + const mockResponses = ["Summary for first link", "Summary for second link", "Summary for third link"]; + AiAgentServiceLocal.setResponses("TestAgent:summarizeLink", mockResponses); + const result1 = await service.createAndRun(agentConfig, { input: "Summarize link 1" }); + const result2 = await service.createAndRun(agentConfig, { input: "Summarize link 2" }); + const result3 = await service.createAndRun(agentConfig, { input: "Summarize link 3" }); + expect(result1.success).toBe(true); + expect(result1.output).toBe(mockResponses[0]); + expect(result2.success).toBe(true); + expect(result2.output).toBe(mockResponses[1]); + expect(result3.success).toBe(true); + expect(result3.output).toBe(mockResponses[2]); + }); + + it("should support adding responses incrementally with setResponse", async () => { + const agentConfig: AgentConfig = { name: "IncrementalAgent", instructions: "Test agent", tools: [] }; + AiAgentServiceLocal.setResponse("IncrementalAgent", "Response 1"); + AiAgentServiceLocal.setResponse("IncrementalAgent", "Response 2"); + const result1 = await service.createAndRun(agentConfig, { input: "Test 1" }); + const result2 = await service.createAndRun(agentConfig, { input: "Test 2" }); + expect(result1.output).toBe("Response 1"); + expect(result2.output).toBe("Response 2"); + }); + + it("should mix setResponse and setResponses calls", async () => { + const agentConfig: AgentConfig = { name: "MixedAgent", instructions: "Test agent", tools: [] }; + AiAgentServiceLocal.setResponse("MixedAgent", "First"); + AiAgentServiceLocal.setResponses("MixedAgent", ["Second", "Third"]); + AiAgentServiceLocal.setResponse("MixedAgent", "Fourth"); + const results = await Promise.all([ + service.createAndRun(agentConfig, { input: "1" }), + service.createAndRun(agentConfig, { input: "2" }), + service.createAndRun(agentConfig, { input: "3" }), + service.createAndRun(agentConfig, { input: "4" }) + ]); + expect(results[0].output).toBe("First"); + expect(results[1].output).toBe("Second"); + expect(results[2].output).toBe("Third"); + expect(results[3].output).toBe("Fourth"); + }); + }); + + describe("Error Handling", () => { + it("should return a failed result when an error is set", async () => { + const agentConfig: AgentConfig = { name: "FailingAgent", instructions: "This agent will fail", tools: [] }; + const errorMessage = "Failed to fetch page content"; + AiAgentServiceLocal.setError("FailingAgent", errorMessage); + const result = await service.createAndRun(agentConfig, { input: "This should fail" }); + expect(result.success).toBe(false); + expect(result.error).toBe(errorMessage); + expect(result.output).toBeUndefined(); + }); + + it("should prioritize errors over responses", async () => { + const agentConfig: AgentConfig = { name: "ErrorPriorityAgent", instructions: "Test agent", tools: [] }; + AiAgentServiceLocal.setResponse("ErrorPriorityAgent", "This should not be returned"); + AiAgentServiceLocal.setError("ErrorPriorityAgent", "Error takes priority"); + const result = await service.createAndRun(agentConfig, { input: "Test" }); + expect(result.success).toBe(false); + expect(result.error).toBe("Error takes priority"); + }); + }); + + describe("Default Responses", () => { + it("should return a default string response when no mock is configured", async () => { + const agentConfig: AgentConfig = { name: "UnmockedStringAgent", instructions: "No mock configured", tools: [] }; + const result = await service.createAndRun(agentConfig, { input: "Test" }); + expect(result.success).toBe(true); + expect(result.output).toBe("Mock response for UnmockedStringAgent"); + }); + + it("should return an empty object for structured output when no mock is configured", async () => { + const outputSchema = z.object({ steps: z.array(z.string()) }); + const agentConfig: AgentConfig> = { + name: "UnmockedStructuredAgent", + instructions: "No mock configured", + outputSchema, + tools: [] + }; + const result = await service.createAndRun(agentConfig, { input: "Test" }); + expect(result.success).toBe(true); + expect(result.output).toEqual({}); + }); + + it("should fall back to default after all mocked responses are consumed", async () => { + const agentConfig: AgentConfig = { name: "ExhaustedAgent", instructions: "Test agent", tools: [] }; + AiAgentServiceLocal.setResponses("ExhaustedAgent", ["Response 1", "Response 2"]); + await service.createAndRun(agentConfig, { input: "1" }); + await service.createAndRun(agentConfig, { input: "2" }); + const result = await service.createAndRun(agentConfig, { input: "3" }); + expect(result.success).toBe(true); + expect(result.output).toBe("Mock response for ExhaustedAgent"); + }); + }); + + describe("Cleanup Methods", () => { + it("should clear all responses", async () => { + AiAgentServiceLocal.setResponse("Agent1", "Response 1"); + AiAgentServiceLocal.setResponse("Agent2", "Response 2"); + AiAgentServiceLocal.clearResponses(); + const result1 = await service.createAndRun({ name: "Agent1", instructions: "Test", tools: [] }, { input: "Test" }); + const result2 = await service.createAndRun({ name: "Agent2", instructions: "Test", tools: [] }, { input: "Test" }); + expect(result1.output).toBe("Mock response for Agent1"); + expect(result2.output).toBe("Mock response for Agent2"); + }); + + it("should clear all errors", async () => { + AiAgentServiceLocal.setError("Agent1", "Error 1"); + AiAgentServiceLocal.setError("Agent2", "Error 2"); + AiAgentServiceLocal.clearErrors(); + const result1 = await service.createAndRun({ name: "Agent1", instructions: "Test", tools: [] }, { input: "Test" }); + const result2 = await service.createAndRun({ name: "Agent2", instructions: "Test", tools: [] }, { input: "Test" }); + expect(result1.success).toBe(true); + expect(result2.success).toBe(true); + }); + + it("should clear all overrides (responses and errors)", async () => { + AiAgentServiceLocal.setResponse("Agent1", "Response"); + AiAgentServiceLocal.setError("Agent2", "Error"); + AiAgentServiceLocal.clearAllOverrides(); + const result1 = await service.createAndRun({ name: "Agent1", instructions: "Test", tools: [] }, { input: "Test" }); + const result2 = await service.createAndRun({ name: "Agent2", instructions: "Test", tools: [] }, { input: "Test" }); + expect(result1.success).toBe(true); + expect(result1.output).toBe("Mock response for Agent1"); + expect(result2.success).toBe(true); + expect(result2.output).toBe("Mock response for Agent2"); + }); + }); + + describe("createAgent and runAgent methods", () => { + it("should support the two-step createAgent + runAgent pattern", async () => { + const agentConfig: AgentConfig = { name: "TwoStepAgent", instructions: "Test agent", tools: [] }; + AiAgentServiceLocal.setResponse("TwoStepAgent", "Two-step response"); + const agent = service.createAgent(agentConfig); + const result = await service.runAgent(agent, { input: "Test" }); + expect(result.success).toBe(true); + expect(result.output).toBe("Two-step response"); + }); + }); + + describe("Complex Multi-Phase Scenario", () => { + it("should handle a realistic multi-phase agent workflow", async () => { + const linkExtractionConfig: AgentConfig<{ links: string[] }> = { + name: "TestAgent:extractLinks", + instructions: "Extract links", + outputSchema: z.object({ links: z.array(z.string()) }), + tools: [] + }; + AiAgentServiceLocal.setResponse("TestAgent:extractLinks", { + links: ["https://example.com/apply", "https://example.com/requirements"] + }); + const linksResult = await service.createAndRun(linkExtractionConfig, { input: "Extract links from program page" }); + expect(linksResult.success).toBe(true); + expect(linksResult.output.links).toHaveLength(2); + + const linkSummaryConfig: AgentConfig = { name: "TestAgent:summarizeLink", instructions: "Summarize content", tools: [] }; + AiAgentServiceLocal.setResponses("TestAgent:summarizeLink", [ + "Application requires proof of income", + "Must meet credit score requirements" + ]); + const summaries: string[] = []; + for (const link of linksResult.output.links) { + const summaryResult = await service.createAndRun(linkSummaryConfig, { input: `Summarize ${link}` }); + if (summaryResult.success) { + summaries.push(summaryResult.output); + } + } + expect(summaries).toHaveLength(2); + expect(summaries[0]).toContain("proof of income"); + expect(summaries[1]).toContain("credit score"); + + const webSearchConfig: AgentConfig = { name: "TestAgent:searchWeb", instructions: "Search for program info", tools: [] }; + AiAgentServiceLocal.setResponse("TestAgent:searchWeb", "Program offers up to $10,000 in assistance"); + const searchResult = await service.createAndRun(webSearchConfig, { input: "Search for program details" }); + expect(searchResult.success).toBe(true); + expect(searchResult.output).toContain("$10,000"); + + const synthesisConfig: AgentConfig<{ steps: string[] }> = { + name: "TestAgent:synthesizeFindings", + instructions: "Synthesize findings", + outputSchema: z.object({ steps: z.array(z.string()) }), + tools: [] + }; + AiAgentServiceLocal.setResponse("TestAgent:synthesizeFindings", { + steps: [ + "Gather proof of income documents", + "Check your credit score", + "Apply for up to $10,000 in assistance" + ] + }); + const synthesisResult = await service.createAndRun(synthesisConfig, { + input: `Synthesize: ${summaries.join(", ")} and ${searchResult.output}` + }); + expect(synthesisResult.success).toBe(true); + expect(synthesisResult.output.steps).toHaveLength(3); + expect(synthesisResult.output.steps[0]).toContain("proof of income"); + }); + }); +}); diff --git a/packages/agentic-workflows/test/repository/session/in-memory-conversation-session-repository.spec.ts b/packages/agentic-workflows/test/repository/session/in-memory-conversation-session-repository.spec.ts new file mode 100644 index 0000000..650a32d --- /dev/null +++ b/packages/agentic-workflows/test/repository/session/in-memory-conversation-session-repository.spec.ts @@ -0,0 +1,286 @@ +import "reflect-metadata"; +import { + InMemoryConversationSessionRepository, + RepositorySession +} from "@zeroshotbuilders/agentic-workflows"; +import { Test, TestingModule } from "@nestjs/testing"; + +describe("InMemoryConversationSessionRepository", () => { + let repository: InMemoryConversationSessionRepository; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [InMemoryConversationSessionRepository] + }).compile(); + repository = module.get(InMemoryConversationSessionRepository); + }); + + const clientId = "test-client-123"; + + it("should create a new session", async () => { + const session = await repository.createSession(clientId); + expect(session.sessionId).toBeDefined(); + const retrievedSession = await repository.getSession(session.sessionId); + expect(retrievedSession.clientId).toEqual(clientId); + }); + + it("should store and retrieve conversation items", async () => { + const session = await repository.createSession(clientId); + const sessionId = session.sessionId; + const items = [ + { role: "user", content: "Hello" }, + { role: "assistant", content: "Hi there!", metadata: { model: "gpt-4" } } + ]; + await repository.addConversationItems(sessionId, items); + const retrievedItems = await repository.getConversationItems(sessionId); + expect(retrievedItems).toHaveLength(2); + expect(retrievedItems[0].role).toEqual("user"); + expect(retrievedItems[0].content).toEqual("Hello"); + expect(retrievedItems[0].sequenceNumber).toEqual(0); + expect(retrievedItems[1].role).toEqual("assistant"); + expect(retrievedItems[1].content).toEqual("Hi there!"); + expect(retrievedItems[1].sequenceNumber).toEqual(1); + expect(JSON.parse(retrievedItems[1].metadata)).toEqual({ model: "gpt-4" }); + }); + + it("should update session timestamp on each interaction", async () => { + const session = await repository.createSession(clientId); + const sessionId = session.sessionId; + const initialSession = await repository.getSession(sessionId); + const initialTimestamp = initialSession.updatedAt; + await new Promise((resolve) => setTimeout(resolve, 10)); + await repository.addConversationItems(sessionId, [{ role: "user", content: "Wait a bit" }]); + const updatedSession = await repository.getSession(sessionId); + expect(updatedSession.updatedAt).toBeGreaterThan(initialTimestamp); + }); + + it("should delete conversation items when clearing conversation", async () => { + const session = await repository.createSession(clientId); + const sessionId = session.sessionId; + await repository.addConversationItems(sessionId, [{ role: "user", content: "Clear me" }]); + let items = await repository.getConversationItems(sessionId); + expect(items.length).toBeGreaterThan(0); + await repository.clearConversation(sessionId); + items = await repository.getConversationItems(sessionId); + expect(items).toHaveLength(0); + }); + + it("should delete last item when popping", async () => { + const session = await repository.createSession(clientId); + const sessionId = session.sessionId; + await repository.addConversationItems(sessionId, [ + { role: "user", content: "Item 1" }, + { role: "assistant", content: "Item 2" } + ]); + const itemsBefore = await repository.getConversationItems(sessionId); + const lastItemBefore = itemsBefore[itemsBefore.length - 1]; + const popped = await repository.popLastItem(sessionId); + expect(popped?.itemId).toEqual(lastItemBefore.itemId); + const itemsAfter = await repository.getConversationItems(sessionId); + expect(itemsAfter).toHaveLength(itemsBefore.length - 1); + }); + + describe("RepositorySession with InMemory", () => { + it("should work as an OpenAI Agents SDK Session", async () => { + const sessionModel = await repository.createSession(clientId); + const session = new RepositorySession(sessionModel.sessionId, repository); + await session.addItems([ + { role: "user", content: "Hello" }, + { role: "assistant", content: "Hi!" } + ]); + const items = await session.getItems(); + expect(items).toHaveLength(2); + expect(items[0].role).toEqual("user"); + expect(items[0].content).toEqual([{ type: "input_text", text: "Hello" }]); + const popped = await session.popItem(); + expect(popped?.content).toEqual([{ type: "output_text", text: "Hi!" }]); + const itemsAfterPop = await session.getItems(); + expect(itemsAfterPop).toHaveLength(1); + await session.clearSession(); + const itemsAfterClear = await session.getItems(); + expect(itemsAfterClear).toHaveLength(0); + }); + + describe("chat message filtering (execution artifact removal)", () => { + it("should only persist user, assistant, and system messages", async () => { + const sessionModel = await repository.createSession(clientId); + const session = new RepositorySession(sessionModel.sessionId, repository); + await session.addItems([ + { role: "user", content: "Hello" }, + { role: "assistant", content: "Hi there!" }, + { role: "system", content: "You are a helpful assistant." } + ]); + const items = await session.getItems(); + expect(items).toHaveLength(3); + expect(items[0].role).toEqual("user"); + expect(items[1].role).toEqual("assistant"); + expect(items[2].role).toEqual("system"); + }); + + it("should filter out reasoning items when adding", async () => { + const sessionModel = await repository.createSession(clientId); + const session = new RepositorySession(sessionModel.sessionId, repository); + await session.addItems([ + { role: "user", content: "Hello" }, + { role: "reasoning", content: "Internal reasoning..." } as any, + { role: "assistant", content: "Hi there!" } + ]); + const items = await session.getItems(); + expect(items).toHaveLength(2); + expect(items[0].role).toEqual("user"); + expect(items[1].role).toEqual("assistant"); + }); + + it("should filter out tool_call items when adding", async () => { + const sessionModel = await repository.createSession(clientId); + const session = new RepositorySession(sessionModel.sessionId, repository); + await session.addItems([ + { role: "user", content: "Search for something" }, + { role: "tool_call", content: "search query", id: "call_123" } as any, + { role: "assistant", content: "Here are the results" } + ]); + const items = await session.getItems(); + expect(items).toHaveLength(2); + expect(items[0].role).toEqual("user"); + expect(items[1].role).toEqual("assistant"); + }); + + it("should filter out tool_result items when adding", async () => { + const sessionModel = await repository.createSession(clientId); + const session = new RepositorySession(sessionModel.sessionId, repository); + await session.addItems([ + { role: "user", content: "Search for something" }, + { role: "tool_result", content: "search results", callId: "call_123" } as any, + { role: "assistant", content: "Here are the results" } + ]); + const items = await session.getItems(); + expect(items).toHaveLength(2); + expect(items[0].role).toEqual("user"); + expect(items[1].role).toEqual("assistant"); + }); + + it("should filter out items with type instead of role", async () => { + const sessionModel = await repository.createSession(clientId); + const session = new RepositorySession(sessionModel.sessionId, repository); + await session.addItems([ + { role: "user", content: "Hello" }, + { type: "reasoning", content: "Internal reasoning..." } as any, + { type: "message", id: "msg_123", content: "Some message" } as any, + { role: "assistant", content: "Hi there!" } + ]); + const items = await session.getItems(); + expect(items).toHaveLength(2); + expect(items[0].role).toEqual("user"); + expect(items[1].role).toEqual("assistant"); + }); + + it("should handle empty items array when all items are execution artifacts", async () => { + const sessionModel = await repository.createSession(clientId); + const session = new RepositorySession(sessionModel.sessionId, repository); + await session.addItems([ + { role: "reasoning", content: "Reasoning 1" } as any, + { role: "tool_call", content: "Tool call" } as any, + { role: "tool_result", content: "Tool result" } as any + ]); + const items = await session.getItems(); + expect(items).toHaveLength(0); + }); + + it("should NOT preserve metadata like tool_calls on assistant messages", async () => { + const sessionModel = await repository.createSession(clientId); + const session = new RepositorySession(sessionModel.sessionId, repository); + await session.addItems([ + { role: "user", content: "Hello" }, + { role: "assistant", content: "Let me search for that", tool_calls: [{ id: "call_123", name: "search" }] } as any + ]); + const items = await session.getItems(); + expect(items).toHaveLength(2); + expect(items[1].role).toEqual("assistant"); + expect(items[1].content).toEqual([{ type: "output_text", text: "Let me search for that" }]); + expect((items[1] as any).tool_calls).toBeUndefined(); + }); + + it("should return plain chat messages without any metadata", async () => { + const sessionModel = await repository.createSession(clientId); + const session = new RepositorySession(sessionModel.sessionId, repository); + await session.addItems([ + { role: "user", content: "Hello" }, + { role: "assistant", content: "Hi!" } + ]); + const items = await session.getItems(); + expect(items).toHaveLength(2); + for (const item of items) { + const keys = Object.keys(item); + expect(keys).toEqual(["role", "content"]); + } + }); + + it("should handle non-string content by JSON stringifying and converting to content parts", async () => { + const sessionModel = await repository.createSession(clientId); + const session = new RepositorySession(sessionModel.sessionId, repository); + const arrayContent = [{ type: "text", text: "Hello" }]; + await session.addItems([{ role: "user", content: arrayContent } as any]); + const items = await session.getItems(); + expect(items).toHaveLength(1); + expect(Array.isArray(items[0].content)).toBe(true); + expect(items[0].content).toEqual([{ type: "input_text", text: JSON.stringify(arrayContent) }]); + }); + + it("should handle array content (like assistant content parts) correctly", async () => { + const sessionModel = await repository.createSession(clientId); + const session = new RepositorySession(sessionModel.sessionId, repository); + const arrayContent = [{ type: "output_text", text: "Hello, how can I help you?", annotations: [] as any[], logprobs: [] as any[] }]; + await session.addItems([{ role: "assistant", content: arrayContent } as any]); + const items = await session.getItems(); + expect(items).toHaveLength(1); + expect(Array.isArray(items[0].content)).toBe(true); + expect(items[0].content).toEqual([{ type: "output_text", text: JSON.stringify(arrayContent) }]); + }); + + it("should convert plain string content to content parts array", async () => { + const sessionModel = await repository.createSession(clientId); + const session = new RepositorySession(sessionModel.sessionId, repository); + await session.addItems([ + { role: "user", content: "Hello" }, + { role: "assistant", content: "Hi there!" } + ]); + const items = await session.getItems(); + expect(items).toHaveLength(2); + expect(Array.isArray(items[0].content)).toBe(true); + expect(items[0].content).toEqual([{ type: "input_text", text: "Hello" }]); + expect(Array.isArray(items[1].content)).toBe(true); + expect(items[1].content).toEqual([{ type: "output_text", text: "Hi there!" }]); + }); + + it("should return plain chat message from popItem without metadata", async () => { + const sessionModel = await repository.createSession(clientId); + const session = new RepositorySession(sessionModel.sessionId, repository); + await repository.addConversationItems(sessionModel.sessionId, [ + { role: "user", content: "Hello" }, + { role: "assistant", content: "Hi!", metadata: { id: "msg_123", type: "message" } } + ]); + const popped = await session.popItem(); + expect(popped).toBeDefined(); + expect(popped?.role).toEqual("assistant"); + expect(popped?.content).toEqual([{ type: "output_text", text: "Hi!" }]); + expect((popped as any).id).toBeUndefined(); + expect((popped as any).type).toBeUndefined(); + }); + + it("should handle legacy data with reasoning role by returning all stored items", async () => { + const sessionModel = await repository.createSession(clientId); + const session = new RepositorySession(sessionModel.sessionId, repository); + await repository.addConversationItems(sessionModel.sessionId, [ + { role: "user", content: "Hello" }, + { role: "reasoning", content: "Internal reasoning..." }, + { role: "assistant", content: "Hi there!" } + ]); + const items = await session.getItems(); + expect(items).toHaveLength(3); + expect(items[0].role).toEqual("user"); + expect(items[1].role).toEqual("reasoning"); + expect(items[2].role).toEqual("assistant"); + }); + }); + }); +}); diff --git a/packages/agentic-workflows/test/service/decorators.spec.ts b/packages/agentic-workflows/test/service/decorators.spec.ts new file mode 100644 index 0000000..e218c48 --- /dev/null +++ b/packages/agentic-workflows/test/service/decorators.spec.ts @@ -0,0 +1,86 @@ +import * as fs from "fs"; +import * as path from "path"; +import { + Agent, + AgenticWorkflow, + AgentRunConfig, + AgentRunResult, + AiAgentService, + RepositorySession +} from "../../index"; + +const mockAiAgentService: AiAgentService = { + createAndRun: jest.fn(), + createAgent: jest.fn(), + runAgent: jest.fn() +}; + +@AgenticWorkflow({ + promptsDirectory: path.join(__dirname, "prompts") +}) +class TestWorkflow { + constructor(public readonly aiAgentService: AiAgentService) {} + + @Agent({ tools: [] }) + async testMethod(input: string, session?: RepositorySession): Promise> { + return null; + } + + @Agent({ model: "test-model-override", tools: [] }) + async testModelOverrideMethod(input: string): Promise> { + return null; + } +} + +describe("@Agent decorator", () => { + const promptsDir = path.join(__dirname, "prompts"); + + beforeAll(() => { + if (!fs.existsSync(promptsDir)) { + fs.mkdirSync(promptsDir, { recursive: true }); + } + fs.writeFileSync(path.join(promptsDir, "testMethod.md"), "---\ntools: []\n---\nTest instructions"); + fs.writeFileSync(path.join(promptsDir, "testModelOverrideMethod.md"), "---\ntools: []\n---\nTest instructions"); + }); + + afterAll(() => { + if (fs.existsSync(promptsDir)) { + fs.rmSync(promptsDir, { recursive: true }); + } + }); + + it("should pick up session from arguments", async () => { + const workflow = new TestWorkflow(mockAiAgentService); + const mockSession = Object.create(RepositorySession.prototype); + mockSession.sessionId = "test-session"; + (mockAiAgentService.createAndRun as jest.Mock).mockResolvedValue({ success: true }); + await workflow.testMethod("hello", mockSession); + expect(mockAiAgentService.createAndRun).toHaveBeenCalledWith( + expect.anything(), + expect.objectContaining({ session: mockSession }) + ); + }); + + it("should not include session in the input JSON", async () => { + const workflow = new TestWorkflow(mockAiAgentService); + const mockSession = Object.create(RepositorySession.prototype); + mockSession.sessionId = "test-session"; + (mockAiAgentService.createAndRun as jest.Mock).mockResolvedValue({ success: true }); + await workflow.testMethod("hello", mockSession); + const callArgs = (mockAiAgentService.createAndRun as jest.Mock).mock.calls[0]; + const runConfig: AgentRunConfig = callArgs[1]; + const input = JSON.parse(runConfig.input); + expect(input).toHaveProperty("input", "hello"); + expect(input).not.toHaveProperty("session"); + }); + + it("should pass the model override to createAndRun", async () => { + const workflow = new TestWorkflow(mockAiAgentService); + (mockAiAgentService.createAndRun as jest.Mock).mockResolvedValue({ success: true }); + await workflow.testModelOverrideMethod("hello"); + expect(mockAiAgentService.createAndRun).toHaveBeenCalledWith( + expect.objectContaining({ model: "test-model-override" }), + expect.anything() + ); + }); +}); diff --git a/packages/agentic-workflows/tsconfig.json b/packages/agentic-workflows/tsconfig.json new file mode 100644 index 0000000..46167d5 --- /dev/null +++ b/packages/agentic-workflows/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc" + }, + "files": [], + "include": [], + "references": [ + { "path": "./tsconfig.lib.json" }, + { "path": "./tsconfig.spec.json" } + ] +} diff --git a/packages/agentic-workflows/tsconfig.lib.json b/packages/agentic-workflows/tsconfig.lib.json new file mode 100644 index 0000000..e927de6 --- /dev/null +++ b/packages/agentic-workflows/tsconfig.lib.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "declaration": true, + "types": ["node", "reflect-metadata"] + }, + "include": ["index.ts", "src/**/*.ts"], + "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] +} diff --git a/packages/agentic-workflows/tsconfig.spec.json b/packages/agentic-workflows/tsconfig.spec.json new file mode 100644 index 0000000..3835753 --- /dev/null +++ b/packages/agentic-workflows/tsconfig.spec.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node", "reflect-metadata"] + }, + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.d.ts", + "test/**/*.ts" + ] +} diff --git a/packages/commons-testing/.eslintrc.json b/packages/commons-testing/.eslintrc.json new file mode 100644 index 0000000..ca25810 --- /dev/null +++ b/packages/commons-testing/.eslintrc.json @@ -0,0 +1,10 @@ +{ + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*", "node_modules"], + "overrides": [ + { + "files": ["*.ts"], + "rules": {} + } + ] +} diff --git a/packages/commons-testing/index.ts b/packages/commons-testing/index.ts new file mode 100644 index 0000000..44df151 --- /dev/null +++ b/packages/commons-testing/index.ts @@ -0,0 +1,6 @@ +export * from "./src/postgres/postgres-container"; +export * from "./src/redis/redis-container"; +export * from "./src/ollama/ollama-fixture"; +export * from "./src/async/async-test-utils"; +export * from "./src/booter/booter-configuration"; +export * from "./src/exceptions/jest-exception"; diff --git a/packages/commons-testing/jest.config.ts b/packages/commons-testing/jest.config.ts new file mode 100644 index 0000000..a9b6e50 --- /dev/null +++ b/packages/commons-testing/jest.config.ts @@ -0,0 +1,10 @@ +export default { + displayName: "commons-testing", + preset: "../../jest.preset.js", + testEnvironment: "node", + transform: { + "^.+\\.[tj]s$": "ts-jest" + }, + moduleFileExtensions: ["ts", "js", "html"], + coverageDirectory: "../../coverage/packages/commons-testing" +}; diff --git a/packages/commons-testing/package.json b/packages/commons-testing/package.json new file mode 100644 index 0000000..e501f43 --- /dev/null +++ b/packages/commons-testing/package.json @@ -0,0 +1,17 @@ +{ + "name": "@zeroshotbuilders/commons-testing", + "version": "0.0.1", + "type": "commonjs", + "main": "./src/index.ts", + "publishConfig": { + "main": "./index.js", + "types": "./index.d.ts", + "access": "public" + }, + "dependencies": { + "testcontainers": "^10.24.0" + }, + "peerDependencies": { + "@zeroshotbuilders/commons": ">=0.0.1" + } +} diff --git a/packages/commons-testing/project.json b/packages/commons-testing/project.json new file mode 100644 index 0000000..f3b550d --- /dev/null +++ b/packages/commons-testing/project.json @@ -0,0 +1,29 @@ +{ + "name": "commons-testing", + "sourceRoot": "packages/commons-testing/src", + "projectType": "library", + "targets": { + "build": { + "executor": "@nx/js:tsc", + "options": { + "outputPath": "dist/packages/commons-testing", + "main": "packages/commons-testing/src/index.ts", + "tsConfig": "packages/commons-testing/tsconfig.lib.json" + } + }, + "test": { + "executor": "@nx/jest:jest", + "options": { + "jestConfig": "packages/commons-testing/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": ["packages/commons-testing/**/*.ts"] + } + } + }, + "tags": [] +} diff --git a/packages/commons-testing/src/async/async-test-utils.ts b/packages/commons-testing/src/async/async-test-utils.ts new file mode 100644 index 0000000..080c371 --- /dev/null +++ b/packages/commons-testing/src/async/async-test-utils.ts @@ -0,0 +1,26 @@ +export async function eventually( + runnable: () => Promise, + intervalMs = 100, + durationMs = 10_000 +): Promise { + const startTime = Date.now(); + let lastAttemptTime = startTime; + let lastThrowable; + + while (lastAttemptTime - startTime < durationMs) { + try { + return await runnable(); + } catch (error) { + // Retry after the specified interval + await new Promise((resolve) => setTimeout(resolve, intervalMs)); + lastAttemptTime = Date.now(); + lastThrowable = error; + } + } + + throw lastThrowable; +} + +export async function timeout(millis: number): Promise { + return new Promise((resolve) => setTimeout(resolve, millis)); +} diff --git a/packages/commons-testing/src/booter/booter-configuration.ts b/packages/commons-testing/src/booter/booter-configuration.ts new file mode 100644 index 0000000..badb6d8 --- /dev/null +++ b/packages/commons-testing/src/booter/booter-configuration.ts @@ -0,0 +1,3 @@ +export const TestTimeout = 60_000; +export const BeforeAllTimeout = 600000; +export const AfterAllTimeout = 100000; diff --git a/packages/commons-testing/src/exceptions/jest-exception.ts b/packages/commons-testing/src/exceptions/jest-exception.ts new file mode 100644 index 0000000..69bdc0c --- /dev/null +++ b/packages/commons-testing/src/exceptions/jest-exception.ts @@ -0,0 +1,3 @@ +export const unreachableErr = () => { + throw new Error("Should be unreachable"); +}; diff --git a/packages/commons-testing/src/ollama/ollama-fixture.ts b/packages/commons-testing/src/ollama/ollama-fixture.ts new file mode 100644 index 0000000..b296533 --- /dev/null +++ b/packages/commons-testing/src/ollama/ollama-fixture.ts @@ -0,0 +1,110 @@ +import { GenericContainer, StartedTestContainer, Wait } from "testcontainers"; +import { createLogger, transports } from "winston"; + +export enum OllamaMode { + LOCAL = "LOCAL", + CONTAINER = "CONTAINER" +} + +export interface OllamaFixtureConfig { + mode: OllamaMode; + localHost?: string; + localPort?: number; +} + +/** + * OllamaFixture provides a unified interface for running Ollama either locally + * (for development on Mac with Apple Silicon) or via Docker container (for CI/testing). + * + * Local mode assumes Ollama is installed natively on the host machine. + * Container mode uses the official ollama/ollama Docker image. + * + * For local mode on Mac, install Ollama via: + * brew install ollama + * ollama serve + */ +export class OllamaFixture { + public static readonly PORT = 11434; + public static readonly IMAGE = "ollama/ollama:latest"; + public static readonly DEFAULT_LOCAL_HOST = "localhost"; + + private readonly logger = createLogger({ + transports: [new transports.Console()] + }); + + private readonly mode: OllamaMode; + private readonly localHost: string; + private readonly localPort: number; + + private container: GenericContainer | undefined; + private startedContainer: StartedTestContainer | undefined; + + constructor(config: OllamaFixtureConfig = { mode: OllamaMode.CONTAINER }) { + this.mode = config.mode; + this.localHost = config.localHost ?? OllamaFixture.DEFAULT_LOCAL_HOST; + this.localPort = config.localPort ?? OllamaFixture.PORT; + + if (this.mode === OllamaMode.CONTAINER) { + this.container = new GenericContainer(OllamaFixture.IMAGE) + .withWaitStrategy(Wait.forLogMessage(new RegExp(".*Listening on.*"), 1)) + .withExposedPorts(OllamaFixture.PORT); + } + } + + public async start(): Promise { + if (this.mode === OllamaMode.CONTAINER) { + if (!this.container) { + throw new Error("Container not initialized"); + } + this.logger.info("Starting Ollama container..."); + this.startedContainer = await this.container.start(); + this.logger.info(`Ollama container started at ${this.getBaseUrl()}`); + } else { + this.logger.info(`Using local Ollama instance at ${this.getBaseUrl()}`); + } + } + + public async stop(): Promise { + if (this.mode === OllamaMode.CONTAINER && this.startedContainer) { + this.logger.info("Stopping Ollama container..."); + await this.startedContainer.stop(); + this.startedContainer = undefined; + } + } + + public getHost(): string { + if (this.mode === OllamaMode.CONTAINER) { + if (!this.startedContainer) { + throw new Error("Container not started"); + } + return this.startedContainer.getHost(); + } + return this.localHost; + } + + public getPort(): number { + if (this.mode === OllamaMode.CONTAINER) { + if (!this.startedContainer) { + throw new Error("Container not started"); + } + return this.startedContainer.getMappedPort(OllamaFixture.PORT); + } + return this.localPort; + } + + public getBaseUrl(): string { + return `http://${this.getHost()}:${this.getPort()}`; + } + + public getMode(): OllamaMode { + return this.mode; + } + + public isLocal(): boolean { + return this.mode === OllamaMode.LOCAL; + } + + public isContainer(): boolean { + return this.mode === OllamaMode.CONTAINER; + } +} diff --git a/packages/commons-testing/src/postgres/postgres-container.ts b/packages/commons-testing/src/postgres/postgres-container.ts new file mode 100644 index 0000000..ef47ef5 --- /dev/null +++ b/packages/commons-testing/src/postgres/postgres-container.ts @@ -0,0 +1,135 @@ +import { PostgresConnectionConfig } from "@zeroshotbuilders/commons"; +import * as fs from "fs"; +import { List } from "immutable"; +import * as path from "path"; +import { DataTypes, QueryTypes, Sequelize } from "sequelize"; +import { GenericContainer, StartedTestContainer, Wait } from "testcontainers"; +import * as util from "util"; +import { createLogger, transports } from "winston"; + +const readDir = util.promisify(fs.readdir); +const readFile = util.promisify(fs.readFile); + +function extractNumberFromPrefix(s: string): number { + const numStr = s.slice(1).split("__")[0]; + return parseInt(numStr, 10); +} + +function sortByPrefix(strings: string[]): string[] { + return strings.sort((a, b) => { + return extractNumberFromPrefix(a) - extractNumberFromPrefix(b); + }); +} + +export class PostgresContainer { + public static readonly USER = "postgres"; + public static readonly PASSWORD = "password"; + public static readonly PORT = 5432; + public static readonly IMAGE = "postgres:17-alpine"; + + private readonly logger = createLogger({ + transports: [new transports.Console()] + }); + + private readonly database: string; + private readonly container: GenericContainer; + private startedContainer: StartedTestContainer; + private sequelize: Sequelize; + + constructor(database = "postgres") { + this.database = database; + this.container = new GenericContainer(PostgresContainer.IMAGE) + .withExposedPorts(PostgresContainer.PORT) + .withWaitStrategy( + Wait.forLogMessage( + new RegExp(".*database system is ready to accept connections.*"), + 2 + ) + ) + .withEnvironment({ + POSTGRES_USER: PostgresContainer.USER, + POSTGRES_PASSWORD: PostgresContainer.PASSWORD, + POSTGRES_DATABASE: database + }); + } + + public async start() { + this.startedContainer = await this.container.start(); + } + + public async stop() { + if (this.startedContainer) { + await this.startedContainer.stop(); + } + if (this.sequelize) { + await this.sequelize.close(); + } + } + + public getConnectionConfig( + standardConformingStrings = true, + ignoreClientMinMessages = false + ): PostgresConnectionConfig { + return { + host: this.startedContainer.getHost(), + port: this.startedContainer.getMappedPort(PostgresContainer.PORT), + username: PostgresContainer.USER, + password: PostgresContainer.PASSWORD, + database: this.database, + logging: false, + standardConformingStrings: standardConformingStrings, + ignoreClientMinMessages: ignoreClientMinMessages + }; + } + + public getSequelizeClient(): Sequelize { + if (!this.sequelize) { + this.sequelize = this.makeSequelizeClient(); + } + return this.sequelize; + } + + public async applyMigrations(migrationsDir: string): Promise { + const files: string[] = await readDir(migrationsDir); + const filesSorted = List(sortByPrefix(files)); + for (const file of filesSorted) { + const filePath = path.join(migrationsDir, file); + // Ensure that the file is not a directory + if (fs.statSync(filePath).isFile()) { + const migrationsQuery = await readFile(filePath, "utf-8"); + await this.getSequelizeClient().query(migrationsQuery, { + type: QueryTypes.RAW + }); + } + } + } + + private makeSequelizeClient(): Sequelize { + return new Sequelize( + this.database, + PostgresContainer.USER, + PostgresContainer.PASSWORD, + { + logging: false, + dialect: "postgres", + host: this.startedContainer.getHost(), + port: this.startedContainer.getMappedPort(PostgresContainer.PORT), + hooks: { + afterConnect: () => { + const types = { + DECIMAL: { + ...DataTypes.DECIMAL, + parse: parseFloat + }, + BIGINT: { + ...DataTypes.BIGINT, + parse: parseInt + } + }; + this.sequelize.connectionManager.refreshTypeParser(types); + } + } + } + ); + } +} diff --git a/packages/commons-testing/src/redis/redis-container.ts b/packages/commons-testing/src/redis/redis-container.ts new file mode 100644 index 0000000..d35b546 --- /dev/null +++ b/packages/commons-testing/src/redis/redis-container.ts @@ -0,0 +1,40 @@ +import { GenericContainer, StartedTestContainer, Wait } from "testcontainers"; +import { RedisConnectionConfig } from "@zeroshotbuilders/commons"; +import { createLogger, transports } from "winston"; + +export class RedisContainer { + public static readonly PORT = 6379; + public static readonly IMAGE = "redis:8.4.2"; + + private readonly logger = createLogger({ + transports: [new transports.Console()] + }); + + private readonly container: GenericContainer; + private startedContainer: StartedTestContainer; + + constructor() { + this.container = new GenericContainer(RedisContainer.IMAGE) + .withWaitStrategy( + Wait.forLogMessage(new RegExp(".*Ready to accept connections.*"), 1) + ) + .withExposedPorts(RedisContainer.PORT); + } + + public async start() { + this.startedContainer = await this.container.start(); + } + + public async stop() { + if (this.startedContainer) { + await this.startedContainer.stop(); + } + } + + public getConnectionConfig(): RedisConnectionConfig { + return new RedisConnectionConfig( + this.startedContainer.getMappedPort(RedisContainer.PORT), + this.startedContainer.getHost() + ); + } +} diff --git a/packages/commons-testing/tsconfig.json b/packages/commons-testing/tsconfig.json new file mode 100644 index 0000000..46167d5 --- /dev/null +++ b/packages/commons-testing/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc" + }, + "files": [], + "include": [], + "references": [ + { "path": "./tsconfig.lib.json" }, + { "path": "./tsconfig.spec.json" } + ] +} diff --git a/packages/commons-testing/tsconfig.lib.json b/packages/commons-testing/tsconfig.lib.json new file mode 100644 index 0000000..e927de6 --- /dev/null +++ b/packages/commons-testing/tsconfig.lib.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "declaration": true, + "types": ["node", "reflect-metadata"] + }, + "include": ["index.ts", "src/**/*.ts"], + "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] +} diff --git a/packages/commons-testing/tsconfig.spec.json b/packages/commons-testing/tsconfig.spec.json new file mode 100644 index 0000000..b52d392 --- /dev/null +++ b/packages/commons-testing/tsconfig.spec.json @@ -0,0 +1,14 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node", "reflect-metadata"] + }, + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/packages/commons/.eslintrc.json b/packages/commons/.eslintrc.json new file mode 100644 index 0000000..f1ff0d9 --- /dev/null +++ b/packages/commons/.eslintrc.json @@ -0,0 +1,10 @@ +{ + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "rules": {} + } + ] +} diff --git a/packages/commons/index.ts b/packages/commons/index.ts new file mode 100644 index 0000000..2ad5bef --- /dev/null +++ b/packages/commons/index.ts @@ -0,0 +1,38 @@ +export * from "./src/injection-tokens"; +export * from "./src/crypto/crypto-utils"; +export * from "./src/config/config-module"; +export * from "./src/config/client-config"; +export * from "./src/config/application-config"; +export * from "./src/config/config-utils"; +export * from "./src/logging/winston-logger"; +export * from "./src/port/port-utils"; +export * from "./src/postgres/postgres-connection-config"; +export * from "./src/postgres/postgres-utils"; +export * from "./src/postgres/postgres-connection-module"; +export * from "./src/server/rest-booter"; +export * from "./src/redis/redis-connection-config"; +export * from "./src/redis/redis-connection-module"; +export * from "./src/redis/redis-client-pool"; +export * from "./src/abort-controller/abort-controller"; +export * from "./src/bull/bull-error-handler"; +export * from "./src/bull/bull-module"; +export * from "./src/bull/bull-queue"; +export * from "./src/bull/bull-worker"; +export * from "./src/bull/bull-utils"; +export * from "./src/bull/cron-launcher"; +export * from "./src/collections/collection-utils"; +export * from "./src/resources/closer"; +export * from "./src/decorators/default"; +export * from "./src/decorators/is-optional"; +export * from "./src/decorators/is-safe-string"; +export * from "./src/decorators/is-safe-json"; +export * from "./src/decorators/at-least-one-of"; +export * from "./src/decorators/future-timestamp"; +export * from "./src/decorators/is-image-url"; +export * from "./src/decorators/is-bigger-than"; +export * from "./src/random/random-utils"; +export * from "./src/ip/ip-utils"; +export * from "./src/date/date-utils"; +export * from "./src/internal/not-empty"; +export * from "./src/internal/object-utils"; +export * from "./src/util/timer-utils"; diff --git a/packages/commons/jest.config.ts b/packages/commons/jest.config.ts new file mode 100644 index 0000000..6e455e6 --- /dev/null +++ b/packages/commons/jest.config.ts @@ -0,0 +1,10 @@ +export default { + displayName: "commons", + preset: "../../jest.preset.js", + testEnvironment: "node", + transform: { + "^.+\\.[tj]s$": ["ts-jest", { tsconfig: "/tsconfig.spec.json" }] + }, + moduleFileExtensions: ["ts", "js", "html"], + coverageDirectory: "../../coverage/packages/commons" +}; diff --git a/packages/commons/package.json b/packages/commons/package.json new file mode 100644 index 0000000..aa03e79 --- /dev/null +++ b/packages/commons/package.json @@ -0,0 +1,34 @@ +{ + "name": "@zeroshotbuilders/commons", + "version": "0.0.1", + "type": "commonjs", + "main": "./src/index.ts", + "publishConfig": { + "main": "./index.js", + "types": "./index.d.ts", + "access": "public" + }, + "dependencies": { + "abort-controller-x": "^0.4.0", + "bullmq": "^5.0.0", + "class-transformer": "^0.5.0", + "class-validator": "^0.14.0", + "immutable": "^4.3.0", + "js-yaml": "^4.1.0", + "luxon": "^3.6.0", + "nice-grpc": "^2.1.0", + "randomstring": "^1.3.0", + "redis": "^4.7.0", + "reflect-metadata": "^0.2.0", + "sequelize": "^6.37.0", + "ts-pattern": "^5.0.0", + "uuid": "^11.0.0", + "winston": "^3.17.0" + }, + "peerDependencies": { + "@grpc/grpc-js": ">=1.9.0", + "@nestjs/common": ">=10.0.0", + "@nestjs/core": ">=10.0.0", + "@nestjs/platform-express": ">=10.0.0" + } +} diff --git a/packages/commons/project.json b/packages/commons/project.json new file mode 100644 index 0000000..21d088f --- /dev/null +++ b/packages/commons/project.json @@ -0,0 +1,34 @@ +{ + "name": "commons", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "packages/commons/src", + "projectType": "library", + "targets": { + "build": { + "executor": "@nx/js:tsc", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/packages/commons", + "main": "packages/commons/index.ts", + "tsConfig": "packages/commons/tsconfig.lib.json" + } + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "packages/commons/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["packages/commons/**/*.ts"] + } + } + }, + "tags": [], + "implicitDependencies": ["!commons-testing"] +} diff --git a/packages/commons/src/abort-controller/abort-controller.ts b/packages/commons/src/abort-controller/abort-controller.ts new file mode 100644 index 0000000..45f2afc --- /dev/null +++ b/packages/commons/src/abort-controller/abort-controller.ts @@ -0,0 +1,112 @@ +/** + * Utility class for managing AbortController with timeout functionality. + * This class encapsulates the creation and management of AbortController instances + * with automatic timeout handling for gRPC calls. + */ +export class TimeoutAbortController { + private abortController: AbortController; + private timeoutId: NodeJS.Timeout | null = null; + private abortListener: (() => void) | null = null; + + /** + * Creates a new TimeoutAbortController instance. + */ + constructor() { + this.abortController = new AbortController(); + + // Set up a listener to automatically clear the timeout when abort is triggered + this.abortListener = () => this.clearTimeout(); + this.abortController.signal.addEventListener("abort", this.abortListener); + } + + /** + * Sets a timeout after which the abort controller will automatically abort. + * + * @param timeoutMs - The timeout in milliseconds after which to abort + * @returns The signal from the AbortController for use in gRPC calls + */ + public setTimeout(timeoutMs: number): AbortSignal { + // Clear any existing timeout to prevent memory leaks + this.clearTimeout(); + + // Set a new timeout + this.timeoutId = setTimeout(() => this.abortController.abort(), timeoutMs); + + return this.abortController.signal; + } + + /** + * Clears the timeout to prevent memory leaks. + * This is automatically called when the abort event is triggered, + * but can also be called manually if needed. + */ + public clearTimeout(): void { + if (this.timeoutId) { + clearTimeout(this.timeoutId); + this.timeoutId = null; + } + } + + /** + * Gets the signal from the AbortController. + * Use this if you want to get the signal without setting a timeout. + */ + public get signal(): AbortSignal { + return this.abortController.signal; + } + + /** + * Manually aborts the controller. + * This will automatically clear any active timeout. + */ + public abort(): void { + this.abortController.abort(); + } + + /** + * Releases all resources associated with this controller. + * This should be called when the controller is no longer needed. + */ + public dispose(): void { + this.clearTimeout(); + + // Remove the abort event listener to prevent memory leaks + if (this.abortListener) { + this.abortController.signal.removeEventListener( + "abort", + this.abortListener + ); + this.abortListener = null; + } + } + + /** + * Creates a new TimeoutAbortController, sets a timeout, and returns the signal. + * This is a convenience method for one-off use cases. + * + * @param timeoutMs - The timeout in milliseconds after which to abort + * @returns An object containing the controller and its signal + * + * @remarks + * The returned controller will automatically clear its timeout when the abort event is triggered. + * However, to fully release resources, call controller.dispose() when you're done with it. + * + * Example usage: + * ``` + * const { controller, signal } = TimeoutAbortController.withTimeout(5000); + * try { + * await someAsyncOperation({ signal }); + * } finally { + * controller.dispose(); // Ensure resources are cleaned up + * } + * ``` + */ + public static withTimeout(timeoutMs: number): { + controller: TimeoutAbortController; + signal: AbortSignal; + } { + const controller = new TimeoutAbortController(); + const signal = controller.setTimeout(timeoutMs); + return { controller, signal }; + } +} diff --git a/packages/commons/src/bull/bull-error-handler.ts b/packages/commons/src/bull/bull-error-handler.ts new file mode 100644 index 0000000..4910676 --- /dev/null +++ b/packages/commons/src/bull/bull-error-handler.ts @@ -0,0 +1,16 @@ +import { Status } from "nice-grpc"; + +export function BullErrorHandler(error: Error): { + errorStatus: Status; + errorMessage: string; +} { + const firstColonIndex = error.message.indexOf(":"); + + const errorCode = error.message + .slice(0, firstColonIndex) + .trim() as keyof typeof Status; + const errorMessage = error.message.slice(firstColonIndex + 1).trim(); + const errorStatus = Status[errorCode]; + + return { errorStatus, errorMessage }; +} diff --git a/packages/commons/src/bull/bull-module.ts b/packages/commons/src/bull/bull-module.ts new file mode 100644 index 0000000..ecc6054 --- /dev/null +++ b/packages/commons/src/bull/bull-module.ts @@ -0,0 +1,22 @@ +import { DynamicModule, Module } from "@nestjs/common"; +import { + RedisConnectionModule, + REDIS_CONFIG_ROOT +} from "@zeroshotbuilders/commons"; + +@Module({}) +export class BullModule { + public static forApplicationRoot(applicationRoot: string): DynamicModule { + return { + module: BullModule, + imports: [RedisConnectionModule.forApplicationRoot(applicationRoot)], + providers: [ + { + provide: REDIS_CONFIG_ROOT, + useValue: applicationRoot + } + ], + exports: [REDIS_CONFIG_ROOT] + }; + } +} diff --git a/packages/commons/src/bull/bull-queue.ts b/packages/commons/src/bull/bull-queue.ts new file mode 100644 index 0000000..cf1930d --- /dev/null +++ b/packages/commons/src/bull/bull-queue.ts @@ -0,0 +1,118 @@ +import { Injectable } from "@nestjs/common"; +import { Job, JobsOptions, Queue, QueueEvents } from "bullmq"; +import { + BullErrorHandler, + loadConfig, + RedisConnectionConfig +} from "@zeroshotbuilders/commons"; +import { Closer } from "@zeroshotbuilders/commons"; +import { ServerError } from "nice-grpc"; +import { createLogger, Logger, transports } from "winston"; +import { kebabToCamel } from "../internal/string-utils"; +import { DefaultJobOptions } from "bullmq"; +import { v4 as uuid } from "uuid"; + +const DEFAULT_REMOVE_ON_COMPLETE_SECONDS = 60 * 60 * 24 * 30; // 30 days + +@Injectable() +export abstract class BullQueue { + protected readonly logger: Logger = createLogger({ + transports: [new transports.Console()] + }); + protected readonly queue: Queue; + protected readonly queueEvents: QueueEvents; + + constructor( + applicationRoot: string, + queueName: string, + redisConnectionConfig: RedisConnectionConfig, + closer: Closer + ) { + const queueConfig = this.resolveQueueConfig(applicationRoot, queueName); + this.logger.info("Registering bull queue", { + queueName, + config: queueConfig + }); + this.queue = new Queue(queueName, { + connection: redisConnectionConfig.queueConnection(), + defaultJobOptions: queueConfig + }); + this.queue.on("error", (error) => { + this.logger.error("Error while processing queue", error); + }); + this.queueEvents = new QueueEvents(queueName, { + connection: redisConnectionConfig.queueConnection() + }); + this.queueEvents.on("error", (error) => { + this.logger.error("Error while processing queueEvents", error); + }); + closer.registerShutdownHook({ + resource: this, + closingFunction: async (queue: BullQueue) => { + return await queue.shutdown(); + } + }); + } + + public async add( + jobRequest: JobRequest, + options?: JobsOptions + ): Promise> { + const jobOptions = { + jobId: uuid(), + removeOnComplete: { + age: DEFAULT_REMOVE_ON_COMPLETE_SECONDS + }, + ...options + }; + return this.queue.add(this.queue.name as any, jobRequest as any, jobOptions) as any; + } + + public async addAndAwait( + jobRequest: JobRequest, + options?: JobsOptions + ): Promise { + return this.add(jobRequest, options) + .then(async (job) => job.waitUntilFinished(this.getQueueEvents())) + .catch((error) => { + const { errorStatus, errorMessage } = BullErrorHandler(error); + throw new ServerError(errorStatus, errorMessage); + }); + } + + public getQueue(): Queue { + return this.queue; + } + + public getQueueEvents(): QueueEvents { + return this.queueEvents; + } + + public async shutdown(): Promise { + await this.queue.close().catch((error) => { + this.logger.debug("Error while closing queue", error); + }); + await this.queueEvents.close().catch((error) => { + this.logger.debug("Error while closing queueEvents", error); + }); + } + + private resolveQueueConfig( + applicationRoot: string, + queueName: string + ): DefaultJobOptions { + try { + return ( + loadConfig( + applicationRoot, + kebabToCamel(queueName) + ) ?? {} + ); + } catch (_) { + this.logger.warn( + `Could not load config for ${queueName}. Defaults will be used` + ); + return {}; + } + } +} diff --git a/packages/commons/src/bull/bull-utils.ts b/packages/commons/src/bull/bull-utils.ts new file mode 100644 index 0000000..a46cdce --- /dev/null +++ b/packages/commons/src/bull/bull-utils.ts @@ -0,0 +1,28 @@ +import { ClientError, ServerError, Status } from "nice-grpc"; +import { List } from "immutable"; +import { UnrecoverableError } from "bullmq"; + +export const UnrecoverableGrpcExceptions = List.of( + Status.NOT_FOUND, + Status.FAILED_PRECONDITION, + Status.INVALID_ARGUMENT, + Status.PERMISSION_DENIED +); + +export const withCheckedExceptions = async ( + runnable: () => Promise +): Promise => { + try { + return await runnable(); + } catch (error: any) { + // Handle grpc exceptions + if ( + (error instanceof ServerError || error instanceof ClientError) && + UnrecoverableGrpcExceptions.contains(error.code) + ) { + throw new UnrecoverableError(error.message); + } + // Otherwise job will be retried + throw error; + } +}; diff --git a/packages/commons/src/bull/bull-worker.ts b/packages/commons/src/bull/bull-worker.ts new file mode 100644 index 0000000..7171f7e --- /dev/null +++ b/packages/commons/src/bull/bull-worker.ts @@ -0,0 +1,69 @@ +import { Closer, RedisConnectionConfig } from "@zeroshotbuilders/commons"; +import { Injectable } from "@nestjs/common"; +import { Job, UnrecoverableError, Worker } from "bullmq"; +import { createLogger, Logger, transports } from "winston"; + +@Injectable() +export abstract class BullWorker { + private readonly worker: Worker; + protected readonly logger: Logger = createLogger({ + transports: [new transports.Console()] + }); + + constructor( + queueName: string, + redisConnectionConfig: RedisConnectionConfig, + closer: Closer, + concurrency = 1, + private readonly timeout?: number + ) { + this.worker = new Worker( + queueName, + async (job) => { + const jobTimeout = (job.data as any)?.timeout ?? this.timeout; + if (jobTimeout) { + const controller = new AbortController(); + const timer = setTimeout(() => controller.abort(), jobTimeout); + try { + return await this.run(job, controller.signal); + } catch (err: any) { + if (err.name === "AbortError") { + throw new UnrecoverableError( + `Job ${job.id} timed out after ${jobTimeout}ms` + ); + } + throw err; + } finally { + clearTimeout(timer); + } + } else { + return await this.run(job); + } + }, + { + connection: redisConnectionConfig.queueConnection(), + concurrency: concurrency + } + ); + this.worker.on("error", (error) => { + this.logger.debug("Error in worker processor", error); + }); + closer.registerShutdownHook({ + resource: this, + closingFunction: async (worker: BullWorker) => { + return await worker.shutdown(); + } + }); + } + + abstract run( + job: Job, + signal?: AbortSignal + ): Promise; + + public async shutdown(): Promise { + await this.worker.close(true).catch((error) => { + this.logger.debug("Error while closing worker", error); + }); + } +} diff --git a/packages/commons/src/bull/cron-launcher.ts b/packages/commons/src/bull/cron-launcher.ts new file mode 100644 index 0000000..0fb8edd --- /dev/null +++ b/packages/commons/src/bull/cron-launcher.ts @@ -0,0 +1,77 @@ +import { BullQueue } from "@zeroshotbuilders/commons"; +import { Job, RepeatOptions } from "bullmq"; +import { createLogger, transports } from "winston"; + +interface CronConfig { + queue: BullQueue; + pattern?: string; + interval?: number; + jobId: string; +} + +export class CronLauncher { + private readonly logger = createLogger({ + transports: [new transports.Console()] + }); + + constructor(private cronConfigs: CronConfig[]) {} + + public launchCrons(): void { + this.cronConfigs.forEach((config) => this.launchCron(config)); + } + + private launchCron(config: CronConfig): void { + const { queue, pattern, interval, jobId } = config; + this.logger.info("Draining jobs"); + queue + .getQueue() + .drain(true) + .then(() => { + return queue + .getQueue() + .getRepeatableJobs() + .then((jobs) => { + jobs.map((job) => queue.getQueue().removeRepeatableByKey(job.key)); + }); + }) + .then(() => + queue + .add( + {}, + { + jobId: jobId, + repeat: this.repeatOptions(config) + } + ) + .then((job: Job) => { + this.logger.info( + `Registered cron id:${job.id} with pattern:${pattern}` + ); + queue + .getQueue() + .getRepeatableJobs() + .then((jobs) => this.logger.info("Repeatable Jobs: ", { jobs })); + }) + ); + } + + private repeatOptions(config: CronConfig): RepeatOptions { + if (config.interval) { + this.logger.info("Using interval: " + config.interval); + return { + every: config.interval, + immediately: false + }; + } else if (config.pattern) { + this.logger.info("Using cron pattern: " + config.pattern); + return { + pattern: config.pattern, + immediately: false + }; + } else { + throw new Error( + 'Either "interval" or "pattern" must be provided in CronConfig' + ); + } + } +} diff --git a/packages/commons/src/collections/collection-utils.ts b/packages/commons/src/collections/collection-utils.ts new file mode 100644 index 0000000..3bb8871 --- /dev/null +++ b/packages/commons/src/collections/collection-utils.ts @@ -0,0 +1,20 @@ +import { Map } from "immutable"; + +export function getOrElse( + key: K, + map: Map, + ifEmptyProvider: () => Promise +): Promise { + const value = map.get(key); + if (value) { + return Promise.resolve(value); + } + return ifEmptyProvider(); +} + +export function objectToMap(obj: Record): Map { + return Object.entries(obj).reduce( + (map, [key, value]) => map.set(key, value), + Map() + ); +} diff --git a/packages/commons/src/config/application-config.ts b/packages/commons/src/config/application-config.ts new file mode 100644 index 0000000..5a688a7 --- /dev/null +++ b/packages/commons/src/config/application-config.ts @@ -0,0 +1,35 @@ +import { APPLICATION_ROOT, loadConfig } from "@zeroshotbuilders/commons"; +import { Inject, Injectable } from "@nestjs/common"; + +@Injectable() +export class ApplicationConfig { + local!: boolean; + port: number; + applicationRoot: string; + useRemoteSecrets: boolean; + + constructor(@Inject(APPLICATION_ROOT) applicationRoot?: string) { + if (applicationRoot) { + const config = { + ...loadConfig(applicationRoot), + applicationRoot: applicationRoot + }; + this.local = config.local; + this.port = config.port; + this.applicationRoot = config.applicationRoot; + this.useRemoteSecrets = config.useRemoteSecrets || false; + } + } + + static create( + local: boolean, + port: number, + applicationRoot?: string + ): ApplicationConfig { + const config = new ApplicationConfig(); + config.local = local; + config.port = port; + config.applicationRoot = applicationRoot; + return config; + } +} diff --git a/packages/commons/src/config/client-config.ts b/packages/commons/src/config/client-config.ts new file mode 100644 index 0000000..bbd003d --- /dev/null +++ b/packages/commons/src/config/client-config.ts @@ -0,0 +1,11 @@ +import { Channel } from "@grpc/grpc-js"; +import { createChannel as createGrpcChannel } from "nice-grpc/lib/client/channel"; + +export function toChannel(clientConfig: ClientConfig): Channel { + return createGrpcChannel(`${clientConfig.address}:${clientConfig.port}`); +} + +export class ClientConfig { + readonly address!: string; + readonly port!: number; +} diff --git a/packages/commons/src/config/config-module.ts b/packages/commons/src/config/config-module.ts new file mode 100644 index 0000000..758c3aa --- /dev/null +++ b/packages/commons/src/config/config-module.ts @@ -0,0 +1,19 @@ +import {APPLICATION_ROOT, ApplicationConfig,} from "@zeroshotbuilders/commons"; +import {DynamicModule, Module} from "@nestjs/common"; + +@Module({}) +export class ConfigModule { + public static forApplicationRoot(applicationRoot: string): DynamicModule { + return { + module: ConfigModule, + providers: [ + ApplicationConfig, + { + provide: APPLICATION_ROOT, + useValue: applicationRoot + } + ], + exports: [ApplicationConfig, APPLICATION_ROOT] + }; + } +} diff --git a/packages/commons/src/config/config-utils.ts b/packages/commons/src/config/config-utils.ts new file mode 100644 index 0000000..dd5534c --- /dev/null +++ b/packages/commons/src/config/config-utils.ts @@ -0,0 +1,120 @@ +import fs from "fs"; +import yaml from "js-yaml"; +import path from "path"; +import { createLogger, transports } from "winston"; + +const logger = createLogger({ + transports: [new transports.Console()] +}); + +export function loadConfig( + mainDir: string, + configKey = "", + configFilePath = "assets/config.yaml" +): T { + const packageRoot = path.dirname(mainDir); + const configPath = path.join(packageRoot, configFilePath); + if (!fs.existsSync(configPath)) { + return {} as T; + } + const configFile = fs.readFileSync(configPath, "utf8"); + const config = yaml.load(configFile) as unknown as Record; + + // Add function to read and parse environment variables + function parseEnvVariables(): Record { + const parsedVariables: Record = {}; + + for (const [key, value] of Object.entries(process.env)) { + if (key.startsWith("app_")) { + logger.info(`Environment variable override of ${key} detected.`); + const nestedKeys = key.replace("app_", "").split("___"); + let current: any = parsedVariables; + + nestedKeys.forEach((nestedKey, index) => { + if (!current[nestedKey]) { + if (index === nestedKeys.length - 1) { + if (nestedKey.endsWith("_numeric")) { + const trimmedNestedKey = nestedKey.replace("_numeric", ""); + current[trimmedNestedKey] = Number(value); + } else if (nestedKey.endsWith("_boolean")) { + const trimmedNestedKey = nestedKey.replace("_boolean", ""); + current[trimmedNestedKey] = value === "true"; + } else { + current[nestedKey] = value; + } + } else { + current[nestedKey] = {}; + } + } + + current = current[nestedKey]; + }); + } + } + + return parsedVariables; + } + + // Add function to recursively merge two objects + function deepMerge( + obj1: Record, + obj2: Record + ): Record { + for (const [key, value] of Object.entries(obj2)) { + if (typeof value === "object" && value !== null) { + obj1[key] = deepMerge( + (obj1[key] as Record) || {}, + value as Record + ); + } else { + obj1[key] = value; + } + } + + return obj1; + } + + // Merge the parsed config and environment variables + const mergedConfig = deepMerge(config, parseEnvVariables()); + + if (!configKey) { + return mergedConfig as T; + } + + const keys = configKey.split("."); + let subConfig: unknown = mergedConfig; + for (const key of keys) { + if ( + typeof subConfig === "object" && + subConfig !== null && + Object.prototype.hasOwnProperty.call(subConfig, key) + ) { + subConfig = (subConfig as Record)[key]; + } else { + throw new Error(`Config key '${configKey}' does not exist.`); + } + } + + logger.debug( + `CONFIG { mainDir: ${mainDir}, configKey: ${configKey}, configFilePath: ${configFilePath}}: ${JSON.stringify( + subConfig + )}` + ); + return subConfig as T; +} + +export function runWithEnv( + runnable: () => T, + envVars: Array<[string, string]> +): T { + const oldEnv = { ...process.env }; // Backup the current environment variables + // Set new environment variables + envVars.forEach(([key, value]) => { + process.env[key] = value; + }); + try { + return runnable(); + } finally { + process.env = oldEnv; // Restore the original environment variables + } +} diff --git a/packages/commons/src/crypto/crypto-utils.ts b/packages/commons/src/crypto/crypto-utils.ts new file mode 100644 index 0000000..b368194 --- /dev/null +++ b/packages/commons/src/crypto/crypto-utils.ts @@ -0,0 +1,32 @@ +import crypto, { createHash } from "crypto"; + +export async function hashString(input: string): Promise { + const encoder = new TextEncoder(); + const data = encoder.encode(input); + + const hashBuffer = await crypto.subtle.digest("SHA-256", data); + + // Convert hash to hexadecimal string for display + const hashArray = Array.from(new Uint8Array(hashBuffer)); + const hashHex = hashArray + .map((byte) => byte.toString(16).padStart(2, "0")) + .join(""); + + return hashHex; +} + +export function sha256(input: string): string { + return createHash("sha256").update(input).digest("hex"); +} + +export function randomBytes(byteSize: number): string { + return crypto.randomBytes(byteSize).toString("hex"); +} + +export function djb2Hash(str: string): number { + let hash = 5381; + for (let i = 0; i < str.length; i++) { + hash = (hash << 5) + hash + str.charCodeAt(i); /* hash * 33 + c */ + } + return hash; +} diff --git a/packages/commons/src/date/date-utils.ts b/packages/commons/src/date/date-utils.ts new file mode 100644 index 0000000..e240a0c --- /dev/null +++ b/packages/commons/src/date/date-utils.ts @@ -0,0 +1,12 @@ +import { DateTime } from "luxon"; + +export function getDayOfMonth(date: number): number { + return DateTime.fromMillis(date).get("day"); +} +export function toIsoString(date: number): string { + return new Date(date).toISOString(); +} + +export function fromIsoString(isoString: string): number { + return new Date(isoString).getTime(); +} diff --git a/packages/commons/src/decorators/at-least-one-of.ts b/packages/commons/src/decorators/at-least-one-of.ts new file mode 100644 index 0000000..ab60240 --- /dev/null +++ b/packages/commons/src/decorators/at-least-one-of.ts @@ -0,0 +1,79 @@ +import { + registerDecorator, + ValidationArguments, + ValidationOptions +} from "class-validator"; + +/** + * Validates that at least one of the specified properties has a value. + * This is useful for validating that at least one of a set of related fields is provided. + * + * The validation checks if any of the specified properties: + * - Is an array with at least one element, OR + * - Is a non-array value that is defined and not null + * + * This decorator can only be used at the class level. + * + * @param properties - Array of property names to check + * @param validationOptions - Optional validation options from class-validator + * + * @example + * // With array properties + * @AtLeastOneOf(['clientIds', 'sessionChainIds'], { + * message: 'At least one of clientIds or sessionChainIds must be specified' + * }) + * class GetSessionChainSummariesRequestDto { + * @IsOptional() + * readonly clientIds: string[] | undefined; + * + * @IsOptional() + * readonly sessionChainIds: string[] | undefined; + * } + * + * // With non-array properties + * @AtLeastOneOf(['name', 'email'], { + * message: 'At least one of name or email must be specified' + * }) + * class UserSearchDto { + * @IsOptional() + * readonly name: string | undefined; + * + * @IsOptional() + * readonly email: string | undefined; + * } + */ +export function AtLeastOneOf( + properties: string[], + validationOptions?: ValidationOptions +): ClassDecorator { + return function (target: any) { + registerDecorator({ + name: "atLeastOneOf", + target: target, + propertyName: "", + constraints: [properties], + options: validationOptions, + validator: { + validate(value: any, args: ValidationArguments) { + const [relatedPropertyNames] = args.constraints; + const object = args.object as any; + return relatedPropertyNames.some((propertyName: string | symbol) => { + const value = object[propertyName]; + // Check if it's an array with at least one element + if (Array.isArray(value)) { + return value.length > 0; + } + // Check if it's a non-array value that is defined and not null + return value !== undefined && value !== null && value !== ""; + }); + }, + defaultMessage(args: ValidationArguments) { + const [relatedPropertyNames] = args.constraints; + return `At least one of the following properties must be specified: ${relatedPropertyNames.join( + ", " + )}`; + } + } + }); + }; +} diff --git a/packages/commons/src/decorators/default.ts b/packages/commons/src/decorators/default.ts new file mode 100644 index 0000000..763652a --- /dev/null +++ b/packages/commons/src/decorators/default.ts @@ -0,0 +1,10 @@ +import { Transform } from "class-transformer"; +import { notEmpty } from "../internal/not-empty"; + +export const Default = (defaultValue: any): PropertyDecorator => + Transform(({ value }: any) => (notEmpty(value) ? value : defaultValue)); + +export const DefaultProvider = ( + defaultProvider: () => any +): PropertyDecorator => + Transform(({ value }: any) => (notEmpty(value) ? value : defaultProvider())); diff --git a/packages/commons/src/decorators/future-timestamp.ts b/packages/commons/src/decorators/future-timestamp.ts new file mode 100644 index 0000000..35e792d --- /dev/null +++ b/packages/commons/src/decorators/future-timestamp.ts @@ -0,0 +1,65 @@ +import { + registerDecorator, + ValidationArguments, + ValidationOptions +} from "class-validator"; +import { DateTime, Duration } from "luxon"; + +/** + * Validates that a timestamp (number) is at least a specified duration in the future. + * This is useful for validating that dates are set in the future by a minimum amount of time. + * The minimum timestamp is calculated at validation time, not at decorator definition time. + * + * @param offsetDuration - The minimum duration in the future the timestamp must be (Luxon Duration object). + * @param validationOptions - Optional validation options from class-validator + * + * @example + * class BasicReminder { + * @IsOptional() + * @FutureTimestamp(Duration.fromObject({ hours: 1 }), { message: 'Reminder must be at least one hour in the future' }) + * reminderDate: number | undefined; + * } + */ +export function FutureTimestamp( + offsetDuration: Duration, + validationOptions?: ValidationOptions +): PropertyDecorator { + return function (object: object, propertyName: string | symbol) { + registerDecorator({ + name: "futureTimestamp", + target: object.constructor, + propertyName: propertyName.toString(), + constraints: [offsetDuration], + options: validationOptions, + validator: { + validate(value: unknown, args: ValidationArguments) { + // Skip validation if value is undefined or null + if (value === undefined || value === null) { + return true; + } + + // Only validate if value is a number + if (typeof value !== "number") { + return false; + } + + const [duration] = args.constraints as Duration[]; + const minTimestamp = DateTime.now().plus(duration).toMillis(); + + return value >= minTimestamp; + }, + defaultMessage(args: ValidationArguments) { + const [duration] = args.constraints as Duration[]; + const durationText = duration.toHuman(); + const minTimestamp = DateTime.now().plus(duration).toMillis(); + + return `${args.property} [${new Date( + args.value as number + ).toISOString()}] must be set at least ${durationText} into the future [${new Date( + minTimestamp + ).toISOString()}]`; + } + } + }); + }; +} diff --git a/packages/commons/src/decorators/is-bigger-than.ts b/packages/commons/src/decorators/is-bigger-than.ts new file mode 100644 index 0000000..1462870 --- /dev/null +++ b/packages/commons/src/decorators/is-bigger-than.ts @@ -0,0 +1,56 @@ +import { + registerDecorator, + ValidationArguments, + ValidationOptions +} from "class-validator"; + +/** + * Validates that a numeric property is greater than another numeric property in the same object. + * This is useful for validating ranges, time periods, or any numeric relationships between properties. + * + * @param property - The name of the property to compare against + * @param validationOptions - Optional validation options from class-validator + * + * @example + * class TimeRange { + * @IsNumber() + * startTime: number; + * + * @IsNumber() + * @IsBiggerThan('startTime', { message: 'End time must be after start time' }) + * endTime: number; + * } + */ +export function IsBiggerThan( + property: string, + validationOptions?: ValidationOptions +): PropertyDecorator { + return function (object: object, propertyName: string | symbol) { + registerDecorator({ + name: "isBiggerThan", + target: object.constructor, + propertyName: propertyName.toString(), + constraints: [property], + options: validationOptions, + validator: { + validate(value: unknown, args: ValidationArguments) { + const [relatedPropertyName] = args.constraints; + const relatedValue = (args.object as Record)[ + relatedPropertyName + ]; + + // Only validate if both values are numbers + return ( + typeof value === "number" && + typeof relatedValue === "number" && + value > relatedValue + ); + }, + defaultMessage(args: ValidationArguments) { + const [relatedPropertyName] = args.constraints; + return `${args.property} must be greater than ${relatedPropertyName}`; + } + } + }); + }; +} diff --git a/packages/commons/src/decorators/is-image-url.ts b/packages/commons/src/decorators/is-image-url.ts new file mode 100644 index 0000000..674444f --- /dev/null +++ b/packages/commons/src/decorators/is-image-url.ts @@ -0,0 +1,58 @@ +import { + registerDecorator, + ValidationArguments, + ValidationOptions +} from "class-validator"; + +const validImageExtensions = [".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg"]; + +export function isImageUrl( + hostNameContains: string | string[], + validationOptions?: ValidationOptions +): PropertyDecorator { + return function (object: any, propertyName: string | symbol) { + registerDecorator({ + name: "isImageUrl", + target: object.constructor, + propertyName: propertyName.toString(), + options: validationOptions, + validator: { + validate(value: any) { + if (typeof value !== "string" || !value) return true; + + try { + const url = new URL(value); + const hostMatches = + hostNameContains === "" + ? true + : Array.isArray(hostNameContains) + ? hostNameContains.some((host) => url.hostname.includes(host)) + : url.hostname.includes(hostNameContains); + + const extensionMatches = validImageExtensions.some((ext) => + url.pathname.toLowerCase().endsWith(ext) + ); + + return hostMatches && extensionMatches; + } catch { + return false; + } + }, + defaultMessage(args: ValidationArguments) { + const hostDesc = + hostNameContains === "" + ? "any host" + : Array.isArray(hostNameContains) + ? `host(s) containing ${hostNameContains.join(", ")}` + : `a host containing "${hostNameContains}"`; + + return `${ + args.property + } must be a valid image URL from ${hostDesc} ending with one of: ${validImageExtensions.join( + ", " + )}`; + } + } + }); + }; +} diff --git a/packages/commons/src/decorators/is-optional.ts b/packages/commons/src/decorators/is-optional.ts new file mode 100644 index 0000000..0259f67 --- /dev/null +++ b/packages/commons/src/decorators/is-optional.ts @@ -0,0 +1,9 @@ +import { ValidateIf, ValidationOptions } from "class-validator"; +import { notEmpty } from "../internal/not-empty"; + +export const IsOptional = ( + validationOptions?: ValidationOptions +): PropertyDecorator => + ValidateIf((obj, value) => { + return notEmpty(value); + }, validationOptions); diff --git a/packages/commons/src/decorators/is-safe-json.ts b/packages/commons/src/decorators/is-safe-json.ts new file mode 100644 index 0000000..d37ae16 --- /dev/null +++ b/packages/commons/src/decorators/is-safe-json.ts @@ -0,0 +1,95 @@ +import { + registerDecorator, + ValidationArguments, + ValidationOptions +} from "class-validator"; + +/** + * Regular expression to detect potentially malicious links. + * This is the same pattern used in your IsSafeString validator. + */ +const maliciousLinkPattern = + /(|href=|src=|http:\/\/|https:\/\/|www\.|[^<]\[[^\]]+\]\([^)]+\))/i; + +function isUnsafeString(value: string): boolean { + return maliciousLinkPattern.test(value); +} + +/** + * Recursively traverses an object or array to find strings with malicious content. + * @param obj The object to traverse. + * @returns An array of paths to unsafe strings. + */ +function findUnsafeStringPaths(obj: any): string[] { + const unsafePaths: string[] = []; + + function traverse(current: any, path: string) { + if (!current) { + return; + } + + if (typeof current === "string") { + if (isUnsafeString(current)) { + unsafePaths.push(path || "root"); + } + return; + } + + if (Array.isArray(current)) { + for (let i = 0; i < current.length; i++) { + traverse(current[i], `${path}[${i}]`); + } + return; + } + + if (typeof current === "object") { + for (const key of Object.keys(current)) { + traverse(current[key], path ? `${path}.${key}` : key); + } + } + } + + traverse(obj, ""); + return unsafePaths; +} + +/** + * Validates that a JSON object does not contain strings with potentially malicious links. + * This is to protect against link injection. + */ +export function IsSafeJson( + validationOptions?: ValidationOptions +): PropertyDecorator { + return function (object: any, propertyName: string | symbol) { + registerDecorator({ + name: "isSafeJson", + target: object.constructor, + propertyName: propertyName.toString(), + options: validationOptions, + validator: { + validate(value: any, args: ValidationArguments) { + if (typeof value !== "object" || value === null) { + return true; // Only validate objects (and arrays). + } + + const unsafePaths = findUnsafeStringPaths(value); + + if (unsafePaths.length > 0) { + // Store details for a more informative error message. + (args.object as any)[`${args.property}_unsafeDetails`] = + unsafePaths.join(", "); + return false; + } + + return true; + }, + defaultMessage(args: ValidationArguments) { + const unsafeDetails = (args.object as any)[ + `${args.property}_unsafeDetails` + ]; + return `${args.property} contains potentially malicious content at the following paths: ${unsafeDetails}`; + } + } + }); + }; +} diff --git a/packages/commons/src/decorators/is-safe-string.ts b/packages/commons/src/decorators/is-safe-string.ts new file mode 100644 index 0000000..d2953dd --- /dev/null +++ b/packages/commons/src/decorators/is-safe-string.ts @@ -0,0 +1,55 @@ +import { + registerDecorator, + ValidationArguments, + ValidationOptions +} from "class-validator"; + +/** + * Validates that a string does not contain potentially malicious links. + * This is to protect against link injection in free text fields. + * It guards against malicious links that would be rendered as a link in an email. + * It does not block normal strings. + */ +export function IsSafeString( + validationOptions?: ValidationOptions +): PropertyDecorator { + return function (object: any, propertyName: string | symbol) { + registerDecorator({ + name: "isSafeString", + target: object.constructor, + propertyName: propertyName.toString(), + options: validationOptions, + validator: { + validate(value: any): boolean { + if (typeof value !== "string") { + return true; // Only validate strings + } + + // Block obvious HTML tags and script/style blocks + const htmlTagPattern = /<\/?\s*[a-z][\s\S]*?>/i; // matches or + const scriptStylePattern = + /<(script|style)\b[\s\S]*?>[\s\S]*?<\/\1>/i; + + // Block URLs and link-like content + const urlPattern = /(http:\/\/|https:\/\/|www\.)/i; + + // Block Markdown links [text](url) + const markdownLinkPattern = /\[[^\]]+\]\([^)]+\)/; + + // Block href attributes even without protocol (e.g., href='example.com') + const hrefAttributePattern = /\bhref\s*=\s*(['"])?[^'"\s>]+\1?/i; + + // Combine checks + if (htmlTagPattern.test(value)) return false; + if (scriptStylePattern.test(value)) return false; + if (urlPattern.test(value)) return false; + if (markdownLinkPattern.test(value)) return false; + return !hrefAttributePattern.test(value); + }, + defaultMessage(args: ValidationArguments) { + return `${args.property} contains potentially malicious content`; + } + } + }); + }; +} diff --git a/packages/commons/src/injection-tokens.ts b/packages/commons/src/injection-tokens.ts new file mode 100644 index 0000000..0deafc4 --- /dev/null +++ b/packages/commons/src/injection-tokens.ts @@ -0,0 +1,7 @@ +export const POSTGRES_CONFIG_ROOT = "POSTGRES_CONFIG_ROOT"; +export const APPLICATION_ROOT = "APPLICATION_ROOT"; +export const REDIS_CONFIG_ROOT = "REDIS_CONFIG_ROOT"; +export const REDIS_CLIENT = "REDIS_CLIENT"; +export const REDIS_CONFIG_PORT = "REDIS_PORT"; +export const REDIS_CONFIG_HOST = "REDIS_HOST"; +export const REDIS_CONFIG_POOL_SIZE = "REDIS_POOL_SIZE"; diff --git a/packages/commons/src/internal/not-empty.ts b/packages/commons/src/internal/not-empty.ts new file mode 100644 index 0000000..9e97a89 --- /dev/null +++ b/packages/commons/src/internal/not-empty.ts @@ -0,0 +1,11 @@ +export const notEmpty = (value: any): boolean => { + return ( + value !== null && + value !== undefined && + // proto numbers + value !== 0 && + value !== "" && + // proto enums + !(typeof value == "string" && value.toLowerCase().includes("unknown")) + ); +}; diff --git a/packages/commons/src/internal/object-utils.ts b/packages/commons/src/internal/object-utils.ts new file mode 100644 index 0000000..efd9d33 --- /dev/null +++ b/packages/commons/src/internal/object-utils.ts @@ -0,0 +1,25 @@ +// Recursively checks for specific properties on nested objects and removes them. +export const removeProps = (obj: any, ...props: string[]): any => { + const maxDepth = 3; + const removePropsRecursive = (inputObj: any, currentDepth: number): any => { + if (currentDepth <= maxDepth) { + const newObj: any = Array.isArray(inputObj) ? [] : {}; + for (const key in inputObj) { + if (props.includes(key)) { + // noinspection UnnecessaryContinueJS + continue; + } else if ( + typeof inputObj[key] === "object" && + inputObj[key] !== null + ) { + newObj[key] = removePropsRecursive(inputObj[key], currentDepth + 1); + } else { + newObj[key] = inputObj[key]; + } + } + return newObj; + } + return inputObj; + }; + return removePropsRecursive(obj, 1); +}; diff --git a/packages/commons/src/internal/string-utils.ts b/packages/commons/src/internal/string-utils.ts new file mode 100644 index 0000000..07196be --- /dev/null +++ b/packages/commons/src/internal/string-utils.ts @@ -0,0 +1,2 @@ +export const kebabToCamel = (kebabCase: string): string => + kebabCase.replace(/-([a-z])/g, (_, match) => match.toUpperCase()); diff --git a/packages/commons/src/ip/ip-utils.ts b/packages/commons/src/ip/ip-utils.ts new file mode 100644 index 0000000..e5e7d06 --- /dev/null +++ b/packages/commons/src/ip/ip-utils.ts @@ -0,0 +1,58 @@ +export function parseIpAddressFromXForwardedFor( + ipAddressFromXForwardedFor?: string +): string | undefined { + // Value could be an array of values, comma separated. + const maybeIpAddress = ipAddressFromXForwardedFor?.split(",")[0].trim(); + return maybeIpAddress && isValidIpAddress(maybeIpAddress) + ? maybeIpAddress + : undefined; +} + +function isValidIpAddress(ipAddress: string): boolean { + if (!ipAddress) { + return false; + } + const ipRegex = + /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; + return ipRegex.test(ipAddress); +} + +export function isValidIpCidrBlock(cidrBlock: string): boolean { + if (!cidrBlock) { + return false; + } + const cidrRegex = + /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/(?:[0-9]|[1-2][0-9]|3[0-2])$/; + return cidrRegex.test(cidrBlock); +} + +function ipToLong(ip: string): number { + return ( + ip.split(".").reduce((acc, octet) => { + return (acc << 8) + parseInt(octet, 10); + }, 0) >>> 0 + ); +} + +export function isIpInCidrBlock(ipAddress: string, cidrBlock: string): boolean { + if (!isValidIpAddress(ipAddress) || !isValidIpCidrBlock(cidrBlock)) { + return false; + } + + const [cidrIp, prefixStr] = cidrBlock.split("/"); + const prefix = parseInt(prefixStr, 10); + + // A prefix of 0 is a special case that matches all IPs. The bitwise operations + // below do not work correctly for a prefix of 0 in JS, so we handle it separately. + if (prefix === 0) { + return true; + } + + const ipLong = ipToLong(ipAddress); + const cidrIpLong = ipToLong(cidrIp); + + // Create a mask of 'prefix' bits + const mask = (-1 << (32 - prefix)) >>> 0; + + return (ipLong & mask) === (cidrIpLong & mask); +} diff --git a/packages/commons/src/logging/winston-logger.ts b/packages/commons/src/logging/winston-logger.ts new file mode 100644 index 0000000..90b3777 --- /dev/null +++ b/packages/commons/src/logging/winston-logger.ts @@ -0,0 +1,32 @@ +import { LoggerService } from "@nestjs/common"; +import { createLogger, Logger, transports } from "winston"; + +export class WinstonLogger implements LoggerService { + private readonly logger: Logger; + + constructor() { + this.logger = createLogger({ + transports: [new transports.Console()] + }); + } + + log(message: any, context?: string) { + this.logger.info(message, { context }); + } + + error(message: any, trace?: string, context?: string) { + this.logger.error(message, { trace, context }); + } + + warn(message: any, context?: string) { + this.logger.warn(message, { context }); + } + + debug?(message: any, context?: string) { + this.logger.debug(message, { context }); + } + + verbose?(message: any, context?: string) { + this.logger.verbose(message, { context }); + } +} diff --git a/packages/commons/src/port/port-utils.ts b/packages/commons/src/port/port-utils.ts new file mode 100644 index 0000000..3d283c4 --- /dev/null +++ b/packages/commons/src/port/port-utils.ts @@ -0,0 +1,50 @@ +import * as net from "net"; +import { Pattern, match } from "ts-pattern"; +import { Range, Seq } from "immutable"; + +export interface PortStatus { + port: number; + isOpen: boolean; +} + +export class PortConfig { + readonly minPort!: number; + readonly maxPort!: number; +} + +export async function findOpenPort(config: PortConfig): Promise { + if (config.minPort > config.maxPort) { + throw new Error("minPort must be less than or equal to maxPort"); + } + const openPort: number | undefined = await Seq( + Range(config.minPort, config.maxPort + 1) + ).reduce( + async (prevPortPromise: Promise, port: number) => { + const prevPort: number | undefined = await prevPortPromise; + if (prevPort !== undefined) { + return prevPort; + } + const result: PortStatus = await checkPort(port); + return result.isOpen ? result.port : undefined; + }, + Promise.resolve(undefined) + ); + return match(openPort) + .with(Pattern.not(undefined), (port) => port) + .otherwise(() => { + throw new Error("No open port found in the specified range"); + }); +} + +export function checkPort(port: number): Promise { + return new Promise((resolve) => { + const server: net.Server = net.createServer(); + + server.unref(); + server.on("error", () => resolve({ port, isOpen: false })); + + server.listen(port, "0.0.0.0", () => { + server.close(() => resolve({ port, isOpen: true })); + }); + }); +} diff --git a/packages/commons/src/postgres/postgres-connection-config.ts b/packages/commons/src/postgres/postgres-connection-config.ts new file mode 100644 index 0000000..a8755af --- /dev/null +++ b/packages/commons/src/postgres/postgres-connection-config.ts @@ -0,0 +1,44 @@ +import { + ApplicationConfig, + loadConfig +} from "@zeroshotbuilders/commons"; +import { Injectable } from "@nestjs/common"; + +@Injectable() +export class PostgresConnectionConfig { + public static POSTGRES_CONFIG_KEY = "postgres"; + + readonly port: number; + readonly host: string; + readonly username: string; + readonly password: string; + readonly database: string; + readonly logging: boolean; + readonly standardConformingStrings: boolean; + readonly ignoreClientMinMessages: boolean; + readonly poolMax?: number; + readonly poolAcquire?: number; + readonly poolIdle?: number; + + static async create( + applicationConfig: ApplicationConfig + ): Promise { + const config = loadConfig( + applicationConfig.applicationRoot, + PostgresConnectionConfig.POSTGRES_CONFIG_KEY + ); + return { + port: config.port, + host: config.host, + username: config.username, + password: config.password, + database: config.database, + logging: config.logging || false, + standardConformingStrings: config.standardConformingStrings ?? true, + ignoreClientMinMessages: config.ignoreClientMinMessages ?? false, + poolMax: config.poolMax, + poolAcquire: config.poolAcquire, + poolIdle: config.poolIdle + }; + } +} diff --git a/packages/commons/src/postgres/postgres-connection-module.ts b/packages/commons/src/postgres/postgres-connection-module.ts new file mode 100644 index 0000000..d200e3e --- /dev/null +++ b/packages/commons/src/postgres/postgres-connection-module.ts @@ -0,0 +1,94 @@ +import { + ApplicationConfig, + POSTGRES_CONFIG_ROOT, + PostgresConnectionConfig +} from "@zeroshotbuilders/commons"; +import { DynamicModule, Module } from "@nestjs/common"; +import { DataTypes, Sequelize } from "sequelize"; + +async function createSequelizeInstance( + clientConfig: PostgresConnectionConfig +): Promise { + const sequelize = new Sequelize( + clientConfig.database, + clientConfig.username, + clientConfig.password, + { + logging: clientConfig.logging, + dialect: "postgres", + host: clientConfig.host, + port: clientConfig.port, + standardConformingStrings: clientConfig.standardConformingStrings, + pool: { + max: clientConfig.poolMax ?? 5, + acquire: clientConfig.poolAcquire ?? 60000, + idle: clientConfig.poolIdle ?? 10000 + }, + dialectOptions: { + bigNumberStrings: false, + supportBigNumbers: true, + ...(clientConfig.ignoreClientMinMessages && { + clientMinMessages: "ignore" + }) + }, + hooks: { + afterConnect: () => { + const types = { + DECIMAL: { + ...DataTypes.DECIMAL, + parse: parseFloat + }, + BIGINT: { + ...DataTypes.BIGINT, + parse: parseInt + } + }; + sequelize.connectionManager.refreshTypeParser(types); + } + } + } + ); + await sequelize.authenticate(); + return sequelize; +} + +@Module({}) +export class PostgresConnectionModule { + public static forApplicationRoot(applicationRoot: string): DynamicModule { + return { + module: PostgresConnectionModule, + providers: [ + { + provide: POSTGRES_CONFIG_ROOT, + useValue: applicationRoot + }, + { + provide: PostgresConnectionConfig, + useFactory: async ( + applicationConfig: ApplicationConfig + ) => { + return await PostgresConnectionConfig.create( + applicationConfig + ); + }, + inject: [ + ApplicationConfig, + POSTGRES_CONFIG_ROOT + ] + }, + { + provide: Sequelize, + inject: [PostgresConnectionConfig], + useFactory: async (clientConfig: PostgresConnectionConfig) => { + return createSequelizeInstance(clientConfig); + } + } + ], + exports: [ + POSTGRES_CONFIG_ROOT, + Sequelize, + PostgresConnectionConfig + ] + }; + } +} diff --git a/packages/commons/src/postgres/postgres-utils.ts b/packages/commons/src/postgres/postgres-utils.ts new file mode 100644 index 0000000..352029b --- /dev/null +++ b/packages/commons/src/postgres/postgres-utils.ts @@ -0,0 +1,84 @@ +import { ServerError, Status } from "nice-grpc"; +import { Error as SequelizeError, UniqueConstraintError } from "sequelize"; +import { Set } from "immutable"; + +export enum SequelizeErrors { + UNIQUE_CONSTRAINT = "SequelizeUniqueConstraintError", + FOREIGN_KEY_CONSTRAINT = "SequelizeForeignKeyConstraintError" +} + +export async function withRecovery( + supplier: () => Promise, + errors: Set +): Promise { + try { + await supplier(); + } catch (error) { + if (error instanceof SequelizeError && errors.includes(error.name)) { + return; + } + throw error; + } +} + +export async function withAlreadyExists( + supplier: () => Promise +): Promise { + try { + return await supplier(); + } catch (error) { + if ( + error instanceof SequelizeError && + error.name == SequelizeErrors.UNIQUE_CONSTRAINT + ) { + const constraintError = error as UniqueConstraintError; + throw new ServerError( + Status.ALREADY_EXISTS, + `Entity already exists: ${JSON.stringify( + constraintError.fields, + null, + 2 + )}` + ); + } + throw error; + } +} + +export function handleIdempotency( + baseError: SequelizeError, + recoveryRunnable: () => Promise, + recoverableConstraintViolations: Set = Set.of("idempotency_key") +): Promise { + if (baseError.name == SequelizeErrors.UNIQUE_CONSTRAINT) { + const uniqueConstraintError = baseError as UniqueConstraintError; + if (shouldRecover(uniqueConstraintError, recoverableConstraintViolations)) { + try { + return recoveryRunnable(); + } catch (error) { + throw new Error(`Failed to recover idempotency violation: ${error}`); + } + } + throw new ServerError( + Status.ALREADY_EXISTS, + `Item already exists: ${JSON.stringify( + uniqueConstraintError.fields, + null, + 2 + )}` + ); + } + throw baseError; +} + +function shouldRecover( + error: UniqueConstraintError, + recoverableConstraintViolations: Set = Set.of("idempotency_key") +): boolean { + for (const constraintViolation of recoverableConstraintViolations) { + if (constraintViolation in error.fields) { + return true; + } + } + return false; +} diff --git a/packages/commons/src/random/random-utils.ts b/packages/commons/src/random/random-utils.ts new file mode 100644 index 0000000..971015b --- /dev/null +++ b/packages/commons/src/random/random-utils.ts @@ -0,0 +1,5 @@ +export function randomInt(min?: number, max?: number): number { + min = Math.ceil(min || 0); + max = Math.floor(max || Number.MAX_SAFE_INTEGER); + return Math.floor(Math.random() * (max - min + 1)) + min; +} diff --git a/packages/commons/src/redis/redis-client-pool.ts b/packages/commons/src/redis/redis-client-pool.ts new file mode 100644 index 0000000..04d392f --- /dev/null +++ b/packages/commons/src/redis/redis-client-pool.ts @@ -0,0 +1,70 @@ +import { RedisClientType, createClient } from "redis"; +import { Closer, RedisConnectionConfig } from "@zeroshotbuilders/commons"; +import { createLogger, Logger, transports } from "winston"; + +export class RedisClientPool { + private readonly logger: Logger = createLogger({ + transports: [new transports.Console()] + }); + private clientPool: RedisClientType[] = []; + + constructor(connectionConfig: RedisConnectionConfig, closer: Closer) { + const poolSize = connectionConfig.poolSize || 10; + for (let i = 0; i < poolSize; i++) { + const client: RedisClientType = createClient({ + url: connectionConfig.url + }); + client.on("error", (error) => { + if (error.message === "Socket closed unexpectedly") { + this.logger.debug( + "Redis socket closed unexpectedly. This could be thrown from a shutdown hook.", + error + ); + } else { + this.logger.error("Redis error.", error); + } + }); + closer.registerShutdownHook({ + resource: client, + closingFunction: async (client: RedisClientType) => { + if (client && client.isOpen) { + await client.disconnect(); + } + } + }); + this.clientPool.push(client); + } + } + + public async acquire(): Promise { + while (this.clientPool.length === 0) { + this.logger.warn("No redis clients available"); + await new Promise((resolve) => setTimeout(resolve, 100)); + } + const client = this.clientPool.pop(); + + if (client) { + if (!client.isOpen) { + await client.connect(); + } + return client; + } else { + throw new Error("Failed to acquire a Redis client."); + } + } + + public release(client: RedisClientType): void { + this.clientPool.push(client); + } + + public async withConnection( + func: (client: RedisClientType) => Promise | T + ): Promise { + const client = await this.acquire(); + try { + return await func(client); + } finally { + this.release(client); + } + } +} diff --git a/packages/commons/src/redis/redis-connection-config.ts b/packages/commons/src/redis/redis-connection-config.ts new file mode 100644 index 0000000..efeb761 --- /dev/null +++ b/packages/commons/src/redis/redis-connection-config.ts @@ -0,0 +1,39 @@ +import { Inject, Injectable } from "@nestjs/common"; +import { + REDIS_CONFIG_HOST, + REDIS_CONFIG_PORT, + REDIS_CONFIG_POOL_SIZE +} from "@zeroshotbuilders/commons"; +import { ConnectionOptions } from "bullmq"; + +@Injectable() +export class RedisConnectionConfig { + public readonly port: number; + public readonly host: string; + public readonly poolSize?: number; + + constructor( + @Inject(REDIS_CONFIG_PORT) port: number, + @Inject(REDIS_CONFIG_HOST) host: string, + @Inject(REDIS_CONFIG_POOL_SIZE) poolSize?: number + ) { + this.port = port; + this.host = host; + this.poolSize = poolSize; + } + + public get url(): string { + /** + * `redis[s]://[[username][:password]@][host][:port][/db-number]` + * See [`redis`](https://www.iana.org/assignments/uri-schemes/prov/redis) and [`rediss`](https://www.iana.org/assignments/uri-schemes/prov/rediss) IANA registration for more details + */ + return `redis://${this.host}:${this.port}`; + } + + public queueConnection(): ConnectionOptions { + return { + host: this.host, + port: this.port + }; + } +} diff --git a/packages/commons/src/redis/redis-connection-module.ts b/packages/commons/src/redis/redis-connection-module.ts new file mode 100644 index 0000000..6682bf3 --- /dev/null +++ b/packages/commons/src/redis/redis-connection-module.ts @@ -0,0 +1,104 @@ +import { + DynamicModule, + Module, + Provider, + ModuleMetadata +} from "@nestjs/common"; +import { + REDIS_CLIENT, + REDIS_CONFIG_HOST, + REDIS_CONFIG_PORT, + REDIS_CONFIG_ROOT, + RedisConnectionConfig, + loadConfig, + Closer, + REDIS_CONFIG_POOL_SIZE +} from "@zeroshotbuilders/commons"; +import { createClient, RedisClientType } from "redis"; +import { createLogger, Logger, transports } from "winston"; +import { RedisClientPool } from "./redis-client-pool"; + +const logger: Logger = createLogger({ + transports: [new transports.Console()] +}); + +@Module({}) +export class RedisConnectionModule { + public static REDIS_CONFIG_KEY = "redis"; + + public static forApplicationRoot(applicationRoot: string): DynamicModule { + const config = loadConfig( + applicationRoot, + RedisConnectionModule.REDIS_CONFIG_KEY + ); + + const resource: Provider[] = [ + { + provide: REDIS_CONFIG_ROOT, + useValue: applicationRoot + }, + { + provide: REDIS_CONFIG_PORT, + useValue: config.port + }, + { + provide: REDIS_CONFIG_HOST, + useValue: config.host + }, + { + provide: REDIS_CONFIG_POOL_SIZE, + useValue: config.poolSize + }, + RedisConnectionConfig, + Closer, + { + provide: RedisClientPool, + inject: [RedisConnectionConfig, Closer], + useFactory: ( + connectionConfig: RedisConnectionConfig, + closer: Closer + ) => { + return new RedisClientPool(connectionConfig, closer); + } + }, + { + inject: [RedisConnectionConfig, Closer], + provide: REDIS_CLIENT, + useFactory: async ( + connectionConfig: RedisConnectionConfig, + closer: Closer + ) => { + const client: RedisClientType = createClient({ + url: connectionConfig.url + }); + await client.connect(); + client.on("error", (error) => { + if (error.message === "Socket closed unexpectedly") { + logger.debug( + "Redis socket closed unexpectedly. This could be thrown from a shutdown hook.", + error + ); + } else { + logger.error("Redis error.", error); + } + }); + closer.registerShutdownHook({ + resource: client, + closingFunction: async (client: RedisClientType) => { + if (client && client.isOpen) { + await client.disconnect(); + } + } + }); + return client; + } + } + ]; + + return { + module: RedisConnectionModule, + providers: resource, + exports: resource as ModuleMetadata["exports"] + }; + } +} diff --git a/packages/commons/src/resources/closer.ts b/packages/commons/src/resources/closer.ts new file mode 100644 index 0000000..234ce3f --- /dev/null +++ b/packages/commons/src/resources/closer.ts @@ -0,0 +1,71 @@ +import { Injectable } from "@nestjs/common"; +import { createLogger, transports } from "winston"; + +const CLOSER_FUNCTION_TIMEOUT = 10000; + +type CloseableResource = { + resource: T; + closingFunction: (r: T) => Promise; +}; + +function withTimeout( + promise: Promise, + timeoutMilliseconds: number +): Promise { + let timeout: NodeJS.Timeout; + const timeoutPromise = new Promise((_, reject) => { + timeout = setTimeout(() => { + reject(new Error("Timeout")); + }, timeoutMilliseconds); + }); + + return Promise.race([promise, timeoutPromise]).finally(() => + clearTimeout(timeout) + ); +} + +@Injectable() +export class Closer { + private readonly logger = createLogger({ + transports: [new transports.Console()] + }); + private closeableResources: CloseableResource[]; + + public static create(...closeables: CloseableResource[]): Closer { + const closer = new Closer(); + closer.closeableResources = [...closeables]; + return closer; + } + + constructor() { + this.closeableResources = []; + } + + public registerShutdownHook(closeable: CloseableResource) { + this.closeableResources.push(closeable); + } + + public async close(): Promise { + for (const closeable of this.closeableResources) { + const resourceName = closeable.resource.constructor.name; + this.logger.info("Closing resource", { + resourceName + }); + await withTimeout( + closeable.closingFunction(closeable.resource).catch((error) => { + this.logger.warn("Exception while closing resource", error, { + resourceName + }); + }), + CLOSER_FUNCTION_TIMEOUT + ).catch((error) => { + this.logger.warn("Timed out while closing resource", error, { + resourceName + }); + }); + this.logger.info("Successfully closed resource", { + resourceName + }); + } + } +} diff --git a/packages/commons/src/server/rest-booter.ts b/packages/commons/src/server/rest-booter.ts new file mode 100644 index 0000000..685b46a --- /dev/null +++ b/packages/commons/src/server/rest-booter.ts @@ -0,0 +1,29 @@ +import { INestApplication } from "@nestjs/common"; +import { NestFactory } from "@nestjs/core"; +import { WinstonLogger } from "../logging/winston-logger"; + +const logger = new WinstonLogger(); + +export async function bootRest( + module: any, + component: any, + bootstrap: (comp: ComponentT, app: INestApplication) => Promise, + shutdown: (comp: ComponentT, app: INestApplication) => Promise +) { + const app = await NestFactory.create(module, { + logger + }); + const serviceComponent = app.get(component); + logger.log("Booting REST service..."); + bootstrap(serviceComponent, app); + process.on("SIGINT", async () => { + logger.log("Received SIGINT signal. Shutting down gracefully..."); + await shutdown(serviceComponent, app); + process.exit(0); + }); + process.on("SIGTERM", async () => { + logger.log("Received SIGTERM signal. Shutting down gracefully..."); + await shutdown(serviceComponent, app); + process.exit(0); + }); +} diff --git a/packages/commons/src/util/timer-utils.ts b/packages/commons/src/util/timer-utils.ts new file mode 100644 index 0000000..a23b723 --- /dev/null +++ b/packages/commons/src/util/timer-utils.ts @@ -0,0 +1,17 @@ +import { createLogger, transports } from "winston"; + +const logger = createLogger({ + transports: [new transports.Console()] +}); + +export const timeFunction = async ( + func: () => Promise, + funcName = "Function" +) => { + const start = process.hrtime(); + const result = await func(); + const diff = process.hrtime(start); + const time = diff[0] * 1e3 + diff[1] / 1e6; // convert to milliseconds + logger.info(`${funcName} execution time: ${time} milliseconds`); + return result; +}; diff --git a/packages/commons/test/abort-controller/abort-controller.spec.ts b/packages/commons/test/abort-controller/abort-controller.spec.ts new file mode 100644 index 0000000..d38412e --- /dev/null +++ b/packages/commons/test/abort-controller/abort-controller.spec.ts @@ -0,0 +1,167 @@ +import { TimeoutAbortController } from "@zeroshotbuilders/commons"; + +describe("TimeoutAbortController", () => { + let setTimeoutSpy: jest.SpyInstance; + let clearTimeoutSpy: jest.SpyInstance; + + beforeEach(() => { + jest.useFakeTimers(); + setTimeoutSpy = jest.spyOn(global, "setTimeout"); + clearTimeoutSpy = jest.spyOn(global, "clearTimeout"); + }); + + afterEach(() => { + setTimeoutSpy.mockRestore(); + clearTimeoutSpy.mockRestore(); + jest.useRealTimers(); + }); + + describe("constructor", () => { + it("should create a new instance with an abort controller", () => { + const controller = new TimeoutAbortController(); + expect(controller).toBeDefined(); + expect(controller.signal).toBeDefined(); + expect(controller.signal.aborted).toBeFalsy(); + }); + }); + + describe("setTimeout", () => { + it("should set a timeout and return the signal", () => { + const controller = new TimeoutAbortController(); + const timeoutMs = 5000; + const signal = controller.setTimeout(timeoutMs); + expect(signal).toBeDefined(); + expect(signal.aborted).toBeFalsy(); + expect(setTimeoutSpy).toHaveBeenCalledTimes(1); + expect(setTimeoutSpy).toHaveBeenLastCalledWith(expect.any(Function), timeoutMs); + }); + + it("should clear any existing timeout when setting a new one", () => { + const controller = new TimeoutAbortController(); + const clearTimeoutSpy = jest.spyOn(controller, "clearTimeout"); + controller.setTimeout(5000); + controller.setTimeout(10000); + expect(clearTimeoutSpy).toHaveBeenCalledTimes(2); + }); + + it("should abort after the specified timeout", () => { + const controller = new TimeoutAbortController(); + const timeoutMs = 5000; + const signal = controller.setTimeout(timeoutMs); + jest.advanceTimersByTime(timeoutMs); + expect(signal.aborted).toBeTruthy(); + }); + }); + + describe("clearTimeout", () => { + it("should clear the timeout", () => { + const controller = new TimeoutAbortController(); + controller.setTimeout(5000); + controller.clearTimeout(); + expect(clearTimeoutSpy).toHaveBeenCalled(); + jest.advanceTimersByTime(10000); + expect(controller.signal.aborted).toBeFalsy(); + }); + + it("should do nothing if no timeout is set", () => { + const controller = new TimeoutAbortController(); + controller.clearTimeout(); + expect(clearTimeoutSpy).not.toHaveBeenCalled(); + }); + }); + + describe("signal getter", () => { + it("should return the abort signal", () => { + const controller = new TimeoutAbortController(); + const signal = controller.signal; + expect(signal).toBeDefined(); + expect(signal.aborted).toBeFalsy(); + }); + }); + + describe("abort", () => { + it("should abort the controller", () => { + const controller = new TimeoutAbortController(); + controller.abort(); + expect(controller.signal.aborted).toBeTruthy(); + }); + + it("should clear the timeout when aborting", () => { + const controller = new TimeoutAbortController(); + const clearTimeoutSpy = jest.spyOn(controller, "clearTimeout"); + controller.setTimeout(5000); + controller.abort(); + expect(clearTimeoutSpy).toHaveBeenCalled(); + }); + + it("should trigger the abort event", () => { + const controller = new TimeoutAbortController(); + const abortHandler = jest.fn(); + controller.signal.addEventListener("abort", abortHandler); + controller.abort(); + expect(abortHandler).toHaveBeenCalledTimes(1); + }); + }); + + describe("dispose", () => { + it("should clear the timeout", () => { + const controller = new TimeoutAbortController(); + const clearTimeoutSpy = jest.spyOn(controller, "clearTimeout"); + controller.setTimeout(5000); + controller.dispose(); + expect(clearTimeoutSpy).toHaveBeenCalled(); + }); + + it("should remove the abort event listener", () => { + const controller = new TimeoutAbortController(); + const removeEventListenerSpy = jest.spyOn(controller.signal, "removeEventListener"); + controller.dispose(); + expect(removeEventListenerSpy).toHaveBeenCalledWith("abort", expect.any(Function)); + }); + }); + + describe("withTimeout static method", () => { + it("should create a controller with a timeout", () => { + const timeoutMs = 5000; + const { controller, signal } = TimeoutAbortController.withTimeout(timeoutMs); + expect(controller).toBeInstanceOf(TimeoutAbortController); + expect(signal).toBeDefined(); + expect(signal.aborted).toBeFalsy(); + expect(setTimeoutSpy).toHaveBeenCalledTimes(1); + expect(setTimeoutSpy).toHaveBeenLastCalledWith(expect.any(Function), timeoutMs); + }); + + it("should abort after the specified timeout", () => { + const timeoutMs = 5000; + const { signal } = TimeoutAbortController.withTimeout(timeoutMs); + jest.advanceTimersByTime(timeoutMs); + expect(signal.aborted).toBeTruthy(); + }); + }); + + describe("integration tests", () => { + it("should handle a complete lifecycle", () => { + const controller = new TimeoutAbortController(); + const signal = controller.setTimeout(5000); + const abortHandler = jest.fn(); + signal.addEventListener("abort", abortHandler); + jest.advanceTimersByTime(2000); + expect(signal.aborted).toBeFalsy(); + expect(abortHandler).not.toHaveBeenCalled(); + controller.abort(); + expect(signal.aborted).toBeTruthy(); + expect(abortHandler).toHaveBeenCalledTimes(1); + controller.dispose(); + jest.advanceTimersByTime(10000); + expect(abortHandler).toHaveBeenCalledTimes(1); + }); + + it("should automatically clear timeout when aborted", () => { + const controller = new TimeoutAbortController(); + const clearTimeoutSpy = jest.spyOn(controller, "clearTimeout"); + controller.setTimeout(5000); + controller.abort(); + expect(clearTimeoutSpy).toHaveBeenCalled(); + }); + }); +}); diff --git a/packages/commons/test/assets/config.yaml b/packages/commons/test/assets/config.yaml new file mode 100644 index 0000000..9891d87 --- /dev/null +++ b/packages/commons/test/assets/config.yaml @@ -0,0 +1,9 @@ +local: true +port: 8080 +redis: + host: localhost +testingBullQueue: + attempts: 4 + backoff: + type: "exponential" + delay: 1 diff --git a/packages/commons/test/bull/bull-module.spec.ts b/packages/commons/test/bull/bull-module.spec.ts new file mode 100644 index 0000000..b57af90 --- /dev/null +++ b/packages/commons/test/bull/bull-module.spec.ts @@ -0,0 +1,97 @@ +import * as randomstring from "randomstring"; +import { + Closer, + ApplicationConfig, + RedisConnectionConfig +} from "@zeroshotbuilders/commons"; +import { BullTestingModule } from "./bull-testing-module"; +import { BullTestingService } from "./bull-testing-service"; +import { RedisContainer } from "@zeroshotbuilders/commons-testing"; +import { Test, TestingModule } from "@nestjs/testing"; +import { TestingBullWorker } from "./testing-bull-worker"; +import { JobScenario } from "./testing-bull-queue"; + +describe("BullMQ utils", () => { + let closer: Closer; + let redisContainer: RedisContainer; + let testingModule: TestingModule; + let bullService: BullTestingService; + + beforeAll(async () => { + redisContainer = new RedisContainer(); + await redisContainer.start(); + closer = Closer.create({ + resource: redisContainer, + closingFunction: (redisContainer: RedisContainer) => redisContainer.stop() + }); + testingModule = await Test.createTestingModule({ + providers: [BullTestingModule], + imports: [BullTestingModule] + }) + .overrideProvider(RedisConnectionConfig) + .useValue(redisContainer.getConnectionConfig()) + .overrideProvider(Closer) + .useValue(closer) + .overrideProvider(ApplicationConfig) + .useValue({ + applicationRoot: __dirname + }) + .compile(); + bullService = testingModule.get(BullTestingService); + }, 30000); + + afterAll(async () => { + await closer.close(); + }, 30000); + + it("bull job should retry and eventually succeed", async () => { + const inputData = randomstring.generate(); + const result = await bullService.doSomething({ + input: inputData, + scenario: JobScenario.RETRYABLE_ERROR, + succeedAfterAttempts: 2 + }); + expect(result.output).toEqual( + inputData + TestingBullWorker.PROCESSING_SUFFIX + ); + expect(result.attemptsMade).toEqual(2); + }); + + it("bull job should succeed", async () => { + const inputData = randomstring.generate(); + const result = await bullService.doSomething({ + input: inputData, + scenario: JobScenario.SUCCESS + }); + expect(result.output).toEqual( + inputData + TestingBullWorker.PROCESSING_SUFFIX + ); + expect(result.attemptsMade).toEqual(0); + }); + + it("bull job should fail on unrecoverable exception", async () => { + const inputData = randomstring.generate(); + try { + await bullService.doSomething({ + input: inputData, + scenario: JobScenario.UNRECOVERABLE_ERROR + }); + } catch (error) { + expect((error as Error).message).toEqual("GG"); + } + }); + + it("bull job should timeout", async () => { + const inputData = randomstring.generate(); + try { + await bullService.doSomething({ + input: inputData, + scenario: JobScenario.TIMEOUT, + timeout: 500 + }); + fail("Should have timed out"); + } catch (error: any) { + expect(error.message).toContain("timed out after 500ms"); + } + }); +}); diff --git a/packages/commons/test/bull/bull-testing-module.ts b/packages/commons/test/bull/bull-testing-module.ts new file mode 100644 index 0000000..ad0fae2 --- /dev/null +++ b/packages/commons/test/bull/bull-testing-module.ts @@ -0,0 +1,25 @@ +import { + BullModule, + ConfigModule, + RedisConnectionConfig +} from "@zeroshotbuilders/commons"; +import { Closer } from "@zeroshotbuilders/commons"; +import { BullTestingService } from "./bull-testing-service"; +import { Module } from "@nestjs/common"; +import { TestingBullQueue } from "./testing-bull-queue"; +import { TestingBullWorker } from "./testing-bull-worker"; + +@Module({ + providers: [ + TestingBullQueue, + TestingBullWorker, + BullTestingService, + RedisConnectionConfig, + Closer + ], + imports: [ + ConfigModule.forApplicationRoot(__dirname), + BullModule.forApplicationRoot(__dirname) + ] +}) +export class BullTestingModule {} diff --git a/packages/commons/test/bull/bull-testing-service.ts b/packages/commons/test/bull/bull-testing-service.ts new file mode 100644 index 0000000..c42a341 --- /dev/null +++ b/packages/commons/test/bull/bull-testing-service.ts @@ -0,0 +1,19 @@ +import { Injectable } from "@nestjs/common"; +import { + TestingBullJobRequest, + TestingBullJobResponse, + TestingBullQueue +} from "./testing-bull-queue"; + +@Injectable() +export class BullTestingService { + constructor(private testQueue: TestingBullQueue) {} + + public async doSomething( + request: TestingBullJobRequest + ): Promise { + return this.testQueue + .add(request) + .then((job) => job.waitUntilFinished(this.testQueue.getQueueEvents())); + } +} diff --git a/packages/commons/test/bull/bull-utils.spec.ts b/packages/commons/test/bull/bull-utils.spec.ts new file mode 100644 index 0000000..367b4fb --- /dev/null +++ b/packages/commons/test/bull/bull-utils.spec.ts @@ -0,0 +1,30 @@ +import { withCheckedExceptions } from "../../src/bull/bull-utils"; +import { ServerError, Status } from "nice-grpc"; +import { UnrecoverableError } from "bullmq"; + +describe("Bull utils", () => { + it("should return result", async () => { + const response = await withCheckedExceptions(async () => "rekt"); + expect(response).toEqual("rekt"); + }); + + it("should throw recoverable exception", async () => { + try { + await withCheckedExceptions(() => { + throw new ServerError(Status.INTERNAL, "Connection timeout"); + }); + } catch (error) { + expect(error).toBeInstanceOf(Error); + } + }); + + it("should throw unrecoverable exception for grpc errors", async () => { + try { + await withCheckedExceptions(() => { + throw new ServerError(Status.NOT_FOUND, "Customer not found"); + }); + } catch (error) { + expect(error).toBeInstanceOf(UnrecoverableError); + } + }); +}); diff --git a/packages/commons/test/bull/testing-bull-queue.ts b/packages/commons/test/bull/testing-bull-queue.ts new file mode 100644 index 0000000..b18db0e --- /dev/null +++ b/packages/commons/test/bull/testing-bull-queue.ts @@ -0,0 +1,44 @@ +import { BullQueue, ApplicationConfig } from "@zeroshotbuilders/commons"; +import { Injectable } from "@nestjs/common"; +import { RedisConnectionConfig } from "@zeroshotbuilders/commons"; +import { Closer } from "@zeroshotbuilders/commons"; + +export type TestingBullJobRequest = { + input: string; + scenario: JobScenario; + succeedAfterAttempts?: number; + timeout?: number; +}; + +export type TestingBullJobResponse = { + output: string; + attemptsMade: number; +}; + +export enum JobScenario { + RETRYABLE_ERROR, + UNRECOVERABLE_ERROR, + SUCCESS, + TIMEOUT +} + +export const TESTING_BULL_QUEUE = "testing-bull-queue"; + +@Injectable() +export class TestingBullQueue extends BullQueue< + TestingBullJobRequest, + TestingBullJobResponse +> { + constructor( + appConfig: ApplicationConfig, + redisConnectionConfig: RedisConnectionConfig, + closer: Closer + ) { + super( + appConfig.applicationRoot, + TESTING_BULL_QUEUE, + redisConnectionConfig, + closer + ); + } +} diff --git a/packages/commons/test/bull/testing-bull-worker.ts b/packages/commons/test/bull/testing-bull-worker.ts new file mode 100644 index 0000000..0f33731 --- /dev/null +++ b/packages/commons/test/bull/testing-bull-worker.ts @@ -0,0 +1,78 @@ +import { + BullWorker, + Closer, + RedisConnectionConfig +} from "@zeroshotbuilders/commons"; +import { Injectable } from "@nestjs/common"; +import { Job, UnrecoverableError } from "bullmq"; +import { + JobScenario, + TESTING_BULL_QUEUE, + TestingBullJobRequest, + TestingBullJobResponse +} from "./testing-bull-queue"; +import { match } from "ts-pattern"; + +@Injectable() +export class TestingBullWorker extends BullWorker< + TestingBullJobRequest, + TestingBullJobResponse +> { + public static readonly PROCESSING_SUFFIX = " - processed"; + + constructor(redisConnectionConfig: RedisConnectionConfig, closer: Closer) { + super(TESTING_BULL_QUEUE, redisConnectionConfig, closer); + } + + async run( + job: Job, + signal?: AbortSignal + ): Promise { + this.logger.info("Attempting to run a job", { + counter: job.attemptsMade + }); + return match(job.data.scenario) + .when( + (scenario) => scenario === JobScenario.RETRYABLE_ERROR, + (): TestingBullJobResponse => { + if (job.attemptsMade === job.data.succeedAfterAttempts) { + return { + output: job.data.input + TestingBullWorker.PROCESSING_SUFFIX, + attemptsMade: job.attemptsMade + }; + } + throw new Error("Transient error"); + } + ) + .when( + (scenario) => scenario === JobScenario.UNRECOVERABLE_ERROR, + () => { + throw new UnrecoverableError("GG"); + } + ) + .when( + (scenario) => scenario === JobScenario.TIMEOUT, + async () => { + await new Promise((resolve, reject) => { + const timeout = setTimeout(resolve, 10000); + signal?.addEventListener("abort", () => { + clearTimeout(timeout); + const err = new Error("AbortError"); + err.name = "AbortError"; + reject(err); + }); + }); + return { + output: job.data.input + TestingBullWorker.PROCESSING_SUFFIX, + attemptsMade: job.attemptsMade + }; + } + ) + .otherwise((): TestingBullJobResponse => { + return { + output: job.data.input + TestingBullWorker.PROCESSING_SUFFIX, + attemptsMade: job.attemptsMade + }; + }); + } +} diff --git a/packages/commons/test/config/config-utils.spec.ts b/packages/commons/test/config/config-utils.spec.ts new file mode 100644 index 0000000..eef4c98 --- /dev/null +++ b/packages/commons/test/config/config-utils.spec.ts @@ -0,0 +1,94 @@ +import * as randomstring from "randomstring"; +import { loadConfig, runWithEnv, randomInt } from "@zeroshotbuilders/commons"; + +interface TestConfig { + key1: number; + key2: string; + listLol: string[]; + nested: { + key3: string; + }; + moarNested: { + key4: number; + key5: { + key6: string; + }; + }; +} + +describe("loadConfig", () => { + it("should load a configuration file and return the correct object", () => { + const configPath = "./config/test-config.yaml"; + const config = loadConfig(__dirname, "", configPath); + expect(config).toEqual({ + key1: 1.01, + key2: "value2", + nested: { + key3: "value3" + }, + listLol: ["a", "b", "c"], + moarNested: { + key4: 2, + key5: { + key6: "value6" + } + } + }); + }); + + it("should load a configuration file and return the correct object when a config key is provided", () => { + const configPath = "./config/test-config.yaml"; + const config = loadConfig(__dirname, "moarNested", configPath); + expect(config).toEqual({ + key4: 2, + key5: { + key6: "value6" + } + }); + }); + + it("should load a configuration file and return the correct object when a nested config key is provided", () => { + const configPath = "./config/test-config.yaml"; + const config = loadConfig(__dirname, "moarNested.key5", configPath); + expect(config).toEqual({ + key6: "value6" + }); + }); + + it("should load a configuration file and override the values with env vars", () => { + const configPath = "./config/test-config.yaml"; + const key1Value = "23.1"; + const key6Value = randomstring.generate(); + const key4Value = randomInt(); + const key7Value = false; + const key8Value = true; + const key9Value = 0.75; + runWithEnv(() => { + const config = loadConfig(__dirname, "", configPath); + expect(config).toEqual({ + key1: key1Value, + key2: "value2", + nested: { + key3: "value3" + }, + listLol: ["a", "b", "c"], + moarNested: { + key4: key4Value, + key5: { + key6: key6Value + }, + key7: key7Value, + key8: key8Value, + key9: key9Value + } + }); + }, [ + ["app_key1", key1Value], + ["app_moarNested___key5___key6", key6Value], + ["app_moarNested___key4_numeric", key4Value.toString()], + ["app_moarNested___key7_boolean", key7Value.toString()], + ["app_moarNested___key8_boolean", key8Value.toString()], + ["app_moarNested___key9_numeric", "0.75"] + ]); + }); +}); diff --git a/packages/commons/test/config/test-config.yaml b/packages/commons/test/config/test-config.yaml new file mode 100644 index 0000000..cbfdd44 --- /dev/null +++ b/packages/commons/test/config/test-config.yaml @@ -0,0 +1,12 @@ +key1: 1.01 +key2: value2 +nested: + key3: value3 +moarNested: + key4: 2 + key5: + key6: value6 +listLol: + - a + - b + - c diff --git a/packages/commons/test/crypto/crypto-utils.spec.ts b/packages/commons/test/crypto/crypto-utils.spec.ts new file mode 100644 index 0000000..233ac3d --- /dev/null +++ b/packages/commons/test/crypto/crypto-utils.spec.ts @@ -0,0 +1,39 @@ +import {djb2Hash, hashString, randomBytes, sha256} from "@zeroshotbuilders/commons"; +import * as randomstring from "randomstring"; + +describe("hashing utils", () => { + it("should hash a string", async () => { + const input1 = randomstring.generate(10); + const input2 = randomstring.generate(10); + const hash1 = await hashString(input1); + const hash2 = await hashString(input2); + expect(hash1).toBeDefined(); + expect(hash2).toBeDefined(); + expect(hash1).not.toEqual(hash2); + }); + + it("should hash a string using djb2", () => { + const input1 = randomstring.generate(10); + const input2 = randomstring.generate(10); + const hash1 = djb2Hash(input1); + const hash2 = djb2Hash(input2); + expect(hash1).toBeDefined(); + expect(hash2).toBeDefined(); + expect(hash1).not.toEqual(hash2); + }); + + it("should hash a string using sha256", () => { + const input = randomstring.generate(10); + const hash = sha256(input); + expect(hash).toBeDefined(); + expect(hash.length).toEqual(64); + }); + + it("should properly generate random bytes", () => { + const bytes1 = randomBytes(32); + const bytes2 = randomBytes(32); + expect(bytes1.length).toEqual(64); + expect(bytes2.length).toEqual(64); + expect(bytes1).not.toEqual(bytes2); + }); +}); diff --git a/packages/commons/test/decorators/is-safe-string.spec.ts b/packages/commons/test/decorators/is-safe-string.spec.ts new file mode 100644 index 0000000..ead0663 --- /dev/null +++ b/packages/commons/test/decorators/is-safe-string.spec.ts @@ -0,0 +1,53 @@ +import { validate } from "class-validator"; +import { IsSafeString } from "../../src/decorators/is-safe-string"; + +class TestClass { + @IsSafeString() + text: string; + + constructor(text: string) { + this.text = text; + } +} + +describe("IsSafeString", () => { + it("should pass validation for normal strings", async () => { + const normalStrings = [ + "This is a normal string", + "This contains the word http but not as a link", + "This contains the word www but not as a link", + "This contains square brackets [] but not as a markdown link", + "This contains parentheses () but not as a markdown link", + "This contains both [] and () but not together like []() for a markdown link" + ]; + for (const str of normalStrings) { + const testObj = new TestClass(str); + const errors = await validate(testObj); + expect(errors.length).toBe(0); + } + }); + + it("should fail validation for strings with malicious links", async () => { + const maliciousStrings = [ + "Check out http://example.com", + "Visit https://example.com for more info", + "Go to www.example.com", + "Click here", + "This has an HTML tag link", + "This has an href attribute href='example.com'", + "This has a markdown link [click here](http://example.com)" + ]; + for (const str of maliciousStrings) { + const testObj = new TestClass(str); + const errors = await validate(testObj); + expect(errors.length).toBeGreaterThan(0); + expect(errors[0].constraints?.["isSafeString"]).toBeDefined(); + } + }); + + it("should pass validation for non-string values", async () => { + const testObj = new TestClass(null as any); + const errors = await validate(testObj); + expect(errors.length).toBe(0); + }); +}); diff --git a/packages/commons/test/ip/ip-utils.spec.ts b/packages/commons/test/ip/ip-utils.spec.ts new file mode 100644 index 0000000..5add6a2 --- /dev/null +++ b/packages/commons/test/ip/ip-utils.spec.ts @@ -0,0 +1,47 @@ +import { + isIpInCidrBlock, + isValidIpCidrBlock, + parseIpAddressFromXForwardedFor +} from "../../src/ip/ip-utils"; + +test("should parse ip addresses from x-forwarded-for correctly", () => { + expect(parseIpAddressFromXForwardedFor("10.10.100.1")).toEqual("10.10.100.1"); + expect(parseIpAddressFromXForwardedFor("111.255.255.255")).toEqual("111.255.255.255"); + expect(parseIpAddressFromXForwardedFor("111.255.255.256")).toEqual(undefined); + expect(parseIpAddressFromXForwardedFor("10.10.100.1,10.10.100.2")).toEqual("10.10.100.1"); + expect(parseIpAddressFromXForwardedFor("10.10.100.1,garbage")).toEqual("10.10.100.1"); + expect(parseIpAddressFromXForwardedFor("2")).toEqual(undefined); + expect(parseIpAddressFromXForwardedFor("10.10.10.10.10.10.10")).toEqual(undefined); + expect(parseIpAddressFromXForwardedFor("2,10.10.100.1")).toEqual(undefined); +}); + +test("should validate IP CIDR blocks correctly", () => { + expect(isValidIpCidrBlock("192.168.1.0/24")).toBe(true); + expect(isValidIpCidrBlock("10.0.0.0/8")).toBe(true); + expect(isValidIpCidrBlock("0.0.0.0/0")).toBe(true); + expect(isValidIpCidrBlock("255.255.255.255/32")).toBe(true); + expect(isValidIpCidrBlock("192.168.1.0")).toBe(false); + expect(isValidIpCidrBlock("192.168.1.0/33")).toBe(false); + expect(isValidIpCidrBlock("256.168.1.0/24")).toBe(false); + expect(isValidIpCidrBlock("192.168.1.0/-1")).toBe(false); + expect(isValidIpCidrBlock("not a cidr")).toBe(false); + expect(isValidIpCidrBlock(null)).toBe(false); + expect(isValidIpCidrBlock(undefined)).toBe(false); + expect(isValidIpCidrBlock("")).toBe(false); +}); + +test("should check if an IP is within a CIDR block correctly", () => { + expect(isIpInCidrBlock("192.168.1.100", "192.168.1.0/24")).toBe(true); + expect(isIpInCidrBlock("10.10.10.10", "10.0.0.0/8")).toBe(true); + expect(isIpInCidrBlock("172.16.0.1", "172.16.0.0/16")).toBe(true); + expect(isIpInCidrBlock("192.168.1.1", "192.168.1.1/32")).toBe(true); + expect(isIpInCidrBlock("8.8.8.8", "0.0.0.0/0")).toBe(true); + expect(isIpInCidrBlock("192.168.2.1", "192.168.1.0/24")).toBe(false); + expect(isIpInCidrBlock("11.0.0.1", "10.0.0.0/8")).toBe(false); + expect(isIpInCidrBlock("192.168.1.2", "192.168.1.1/32")).toBe(false); + expect(isIpInCidrBlock("not-an-ip", "192.168.1.0/24")).toBe(false); + expect(isIpInCidrBlock("192.168.1.100", "not-a-cidr")).toBe(false); + expect(isIpInCidrBlock("not-an-ip", "not-a-cidr")).toBe(false); + expect(isIpInCidrBlock(null, "192.168.1.0/24")).toBe(false); + expect(isIpInCidrBlock("192.168.1.100", undefined)).toBe(false); +}); diff --git a/packages/commons/test/port/port-utils.spec.ts b/packages/commons/test/port/port-utils.spec.ts new file mode 100644 index 0000000..155cc3a --- /dev/null +++ b/packages/commons/test/port/port-utils.spec.ts @@ -0,0 +1,33 @@ +import { List } from "immutable"; +import { findOpenPort } from "@zeroshotbuilders/commons"; +import net from "net"; + +describe("findOpenPort", () => { + let servers: List = List(); + + beforeAll((done) => { + const blockedPorts = List([7080, 7081, 7082]); + let remainingPorts = blockedPorts.size; + blockedPorts.forEach((port) => { + const server = net.createServer(); + server.listen(port, () => { + remainingPorts--; + if (remainingPorts === 0) { + done(); + } + }); + servers = servers.push(server); + }); + }); + + afterAll(() => { + servers.forEach((server) => { + server.close(); + }); + }); + + test("should find 8083 as the first open port", async () => { + const openPort = await findOpenPort({ minPort: 7080, maxPort: 7085 }); + expect(openPort).toEqual(7083); + }); +}); diff --git a/packages/commons/test/redis/redis-connection-module.spec.ts b/packages/commons/test/redis/redis-connection-module.spec.ts new file mode 100644 index 0000000..c3e55b6 --- /dev/null +++ b/packages/commons/test/redis/redis-connection-module.spec.ts @@ -0,0 +1,100 @@ +import { + Closer, + ConfigModule, + ApplicationConfig, + REDIS_CLIENT, + RedisConnectionConfig, + RedisConnectionModule, + RedisClientPool, + randomInt +} from "@zeroshotbuilders/commons"; +import { RedisContainer, timeout } from "@zeroshotbuilders/commons-testing"; +import { Test, TestingModule } from "@nestjs/testing"; +import * as randomstring from "randomstring"; +import { RedisClientType } from "redis"; + +describe("Redis module", () => { + let testModule: TestingModule; + let closer: Closer; + let redisClient: RedisClientType; + let redisClientPool: RedisClientPool; + beforeAll(async () => { + const redisContainer = new RedisContainer(); + await redisContainer.start(); + testModule = await Test.createTestingModule({ + imports: [ + RedisConnectionModule.forApplicationRoot(__dirname), + ConfigModule.forApplicationRoot(__dirname) + ] + }) + .overrideProvider(RedisConnectionConfig) + .useValue(redisContainer.getConnectionConfig()) + .overrideProvider(Closer) + .useValue(closer) + .overrideProvider(ApplicationConfig) + .useValue({ + applicationRoot: __dirname + }) + .compile(); + closer = testModule.get(Closer); + redisClient = testModule.get(REDIS_CLIENT); + redisClientPool = testModule.get(RedisClientPool); + closer.registerShutdownHook({ + resource: redisContainer, + closingFunction: async (redisContainer: RedisContainer) => + await redisContainer.stop() + }); + }, 20000); + + afterAll(async () => { + if (closer) await closer.close(); + }); + + it("should fail when a value cannot be set due to a change", async () => { + const key = randomstring.generate(); + const val1 = randomstring.generate(); + await redisClient.set(key, val1); + await redisClient.watch(key); + const val2 = randomstring.generate(); + const multi = redisClient.multi().set(key, val2); + await redisClient.set(key, val2); + await expect(multi.exec()).rejects.toThrow(); + }); + + it("should fail when a value is changed by another client", async () => { + const key = randomstring.generate(); + const val1 = randomstring.generate(); + await redisClientPool.withConnection((client) => client.set(key, val1)); + const results = []; + const val2 = randomstring.generate(); + const val3 = randomstring.generate(); + for (let i = 0; i < 10; i++) { + const [resultOne, _] = await Promise.allSettled([ + redisClientPool.withConnection(async (client) => { + await client.watch(key); + const multi = client.multi().set(key, val2); + await timeout(randomInt(0, 500)); + const [result] = await multi.exec(); + return result; + }), + redisClientPool.withConnection(async (client) => { + await client.unwatch(); + const multi = client.multi().set(key, val3); + await timeout(randomInt(0, 500)); + const [result] = await multi.exec(); + return result; + }) + ]); + results.push(resultOne); + } + const rejectedPromises = results.filter( + (promise) => promise.status === "rejected" + ); + expect(rejectedPromises.length).toBeGreaterThan(0); + const [rejection] = rejectedPromises; + expect(rejection).toEqual({ + reason: new Error("One (or more) of the watched keys has been changed"), + status: "rejected" + }); + }); +}); diff --git a/packages/commons/test/util/not-empty.spec.ts b/packages/commons/test/util/not-empty.spec.ts new file mode 100644 index 0000000..747cda4 --- /dev/null +++ b/packages/commons/test/util/not-empty.spec.ts @@ -0,0 +1,25 @@ +import { notEmpty } from "@zeroshotbuilders/commons"; + +enum LolEnum { + UNKNOWN_LOL = "unknown_lol", + BIG_LOL = "big_lol" +} + +describe("notEmpty", () => { + it("should return true if value is set", () => { + const stringValue = "lol"; + expect(notEmpty(stringValue)).toBeTruthy(); + const enumValue = LolEnum.BIG_LOL; + expect(notEmpty(enumValue)).toBeTruthy(); + const numberValue = 3; + expect(notEmpty(numberValue)).toBeTruthy(); + }); + + it("should return false if value is not set", () => { + expect(notEmpty("")).toBeFalsy(); + expect(notEmpty(0)).toBeFalsy(); + expect(notEmpty(undefined)).toBeFalsy(); + expect(notEmpty(null)).toBeFalsy(); + expect(notEmpty(LolEnum.UNKNOWN_LOL)).toBeFalsy(); + }); +}); diff --git a/packages/commons/tsconfig.json b/packages/commons/tsconfig.json new file mode 100644 index 0000000..46167d5 --- /dev/null +++ b/packages/commons/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc" + }, + "files": [], + "include": [], + "references": [ + { "path": "./tsconfig.lib.json" }, + { "path": "./tsconfig.spec.json" } + ] +} diff --git a/packages/commons/tsconfig.lib.json b/packages/commons/tsconfig.lib.json new file mode 100644 index 0000000..e927de6 --- /dev/null +++ b/packages/commons/tsconfig.lib.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "declaration": true, + "types": ["node", "reflect-metadata"] + }, + "include": ["index.ts", "src/**/*.ts"], + "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] +} diff --git a/packages/commons/tsconfig.spec.json b/packages/commons/tsconfig.spec.json new file mode 100644 index 0000000..3835753 --- /dev/null +++ b/packages/commons/tsconfig.spec.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node", "reflect-metadata"] + }, + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.d.ts", + "test/**/*.ts" + ] +} diff --git a/packages/openai-utils/.eslintrc.json b/packages/openai-utils/.eslintrc.json new file mode 100644 index 0000000..f1ff0d9 --- /dev/null +++ b/packages/openai-utils/.eslintrc.json @@ -0,0 +1,10 @@ +{ + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "rules": {} + } + ] +} diff --git a/packages/openai-utils/index.ts b/packages/openai-utils/index.ts new file mode 100644 index 0000000..ec7b102 --- /dev/null +++ b/packages/openai-utils/index.ts @@ -0,0 +1,6 @@ +export const OPENAI_APPLICATION_ROOT = "OpenAIApplicationRoot"; +export * from "./src/openai-client-module"; +export * from "./src/openai-client-factory"; +export * from "./src/service/conversion/openai-service-local"; +export * from "./src/service/conversion/openai-service-remote"; +export * from "./src/service/conversion/openai-service"; diff --git a/packages/openai-utils/jest.config.ts b/packages/openai-utils/jest.config.ts new file mode 100644 index 0000000..46ee0df --- /dev/null +++ b/packages/openai-utils/jest.config.ts @@ -0,0 +1,10 @@ +export default { + displayName: "openai-utils", + preset: "../../jest.preset.js", + testEnvironment: "node", + transform: { + "^.+\\.[tj]s$": ["ts-jest", { tsconfig: "/tsconfig.spec.json" }] + }, + moduleFileExtensions: ["ts", "js", "html"], + coverageDirectory: "../../coverage/packages/openai-utils" +}; diff --git a/packages/openai-utils/package.json b/packages/openai-utils/package.json new file mode 100644 index 0000000..4f0eb9a --- /dev/null +++ b/packages/openai-utils/package.json @@ -0,0 +1,18 @@ +{ + "name": "@zeroshotbuilders/openai-utils", + "version": "0.0.1", + "type": "commonjs", + "main": "./src/index.ts", + "publishConfig": { + "main": "./index.js", + "types": "./index.d.ts", + "access": "public" + }, + "dependencies": { + "openai": "^4.77.0" + }, + "peerDependencies": { + "@nestjs/common": ">=10.0.0", + "@zeroshotbuilders/commons": ">=0.0.1" + } +} diff --git a/packages/openai-utils/project.json b/packages/openai-utils/project.json new file mode 100644 index 0000000..b41d4c2 --- /dev/null +++ b/packages/openai-utils/project.json @@ -0,0 +1,29 @@ +{ + "name": "openai-utils", + "sourceRoot": "packages/openai-utils/src", + "projectType": "library", + "targets": { + "build": { + "executor": "@nx/js:tsc", + "options": { + "outputPath": "dist/packages/openai-utils", + "main": "packages/openai-utils/src/index.ts", + "tsConfig": "packages/openai-utils/tsconfig.lib.json" + } + }, + "test": { + "executor": "@nx/jest:jest", + "options": { + "jestConfig": "packages/openai-utils/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": ["packages/openai-utils/**/*.ts"] + } + } + }, + "tags": [] +} diff --git a/packages/openai-utils/src/config/openai-client-config.ts b/packages/openai-utils/src/config/openai-client-config.ts new file mode 100644 index 0000000..dd8efb5 --- /dev/null +++ b/packages/openai-utils/src/config/openai-client-config.ts @@ -0,0 +1,20 @@ +import { ApplicationConfig, loadConfig } from "@zeroshotbuilders/commons"; +import { Injectable } from "@nestjs/common"; + +@Injectable() +export class OpenaiClientConfig { + private static readonly CONFIG_KEY = "openai"; + + readonly apiToken: string; + + constructor(applicationConfig: ApplicationConfig) { + const config = loadConfig( + applicationConfig.applicationRoot, + OpenaiClientConfig.CONFIG_KEY + ); + + return { + apiToken: config.apiToken + }; + } +} diff --git a/packages/openai-utils/src/openai-client-factory.ts b/packages/openai-utils/src/openai-client-factory.ts new file mode 100644 index 0000000..2669d90 --- /dev/null +++ b/packages/openai-utils/src/openai-client-factory.ts @@ -0,0 +1,23 @@ +import { ApplicationConfig } from "@zeroshotbuilders/commons"; +import { + OpenaiService, + OpenaiServiceLocal, + OpenaiServiceRemote +} from "@zeroshotbuilders/openai-utils"; +import { Injectable } from "@nestjs/common"; +import { OpenaiClientConfig } from "./config/openai-client-config"; + +@Injectable() +export class OpenaiClientFactory { + constructor( + private readonly applicationConfig: ApplicationConfig, + private readonly config: OpenaiClientConfig + ) {} + + public makeOpenaiService(): OpenaiService { + if (this.applicationConfig.local) { + return OpenaiServiceLocal.getInstance(); + } + return new OpenaiServiceRemote(this.config); + } +} diff --git a/packages/openai-utils/src/openai-client-module.ts b/packages/openai-utils/src/openai-client-module.ts new file mode 100644 index 0000000..38c4864 --- /dev/null +++ b/packages/openai-utils/src/openai-client-module.ts @@ -0,0 +1,31 @@ +import { ConfigModule } from "@zeroshotbuilders/commons"; +import { DynamicModule, Module } from "@nestjs/common"; +import { OPENAI_APPLICATION_ROOT, OpenaiClientFactory } from "../index"; +import { OpenaiClientConfig } from "./config/openai-client-config"; + +export const OPENAI_CLIENT = "OPENAI_CLIENT"; + +@Module({}) +export class OpenaiClientModule { + public static forApplicationRoot(applicationRoot: string): DynamicModule { + return { + module: OpenaiClientModule, + imports: [ConfigModule.forApplicationRoot(applicationRoot)], + providers: [ + { + provide: OPENAI_APPLICATION_ROOT, + useValue: applicationRoot + }, + OpenaiClientConfig, + OpenaiClientFactory, + { + provide: OPENAI_CLIENT, + useFactory: (openaiClientFactory: OpenaiClientFactory) => + openaiClientFactory.makeOpenaiService(), + inject: [OpenaiClientFactory] + } + ], + exports: [OPENAI_CLIENT] + }; + } +} diff --git a/packages/openai-utils/src/service/conversion/openai-service-local.ts b/packages/openai-utils/src/service/conversion/openai-service-local.ts new file mode 100644 index 0000000..cefb3fb --- /dev/null +++ b/packages/openai-utils/src/service/conversion/openai-service-local.ts @@ -0,0 +1,69 @@ +import * as randomstring from "randomstring"; +import { ChatResponse, OpenaiService, Prompt } from "./openai-service"; + +export class OpenaiServiceLocal implements OpenaiService { + private static instance: OpenaiServiceLocal = new OpenaiServiceLocal(); + private static responsesByPromptSubstring: Map = new Map(); + private static errorCountsByPromptSubstring: Map = new Map(); + + public static getInstance() { + return OpenaiServiceLocal.instance; + } + + public static setResponse(promptSubstring: string, response: string): void { + this.responsesByPromptSubstring.set(promptSubstring, response); + } + + public static setError(promptSubstring: string, count: number): void { + this.errorCountsByPromptSubstring.set(promptSubstring, count); + } + + public static clearResponses(): void { + this.responsesByPromptSubstring.clear(); + } + + public static clearErrors(): void { + this.errorCountsByPromptSubstring.clear(); + } + + private static promptText(prompt: Prompt): string { + return `${prompt.systemPrompt ?? ""} ${prompt.message ?? ""}`; + } + + private static shouldErrorForPrompt(prompt: Prompt): boolean { + const text = this.promptText(prompt); + for (const [substring, remaining] of this.errorCountsByPromptSubstring) { + if (substring && text.includes(substring) && remaining > 0) { + const nextRemaining = remaining - 1; + if (nextRemaining > 0) { + this.errorCountsByPromptSubstring.set(substring, nextRemaining); + } else { + this.errorCountsByPromptSubstring.set(substring, 0); + } + return true; + } + } + return false; + } + + private static responseForPrompt(prompt: Prompt): string | undefined { + const text = this.promptText(prompt); + for (const [substring, response] of this.responsesByPromptSubstring) { + if (substring && text.includes(substring)) { + return response; + } + } + return undefined; + } + + async chatCompletion(prompt: Prompt): Promise { + if (OpenaiServiceLocal.shouldErrorForPrompt(prompt)) { + return Promise.resolve(ChatResponse.forException()); + } + const keyed = OpenaiServiceLocal.responseForPrompt(prompt); + if (keyed !== undefined) { + return Promise.resolve(new ChatResponse(keyed)); + } + return Promise.resolve(new ChatResponse(randomstring.generate(10))); + } +} diff --git a/packages/openai-utils/src/service/conversion/openai-service-remote.ts b/packages/openai-utils/src/service/conversion/openai-service-remote.ts new file mode 100644 index 0000000..4d21d44 --- /dev/null +++ b/packages/openai-utils/src/service/conversion/openai-service-remote.ts @@ -0,0 +1,28 @@ +import { OpenAI } from "openai"; +import { createLogger, transports } from "winston"; +import { OpenaiClientConfig } from "../../config/openai-client-config"; +import { ChatResponse, OpenaiService, Prompt } from "./openai-service"; + +export class OpenaiServiceRemote implements OpenaiService { + private readonly logger = createLogger({ + transports: [new transports.Console()] + }); + private readonly client: OpenAI; + + constructor(private readonly config: OpenaiClientConfig) { + this.client = new OpenAI({ + apiKey: config.apiToken + }); + } + + public async chatCompletion(prompt: Prompt): Promise { + try { + const request = prompt.toChatRequest(prompt.model, prompt.temperature); + const response = await this.client.chat.completions.create(request); + return ChatResponse.forCompletion(response); + } catch (error) { + this.logger.error("Error completing chat request", error); + return new ChatResponse(undefined); + } + } +} diff --git a/packages/openai-utils/src/service/conversion/openai-service.ts b/packages/openai-utils/src/service/conversion/openai-service.ts new file mode 100644 index 0000000..bb8b795 --- /dev/null +++ b/packages/openai-utils/src/service/conversion/openai-service.ts @@ -0,0 +1,59 @@ +import { + ChatCompletion, + ChatCompletionCreateParamsNonStreaming +} from "openai/resources/chat/completions"; + +export interface OpenaiService { + chatCompletion(prompt: Prompt): Promise; +} + +export class Prompt { + constructor( + public readonly systemPrompt: string, + public readonly message: string, + public readonly model: string = "gpt-4o", + public readonly temperature: number = 0.8 + ) {} + + public static forValues( + systemPrompt: string, + message: string, + model?: string, + temperature?: number + ): Prompt { + return new Prompt(systemPrompt, message, model, temperature); + } + + public toChatRequest( + model: string, + temperature = 0 + ): ChatCompletionCreateParamsNonStreaming { + return { + model: model, + temperature: model === "gpt-5" ? undefined : temperature, + messages: [ + { + role: "system", + content: this.systemPrompt + }, + { + role: "user", + content: this.message + } + ] + }; + } +} + +export class ChatResponse { + constructor(public readonly completion: string | undefined) {} + + public static forCompletion(completion: ChatCompletion): ChatResponse { + const choice = completion?.choices[0]?.message?.content; + return new ChatResponse(choice); + } + + public static forException(): ChatResponse { + return new ChatResponse(undefined); + } +} diff --git a/packages/openai-utils/test/client-factory.ts b/packages/openai-utils/test/client-factory.ts new file mode 100644 index 0000000..7fb0e13 --- /dev/null +++ b/packages/openai-utils/test/client-factory.ts @@ -0,0 +1,26 @@ +import { ApplicationConfig } from "@zeroshotbuilders/commons"; +import { + OPENAI_CLIENT, + OpenaiClientModule, + OpenaiService +} from "@zeroshotbuilders/openai-utils"; +import { Test } from "@nestjs/testing"; +import { OpenaiClientConfig } from "../src/config/openai-client-config"; + +export const createLocalOpenaiService = async (): Promise => { + const testingModule = await Test.createTestingModule({ + imports: [OpenaiClientModule.forApplicationRoot("")] + }) + .overrideProvider(ApplicationConfig) + .useValue({ + local: true + }) + .overrideProvider(OpenaiClientConfig) + .useValue({ + apiToken: "test-token", + model: "test-model", + temperature: 1 + }) + .compile(); + return testingModule.get(OPENAI_CLIENT); +}; diff --git a/packages/openai-utils/test/service/openai-client.spec.ts b/packages/openai-utils/test/service/openai-client.spec.ts new file mode 100644 index 0000000..b480d8d --- /dev/null +++ b/packages/openai-utils/test/service/openai-client.spec.ts @@ -0,0 +1,78 @@ +import { + OpenaiService, + OpenaiServiceLocal, + Prompt +} from "@zeroshotbuilders/openai-utils"; +import { createLocalOpenaiService } from "../client-factory"; + +const JSON_RESPONSE = ` +{ + "questions": [ + { + "question": "Best Denver craft brewery?", + "options": ["Great Divide", "Denver Beer Co", "Wynkoop", "Odell"] + }, + { + "question": "Favorite Denver sports team?", + "options": ["Broncos", "Nuggets", "Avalanche", "Rockies"] + } + ] +}`; + +describe("OpenAI Client", () => { + let client: OpenaiService; + + beforeAll(async () => { + client = await createLocalOpenaiService(); + }); + + beforeEach(() => { + OpenaiServiceLocal.clearErrors(); + OpenaiServiceLocal.clearResponses(); + }); + + it("should generate a chat response", async () => { + const prompt = Prompt.forValues( + "You are a chatbot. You are helping a user with a question. The user asks:", + "What is the meaning of life, the universe, and everything?" + ); + const response = await client.chatCompletion(prompt); + expect(response.completion).toBeDefined(); + expect(response.completion).not.toEqual(""); + }); + + it("should return undefined on error", async () => { + OpenaiServiceLocal.setError("chatbot", 1); + const prompt = Prompt.forValues( + "You are a chatbot. You are helping a user with a question. The user asks:", + "What is the meaning of life, the universe, and everything?" + ); + const response1 = await client.chatCompletion(prompt); + expect(response1.completion).toBeUndefined(); + const response2 = await client.chatCompletion(prompt); + expect(response2.completion).toBeDefined(); + }); + + it("should return json when i ask it to", async () => { + OpenaiServiceLocal.setResponse("json", JSON_RESPONSE); + const prompt = Prompt.forValues("Give me json plz", "Denver, CO"); + const response = await client.chatCompletion(prompt); + expect(response.completion).toBeDefined(); + const value = JSON.parse(response.completion); + expect(value.questions).toHaveLength(2); + }); + + it("should error n times before returning a response", async () => { + OpenaiServiceLocal.setError("json", 3); + OpenaiServiceLocal.setResponse("json", JSON_RESPONSE); + const prompt = Prompt.forValues("Give me json plz", "Denver, CO"); + const response1 = await client.chatCompletion(prompt); + expect(response1.completion).toBeUndefined(); + const response2 = await client.chatCompletion(prompt); + expect(response2.completion).toBeUndefined(); + const response3 = await client.chatCompletion(prompt); + expect(response3.completion).toBeUndefined(); + const response4 = await client.chatCompletion(prompt); + expect(response4.completion).toBeDefined(); + }); +}); diff --git a/packages/openai-utils/tsconfig.json b/packages/openai-utils/tsconfig.json new file mode 100644 index 0000000..46167d5 --- /dev/null +++ b/packages/openai-utils/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc" + }, + "files": [], + "include": [], + "references": [ + { "path": "./tsconfig.lib.json" }, + { "path": "./tsconfig.spec.json" } + ] +} diff --git a/packages/openai-utils/tsconfig.lib.json b/packages/openai-utils/tsconfig.lib.json new file mode 100644 index 0000000..e927de6 --- /dev/null +++ b/packages/openai-utils/tsconfig.lib.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "declaration": true, + "types": ["node", "reflect-metadata"] + }, + "include": ["index.ts", "src/**/*.ts"], + "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] +} diff --git a/packages/openai-utils/tsconfig.spec.json b/packages/openai-utils/tsconfig.spec.json new file mode 100644 index 0000000..3835753 --- /dev/null +++ b/packages/openai-utils/tsconfig.spec.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node", "reflect-metadata"] + }, + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.d.ts", + "test/**/*.ts" + ] +} diff --git a/packages/sql-decorators/.eslintrc.json b/packages/sql-decorators/.eslintrc.json new file mode 100644 index 0000000..f1ff0d9 --- /dev/null +++ b/packages/sql-decorators/.eslintrc.json @@ -0,0 +1,10 @@ +{ + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "rules": {} + } + ] +} diff --git a/packages/sql-decorators/index.ts b/packages/sql-decorators/index.ts new file mode 100644 index 0000000..f24280a --- /dev/null +++ b/packages/sql-decorators/index.ts @@ -0,0 +1,3 @@ +export * from "./src/decorators"; +export * from "./src/result/result-types"; +export * from "./src/stream-iterator"; diff --git a/packages/sql-decorators/jest.config.ts b/packages/sql-decorators/jest.config.ts new file mode 100644 index 0000000..3bb475f --- /dev/null +++ b/packages/sql-decorators/jest.config.ts @@ -0,0 +1,10 @@ +export default { + displayName: "sql-decorators", + preset: "../../jest.preset.js", + testEnvironment: "node", + transform: { + "^.+\\.[tj]s$": ["ts-jest", { tsconfig: "/tsconfig.spec.json" }] + }, + moduleFileExtensions: ["ts", "js", "html"], + coverageDirectory: "../../coverage/packages/sql-decorators" +}; diff --git a/packages/sql-decorators/package.json b/packages/sql-decorators/package.json new file mode 100644 index 0000000..377dd37 --- /dev/null +++ b/packages/sql-decorators/package.json @@ -0,0 +1,18 @@ +{ + "name": "@zeroshotbuilders/sql-decorators", + "version": "0.0.1", + "type": "commonjs", + "main": "./src/index.ts", + "publishConfig": { + "main": "./index.js", + "types": "./index.d.ts", + "access": "public" + }, + "dependencies": { + "reflect-metadata": "^0.2.0", + "sequelize": "^6.37.0" + }, + "peerDependencies": { + "@zeroshotbuilders/commons": ">=0.0.1" + } +} diff --git a/packages/sql-decorators/project.json b/packages/sql-decorators/project.json new file mode 100644 index 0000000..5223462 --- /dev/null +++ b/packages/sql-decorators/project.json @@ -0,0 +1,29 @@ +{ + "name": "sql-decorators", + "sourceRoot": "packages/sql-decorators/src", + "projectType": "library", + "targets": { + "build": { + "executor": "@nx/js:tsc", + "options": { + "outputPath": "dist/packages/sql-decorators", + "main": "packages/sql-decorators/src/index.ts", + "tsConfig": "packages/sql-decorators/tsconfig.lib.json" + } + }, + "test": { + "executor": "@nx/jest:jest", + "options": { + "jestConfig": "packages/sql-decorators/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": ["packages/sql-decorators/**/*.ts"] + } + } + }, + "tags": [] +} diff --git a/packages/sql-decorators/src/decorators.ts b/packages/sql-decorators/src/decorators.ts new file mode 100644 index 0000000..eb1352e --- /dev/null +++ b/packages/sql-decorators/src/decorators.ts @@ -0,0 +1,235 @@ +import { Injectable } from "@nestjs/common"; +import { + QueryTypes, + Sequelize, + Transaction, + TransactionOptions +} from "sequelize"; +import { createLogger, transports } from "winston"; +import { Query } from "./query/query"; +import { QueryParameterMapper } from "./query/query-parameter-mapper"; +import { QueryRunner } from "./query/query-runner"; +import { ResultMapper } from "./result/result-mapper"; +import { StreamIterator } from "./stream-iterator"; + +const logger = createLogger({ + transports: [new transports.Console()] +}); + +/** + * Customizable options for specifying DAOs + * - queryDirectory (optional): the directory to look for queries in. If not specified, then each individual method + * must specify the query to execute. Should use `__dirname` to specify the directory so that it's relative to + * the DAO class. + */ +export type DaoOptions = { + queryDirectory?: string; +}; + +/** + * Decorator for a Data Access Object (DAO) class that contains SQL queries + * @param options the class-namespaced options for the DAO + * @constructor + */ +export function Dao(options?: DaoOptions): ClassDecorator { + return function (target: any) { + target.prototype.initialized = true; + target.prototype.options = options; + }; +} + +/** + * The base class that handles dependency injection of the Sequelize instance + */ +@Injectable() +export class DaoBase { + private options?: DaoOptions; + private initialized?: boolean; + private sequelize: Sequelize; + + constructor(sequelize: Sequelize) { + this.sequelize = sequelize; + } +} + +/** + * Decorator for any class that wants to initialize a SqlTransaction. + * This will generally be used on "Repositories" that need to initiate multi-DAO transactions. + * @constructor + */ +export function WithTransactionality(): ClassDecorator { + return function (target: any) { + target.prototype.initialized = true; + }; +} + +/** + * The base class for repositories that handles dependency injection of the Sequelize instance. + * This will generally be used on "Repositories" that need to initiate multi-DAO transactions. + */ +@Injectable() +export class TransactionalityBase { + private initialized?: boolean; + private sequelize: Sequelize; + + constructor(sequelize: Sequelize) { + this.sequelize = sequelize; + } +} + +/** + * A type to specify class constructors. + */ +export type Clazz = new (...args: any[]) => T; + +/** + * Customizable options for specifying SQL queries: + * - (required): the class of DTO that any queries returns + * - queryType (required): the type of query to execute (e.g. SELECT, INSERT, UPDATE, etc...) + * - clazz (optional): the class constructor to map the query results to. If not specified, then T is assumed to be a `type` or `void` (i.e. a plain object) + * - returnList (optional): whether the query returns a list of results (needed for runtime mapping of empty lists) + * - query (optional): If present, the query to execute. + * - file (optional): If present, the file to read the query from. Should use `__dirname` to specify the directory so that it's relative to the DAO class. + * If none of these are present, then the query is assumed to live in a file with the same name as the method + * within the directory specified by DaoOptions.queryDirectory. + */ +export type QueryOptions = { + queryType: QueryTypes; + clazz?: Clazz; + returnList?: boolean; + query?: string; + file?: string; +}; + +/** + * Decorator for a class method that executes a SQL query parameterized by the provided arguments + * @param options + * @constructor + */ +export function SqlQuery(options: QueryOptions): MethodDecorator { + return function ( + target: any, + propertyKey: string | symbol, + descriptor: PropertyDescriptor + ) { + const originalMethod = descriptor.value; + const parameterMapper = QueryParameterMapper.create(originalMethod); + const resultMapper = ResultMapper.create( + options.queryType, + options.clazz, + options.returnList + ); + descriptor.value = async function (...args: any[]): Promise { + const parentClazzInstance = this as any; + validateClazzInstance(parentClazzInstance); + const query = Query.create(options, parentClazzInstance, propertyKey); + const maybeTransaction: Transaction = args.find( + (arg) => arg instanceof Transaction + ); + const replacements = parameterMapper.makeParameterReplacements(args); + const clazzInstanceSequelize = parentClazzInstance.sequelize as Sequelize; + return QueryRunner.create(clazzInstanceSequelize, options.queryType) + .runQuery(query, replacements, maybeTransaction) + .then((queryResult) => resultMapper.mapResult(queryResult)); + }; + }; +} + +export type StreamSelectOptions = { + clazz?: Clazz; + batchSize?: number; + query?: string; + file?: string; +}; + +export function StreamSelect( + options: StreamSelectOptions +): MethodDecorator { + return function ( + target: any, + propertyKey: string | symbol, + descriptor: PropertyDescriptor + ) { + const originalMethod = descriptor.value; + const parameterMapper = QueryParameterMapper.create(originalMethod); + const queryType = QueryTypes.SELECT; + const resultMapper = ResultMapper.create(queryType, options.clazz, true); + descriptor.value = function (...args: any[]): StreamIterator { + try { + const parentClazzInstance = this as any; + const queryOpts: QueryOptions = { + ...options, + queryType: queryType + }; + validateClazzInstance(parentClazzInstance); + const query = Query.create(queryOpts, parentClazzInstance, propertyKey); + const replacements = parameterMapper.makeParameterReplacements(args); + const clazzInstanceSequelize = + parentClazzInstance.sequelize as Sequelize; + const queryRunner = QueryRunner.create( + clazzInstanceSequelize, + queryType + ); + return StreamIterator.create( + query, + queryRunner, + resultMapper, + replacements, + options.batchSize + ); + } catch (e) { + logger.error( + `Error executing query ${propertyKey.toString()} with args: ${args}`, + e + ); + throw e; + } + }; + }; +} + +/** + * Decorator for a class method that contains calls to multiple SQL queries that should be grouped + * together in a single Transactional commit. + * @constructor + */ +export function SqlTransaction(options?: TransactionOptions): MethodDecorator { + return function ( + target: object, + propertyKey: string | symbol, + descriptor: TypedPropertyDescriptor + ) { + const originalMethod = descriptor.value; + descriptor.value = async function (...args: any[]) { + const maybeTransaction: Transaction = args.find( + (arg) => arg instanceof Transaction + ); + if (maybeTransaction) { + throw new Error("Cannot have nested `@SqlTransaction` calls"); + } + const parentClazzInstance = this as any; + validateClazzInstance(parentClazzInstance); + const clazzInstanceSequelize = parentClazzInstance.sequelize as Sequelize; + const transaction = await clazzInstanceSequelize.transaction(options); + try { + const result = await originalMethod.apply(this, [...args, transaction]); + await transaction.commit(); + return result; + } catch (error) { + await transaction.rollback(); + throw error; + } + }; + + return descriptor; + }; +} + +function validateClazzInstance(clazzInstance: any) { + if (!clazzInstance.initialized) { + throw new Error("DAO not initialized"); + } + if (!clazzInstance.sequelize) { + throw new Error("Sequelize not present on DAO"); + } +} diff --git a/packages/sql-decorators/src/query/query-parameter-mapper.ts b/packages/sql-decorators/src/query/query-parameter-mapper.ts new file mode 100644 index 0000000..9be5844 --- /dev/null +++ b/packages/sql-decorators/src/query/query-parameter-mapper.ts @@ -0,0 +1,116 @@ +import { Transaction } from "sequelize"; +import { createLogger, transports } from "winston"; + +export class QueryParameterMapper { + private readonly logger = createLogger({ + transports: [new transports.Console()] + }); + private readonly func: () => void; + private readonly parameterNames: string[]; + + public static create(func: () => void): QueryParameterMapper { + return new QueryParameterMapper(func); + } + + private constructor(func: () => void) { + this.func = func; + this.parameterNames = this.getParameterNames(func); + } + + public makeParameterReplacements(args: any[]): any { + return this.replaceUndefinedWithNull(this.makeReplacementsInternal(args)); + } + + private makeReplacementsInternal(args: any[]): any { + const { cleanArgs, params } = this.cleanArgsAndParameters(args); + if (params.length === 0) { + // No parameters, use empty replacements + return {}; + } else if ( + params.length === 1 && + typeof cleanArgs[0] === "object" && + // Arrays evaluate as objects, so we need to check for array explicitly + !Array.isArray(cleanArgs[0]) + ) { + // Single complex type, pass it directly as the replacements + const replacements: Record = {}; + for (const key of Object.keys(cleanArgs[0])) { + replacements[key] = cleanArgs[0][key]; + } + // Include `get` fields + const prototype = Object.getPrototypeOf(cleanArgs[0]); + if (prototype) { + const descriptors = Object.getOwnPropertyDescriptors(prototype); + for (const [key, descriptor] of Object.entries(descriptors)) { + if (typeof descriptor.get === "function") { + replacements[key] = cleanArgs[0][key]; + } + } + } + return replacements; + } else if (params.length === cleanArgs.length) { + // Named arguments + const namedArgs: Record = {}; + for (let i = 0; i < params.length; i++) { + const paramName = params[i]; + namedArgs[paramName] = cleanArgs[i]; + } + return namedArgs; + } else { + this.logger.debug( + "Found mix of complex and simple types, taking first complex type as replacements" + ); + return cleanArgs[0]; + } + } + + /** + * Remove the Transaction argument from args and the transaction parameter name from parameterNames + * This is required so that we can pass transaction as a separate argument to sequelize query without + * attempting to replace it in the query string + */ + private cleanArgsAndParameters(args: any[]): { + cleanArgs: any[]; + params: string[]; + } { + // Create a copy of args and parameterNames + const argsCopy = [...args]; + const parameterNamesCopy = [...this.parameterNames]; + + // Find the index of the Transaction argument + const transactionIndex = argsCopy.findIndex( + (arg) => arg instanceof Transaction + ); + if (transactionIndex !== -1) { + // Remove the transaction parameter name from the copy + parameterNamesCopy.splice(transactionIndex, 1); + // Also remove the transaction argument from args copy + argsCopy.splice(transactionIndex, 1); + } + return { cleanArgs: argsCopy, params: parameterNamesCopy }; + } + + private getParameterNames(func: () => void): string[] { + const STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm; + const ARGUMENT_NAMES = /([^\s,]+)/g; + const fnStr = func.toString().replace(STRIP_COMMENTS, ""); + const result = fnStr + .slice(fnStr.indexOf("(") + 1, fnStr.indexOf(")")) + .match(ARGUMENT_NAMES); + return result === null ? [] : result; + } + + private replaceUndefinedWithNull(obj: any): any { + if (typeof obj !== "object" || obj === null) { + // obj is a primitive value or null + return obj; + } + const copy: any = Array.isArray(obj) ? [] : {}; + for (const key in obj) { + const value = obj[key]; + copy[key] = + value === undefined ? null : this.replaceUndefinedWithNull(value); + } + return copy; + } +} diff --git a/packages/sql-decorators/src/query/query-runner.ts b/packages/sql-decorators/src/query/query-runner.ts new file mode 100644 index 0000000..0d4699b --- /dev/null +++ b/packages/sql-decorators/src/query/query-runner.ts @@ -0,0 +1,33 @@ +import { BatchingOptions, Query } from "./query"; +import { QueryTypes, Sequelize, Transaction } from "sequelize"; + +export class QueryRunner { + private sequelize: Sequelize; + private queryType: QueryTypes; + + public static create( + sequelize: Sequelize, + queryType: QueryTypes + ): QueryRunner { + return new QueryRunner(sequelize, queryType); + } + + private constructor(sequelize: Sequelize, queryType: QueryTypes) { + this.sequelize = sequelize; + this.queryType = queryType; + } + + public async runQuery( + query: Query, + replacements: any, + transaction?: Transaction, + batchingOptions?: BatchingOptions + ): Promise { + const transactionObject = transaction ? { transaction } : {}; + return this.sequelize.query(query.getQueryString(batchingOptions), { + ...transactionObject, + replacements: Object.assign({}, replacements), + type: this.queryType + }); + } +} diff --git a/packages/sql-decorators/src/query/query.ts b/packages/sql-decorators/src/query/query.ts new file mode 100644 index 0000000..f4258df --- /dev/null +++ b/packages/sql-decorators/src/query/query.ts @@ -0,0 +1,70 @@ +import { QueryOptions } from "@zeroshotbuilders/sql-decorators"; +import fs from "fs"; + +const queryCache: Map = new Map(); + +export type BatchingOptions = { + limit: number; + offset: number; +}; + +export class Query { + private constructor( + private options: QueryOptions, + private parentClazzInstance: any, + public propertyKey: string | symbol + ) {} + + public static create( + options: QueryOptions, + parentClazzInstance: any, + propertyKey: string | symbol + ): Query { + return new Query(options, parentClazzInstance, propertyKey); + } + + public getQueryString(batchingOptions?: BatchingOptions): string { + const queryDirectory = + this.parentClazzInstance.options?.queryDirectory || ""; + const cachingKey = + queryDirectory + + this.parentClazzInstance.constructor.name + + this.propertyKey.toString(); + const cachedQuery = queryCache.get(cachingKey); + if (cachedQuery) { + return this.applyBatchingOptions(cachedQuery, batchingOptions); + } else { + const query = this.makeQuery(); + queryCache.set(cachingKey, query); + return this.applyBatchingOptions(query, batchingOptions); + } + } + + private applyBatchingOptions( + query: string, + batchingOptions?: BatchingOptions + ): string { + if (batchingOptions) { + return `${query} LIMIT ${batchingOptions.limit} OFFSET ${batchingOptions.offset}`; + } else { + return query; + } + } + + private makeQuery(): string { + let query: string | undefined; + if (this.options.query) { + query = this.options.query; + } else if (this.options.file) { + const filePath = `${this.options.file}`; + query = fs.readFileSync(filePath, "utf-8"); + } else if (this.parentClazzInstance.options?.queryDirectory) { + const queryDirectory = this.parentClazzInstance.options.queryDirectory; + const filePath = `${queryDirectory}/${this.propertyKey.toString()}.sql`; + query = fs.readFileSync(filePath, "utf-8"); + } else { + throw new Error("No query or queryDirectory provided"); + } + return query; + } +} diff --git a/packages/sql-decorators/src/result/result-mapper.ts b/packages/sql-decorators/src/result/result-mapper.ts new file mode 100644 index 0000000..df55cd6 --- /dev/null +++ b/packages/sql-decorators/src/result/result-mapper.ts @@ -0,0 +1,137 @@ +import { Clazz } from "@zeroshotbuilders/sql-decorators"; +import { List } from "immutable"; +import { P, match } from "ts-pattern"; +import { QueryTypes } from "sequelize"; +import { plainToInstance } from "class-transformer"; + +export class ResultMapper { + private constructor( + private queryType: QueryTypes, + private clazz: Clazz, + private returnList: boolean + ) {} + + public static create( + queryType: QueryTypes, + clazz: Clazz, + returnList: boolean + ) { + return new ResultMapper(queryType, clazz, returnList); + } + + public mapResult(queryResult: any[]): T { + return match(this.queryType) + .with(QueryTypes.SELECT, () => this.mapSelect(queryResult)) + .with(QueryTypes.INSERT, () => this.mapInsertOrUpdate(queryResult)) + .with(QueryTypes.UPDATE, () => this.mapInsertOrUpdate(queryResult)) + .with(QueryTypes.UPSERT, () => this.mapUpsert()) + .with(QueryTypes.DELETE, () => this.mapDelete()) + .with(QueryTypes.BULKUPDATE, () => this.mapUndefinedResponse()) + .with(QueryTypes.BULKDELETE, () => this.mapUndefinedResponse()) + .with(QueryTypes.RAW, () => this.mapUndefinedResponse()) + .with(P._, () => { + throw new Error(`Unsupported query type: ${this.queryType}`); + }) + .exhaustive(); + } + + private mapSelect(queryResult: any[]): T { + if (this.returnList) { + return List( + queryResult.map((record) => generateInstance(this.clazz, record)) + ) as T; + } else if (queryResult.length == 0) { + return undefined as T; + } else if (queryResult.length == 1) { + return generateInstance( + this.clazz, + queryResult[0] as Record + ); + } else if (queryResult.length > 1) { + throw new Error( + "Multiple records returned. If you want to return a list, set `returnList` to true" + ); + } else { + throw new Error("Invalid query result"); + } + } + + private mapInsertOrUpdate(queryResult: any[]): T { + const result = queryResult[0] as unknown[]; + if (this.returnList) { + return List( + result.map((record) => generateInstance(this.clazz, record)) + ) as T; + } else if (result.length == 0) { + return undefined as T; + } else if (result.length == 1) { + return generateInstance(this.clazz, result[0] as Record); + } else { + throw new Error( + "Multiple records returned. If you want to return a list, set `returnList` to true" + ); + } + } + + private mapUpsert(): T { + return undefined as T; + } + + private mapDelete(): T { + return undefined as T; + } + + private mapUndefinedResponse(): T { + return undefined as T; + } +} + +function generateInstance(clazz: Clazz, record: Record): T { + const camelCaseInstance = snakeToCamel(record); + const nullReplacedInstance = replaceNullWithUndefined(camelCaseInstance); + if (clazz) { + // If a constructor has been passed, then we use it to instantiate the class + return plainToInstance(clazz, nullReplacedInstance); + } else { + // Otherwise, we just return the plain object + return nullReplacedInstance as T; + } +} + +function snakeToCamel(obj: any): any { + if (typeof obj !== "object" || obj === null) { + return obj; + } + + if (Array.isArray(obj)) { + return obj.map((item) => snakeToCamel(item)); + } + + const camelObj: Record = {}; + for (const key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + const camelKey = key.replace(/_([a-z0-9])/g, (_, match) => + match.toUpperCase() + ); + camelObj[camelKey] = snakeToCamel(obj[key]); + } + } + return camelObj; +} + +function replaceNullWithUndefined(obj: any): any { + if (typeof obj !== "object" || obj === null) { + return obj; + } + + if (Array.isArray(obj)) { + return obj.map((item) => replaceNullWithUndefined(item)); + } + + const copy: any = {}; + for (const key in obj) { + const value = obj[key]; + copy[key] = value === null ? undefined : replaceNullWithUndefined(value); + } + return copy; +} diff --git a/packages/sql-decorators/src/result/result-types.ts b/packages/sql-decorators/src/result/result-types.ts new file mode 100644 index 0000000..25b9f59 --- /dev/null +++ b/packages/sql-decorators/src/result/result-types.ts @@ -0,0 +1,15 @@ +export type BooleanResult = { + result: boolean; +}; + +export type StringResult = { + result: string; +}; + +export type NumberResult = { + result: number; +}; + +export type ArrayResult = { + result: string[]; +}; diff --git a/packages/sql-decorators/src/stream-iterator.ts b/packages/sql-decorators/src/stream-iterator.ts new file mode 100644 index 0000000..936b3a1 --- /dev/null +++ b/packages/sql-decorators/src/stream-iterator.ts @@ -0,0 +1,77 @@ +import { List } from "immutable"; +import { Query } from "./query/query"; +import { QueryRunner } from "./query/query-runner"; +import { ResultMapper } from "./result/result-mapper"; +import { createLogger, Logger, transports } from "winston"; + +export class StreamIterator { + private readonly logger: Logger = createLogger({ + transports: [new transports.Console()] + }); + + public static create( + query: Query, + queryRunner: QueryRunner, + resultMapper: ResultMapper, + replacements: any, + batchSize?: number + ): StreamIterator { + return new StreamIterator( + query, + queryRunner, + resultMapper, + replacements, + batchSize + ); + } + + private iterator: AsyncIterator; + + private constructor( + private readonly query: Query, + private readonly queryRunner: QueryRunner, + private readonly resultMapper: ResultMapper, + private readonly replacements: any, + private readonly batchSize: number = 1000 + ) { + this.iterator = this.createAsyncGenerator()[Symbol.asyncIterator](); + } + + private async *createAsyncGenerator(): AsyncGenerator { + let offset = 0; + let batch: List = List.of(); + let done = false; + while (!done) { + batch = await this.queryRunner + .runQuery(this.query, this.replacements, undefined, { + limit: this.batchSize, + offset + }) + .then( + (queryResult) => this.resultMapper.mapResult(queryResult) as List + ) + .catch((e) => { + this.logger.error( + `Error generating batch of results query ${this.query.propertyKey.toString()}`, + e + ); + throw e; + }); + offset += batch.size; + done = batch.size < this.batchSize; + for (const item of batch) { + yield item; + } + } + } + + public async next(): Promise> { + return this.iterator.next(); + } + + public async *[Symbol.asyncIterator](): AsyncGenerator { + for await (const item of this.createAsyncGenerator()) { + yield item; + } + } +} diff --git a/packages/sql-decorators/test/decorators.spec.ts b/packages/sql-decorators/test/decorators.spec.ts new file mode 100644 index 0000000..5300b05 --- /dev/null +++ b/packages/sql-decorators/test/decorators.spec.ts @@ -0,0 +1,672 @@ +import "reflect-metadata"; +import { + BeforeAllTimeout, + PostgresContainer, + unreachableErr +} from "@zeroshotbuilders/commons-testing"; +import { List, Set } from "immutable"; +import * as randomstring from "randomstring"; +import { QueryTypes, Sequelize } from "sequelize"; +import { ArrayDao } from "./repository/array-dao"; +import { BrokenDao } from "./repository/broken-dao"; +import { + ClazzDao, + TEST_GETTER_VALUE, + TestClazz, + TestClazzWithGetter +} from "./repository/clazz-dao"; +import { EnumDao, EnumRecord, SomeEnum } from "./repository/enum-dao"; +import { LolDao } from "./repository/lol-dao"; +import { Nested, NestedDao, SubType } from "./repository/nested-dao"; +import { NullableDao, NullableRecord } from "./repository/nullable-dao"; +import { TestDao, Thing } from "./repository/test-dao"; +import { UnconventionalDao } from "./repository/unconventional-dao"; +import { TestRepository } from "./transaction-repository/test-repository"; + +describe("DAO utils", () => { + let postgres: PostgresContainer; + let sequelize: Sequelize; + + beforeAll(async () => { + postgres = new PostgresContainer(); + await postgres.start(); + sequelize = postgres.getSequelizeClient(); + + await sequelize.query( + "CREATE TABLE test (some_string varchar(255) PRIMARY KEY, some_number NUMERIC NOT NULL UNIQUE, some_int BIGINT NOT NULL);", + { type: QueryTypes.RAW } + ); + await sequelize.query( + "CREATE TABLE lol (some_string varchar(255) PRIMARY KEY);", + { type: QueryTypes.RAW } + ); + await sequelize.query( + "CREATE TABLE clazzes (some_string varchar(255) PRIMARY KEY, some_number NUMERIC NOT NULL);", + { type: QueryTypes.RAW } + ); + await sequelize.query( + "CREATE TABLE broken (some_string varchar(255) PRIMARY KEY);", + { type: QueryTypes.RAW } + ); + await sequelize.query( + "CREATE TABLE nullable_table (some_id varchar(255) PRIMARY KEY," + + "some_nullable_string varchar(255), some_nullable_number NUMERIC);", + { type: QueryTypes.RAW } + ); + await sequelize.query( + "CREATE TABLE enum_table (some_id varchar(255) PRIMARY KEY, some_enum varchar(255));", + { type: QueryTypes.RAW } + ); + await sequelize.query( + "CREATE TABLE nested (id varchar(255) PRIMARY KEY);", + { type: QueryTypes.RAW } + ); + await sequelize.query( + "CREATE TABLE sub_type (name varchar(255) PRIMARY KEY);", + { type: QueryTypes.RAW } + ); + await sequelize.query( + "CREATE TABLE unconventional (some_1_name_2_with_3_numbers_4_intertwined varchar(255) PRIMARY KEY, some_name_ending_in_a_number_1 varchar(255));", + { type: QueryTypes.RAW } + ); + await sequelize.query( + "CREATE TABLE array_table (some_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), some_array_1 VARCHAR(255)[], some_array_2 VARCHAR(255)[], some_jsonb_array JSONB[]);", + { type: QueryTypes.RAW } + ); + await sequelize.query( + "CREATE TABLE clazzes_with_getter (some_string varchar(255) PRIMARY KEY, test_getter VARCHAR);", + { type: QueryTypes.RAW } + ); + }, BeforeAllTimeout); + + afterAll(async () => { + await postgres.stop(); + }); + + it("should work end-to-end in the happy path", async () => { + const testDao = new TestDao(sequelize); + const myString = "abc123"; + const myNumber = 1.01; + const myInt = 1; + const thing: Thing = { someString: myString, someNumber: myNumber, someInt: myInt }; + const insertResult = await testDao.insertQuery(thing); + expect(insertResult).toBeUndefined(); + const selectResult = await testDao.selectQuery(myString); + expect(selectResult).toEqual(thing); + const myNewNumber = 2; + const updateResult = await testDao.updateQuery(myNewNumber, myString); + const newThing: Thing = { someString: myString, someNumber: myNewNumber, someInt: myInt }; + expect(updateResult).toEqual(newThing); + const updatedSelectResult = await testDao.selectQuery(myString); + expect(updatedSelectResult).toEqual(newThing); + const deleteResult = await testDao.deleteQuery(myString); + expect(deleteResult).toBeUndefined(); + const deletedSelectResult = await testDao.selectQuery(myString); + expect(deletedSelectResult).toBeUndefined(); + }); + + it("should return nothing for a SELECT of a non-existent record", async () => { + const testDao = new TestDao(sequelize); + const result = await testDao.selectQuery(randomstring.generate()); + expect(result).toBeUndefined(); + }); + + it("should return nothing for an UPDATE of a non-existent record", async () => { + const testDao = new TestDao(sequelize); + const result = await testDao.updateQuery(1, randomstring.generate()); + expect(result).toBeUndefined(); + }); + + it("should return nothing for a BULK_UPDATE of non-existent records", async () => { + const testDao = new TestDao(sequelize); + const result = await testDao.bulkUpdateMultipleThingsQuery(1, randomstring.generate(), randomstring.generate()); + expect(result).toBeUndefined(); + }); + + it("should return nothing for a DELETE of a non-existent record", async () => { + const testDao = new TestDao(sequelize); + const result = await testDao.deleteQuery(randomstring.generate()); + expect(result).toBeUndefined(); + }); + + it("should return a list when multiple rows are SELECTed", async () => { + const lolDao = new LolDao(sequelize); + const string1 = "abc123"; + const string2 = "def456"; + await lolDao.insertLol({ someString: string1 }); + await lolDao.insertLol({ someString: string2 }); + const result = await lolDao.getMultipleLols(string1, string2); + expect(result).toEqual(List.of({ someString: string1 }, { someString: string2 })); + }); + + it("should return a list when multiple rows are UPDATEd", async () => { + const testDao = new TestDao(sequelize); + const thing1: Thing = { someString: randomstring.generate(), someNumber: randomFloat(), someInt: randomInt() }; + const thing2: Thing = { someString: randomstring.generate(), someNumber: randomFloat(), someInt: randomInt() }; + await testDao.insertQuery(thing1); + await testDao.insertQuery(thing2); + const newNumber = randomInt(); + const result = await testDao.updateMultipleThingsQuery(newNumber, thing1.someString, thing2.someString); + expect(result).toEqual(List.of({ ...thing1, someInt: newNumber }, { ...thing2, someInt: newNumber })); + const updatedThing1 = await testDao.selectQuery(thing1.someString); + const updatedThing2 = await testDao.selectQuery(thing2.someString); + expect(updatedThing1).toEqual({ ...thing1, someInt: newNumber }); + expect(updatedThing2).toEqual({ ...thing2, someInt: newNumber }); + }); + + it("should allow us to BULK_UPDATE", async () => { + const testDao = new TestDao(sequelize); + const thing1: Thing = { someString: randomstring.generate(), someNumber: randomFloat(), someInt: randomInt() }; + const thing2: Thing = { someString: randomstring.generate(), someNumber: randomFloat(), someInt: randomInt() }; + await testDao.insertQuery(thing1); + await testDao.insertQuery(thing2); + const newNumber = randomInt(); + const result = await testDao.bulkUpdateMultipleThingsQuery(newNumber, thing1.someString, thing2.someString); + expect(result).toBeUndefined(); + const updatedThing1 = await testDao.selectQuery(thing1.someString); + const updatedThing2 = await testDao.selectQuery(thing2.someString); + expect(updatedThing1).toEqual({ ...thing1, someInt: newNumber }); + expect(updatedThing2).toEqual({ ...thing2, someInt: newNumber }); + }); + + it("should allow us to BULK_DELETE", async () => { + const testDao = new TestDao(sequelize); + const thing1: Thing = { someString: randomstring.generate(), someNumber: randomFloat(), someInt: randomInt() }; + const thing2: Thing = { someString: randomstring.generate(), someNumber: randomFloat(), someInt: randomInt() }; + await testDao.insertQuery(thing1); + await testDao.insertQuery(thing2); + const result = await testDao.deleteMultipleThingsQuery(thing1.someString, thing2.someString); + expect(result).toBeUndefined(); + const updatedThing1 = await testDao.selectQuery(thing1.someString); + const updatedThing2 = await testDao.selectQuery(thing2.someString); + expect(updatedThing1).toBeUndefined(); + expect(updatedThing2).toBeUndefined(); + }); + + it("should return an empty list when a SELECT of multiple rows returns none", async () => { + const lolDao = new LolDao(sequelize); + const result = await lolDao.getMultipleLols(randomstring.generate(), randomstring.generate()); + expect(result).toEqual(List()); + }); + + it("should run the same results for a query that is executed twice (second run hits the query cache)", async () => { + const testDao = new TestDao(sequelize); + const thing: Thing = { someString: randomstring.generate(), someNumber: randomFloat(), someInt: randomInt() }; + await testDao.insertQuery(thing); + const selectedThing1 = await testDao.selectQuery(thing.someString); + const selectedThing2 = await testDao.selectQuery(thing.someString); + expect(selectedThing1).toEqual(thing); + expect(selectedThing2).toEqual(thing); + }); + + it("should work for class instances and lists of class instances", async () => { + const classDao = new ClazzDao(sequelize); + const instance1 = new TestClazz(randomstring.generate(), randomFloat()); + const instance2 = new TestClazz(randomstring.generate(), randomFloat()); + const lol1 = await classDao.insertTestClazz(instance1); + expect(lol1).toEqual(instance1); + const lol2 = await classDao.insertTestClazz(instance2); + expect(lol2).toEqual(instance2); + const result = await classDao + .getMultipleTestClazzes(instance1.someString, instance2.someString) + .then((response) => response.sort((l, r) => l.someString.localeCompare(r.someString))); + expect(result).toEqual( + List.of(instance1, instance2).sort((a, b) => a.someString.localeCompare(b.someString)) + ); + expect(result.map((a) => a.testFunction())).toEqual(List.of("test", "test")); + }); + + it("should work for updates of class instances", async () => { + const classDao = new ClazzDao(sequelize); + const instance = new TestClazz(randomstring.generate(), randomFloat()); + await classDao.insertTestClazz(instance); + const newNumber = randomFloat(); + const result = await classDao.updateTestClazz(newNumber, instance.someString); + expect(result).toEqual({ ...instance, someNumber: newNumber }); + }); + + it("should work for bulk updates of class instances", async () => { + const classDao = new ClazzDao(sequelize); + const instance1 = new TestClazz(randomstring.generate(), randomFloat()); + const instance2 = new TestClazz(randomstring.generate(), randomFloat()); + await classDao.insertTestClazz(instance1); + await classDao.insertTestClazz(instance2); + const newNumber = randomFloat(); + const result = await classDao.bulkUpdateManyTestClazzes(newNumber, instance1.someString, instance2.someString); + expect(result).toBeUndefined(); + const updatedInstance1 = await classDao.getTestClazz(instance1.someString); + const updatedInstance2 = await classDao.getTestClazz(instance2.someString); + expect(updatedInstance1).toEqual({ ...instance1, someNumber: newNumber }); + expect(updatedInstance2).toEqual({ ...instance2, someNumber: newNumber }); + }); + + it("should work for standard updates of multiple records", async () => { + const classDao = new ClazzDao(sequelize); + const instance1 = new TestClazz(randomstring.generate(), randomFloat()); + const instance2 = new TestClazz(randomstring.generate(), randomFloat()); + await classDao.insertTestClazz(instance1); + await classDao.insertTestClazz(instance2); + const newNumber = randomFloat(); + const result = await classDao.updateManyTestClazzes(newNumber, instance1.someString, instance2.someString); + expect(result).toEqual(List.of({ ...instance1, someNumber: newNumber }, { ...instance2, someNumber: newNumber })); + }); + + it("should propagate errors from the database", async () => { + const testDao = new TestDao(sequelize); + const thing: Thing = { someString: randomstring.generate(), someNumber: randomFloat(), someInt: randomInt() }; + await testDao.insertQuery(thing); + await expect(async () => testDao.insertQuery(thing)).rejects.toThrow(); + }); + + it("should throw exceptions when there is no resolvable file or query reference", async () => { + const brokenDao = new BrokenDao(sequelize); + await brokenDao.insertBrokenType({ someString: randomstring.generate() }); + await expect(async () => brokenDao.noFileOrQueryReference({ someString: randomstring.generate() })).rejects.toThrow(); + }); + + it("should work for unconventional field names", async () => { + const unconventionalDao = new UnconventionalDao(sequelize); + const unconventionalFields = { + some1Name2With3Numbers4Intertwined: randomstring.generate(), + someNameEndingInANumber1: randomstring.generate() + }; + await unconventionalDao.insertUnconventionalType(unconventionalFields); + const selectResult = await unconventionalDao.selectUnconventionalType(); + expect(selectResult).toEqual(unconventionalFields); + }); + + it("should throw exceptions when it attempts to parse the results into a list without specifying the returnList argument in QueryOptions", async () => { + const brokenDao = new BrokenDao(sequelize); + await brokenDao.insertBrokenType({ someString: randomstring.generate() }); + await brokenDao.insertBrokenType({ someString: randomstring.generate() }); + await expect(async () => brokenDao.listNeededWithoutSettingListReturn()).rejects.toThrow(); + }); + + it("should throw exceptions when parameters in the query are mapped incorrectly", async () => { + const brokenDao = new BrokenDao(sequelize); + await brokenDao.insertBrokenType({ someString: randomstring.generate() }); + await expect(async () => brokenDao.incorrectParameterMapping(randomInt(), randomstring.generate())).rejects.toThrow(); + }); + + it("should work with coalescing undefined replacements in UPDATE", async () => { + const testDao = new TestDao(sequelize); + const thing: Thing = { someString: randomstring.generate(), someNumber: randomFloat(), someInt: randomInt() }; + await testDao.insertQuery(thing); + const updatedThing = await testDao.updateQuery(undefined, thing.someString); + expect(updatedThing).toEqual(thing); + }); + + it("should let us insert with undefined fields", async () => { + const nullableDao = new NullableDao(sequelize); + const record: NullableRecord = { someId: randomstring.generate(), someNullableString: undefined, someNullableNumber: undefined }; + const result = await nullableDao.insertNullableRecord(record); + expect(result).toEqual(record); + }); + + it("should let us select records with undefined fields", async () => { + const nullableDao = new NullableDao(sequelize); + const record: NullableRecord = { someId: randomstring.generate(), someNullableString: undefined, someNullableNumber: undefined }; + await nullableDao.insertNullableRecord(record); + const result = await nullableDao.selectNullableRecord(record.someId); + expect(result).toEqual(record); + }); + + it("should work for records with enums", async () => { + const enumDao = new EnumDao(sequelize); + const record: EnumRecord = { someId: randomstring.generate(), someEnum: SomeEnum.A }; + const result = await enumDao.insertEnumRecordTransactionally(record); + expect(result).toEqual(record); + const selectedRecord = await enumDao.selectEnumRecord(record.someId); + expect(selectedRecord).toEqual(record); + }); + + it("should execute multiple queries in a transaction", async () => { + const dao = new EnumDao(sequelize); + const thing1: EnumRecord = { someId: randomstring.generate(), someEnum: SomeEnum.A }; + const thing2: EnumRecord = { someId: randomstring.generate(), someEnum: SomeEnum.B }; + const insertResult = await dao.insertManyTransactionally(List.of(thing1, thing2)); + expect(insertResult.toSet()).toEqual(Set.of(thing1, thing2)); + const selectedThing1 = await dao.selectEnumRecord(thing1.someId); + const selectedThing2 = await dao.selectEnumRecord(thing2.someId); + expect(selectedThing1).toEqual(thing1); + expect(selectedThing2).toEqual(thing2); + }); + + it("should let me execute a query that has the option of being transactional, but without a transaction", async () => { + const dao = new EnumDao(sequelize); + const thing1: EnumRecord = { someId: randomstring.generate(), someEnum: SomeEnum.A }; + const insertResult1 = await dao.insertEnumRecordTransactionally(thing1); + expect(insertResult1).toEqual(thing1); + }); + + it("should rollback a transaction if one of the queries fails", async () => { + const dao = new EnumDao(sequelize); + const thing1: EnumRecord = { someId: randomstring.generate(), someEnum: SomeEnum.A }; + const thing2: EnumRecord = { someId: randomstring.generate(), someEnum: SomeEnum.B }; + await expect(async () => dao.insertManyTransactionally(List.of(thing1, thing2, thing1))).rejects.toThrow(); + const selectedThing1 = await dao.selectEnumRecord(thing1.someId); + const selectedThing2 = await dao.selectEnumRecord(thing2.someId); + expect(selectedThing1).toBeUndefined(); + expect(selectedThing2).toBeUndefined(); + }); + + it("should let us get results from json_agg", async () => { + const dao = new NestedDao(sequelize); + const nested = new Nested(randomstring.generate()); + const subType = new SubType(randomstring.generate()); + const nestedInsertionResult = await dao.insertNested(nested); + const subTypeInsertionResult = await dao.insertSubType(subType); + const singleNestedSelectResult = await dao.getNested(nestedInsertionResult.id); + expect(singleNestedSelectResult).toEqual(new Nested(nestedInsertionResult.id, [subType])); + const newNested = await dao.insertNested(new Nested(randomstring.generate())); + const newSubType = await dao.insertSubType(new SubType(randomstring.generate())); + const multiNestedSelectResult = await dao.getMultipleNesteds(); + expect(multiNestedSelectResult).toEqual( + List.of( + new Nested(nestedInsertionResult.id, [subType, newSubType]), + new Nested(newNested.id, [subType, newSubType]) + ) + ); + }); + + it("should work for empty sub-arrays", async () => { + const dao = new NestedDao(sequelize); + const nested = new Nested(randomstring.generate()); + const subType = new SubType(randomstring.generate()); + await dao.insertNested(nested); + await dao.insertSubType(subType); + const specificNestedResult = await dao.getSpecificNested(nested.id, randomstring.generate()); + expect(specificNestedResult).toEqual(nested); + }); + + it("should work for upserts", async () => { + const dao = new TestDao(sequelize); + const thing = { someString: randomstring.generate(), someNumber: randomFloat(), someInt: randomInt() }; + const inserted = await dao.upsertQueryWithReturn(thing.someString, thing.someNumber, thing.someInt); + expect(inserted).toEqual(thing); + const fetchedInserted = await dao.selectQuery(thing.someString); + expect(fetchedInserted).toEqual(thing); + const updated = await dao.upsertQueryWithReturn(thing.someString, thing.someNumber, thing.someInt + 1); + const expectedNewThing = { ...thing, someInt: thing.someInt + 1 }; + expect(updated).toEqual(expectedNewThing); + const fetchedUpdated = await dao.selectQuery(thing.someString); + expect(fetchedUpdated).toEqual(expectedNewThing); + }); + + it("should return an async iterable of a query", async () => { + const dao = new TestDao(sequelize); + const min = Math.round(Math.random() * 1000000 + 10000000); + const max = min + 100; + for (let i = min; i < max; i++) { + await dao.insertQuery({ someString: randomstring.generate(), someNumber: randomFloat(10000), someInt: i }); + } + const iterator = dao.iterator(min, max); + let count = 0; + for (let i = min; i < max; i++) { + const next = await iterator.next(); + expect(next.value).toEqual({ someString: expect.any(String), someNumber: expect.any(Number), someInt: i }); + count++; + } + expect(count).toEqual(max - min); + }); + + it("should return iterators when a class is specified", async () => { + const dao = new ClazzDao(sequelize); + await dao.insertTestClazz(new TestClazz(randomstring.generate(), randomFloat())); + let items: List = List.of(); + for await (const item of dao.iterator()) { + items = items.push(item); + } + expect(items.size).toBeGreaterThanOrEqual(1); + }); + + it("should handle no results in a stream gracefully", async () => { + const dao = new TestDao(sequelize); + const iterator = dao.iterator(0, 0); + let count = 0; + for await (const item of iterator) { + count++; + } + expect(count).toEqual(0); + }); + + it("should allow for streaming from a sql file", async () => { + const dao = new TestDao(sequelize); + await dao.insertQuery({ someString: randomstring.generate(), someNumber: randomFloat(), someInt: randomInt() }); + const iterator = dao.streamThings(0, Number.MAX_SAFE_INTEGER); + let count = 0; + for await (const item of iterator) { + count++; + } + expect(count).toBeGreaterThanOrEqual(1); + }); + + it("should return bool results", async () => { + const dao = new TestDao(sequelize); + const bool = await dao.booleanResult(); + expect(bool.result).toEqual(true); + }); + + it("should return string results", async () => { + const dao = new TestDao(sequelize); + const str = await dao.stringResult(); + expect(str.result).toEqual("lol"); + }); + + it("should return number results", async () => { + const dao = new TestDao(sequelize); + const num = await dao.numberResult(); + expect(num.result).toEqual(1); + }); + + it("should let me group array values into an `IN` clause with strings", async () => { + const dao = new ClazzDao(sequelize); + const instance1 = new TestClazz(randomstring.generate(), randomFloat()); + const instance2 = new TestClazz(randomstring.generate(), randomFloat()); + await dao.insertTestClazz(instance1); + await dao.insertTestClazz(instance2); + const result = await dao.getGroupedTestClazzesByString([instance1.someString, instance2.someString]); + expect(Set.of(...result)).toEqual(Set.of(instance1, instance2)); + }); + + it("should let me group array values into an `IN` clause with numbers", async () => { + const dao = new ClazzDao(sequelize); + const instance1 = new TestClazz(randomstring.generate(), randomFloat()); + const instance2 = new TestClazz(randomstring.generate(), randomFloat()); + await dao.insertTestClazz(instance1); + await dao.insertTestClazz(instance2); + const result = await dao.getGroupedTestClazzesByNumber([instance1.someNumber, instance2.someNumber]); + expect(Set.of(...result)).toEqual(Set.of(instance1, instance2)); + }); + + it("should let me pass undefined to avoid the IN clause", async () => { + const dao = new ClazzDao(sequelize); + const instance1 = new TestClazz(randomstring.generate(), randomFloat()); + const instance2 = new TestClazz(randomstring.generate(), randomFloat()); + const lol1 = await dao.insertTestClazz(instance1); + const lol2 = await dao.insertTestClazz(instance2); + const result = await dao.getGroupedTestClazzesByString(undefined); + expect(result.toArray()).toContainEqual(lol1); + expect(result.toArray()).toContainEqual(lol2); + }); + + it("should let me group array values into an `IN` clause with strings in a complex type", async () => { + const dao = new ClazzDao(sequelize); + const instance1 = new TestClazz(randomstring.generate(), randomFloat()); + const instance2 = new TestClazz(randomstring.generate(), randomFloat()); + await dao.insertTestClazz(instance1); + await dao.insertTestClazz(instance2); + const result = await dao.getGroupedTestClazzes({ queryStrings: [instance1.someString, instance2.someString], queryNumbers: undefined }); + expect(Set.of(...result)).toEqual(Set.of(instance1, instance2)); + }); + + it("should let me group array values into an `IN` clause with numbers in a complex type", async () => { + const dao = new ClazzDao(sequelize); + const instance1 = new TestClazz(randomstring.generate(), randomFloat()); + const instance2 = new TestClazz(randomstring.generate(), randomFloat()); + await dao.insertTestClazz(instance1); + await dao.insertTestClazz(instance2); + const result = await dao.getGroupedTestClazzes({ queryStrings: undefined, queryNumbers: [instance1.someNumber, instance2.someNumber] }); + expect(Set.of(...result)).toEqual(Set.of(instance1, instance2)); + }); + + it("should let me group multiple array values into separate `IN` clauses with numbers and strings in a complex type", async () => { + const dao = new ClazzDao(sequelize); + const instance1 = new TestClazz(randomstring.generate(), randomFloat()); + const instance2 = new TestClazz(randomstring.generate(), randomFloat()); + const instance3 = new TestClazz(randomstring.generate(), randomFloat()); + const instance4 = new TestClazz(randomstring.generate(), randomFloat()); + await dao.insertTestClazz(instance1); + await dao.insertTestClazz(instance2); + await dao.insertTestClazz(instance3); + await dao.insertTestClazz(instance4); + const result = await dao.getGroupedTestClazzes({ queryStrings: [instance1.someString, instance2.someString], queryNumbers: [instance1.someNumber] }); + expect(Set.of(...result)).toEqual(Set.of(instance1)); + }); + + it("should let me `IN` clauses in StreamSelect", async () => { + const dao = new ClazzDao(sequelize); + const instance1 = new TestClazz(randomstring.generate(), randomFloat()); + const instance2 = new TestClazz(randomstring.generate(), randomFloat()); + const instance3 = new TestClazz(randomstring.generate(), randomFloat()); + const instance4 = new TestClazz(randomstring.generate(), randomFloat()); + const lol1 = await dao.insertTestClazz(instance1); + const lol2 = await dao.insertTestClazz(instance2); + const lol3 = await dao.insertTestClazz(instance3); + await dao.insertTestClazz(instance4); + const resultStream = dao.streamWithInClause([instance1.someString, instance2.someString, instance3.someString]); + const results = []; + for await (const result of resultStream) { + results.push(result); + } + expect(Set.of(...results)).toEqual(Set.of(lol1, lol2, lol3)); + }); + + it("should insert and retrieve array fields", async () => { + const tags = ["lol1", "lol2", "lol3"]; + const arrayDao = new ArrayDao(sequelize); + await arrayDao.insertArray1(tags); + const selectResult = await arrayDao.findArray1ByTag("lol2"); + expect(selectResult.result).toEqual(expect.arrayContaining(tags)); + }); + + it("should insert and retrieve empty array fields", async () => { + const tags: string[] = []; + const arrayDao = new ArrayDao(sequelize); + const inserted = await arrayDao.insertArray1(tags); + const selectResult = await arrayDao.findArray1ById(inserted.someId); + expect(selectResult.result).toEqual(expect.arrayContaining([])); + }); + + it("should retrieve null array fields", async () => { + const arrayDao = new ArrayDao(sequelize); + const inserted = await arrayDao.insertArray1(["abc", "123"]); + const selectResult = await arrayDao.findArray2ById(inserted.someId); + expect(selectResult.result).toBeUndefined(); + }); + + it("should update and retrieve updated array data fields", async () => { + const tags = ["lol4", "lol5"]; + const arrayDao = new ArrayDao(sequelize); + const inserted = await arrayDao.insertArray1(tags); + const selectResult = await arrayDao.findArray1ByTag("lol4"); + expect(selectResult.result).toEqual(expect.arrayContaining(tags)); + const newTags = ["lol6", "lol7", "lol8"]; + await arrayDao.concatArray1(inserted.someId, newTags); + const updated = await arrayDao.findArray1ByTag("lol7"); + expect(updated.result).toEqual(expect.arrayContaining([...tags, ...newTags])); + }); + + it("should let me overwrite array fields to empty", async () => { + const tags = ["lol4", "lol5"]; + const arrayDao = new ArrayDao(sequelize); + const inserted = await arrayDao.insertArray1(tags); + const overwriteResult = await arrayDao.overwriteArray1(inserted.someId, []); + expect(overwriteResult.someArray1).toHaveLength(0); + }); + + it("should insert and retrieve JSONB array fields using stringified JSON", async () => { + const jsonObjects = [ + { name: "Alice", age: 30 }, + { name: "Bob", age: 25 }, + { name: "Charlie", age: 35, nested: { city: "NYC" } } + ]; + const jsonArrayString = JSON.stringify(jsonObjects); + const arrayDao = new ArrayDao(sequelize); + const inserted = await arrayDao.insertJsonbArray(jsonArrayString); + const selectResult = await arrayDao.findJsonbArrayById(inserted.someId); + expect(selectResult.result).toEqual(jsonObjects); + }); + + it("should insert and retrieve empty JSONB array fields", async () => { + const jsonObjects: object[] = []; + const jsonArrayString = JSON.stringify(jsonObjects); + const arrayDao = new ArrayDao(sequelize); + const inserted = await arrayDao.insertJsonbArray(jsonArrayString); + const selectResult = await arrayDao.findJsonbArrayById(inserted.someId); + expect(selectResult.result).toEqual([]); + }); + + it("should let me insert records with a field specified as a getter", async () => { + const dao = new ClazzDao(sequelize); + const clazz = new TestClazzWithGetter(randomstring.generate()); + const inserted = await dao.insertTestGetterValue(clazz); + const result = await dao.selectTestGetterValue(inserted.someString); + expect(result.result).toEqual(TEST_GETTER_VALUE); + }); + + it("should let me upsert", async () => { + const testDao = new TestDao(sequelize); + const name = randomstring.generate(); + const thing1: Thing = { someString: name, someNumber: randomFloat(), someInt: randomInt() }; + await testDao.upsertQuery(thing1); + const inserted = await testDao.selectQuery(name); + expect(inserted).toEqual(thing1); + const thing2: Thing = { someString: name, someNumber: randomFloat(), someInt: randomInt() }; + await testDao.upsertQuery(thing2); + const upserted = await testDao.selectQuery(name); + expect(upserted).toEqual(thing2); + }); + + it("should let me do a multi-row commit in a SQL transaction across multiple DAOs", async () => { + const lolDao = new LolDao(sequelize); + const enumDao = new EnumDao(sequelize); + const testRepository = new TestRepository(sequelize, lolDao, enumDao); + const lolId = randomstring.generate(); + const enumId = randomstring.generate(); + const result = await testRepository.insertLolsAndEnumsInTransaction( + { someString: lolId }, + { someId: enumId, someEnum: SomeEnum.A } + ); + expect(result.lolRecord.someString).toEqual(lolId); + expect(result.enumRecord.someId).toEqual(enumId); + }); + + it("should handle rollbacks in the repository layer", async () => { + const lolDao = new LolDao(sequelize); + const enumDao = new EnumDao(sequelize); + const testRepository = new TestRepository(sequelize, lolDao, enumDao); + const lolRecord = { someString: randomstring.generate() }; + await testRepository.triggerRollback(lolRecord).catch((_): void => null); + const result = await lolDao.getLol(lolRecord.someString); + expect(result).toBeUndefined(); + }); + + it("should error if you try to get too fancy with nested transactions", async () => { + const lolDao = new LolDao(sequelize); + const enumDao = new EnumDao(sequelize); + const testRepository = new TestRepository(sequelize, lolDao, enumDao); + await testRepository + .nestedTransaction() + .then((_) => unreachableErr()) + .catch((err) => expect(err).toBeDefined()); + }); +}); + +function randomInt(): number { + return parseInt(randomstring.generate({ length: 5, charset: "numeric" })); +} + +function randomFloat(scalar = 5): number { + return Math.random() * scalar; +} diff --git a/packages/sql-decorators/test/repository/array-dao.ts b/packages/sql-decorators/test/repository/array-dao.ts new file mode 100644 index 0000000..37fb668 --- /dev/null +++ b/packages/sql-decorators/test/repository/array-dao.ts @@ -0,0 +1,98 @@ +import { ArrayResult, Dao, DaoBase, SqlQuery } from "@zeroshotbuilders/sql-decorators"; +import { QueryTypes } from "sequelize"; + +export type SomeArrayResult = { + someId: string; + someArray1: string[]; + someArray2: string[]; +}; + +export type JsonbArrayResult = { + result: object[] | undefined; +}; + +@Dao() +export class ArrayDao extends DaoBase { + @SqlQuery<{ some_id: string }>({ + queryType: QueryTypes.INSERT, + query: ` + INSERT INTO array_table (some_array_1) + VALUES (COALESCE(ARRAY [:someArray1]::varchar[], ARRAY []::varchar[])) + RETURNING some_id; + ` + }) + insertArray1(someArray1: string[]): Promise<{ someId: string }> { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.SELECT, + query: + "SELECT some_array_1 as result FROM array_table WHERE some_array_1 @> ARRAY[:tag]::VARCHAR[];" + }) + findArray1ByTag(tag: string): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.SELECT, + query: "SELECT some_array_1 as result FROM array_table WHERE some_id = :id;" + }) + findArray1ById(id: string): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.SELECT, + query: "SELECT some_array_2 as result FROM array_table WHERE some_id = :id;" + }) + findArray2ById(id: string): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.UPDATE, + query: ` + UPDATE array_table + SET some_array_1 = array_cat(some_array_1, ARRAY [:newTags]::varchar[]) + WHERE some_id = :id; + ` + }) + concatArray1(id: string, newTags: string[]): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.UPDATE, + query: ` + UPDATE array_table + SET some_array_1 = COALESCE(ARRAY [:someArray1]::varchar[], ARRAY []::varchar[]) + WHERE some_id = :id + RETURNING *; + ` + }) + overwriteArray1(id: string, someArray1: string[]): Promise { + return null; + } + + @SqlQuery<{ some_id: string }>({ + queryType: QueryTypes.INSERT, + query: ` + INSERT INTO array_table (some_jsonb_array) + VALUES (ARRAY(SELECT jsonb_array_elements(:jsonArrayString::JSONB))) + RETURNING some_id; + ` + }) + insertJsonbArray(jsonArrayString: string): Promise<{ someId: string }> { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.SELECT, + query: + "SELECT some_jsonb_array as result FROM array_table WHERE some_id = :id;" + }) + findJsonbArrayById(id: string): Promise { + return null; + } +} diff --git a/packages/sql-decorators/test/repository/broken-dao.ts b/packages/sql-decorators/test/repository/broken-dao.ts new file mode 100644 index 0000000..5d641f3 --- /dev/null +++ b/packages/sql-decorators/test/repository/broken-dao.ts @@ -0,0 +1,44 @@ +import { Dao, DaoBase, SqlQuery } from "@zeroshotbuilders/sql-decorators"; +import { QueryTypes } from "sequelize"; + +export type BrokenType = { + someString: string; +}; + +@Dao() +export class BrokenDao extends DaoBase { + @SqlQuery({ + queryType: QueryTypes.INSERT, + query: "INSERT INTO broken (some_string) VALUES (:someString) RETURNING *" + }) + insertBrokenType(brokenType: BrokenType): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.INSERT + }) + noFileOrQueryReference(lol: BrokenType): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.UPDATE, + query: + "UPDATE broken set some_number = :someNumber WHERE some_string = :lookupString RETURNING *" + }) + incorrectParameterMapping( + newNumber: number, + lookupString: string + ): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.UPDATE, + query: "SELECT * from broken" + }) + listNeededWithoutSettingListReturn(): Promise { + return null; + } +} diff --git a/packages/sql-decorators/test/repository/clazz-dao.ts b/packages/sql-decorators/test/repository/clazz-dao.ts new file mode 100644 index 0000000..66c7b46 --- /dev/null +++ b/packages/sql-decorators/test/repository/clazz-dao.ts @@ -0,0 +1,208 @@ +import { + Dao, + DaoBase, + SqlQuery, + StreamSelect, + StringResult +} from "@zeroshotbuilders/sql-decorators"; +import { List } from "immutable"; +import { QueryTypes } from "sequelize"; +import { StreamIterator } from "../../src/stream-iterator"; + +export const TEST_GETTER_VALUE = "testGetter"; + +export class TestClazzWithGetter { + readonly someString: string; + + constructor(someString: string) { + this.someString = someString; + } + + get testGetter(): string { + return TEST_GETTER_VALUE; + } +} + +export class TestClazz { + readonly someString: string; + readonly someNumber: number; + + constructor(someString: string, someNumber: number) { + this.someString = someString; + this.someNumber = someNumber; + } + + testFunction(): string { + return "test"; + } +} + +export type GroupedQuery = { + queryStrings: string[]; + queryNumbers: number[]; +}; + +@Dao() +export class ClazzDao extends DaoBase { + @SqlQuery({ + queryType: QueryTypes.INSERT, + query: + "INSERT INTO clazzes (some_string, some_number) VALUES (:someString, :someNumber) RETURNING *" + }) + insertTestClazz(lol: TestClazz): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.UPDATE, + clazz: TestClazz, + query: + "UPDATE clazzes set some_number = :newNumber WHERE some_string = :lookupString RETURNING *" + }) + updateTestClazz(newNumber: number, lookupString: string): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.UPDATE, + clazz: TestClazz, + returnList: true, + query: + "UPDATE clazzes set some_number = :newNumber WHERE some_string in (:lookupString1, :lookupString2) RETURNING *" + }) + updateManyTestClazzes( + newNumber: number, + lookupString1: string, + lookupString2: string + ): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.BULKUPDATE, + query: + "UPDATE clazzes set some_number = :newNumber WHERE some_string in (:lookupString1, :lookupString2)" + }) + bulkUpdateManyTestClazzes( + newNumber: number, + lookupString1: string, + lookupString2: string + ): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.SELECT, + clazz: TestClazz, + query: "SELECT * FROM clazzes where some_string = :lookupString" + }) + getTestClazz(lookupString: string): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.SELECT, + clazz: TestClazz, + returnList: true, + query: + "SELECT * FROM clazzes where some_string in (:queryString1, :queryString2) ORDER BY some_string ASC" + }) + getMultipleTestClazzes( + queryString1: string, + queryString2: string + ): Promise> { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.SELECT, + clazz: TestClazz, + returnList: true, + query: + "SELECT * FROM clazzes where (:queryStrings) is null or some_string in (:queryStrings) ORDER BY some_string ASC" + }) + getGroupedTestClazzesByString( + queryStrings: string[] | undefined + ): Promise> { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.SELECT, + clazz: TestClazz, + returnList: true, + query: + "SELECT * FROM clazzes where some_number in (:queryNumbers) ORDER BY some_number ASC" + }) + getGroupedTestClazzesByNumber( + queryNumbers: number[] + ): Promise> { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.SELECT, + clazz: TestClazz, + returnList: true, + query: ` + SELECT * + FROM clazzes + where (( + (:queryNumbers) is null or some_number in (:queryNumbers) + ) AND ( + (:queryStrings) is null or some_string in (:queryStrings) + )) + ORDER BY some_number ASC + ` + }) + getGroupedTestClazzes(groupedQuery: GroupedQuery): Promise> { + return null; + } + + @StreamSelect({ + query: "SELECT * FROM clazzes", + clazz: TestClazz, + batchSize: 2 + }) + iterator(): StreamIterator { + return null; + } + + @StreamSelect({ + clazz: TestClazz, + batchSize: 1, + query: + "SELECT * FROM clazzes where some_string in (:queryStrings) ORDER BY some_string ASC" + }) + streamWithInClause(queryStrings: string[]): StreamIterator { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.INSERT, + clazz: TestClazzWithGetter, + query: ` + INSERT INTO clazzes_with_getter (some_string, test_getter) + VALUES (:someString, :testGetter) + RETURNING * + ` + }) + insertTestGetterValue( + testClazz: TestClazzWithGetter + ): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.SELECT, + clazz: TestClazzWithGetter, + query: ` + SELECT test_getter as result + FROM clazzes_with_getter + where some_string = :someString + ` + }) + selectTestGetterValue(someString: string): Promise { + return null; + } +} diff --git a/packages/sql-decorators/test/repository/enum-dao.ts b/packages/sql-decorators/test/repository/enum-dao.ts new file mode 100644 index 0000000..b164e34 --- /dev/null +++ b/packages/sql-decorators/test/repository/enum-dao.ts @@ -0,0 +1,63 @@ +import { Dao, DaoBase, SqlQuery, SqlTransaction } from "@zeroshotbuilders/sql-decorators"; +import { List } from "immutable"; +import { QueryTypes, Transaction } from "sequelize"; + +export enum SomeEnum { + A = "A", + B = "B" +} + +export type EnumRecord = { + someId: string; + someEnum: SomeEnum; +}; + +@Dao() +export class EnumDao extends DaoBase { + @SqlQuery({ + queryType: QueryTypes.INSERT, + query: + "INSERT INTO enum_table (some_id, some_enum) VALUES (:someId, :someEnum) RETURNING *" + }) + insertEnumRecordTransactionally( + enumRecord: EnumRecord, + transaction?: Transaction + ): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.INSERT, + query: + "INSERT INTO enum_table (some_id, some_enum) VALUES (:someId, :someEnum) RETURNING *" + }) + insertEnumByFields( + someId: string, + someEnum: SomeEnum, + transaction?: Transaction + ): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.SELECT, + query: "SELECT * FROM enum_table WHERE some_id = :id" + }) + selectEnumRecord(id: string): Promise { + return null; + } + + @SqlTransaction() + async insertManyTransactionally( + enumRecords: List, + transaction?: Transaction + ): Promise> { + return List( + await Promise.all( + enumRecords.map((record) => + this.insertEnumRecordTransactionally(record, transaction) + ) + ) + ); + } +} diff --git a/packages/sql-decorators/test/repository/insertQuery.sql b/packages/sql-decorators/test/repository/insertQuery.sql new file mode 100644 index 0000000..fe328dc --- /dev/null +++ b/packages/sql-decorators/test/repository/insertQuery.sql @@ -0,0 +1,9 @@ +INSERT INTO test ( + some_string, + some_number, + some_int +) VALUES ( + :someString, + :someNumber, + :someInt +); diff --git a/packages/sql-decorators/test/repository/lol-dao.ts b/packages/sql-decorators/test/repository/lol-dao.ts new file mode 100644 index 0000000..4d3699e --- /dev/null +++ b/packages/sql-decorators/test/repository/lol-dao.ts @@ -0,0 +1,57 @@ +import { Dao, SqlQuery } from "@zeroshotbuilders/sql-decorators"; +import { List } from "immutable"; +import { QueryTypes, Sequelize, Transaction } from "sequelize"; + +export type Lol = { + someString: string; +}; + +@Dao() +export class LolDao { + private sequelize: Sequelize; + + constructor(sequelize: Sequelize) { + this.sequelize = sequelize; + } + + @SqlQuery({ + queryType: QueryTypes.INSERT, + query: "INSERT INTO lol (some_string) VALUES (:someString) RETURNING *" + }) + insertLol(lol: Lol): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.INSERT, + query: "INSERT INTO lol (some_string) VALUES (:someString) RETURNING *" + }) + insertLolTransactionally(lol: Lol, transaction?: Transaction): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.SELECT, + query: ` + SELECT * + FROM lol + where some_string = :queryString + ` + }) + getLol(queryString: string): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.SELECT, + returnList: true, + query: + "SELECT * FROM lol where some_string in (:queryString1, :queryString2) ORDER BY some_string ASC" + }) + getMultipleLols( + queryString1: string, + queryString2: string + ): Promise> { + return null; + } +} diff --git a/packages/sql-decorators/test/repository/nested-dao.ts b/packages/sql-decorators/test/repository/nested-dao.ts new file mode 100644 index 0000000..3d3186c --- /dev/null +++ b/packages/sql-decorators/test/repository/nested-dao.ts @@ -0,0 +1,80 @@ +import { Dao, SqlQuery } from "@zeroshotbuilders/sql-decorators"; +import { List } from "immutable"; +import { QueryTypes, Sequelize } from "sequelize"; + +export class SubType { + constructor(public readonly name: string) {} +} + +export class Nested { + constructor( + public readonly id: string, + public readonly someArrayField?: SubType[] + ) {} +} + +@Dao() +export class NestedDao { + private sequelize: Sequelize; + + constructor(sequelize: Sequelize) { + this.sequelize = sequelize; + } + + @SqlQuery({ + queryType: QueryTypes.INSERT, + query: "INSERT INTO nested (id) VALUES (:id) RETURNING *" + }) + insertNested(nested: Nested): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.INSERT, + query: "INSERT INTO sub_type (name) VALUES (:name) RETURNING *" + }) + insertSubType(subType: SubType): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.SELECT, + query: + "SELECT nested.*, (\n" + + " SELECT json_agg(sub_type.*)\n" + + " FROM sub_type\n" + + ") as some_array_field\n" + + "FROM nested WHERE nested.id = :id" + }) + getNested(id: string): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.SELECT, + query: + "SELECT nested.*, (\n" + + " SELECT json_agg(sub_type.*)\n" + + " FROM sub_type\n" + + " WHERE sub_type.name = :name\n" + + ") as some_array_field\n" + + "FROM nested WHERE nested.id = :id" + }) + getSpecificNested(id: string, name: string): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.SELECT, + returnList: true, + query: + "SELECT nested.*, (\n" + + " SELECT json_agg(sub_type.*)\n" + + " FROM sub_type\n" + + ") as some_array_field\n" + + "FROM nested" + }) + getMultipleNesteds(): Promise> { + return null; + } +} diff --git a/packages/sql-decorators/test/repository/nullable-dao.ts b/packages/sql-decorators/test/repository/nullable-dao.ts new file mode 100644 index 0000000..9e19259 --- /dev/null +++ b/packages/sql-decorators/test/repository/nullable-dao.ts @@ -0,0 +1,31 @@ +import { Dao, DaoBase, SqlQuery } from "@zeroshotbuilders/sql-decorators"; +import { QueryTypes } from "sequelize"; + +export type NullableRecord = { + someId: string; + someNullableString: string | undefined; + someNullableNumber: number | undefined; +}; + +@Dao() +export class NullableDao extends DaoBase { + @SqlQuery({ + queryType: QueryTypes.INSERT, + query: + "INSERT INTO nullable_table (some_id, some_nullable_string, some_nullable_number) " + + "VALUES (:someId, :someNullableString, :someNullableNumber) RETURNING *" + }) + insertNullableRecord( + nullableRecord: NullableRecord + ): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.INSERT, + query: "SELECT * FROM nullable_table WHERE some_id = :id" + }) + selectNullableRecord(id: string): Promise { + return null; + } +} diff --git a/packages/sql-decorators/test/repository/some-folder/updateQuery.sql b/packages/sql-decorators/test/repository/some-folder/updateQuery.sql new file mode 100644 index 0000000..a85bf1e --- /dev/null +++ b/packages/sql-decorators/test/repository/some-folder/updateQuery.sql @@ -0,0 +1,4 @@ +UPDATE test +SET some_number = COALESCE(:newNumber, some_number) +WHERE some_string = :searchString +RETURNING *; diff --git a/packages/sql-decorators/test/repository/streamThings.sql b/packages/sql-decorators/test/repository/streamThings.sql new file mode 100644 index 0000000..3cb5245 --- /dev/null +++ b/packages/sql-decorators/test/repository/streamThings.sql @@ -0,0 +1,2 @@ +SELECT * +FROM test diff --git a/packages/sql-decorators/test/repository/test-dao.ts b/packages/sql-decorators/test/repository/test-dao.ts new file mode 100644 index 0000000..df0acd0 --- /dev/null +++ b/packages/sql-decorators/test/repository/test-dao.ts @@ -0,0 +1,157 @@ +import { Dao, SqlQuery, StreamSelect } from "@zeroshotbuilders/sql-decorators"; +import { QueryTypes, Sequelize } from "sequelize"; +import { + BooleanResult, + NumberResult, + StringResult +} from "../../src/result/result-types"; +import { StreamIterator } from "../../src/stream-iterator"; + +export type Thing = { + someString: string; + someNumber: number; + someInt: number; +}; + +@Dao({ + queryDirectory: __dirname +}) +export class TestDao { + private sequelize: Sequelize; + + constructor(sequelize: Sequelize) { + this.sequelize = sequelize; + } + + @SqlQuery({ + queryType: QueryTypes.INSERT + }) + insertQuery(thing: Thing): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.UPDATE, + file: `${__dirname}/some-folder/updateQuery.sql` + }) + updateQuery(newNumber: number, searchString: string): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.UPDATE, + returnList: true, + query: + "UPDATE test SET some_int = :newInt WHERE some_string in (:searchString1, :searchString2) returning *" + }) + updateMultipleThingsQuery( + newInt: number, + searchString1: string, + searchString2: string + ): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.BULKUPDATE, + query: + "UPDATE test SET some_int = :newInt WHERE some_string in (:searchString1, :searchString2)" + }) + bulkUpdateMultipleThingsQuery( + newInt: number, + searchString1: string, + searchString2: string + ): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.BULKDELETE, + query: + "DELETE FROM test WHERE some_string in (:searchString1, :searchString2)" + }) + deleteMultipleThingsQuery( + searchString1: string, + searchString2: string + ): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.SELECT, + query: "SELECT * FROM test where some_string = :someString" + }) + selectQuery(someString: string): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.UPSERT, + query: + "INSERT INTO test(some_string, some_number, some_int) VALUES (:someString, :someNumber, :someInt) ON CONFLICT (some_string) DO UPDATE SET some_number = :someNumber, some_int = :someInt;" + }) + upsertQuery(thing: Thing): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.UPDATE, + query: + "INSERT INTO test(some_string, some_number, some_int) VALUES (:someString, :someNumber, :someInt) ON CONFLICT (some_number) DO UPDATE SET some_int = :someInt RETURNING *;" + }) + upsertQueryWithReturn( + someString: string, + someNumber: number, + someInt: number + ): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.DELETE, + query: "DELETE FROM test where some_string = :someString" + }) + deleteQuery(someString: string): Promise { + return null; + } + + @StreamSelect({ + query: + "SELECT * FROM test where some_int >= :minInt and some_int <= :maxInt ORDER BY some_int ASC", + batchSize: 2 + }) + iterator(minInt: number, maxInt: number): StreamIterator { + return null; + } + + @StreamSelect({ + batchSize: 2 + }) + streamThings(minInt: number, maxInt: number): StreamIterator { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.SELECT, + query: "SELECT true as result" + }) + booleanResult(): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.SELECT, + query: "SELECT 'lol' as result" + }) + stringResult(): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.SELECT, + query: "SELECT 1 as result" + }) + numberResult(): Promise { + return null; + } +} diff --git a/packages/sql-decorators/test/repository/unconventional-dao.ts b/packages/sql-decorators/test/repository/unconventional-dao.ts new file mode 100644 index 0000000..e38ddbf --- /dev/null +++ b/packages/sql-decorators/test/repository/unconventional-dao.ts @@ -0,0 +1,29 @@ +import { Dao, DaoBase, SqlQuery } from "@zeroshotbuilders/sql-decorators"; +import { QueryTypes } from "sequelize"; + +export type UnconventionalType = { + some1Name2With3Numbers4Intertwined: string; + someNameEndingInANumber1: string; +}; + +@Dao() +export class UnconventionalDao extends DaoBase { + @SqlQuery({ + queryType: QueryTypes.INSERT, + query: + "INSERT INTO unconventional (some_1_name_2_with_3_numbers_4_intertwined, some_name_ending_in_a_number_1) VALUES (:some1Name2With3Numbers4Intertwined, :someNameEndingInANumber1) RETURNING *" + }) + insertUnconventionalType( + unconventionalType: UnconventionalType + ): Promise { + return null; + } + + @SqlQuery({ + queryType: QueryTypes.SELECT, + query: "SELECT * FROM unconventional" + }) + selectUnconventionalType(): Promise { + return null; + } +} diff --git a/packages/sql-decorators/test/transaction-repository/test-repository.ts b/packages/sql-decorators/test/transaction-repository/test-repository.ts new file mode 100644 index 0000000..490d73c --- /dev/null +++ b/packages/sql-decorators/test/transaction-repository/test-repository.ts @@ -0,0 +1,91 @@ +import { + SqlTransaction, + TransactionalityBase, + WithTransactionality +} from "@zeroshotbuilders/sql-decorators"; +import { List } from "immutable"; +import * as randomstring from "randomstring"; +import { Sequelize, Transaction } from "sequelize"; +import { EnumDao, EnumRecord, SomeEnum } from "../repository/enum-dao"; +import { Lol, LolDao } from "../repository/lol-dao"; + +@WithTransactionality() +export class TestRepository extends TransactionalityBase { + constructor( + sequelize: Sequelize, + private readonly lolDao: LolDao, + private readonly enumDao: EnumDao + ) { + super(sequelize); + } + + @SqlTransaction() + public async insertLolsAndEnumsInTransaction( + lolRecord: Lol, + enumRecord: EnumRecord, + transaction?: Transaction + ): Promise<{ lolRecord: Lol; enumRecord: EnumRecord }> { + const insertedEnumRecord = + await this.enumDao.insertEnumRecordTransactionally( + enumRecord, + transaction + ); + const insertedLolRecord = await this.lolDao.insertLolTransactionally( + lolRecord, + transaction + ); + return { + lolRecord: insertedLolRecord, + enumRecord: insertedEnumRecord + }; + } + + @SqlTransaction({ + isolationLevel: Transaction.ISOLATION_LEVELS.SERIALIZABLE, + type: Transaction.TYPES.IMMEDIATE + }) + public async nestedTransaction( + transaction?: Transaction + ): Promise> { + return this.enumDao.insertManyTransactionally( + List.of( + { + someId: randomstring.generate(), + someEnum: SomeEnum.A + }, + { + someId: randomstring.generate(), + someEnum: SomeEnum.B + } + ), + transaction + ); + } + + @SqlTransaction({ + isolationLevel: Transaction.ISOLATION_LEVELS.SERIALIZABLE, + type: Transaction.TYPES.IMMEDIATE + }) + public async triggerRollback( + lolRecord: Lol, + transaction?: Transaction + ): Promise { + // Should get rolled back + const insertedLolRecord = await this.lolDao.insertLolTransactionally( + lolRecord, + transaction + ); + const repeatedId = randomstring.generate(); + const insertedEnumRecord = + await this.enumDao.insertEnumRecordTransactionally( + { someId: repeatedId, someEnum: SomeEnum.A }, + transaction + ); + // Should fail on duplicate PK + const failedEnumRecord = await this.enumDao.insertEnumRecordTransactionally( + { someId: repeatedId, someEnum: SomeEnum.B }, + transaction + ); + return insertedLolRecord; + } +} diff --git a/packages/sql-decorators/tsconfig.json b/packages/sql-decorators/tsconfig.json new file mode 100644 index 0000000..46167d5 --- /dev/null +++ b/packages/sql-decorators/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc" + }, + "files": [], + "include": [], + "references": [ + { "path": "./tsconfig.lib.json" }, + { "path": "./tsconfig.spec.json" } + ] +} diff --git a/packages/sql-decorators/tsconfig.lib.json b/packages/sql-decorators/tsconfig.lib.json new file mode 100644 index 0000000..e927de6 --- /dev/null +++ b/packages/sql-decorators/tsconfig.lib.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "declaration": true, + "types": ["node", "reflect-metadata"] + }, + "include": ["index.ts", "src/**/*.ts"], + "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] +} diff --git a/packages/sql-decorators/tsconfig.spec.json b/packages/sql-decorators/tsconfig.spec.json new file mode 100644 index 0000000..3835753 --- /dev/null +++ b/packages/sql-decorators/tsconfig.spec.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node", "reflect-metadata"] + }, + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.d.ts", + "test/**/*.ts" + ] +} diff --git a/packages/tavily-utils/.eslintrc.json b/packages/tavily-utils/.eslintrc.json new file mode 100644 index 0000000..f1ff0d9 --- /dev/null +++ b/packages/tavily-utils/.eslintrc.json @@ -0,0 +1,10 @@ +{ + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "rules": {} + } + ] +} diff --git a/packages/tavily-utils/index.ts b/packages/tavily-utils/index.ts new file mode 100644 index 0000000..8df77eb --- /dev/null +++ b/packages/tavily-utils/index.ts @@ -0,0 +1,8 @@ +export const TAVILY_APPLICATION_ROOT = "TavilyApplicationRoot"; +export * from "./src/tavily-client-module"; +export * from "./src/tavily-client-factory"; +export * from "./src/config/tavily-client-config"; +export * from "./src/service/tavily-service"; +export * from "./src/service/tavily-service-local"; +export * from "./src/service/tavily-service-remote"; +export * from "./src/tools"; diff --git a/packages/tavily-utils/jest.config.ts b/packages/tavily-utils/jest.config.ts new file mode 100644 index 0000000..19470d8 --- /dev/null +++ b/packages/tavily-utils/jest.config.ts @@ -0,0 +1,10 @@ +export default { + displayName: "tavily-utils", + preset: "../../jest.preset.js", + testEnvironment: "node", + transform: { + "^.+\\.[tj]s$": "ts-jest" + }, + moduleFileExtensions: ["ts", "js", "html"], + coverageDirectory: "../../coverage/packages/tavily-utils" +}; diff --git a/packages/tavily-utils/package.json b/packages/tavily-utils/package.json new file mode 100644 index 0000000..d1e06b5 --- /dev/null +++ b/packages/tavily-utils/package.json @@ -0,0 +1,19 @@ +{ + "name": "@zeroshotbuilders/tavily-utils", + "version": "0.0.1", + "type": "commonjs", + "main": "./src/index.ts", + "publishConfig": { + "main": "./index.js", + "types": "./index.d.ts", + "access": "public" + }, + "dependencies": { + "@tavily/core": "^0.6.0" + }, + "peerDependencies": { + "@nestjs/common": ">=10.0.0", + "@openai/agents": ">=0.3.0", + "@zeroshotbuilders/commons": ">=0.0.1" + } +} diff --git a/packages/tavily-utils/project.json b/packages/tavily-utils/project.json new file mode 100644 index 0000000..8819c77 --- /dev/null +++ b/packages/tavily-utils/project.json @@ -0,0 +1,29 @@ +{ + "name": "tavily-utils", + "sourceRoot": "packages/tavily-utils/src", + "projectType": "library", + "targets": { + "build": { + "executor": "@nx/js:tsc", + "options": { + "outputPath": "dist/packages/tavily-utils", + "main": "packages/tavily-utils/src/index.ts", + "tsConfig": "packages/tavily-utils/tsconfig.lib.json" + } + }, + "test": { + "executor": "@nx/jest:jest", + "options": { + "jestConfig": "packages/tavily-utils/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": ["packages/tavily-utils/**/*.ts"] + } + } + }, + "tags": [] +} diff --git a/packages/tavily-utils/src/config/tavily-client-config.ts b/packages/tavily-utils/src/config/tavily-client-config.ts new file mode 100644 index 0000000..3ed1cb4 --- /dev/null +++ b/packages/tavily-utils/src/config/tavily-client-config.ts @@ -0,0 +1,20 @@ +import { ApplicationConfig, loadConfig } from "@zeroshotbuilders/commons"; +import { Injectable } from "@nestjs/common"; + +@Injectable() +export class TavilyClientConfig { + private static readonly CONFIG_KEY = "tavily"; + + readonly apiToken: string; + + constructor(applicationConfig: ApplicationConfig) { + const config = loadConfig( + applicationConfig.applicationRoot, + TavilyClientConfig.CONFIG_KEY + ); + + return { + apiToken: config.apiToken + }; + } +} diff --git a/packages/tavily-utils/src/service/tavily-service-local.ts b/packages/tavily-utils/src/service/tavily-service-local.ts new file mode 100644 index 0000000..0262ccd --- /dev/null +++ b/packages/tavily-utils/src/service/tavily-service-local.ts @@ -0,0 +1,91 @@ +import { + ExtractOptions, + ExtractResponse, + SearchOptions, + SearchResponse, + TavilyService +} from "./tavily-service"; + +export class TavilyServiceLocal implements TavilyService { + private static instance: TavilyServiceLocal = new TavilyServiceLocal(); + + private static extractOverride: + | ((urls: string[], options?: ExtractOptions) => Promise) + | undefined; + + private static searchOverride: + | ((query: string, options?: SearchOptions) => Promise) + | undefined; + + public static getInstance(): TavilyServiceLocal { + return TavilyServiceLocal.instance; + } + + public static setExtractOverride( + override: ( + urls: string[], + options?: ExtractOptions + ) => Promise + ): void { + this.extractOverride = override; + } + + public static setSearchOverride( + override: ( + query: string, + options?: SearchOptions + ) => Promise + ): void { + this.searchOverride = override; + } + + public static clearExtractOverride(): void { + this.extractOverride = undefined; + } + + public static clearSearchOverride(): void { + this.searchOverride = undefined; + } + + public static clearAllOverrides(): void { + this.extractOverride = undefined; + this.searchOverride = undefined; + } + + async extract( + urls: string[], + options?: ExtractOptions + ): Promise { + if (TavilyServiceLocal.extractOverride) { + return TavilyServiceLocal.extractOverride(urls, options); + } + + return { + results: urls.map((url) => ({ + url, + rawContent: `Mock content for ${url}` + })), + failedResults: [] + }; + } + + async search( + query: string, + options?: SearchOptions + ): Promise { + if (TavilyServiceLocal.searchOverride) { + return TavilyServiceLocal.searchOverride(query, options); + } + + const maxResults = options?.maxResults ?? 5; + return { + answer: options?.includeAnswer ? `Mock answer for: ${query}` : undefined, + results: Array.from({ length: maxResults }, (_, i) => ({ + title: `Mock Result ${i + 1} for ${query}`, + url: `https://example.com/result-${i + 1}`, + content: `Mock content snippet ${i + 1} for query: ${query}`, + score: 1 - i * 0.1 + })) + }; + } +} diff --git a/packages/tavily-utils/src/service/tavily-service-remote.ts b/packages/tavily-utils/src/service/tavily-service-remote.ts new file mode 100644 index 0000000..95287b3 --- /dev/null +++ b/packages/tavily-utils/src/service/tavily-service-remote.ts @@ -0,0 +1,57 @@ +import { tavily } from "@tavily/core"; +import { TavilyClientConfig } from "../config/tavily-client-config"; +import { + ExtractOptions, + ExtractResponse, + SearchOptions, + SearchResponse, + TavilyService +} from "./tavily-service"; + +export class TavilyServiceRemote implements TavilyService { + private readonly client: ReturnType; + + constructor(config: TavilyClientConfig) { + this.client = tavily({ apiKey: config.apiToken }); + } + + async extract( + urls: string[], + options?: ExtractOptions + ): Promise { + const response = await this.client.extract(urls, { + format: options?.format + }); + + return { + results: response.results.map((result) => ({ + url: result.url, + rawContent: result.rawContent + })), + failedResults: response.failedResults.map((result) => ({ + url: result.url, + error: result.error + })) + }; + } + + async search( + query: string, + options?: SearchOptions + ): Promise { + const response = await this.client.search(query, { + maxResults: options?.maxResults, + includeAnswer: options?.includeAnswer + }); + + return { + answer: response.answer, + results: response.results.map((result) => ({ + title: result.title, + url: result.url, + content: result.content, + score: result.score + })) + }; + } +} diff --git a/packages/tavily-utils/src/service/tavily-service.ts b/packages/tavily-utils/src/service/tavily-service.ts new file mode 100644 index 0000000..8a31b85 --- /dev/null +++ b/packages/tavily-utils/src/service/tavily-service.ts @@ -0,0 +1,40 @@ +export interface ExtractResult { + url: string; + rawContent: string; +} + +export interface ExtractFailedResult { + url: string; + error: string; +} + +export interface ExtractResponse { + results: ExtractResult[]; + failedResults: ExtractFailedResult[]; +} + +export interface ExtractOptions { + format?: "markdown" | "text"; +} + +export interface SearchResult { + title: string; + url: string; + content: string; + score: number; +} + +export interface SearchResponse { + answer?: string; + results: SearchResult[]; +} + +export interface SearchOptions { + maxResults?: number; + includeAnswer?: boolean; +} + +export interface TavilyService { + extract(urls: string[], options?: ExtractOptions): Promise; + search(query: string, options?: SearchOptions): Promise; +} diff --git a/packages/tavily-utils/src/tavily-client-factory.ts b/packages/tavily-utils/src/tavily-client-factory.ts new file mode 100644 index 0000000..a8acd13 --- /dev/null +++ b/packages/tavily-utils/src/tavily-client-factory.ts @@ -0,0 +1,21 @@ +import { ApplicationConfig } from "@zeroshotbuilders/commons"; +import { Injectable } from "@nestjs/common"; +import { TavilyClientConfig } from "./config/tavily-client-config"; +import { TavilyService } from "./service/tavily-service"; +import { TavilyServiceLocal } from "./service/tavily-service-local"; +import { TavilyServiceRemote } from "./service/tavily-service-remote"; + +@Injectable() +export class TavilyClientFactory { + constructor( + private readonly applicationConfig: ApplicationConfig, + private readonly config: TavilyClientConfig + ) {} + + public makeTavilyService(): TavilyService { + if (this.applicationConfig.local) { + return TavilyServiceLocal.getInstance(); + } + return new TavilyServiceRemote(this.config); + } +} diff --git a/packages/tavily-utils/src/tavily-client-module.ts b/packages/tavily-utils/src/tavily-client-module.ts new file mode 100644 index 0000000..c7ae915 --- /dev/null +++ b/packages/tavily-utils/src/tavily-client-module.ts @@ -0,0 +1,37 @@ +import { + ConfigModule, + ApplicationConfig +} from "@zeroshotbuilders/commons"; +import { DynamicModule, Module } from "@nestjs/common"; +import { TAVILY_APPLICATION_ROOT } from "../index"; +import { TavilyClientConfig } from "./config/tavily-client-config"; +import { TavilyClientFactory } from "./tavily-client-factory"; + +export const TAVILY_CLIENT = "TAVILY_CLIENT"; + +@Module({}) +export class TavilyClientModule { + public static forApplicationRoot(applicationRoot: string): DynamicModule { + return { + module: TavilyClientModule, + imports: [ + ConfigModule.forApplicationRoot(applicationRoot) + ], + providers: [ + { + provide: TAVILY_APPLICATION_ROOT, + useValue: applicationRoot + }, + TavilyClientConfig, + TavilyClientFactory, + { + provide: TAVILY_CLIENT, + useFactory: (tavilyClientFactory: TavilyClientFactory) => + tavilyClientFactory.makeTavilyService(), + inject: [TavilyClientFactory] + } + ], + exports: [TAVILY_CLIENT] + }; + } +} diff --git a/packages/tavily-utils/src/tools/get-web-content.ts b/packages/tavily-utils/src/tools/get-web-content.ts new file mode 100644 index 0000000..c7e81f8 --- /dev/null +++ b/packages/tavily-utils/src/tools/get-web-content.ts @@ -0,0 +1,64 @@ +import { tool } from "@openai/agents"; +import { TavilyService } from "../service/tavily-service"; +import { z } from "zod"; + +const GetWebContentParametersSchema = z.object({ + urls: z + .array(z.string()) + .describe("The URLs of the web pages to extract content from") +}); + +export type GetWebContentOptions = { + tavilyService: TavilyService; + maxContentLength?: number; +}; + +export const GET_WEB_CONTENT_TOOL_NAME = "get_web_content"; + +/** + * Creates a tool that uses Tavily extract to fetch the contents of web pages. + * + * @param options Configuration options including the Tavily service + * @returns A function tool that can be used with AI agents + */ +export function getWebContentTool(options: GetWebContentOptions) { + const { tavilyService } = options; + const maxContentLength = options.maxContentLength ?? 12000; + + const truncateContent = (content: string, maxLength: number): string => { + if (content.length <= maxLength) { + return content; + } + return `${content.slice( + 0, + maxLength + )}\n\n[Content truncated to ${maxLength} characters]`; + }; + + return tool({ + name: GET_WEB_CONTENT_TOOL_NAME, + description: + "Fetch and extract the content from one or more web pages. Returns the raw content of each page.", + parameters: GetWebContentParametersSchema, + execute: async (input) => { + const response = await tavilyService.extract(input.urls, { + format: "markdown" + }); + + const results = response.results.map((result) => ({ + url: result.url, + content: truncateContent(result.rawContent, maxContentLength) + })); + + const failedResults = response.failedResults.map((result) => ({ + url: result.url, + error: result.error + })); + + return JSON.stringify({ + results, + failedResults + }); + } + }); +} diff --git a/packages/tavily-utils/src/tools/index.ts b/packages/tavily-utils/src/tools/index.ts new file mode 100644 index 0000000..2e08f54 --- /dev/null +++ b/packages/tavily-utils/src/tools/index.ts @@ -0,0 +1,16 @@ +import { GET_WEB_CONTENT_TOOL_NAME } from "./get-web-content"; +import { WEB_SEARCH_TOOL_NAME } from "./web-search"; + +/** + * Registry of common tools available across all agents. + * Maps human-friendly keys to actual tool names. + */ +export const COMMON_TOOL_REGISTRY = { + webSearch: WEB_SEARCH_TOOL_NAME, + webContent: GET_WEB_CONTENT_TOOL_NAME +} as const; + +export type CommonToolKey = keyof typeof COMMON_TOOL_REGISTRY; + +export * from "./get-web-content"; +export * from "./web-search"; diff --git a/packages/tavily-utils/src/tools/web-search.ts b/packages/tavily-utils/src/tools/web-search.ts new file mode 100644 index 0000000..7056a70 --- /dev/null +++ b/packages/tavily-utils/src/tools/web-search.ts @@ -0,0 +1,53 @@ +import { TavilyService } from "../service/tavily-service"; +import { tool } from "@openai/agents"; +import { z } from "zod"; + +const WebSearchParametersSchema = z.object({ + query: z.string().describe("The search query to look up on the web"), + maxResults: z + .number() + .default(5) + .describe("Maximum number of results to return (default: 5)") +}); + +export type WebSearchOptions = { + tavilyService: TavilyService; + maxResults?: number; +}; + +export const WEB_SEARCH_TOOL_NAME = "web_search"; + +/** + * Creates a web search tool that uses Tavily to search the web for a given query. + * + * @param options Configuration options including the Tavily service + * @returns A function tool that can be used with AI agents + */ +export function webSearchTool(options: WebSearchOptions) { + const { tavilyService } = options; + + return tool({ + name: WEB_SEARCH_TOOL_NAME, + description: + "Search the web for information about a given query. Returns relevant search results with titles, URLs, and content snippets.", + parameters: WebSearchParametersSchema, + execute: async (input) => { + const response = await tavilyService.search(input.query, { + maxResults: input.maxResults ?? options.maxResults ?? 5, + includeAnswer: true + }); + + const results = response.results.map((result) => ({ + title: result.title, + url: result.url, + content: result.content, + score: result.score + })); + + return JSON.stringify({ + answer: response.answer, + results + }); + } + }); +} diff --git a/packages/tavily-utils/tsconfig.json b/packages/tavily-utils/tsconfig.json new file mode 100644 index 0000000..46167d5 --- /dev/null +++ b/packages/tavily-utils/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc" + }, + "files": [], + "include": [], + "references": [ + { "path": "./tsconfig.lib.json" }, + { "path": "./tsconfig.spec.json" } + ] +} diff --git a/packages/tavily-utils/tsconfig.lib.json b/packages/tavily-utils/tsconfig.lib.json new file mode 100644 index 0000000..e927de6 --- /dev/null +++ b/packages/tavily-utils/tsconfig.lib.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "declaration": true, + "types": ["node", "reflect-metadata"] + }, + "include": ["index.ts", "src/**/*.ts"], + "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] +} diff --git a/packages/tavily-utils/tsconfig.spec.json b/packages/tavily-utils/tsconfig.spec.json new file mode 100644 index 0000000..b52d392 --- /dev/null +++ b/packages/tavily-utils/tsconfig.spec.json @@ -0,0 +1,14 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node", "reflect-metadata"] + }, + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/tsconfig.base.json b/tsconfig.base.json new file mode 100644 index 0000000..1aeeb12 --- /dev/null +++ b/tsconfig.base.json @@ -0,0 +1,36 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es2022", + "lib": ["es2022"], + "moduleResolution": "node", + "baseUrl": ".", + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "useDefineForClassFields": false, + "esModuleInterop": true, + "skipLibCheck": true, + "strictNullChecks": false, + "strictFunctionTypes": true, + "strictBindCallApply": true, + "strictPropertyInitialization": false, + "noImplicitAny": true, + "noImplicitThis": true, + "alwaysStrict": true, + "removeComments": true, + "incremental": true, + "types": ["reflect-metadata"], + "paths": { + "@zeroshotbuilders/commons": ["packages/commons/index.ts"], + "@zeroshotbuilders/commons-testing": ["packages/commons-testing/index.ts"], + "@zeroshotbuilders/agentic-workflows": ["packages/agentic-workflows/index.ts"], + "@zeroshotbuilders/openai-utils": ["packages/openai-utils/index.ts"], + "@zeroshotbuilders/sql-decorators": ["packages/sql-decorators/index.ts"], + "@zeroshotbuilders/tavily-utils": ["packages/tavily-utils/index.ts"] + } + }, + "exclude": ["node_modules"] +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..e108d2b --- /dev/null +++ b/yarn.lock @@ -0,0 +1,13790 @@ +# This file is generated by running "yarn install" inside your project. +# Manual changes might be lost - proceed with caution! + +__metadata: + version: 8 + cacheKey: 10c0 + +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.27.1, @babel/code-frame@npm:^7.28.6, @babel/code-frame@npm:^7.29.0": + version: 7.29.0 + resolution: "@babel/code-frame@npm:7.29.0" + dependencies: + "@babel/helper-validator-identifier": "npm:^7.28.5" + js-tokens: "npm:^4.0.0" + picocolors: "npm:^1.1.1" + checksum: 10c0/d34cc504e7765dfb576a663d97067afb614525806b5cad1a5cc1a7183b916fec8ff57fa233585e3926fd5a9e6b31aae6df91aa81ae9775fb7a28f658d3346f0d + languageName: node + linkType: hard + +"@babel/compat-data@npm:^7.28.6, @babel/compat-data@npm:^7.29.0": + version: 7.29.0 + resolution: "@babel/compat-data@npm:7.29.0" + checksum: 10c0/08f348554989d23aa801bf1405aa34b15e841c0d52d79da7e524285c77a5f9d298e70e11d91cc578d8e2c9542efc586d50c5f5cf8e1915b254a9dcf786913a94 + languageName: node + linkType: hard + +"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.23.2, @babel/core@npm:^7.23.9, @babel/core@npm:^7.27.4": + version: 7.29.0 + resolution: "@babel/core@npm:7.29.0" + dependencies: + "@babel/code-frame": "npm:^7.29.0" + "@babel/generator": "npm:^7.29.0" + "@babel/helper-compilation-targets": "npm:^7.28.6" + "@babel/helper-module-transforms": "npm:^7.28.6" + "@babel/helpers": "npm:^7.28.6" + "@babel/parser": "npm:^7.29.0" + "@babel/template": "npm:^7.28.6" + "@babel/traverse": "npm:^7.29.0" + "@babel/types": "npm:^7.29.0" + "@jridgewell/remapping": "npm:^2.3.5" + convert-source-map: "npm:^2.0.0" + debug: "npm:^4.1.0" + gensync: "npm:^1.0.0-beta.2" + json5: "npm:^2.2.3" + semver: "npm:^6.3.1" + checksum: 10c0/5127d2e8e842ae409e11bcbb5c2dff9874abf5415e8026925af7308e903f4f43397341467a130490d1a39884f461bc2b67f3063bce0be44340db89687fd852aa + languageName: node + linkType: hard + +"@babel/generator@npm:^7.27.5, @babel/generator@npm:^7.29.0, @babel/generator@npm:^7.7.2": + version: 7.29.1 + resolution: "@babel/generator@npm:7.29.1" + dependencies: + "@babel/parser": "npm:^7.29.0" + "@babel/types": "npm:^7.29.0" + "@jridgewell/gen-mapping": "npm:^0.3.12" + "@jridgewell/trace-mapping": "npm:^0.3.28" + jsesc: "npm:^3.0.2" + checksum: 10c0/349086e6876258ef3fb2823030fee0f6c0eb9c3ebe35fc572e16997f8c030d765f636ddc6299edae63e760ea6658f8ee9a2edfa6d6b24c9a80c917916b973551 + languageName: node + linkType: hard + +"@babel/helper-annotate-as-pure@npm:^7.27.1, @babel/helper-annotate-as-pure@npm:^7.27.3": + version: 7.27.3 + resolution: "@babel/helper-annotate-as-pure@npm:7.27.3" + dependencies: + "@babel/types": "npm:^7.27.3" + checksum: 10c0/94996ce0a05b7229f956033e6dcd69393db2b0886d0db6aff41e704390402b8cdcca11f61449cb4f86cfd9e61b5ad3a73e4fa661eeed7846b125bd1c33dbc633 + languageName: node + linkType: hard + +"@babel/helper-compilation-targets@npm:^7.27.1, @babel/helper-compilation-targets@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/helper-compilation-targets@npm:7.28.6" + dependencies: + "@babel/compat-data": "npm:^7.28.6" + "@babel/helper-validator-option": "npm:^7.27.1" + browserslist: "npm:^4.24.0" + lru-cache: "npm:^5.1.1" + semver: "npm:^6.3.1" + checksum: 10c0/3fcdf3b1b857a1578e99d20508859dbd3f22f3c87b8a0f3dc540627b4be539bae7f6e61e49d931542fe5b557545347272bbdacd7f58a5c77025a18b745593a50 + languageName: node + linkType: hard + +"@babel/helper-create-class-features-plugin@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/helper-create-class-features-plugin@npm:7.28.6" + dependencies: + "@babel/helper-annotate-as-pure": "npm:^7.27.3" + "@babel/helper-member-expression-to-functions": "npm:^7.28.5" + "@babel/helper-optimise-call-expression": "npm:^7.27.1" + "@babel/helper-replace-supers": "npm:^7.28.6" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.27.1" + "@babel/traverse": "npm:^7.28.6" + semver: "npm:^6.3.1" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/0b62b46717891f4366006b88c9b7f277980d4f578c4c3789b7a4f5a2e09e121de4cda9a414ab403986745cd3ad1af3fe2d948c9f78ab80d4dc085afc9602af50 + languageName: node + linkType: hard + +"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.27.1, @babel/helper-create-regexp-features-plugin@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/helper-create-regexp-features-plugin@npm:7.28.5" + dependencies: + "@babel/helper-annotate-as-pure": "npm:^7.27.3" + regexpu-core: "npm:^6.3.1" + semver: "npm:^6.3.1" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/7af3d604cadecdb2b0d2cedd696507f02a53a58be0523281c2d6766211443b55161dde1e6c0d96ab16ddfd82a2607a2f792390caa24797e9733631f8aa86859f + languageName: node + linkType: hard + +"@babel/helper-define-polyfill-provider@npm:^0.6.5, @babel/helper-define-polyfill-provider@npm:^0.6.8": + version: 0.6.8 + resolution: "@babel/helper-define-polyfill-provider@npm:0.6.8" + dependencies: + "@babel/helper-compilation-targets": "npm:^7.28.6" + "@babel/helper-plugin-utils": "npm:^7.28.6" + debug: "npm:^4.4.3" + lodash.debounce: "npm:^4.0.8" + resolve: "npm:^1.22.11" + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: 10c0/306a169f2cb285f368578219ef18ea9702860d3d02d64334f8d45ea38648be0b9e1edad8c8f732fa34bb4206ccbb9883c395570fd57ab7bbcf293bc5964c5b3a + languageName: node + linkType: hard + +"@babel/helper-globals@npm:^7.28.0": + version: 7.28.0 + resolution: "@babel/helper-globals@npm:7.28.0" + checksum: 10c0/5a0cd0c0e8c764b5f27f2095e4243e8af6fa145daea2b41b53c0c1414fe6ff139e3640f4e2207ae2b3d2153a1abd346f901c26c290ee7cb3881dd922d4ee9232 + languageName: node + linkType: hard + +"@babel/helper-member-expression-to-functions@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/helper-member-expression-to-functions@npm:7.28.5" + dependencies: + "@babel/traverse": "npm:^7.28.5" + "@babel/types": "npm:^7.28.5" + checksum: 10c0/4e6e05fbf4dffd0bc3e55e28fcaab008850be6de5a7013994ce874ec2beb90619cda4744b11607a60f8aae0227694502908add6188ceb1b5223596e765b44814 + languageName: node + linkType: hard + +"@babel/helper-module-imports@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/helper-module-imports@npm:7.28.6" + dependencies: + "@babel/traverse": "npm:^7.28.6" + "@babel/types": "npm:^7.28.6" + checksum: 10c0/b49d8d8f204d9dbfd5ac70c54e533e5269afb3cea966a9d976722b13e9922cc773a653405f53c89acb247d5aebdae4681d631a3ae3df77ec046b58da76eda2ac + languageName: node + linkType: hard + +"@babel/helper-module-transforms@npm:^7.27.1, @babel/helper-module-transforms@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/helper-module-transforms@npm:7.28.6" + dependencies: + "@babel/helper-module-imports": "npm:^7.28.6" + "@babel/helper-validator-identifier": "npm:^7.28.5" + "@babel/traverse": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/6f03e14fc30b287ce0b839474b5f271e72837d0cafe6b172d759184d998fbee3903a035e81e07c2c596449e504f453463d58baa65b6f40a37ded5bec74620b2b + languageName: node + linkType: hard + +"@babel/helper-optimise-call-expression@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helper-optimise-call-expression@npm:7.27.1" + dependencies: + "@babel/types": "npm:^7.27.1" + checksum: 10c0/6b861e7fcf6031b9c9fc2de3cd6c005e94a459d6caf3621d93346b52774925800ca29d4f64595a5ceacf4d161eb0d27649ae385110ed69491d9776686fa488e6 + languageName: node + linkType: hard + +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.27.1, @babel/helper-plugin-utils@npm:^7.28.6, @babel/helper-plugin-utils@npm:^7.8.0": + version: 7.28.6 + resolution: "@babel/helper-plugin-utils@npm:7.28.6" + checksum: 10c0/3f5f8acc152fdbb69a84b8624145ff4f9b9f6e776cb989f9f968f8606eb7185c5c3cfcf3ba08534e37e1e0e1c118ac67080610333f56baa4f7376c99b5f1143d + languageName: node + linkType: hard + +"@babel/helper-remap-async-to-generator@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helper-remap-async-to-generator@npm:7.27.1" + dependencies: + "@babel/helper-annotate-as-pure": "npm:^7.27.1" + "@babel/helper-wrap-function": "npm:^7.27.1" + "@babel/traverse": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/5ba6258f4bb57c7c9fa76b55f416b2d18c867b48c1af4f9f2f7cd7cc933fe6da7514811d08ceb4972f1493be46f4b69c40282b811d1397403febae13c2ec57b5 + languageName: node + linkType: hard + +"@babel/helper-replace-supers@npm:^7.27.1, @babel/helper-replace-supers@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/helper-replace-supers@npm:7.28.6" + dependencies: + "@babel/helper-member-expression-to-functions": "npm:^7.28.5" + "@babel/helper-optimise-call-expression": "npm:^7.27.1" + "@babel/traverse": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/04663c6389551b99b8c3e7ba4e2638b8ca2a156418c26771516124c53083aa8e74b6a45abe5dd46360af79709a0e9c6b72c076d0eab9efecdd5aaf836e79d8d5 + languageName: node + linkType: hard + +"@babel/helper-skip-transparent-expression-wrappers@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.27.1" + dependencies: + "@babel/traverse": "npm:^7.27.1" + "@babel/types": "npm:^7.27.1" + checksum: 10c0/f625013bcdea422c470223a2614e90d2c1cc9d832e97f32ca1b4f82b34bb4aa67c3904cb4b116375d3b5b753acfb3951ed50835a1e832e7225295c7b0c24dff7 + languageName: node + linkType: hard + +"@babel/helper-string-parser@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helper-string-parser@npm:7.27.1" + checksum: 10c0/8bda3448e07b5583727c103560bcf9c4c24b3c1051a4c516d4050ef69df37bb9a4734a585fe12725b8c2763de0a265aa1e909b485a4e3270b7cfd3e4dbe4b602 + languageName: node + linkType: hard + +"@babel/helper-validator-identifier@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/helper-validator-identifier@npm:7.28.5" + checksum: 10c0/42aaebed91f739a41f3d80b72752d1f95fd7c72394e8e4bd7cdd88817e0774d80a432451bcba17c2c642c257c483bf1d409dd4548883429ea9493a3bc4ab0847 + languageName: node + linkType: hard + +"@babel/helper-validator-option@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helper-validator-option@npm:7.27.1" + checksum: 10c0/6fec5f006eba40001a20f26b1ef5dbbda377b7b68c8ad518c05baa9af3f396e780bdfded24c4eef95d14bb7b8fd56192a6ed38d5d439b97d10efc5f1a191d148 + languageName: node + linkType: hard + +"@babel/helper-wrap-function@npm:^7.27.1": + version: 7.28.6 + resolution: "@babel/helper-wrap-function@npm:7.28.6" + dependencies: + "@babel/template": "npm:^7.28.6" + "@babel/traverse": "npm:^7.28.6" + "@babel/types": "npm:^7.28.6" + checksum: 10c0/110674c7aa705dd8cc34f278628f540b37a4cb35e81fcaf557772e026a6fd95f571feb51a8efb146e4e91bbf567dc9dd7f534f78da80f55f4be2ec842f36b678 + languageName: node + linkType: hard + +"@babel/helpers@npm:^7.28.6": + version: 7.29.2 + resolution: "@babel/helpers@npm:7.29.2" + dependencies: + "@babel/template": "npm:^7.28.6" + "@babel/types": "npm:^7.29.0" + checksum: 10c0/dab0e65b9318b2502a62c58bc0913572318595eec0482c31f0ad416b72636e6698a1d7c57cd2791d4528eb8c548bca88d338dc4d2a55a108dc1f6702f9bc5512 + languageName: node + linkType: hard + +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.28.6, @babel/parser@npm:^7.29.0": + version: 7.29.2 + resolution: "@babel/parser@npm:7.29.2" + dependencies: + "@babel/types": "npm:^7.29.0" + bin: + parser: ./bin/babel-parser.js + checksum: 10c0/e5a4e69e3ac7acdde995f37cf299a68458cfe7009dff66bd0962fd04920bef287201169006af365af479c08ff216bfefbb595e331f87f6ae7283858aebbc3317 + languageName: node + linkType: hard + +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.28.5" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + "@babel/traverse": "npm:^7.28.5" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/844b7c7e9eec6d858262b2f3d5af75d3a6bbd9d3ecc740d95271fbdd84985731674536f5d8ac98f2dc0e8872698b516e406636e4d0cb04b50afe471172095a53 + languageName: node + linkType: hard + +"@babel/plugin-bugfix-safari-class-field-initializer-scope@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-bugfix-safari-class-field-initializer-scope@npm:7.27.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/2cd7a55a856e5e59bbd9484247c092a41e0d9f966778e7019da324d9e0928892d26afc4fbb2ac3d76a3c5a631cd3cf0d72dd2653b44f634f6c663b9e6f80aacd + languageName: node + linkType: hard + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.27.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/cf29835498c4a25bd470908528919729a0799b2ec94e89004929a5532c94a5e4b1a49bc5d6673a22e5afe05d08465873e14ee3b28c42eb3db489cdf5ca47c680 + languageName: node + linkType: hard + +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:7.27.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.27.1" + "@babel/plugin-transform-optional-chaining": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.13.0 + checksum: 10c0/eddcd056f76e198868cbff883eb148acfade8f0890973ab545295df0c08e39573a72e65372bcc0b0bfadba1b043fe1aea6b0907d0b4889453ac154c404194ebc + languageName: node + linkType: hard + +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.28.6" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.28.6" + "@babel/traverse": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/f1a9194e8d1742081def7af748e9249eb5082c25d0ced292720a1f054895f99041c764a05f45af669a2c8898aeb79266058aedb0d3e1038963ad49be8288918a + languageName: node + linkType: hard + +"@babel/plugin-proposal-decorators@npm:^7.22.7": + version: 7.29.0 + resolution: "@babel/plugin-proposal-decorators@npm:7.29.0" + dependencies: + "@babel/helper-create-class-features-plugin": "npm:^7.28.6" + "@babel/helper-plugin-utils": "npm:^7.28.6" + "@babel/plugin-syntax-decorators": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/b397506fb245374544e2c52909dcbd2193b0327594e3493ea4a47d8a22f6991a90128900d6ee3b129be5246ee08b0d07c8796cfb60502aacf20ac52cc6a92b68 + languageName: node + linkType: hard + +"@babel/plugin-proposal-private-property-in-object@npm:7.21.0-placeholder-for-preset-env.2": + version: 7.21.0-placeholder-for-preset-env.2 + resolution: "@babel/plugin-proposal-private-property-in-object@npm:7.21.0-placeholder-for-preset-env.2" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/e605e0070da087f6c35579499e65801179a521b6842c15181a1e305c04fded2393f11c1efd09b087be7f8b083d1b75e8f3efcbc1292b4f60d3369e14812cff63 + languageName: node + linkType: hard + +"@babel/plugin-syntax-async-generators@npm:^7.8.4": + version: 7.8.4 + resolution: "@babel/plugin-syntax-async-generators@npm:7.8.4" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.8.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/d13efb282838481348c71073b6be6245b35d4f2f964a8f71e4174f235009f929ef7613df25f8d2338e2d3e44bc4265a9f8638c6aaa136d7a61fe95985f9725c8 + languageName: node + linkType: hard + +"@babel/plugin-syntax-bigint@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-bigint@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.8.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/686891b81af2bc74c39013655da368a480f17dd237bf9fbc32048e5865cb706d5a8f65438030da535b332b1d6b22feba336da8fa931f663b6b34e13147d12dde + languageName: node + linkType: hard + +"@babel/plugin-syntax-class-properties@npm:^7.12.13": + version: 7.12.13 + resolution: "@babel/plugin-syntax-class-properties@npm:7.12.13" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.12.13" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/95168fa186416195280b1264fb18afcdcdcea780b3515537b766cb90de6ce042d42dd6a204a39002f794ae5845b02afb0fd4861a3308a861204a55e68310a120 + languageName: node + linkType: hard + +"@babel/plugin-syntax-class-static-block@npm:^7.14.5": + version: 7.14.5 + resolution: "@babel/plugin-syntax-class-static-block@npm:7.14.5" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.14.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/4464bf9115f4a2d02ce1454411baf9cfb665af1da53709c5c56953e5e2913745b0fcce82982a00463d6facbdd93445c691024e310b91431a1e2f024b158f6371 + languageName: node + linkType: hard + +"@babel/plugin-syntax-decorators@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/plugin-syntax-decorators@npm:7.28.6" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/bd12119646f65e156709d1d6f4949758de36a4192c5c3057b5a5972b896386da5411a763aba087691edf539808616b254b84084b3340cff6e7968f9cab5004dd + languageName: node + linkType: hard + +"@babel/plugin-syntax-import-assertions@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/plugin-syntax-import-assertions@npm:7.28.6" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/f3b8bdccb9b4d3e3b9226684ca518e055399d05579da97dfe0160a38d65198cfe7dce809e73179d6463a863a040f980de32425a876d88efe4eda933d0d95982c + languageName: node + linkType: hard + +"@babel/plugin-syntax-import-attributes@npm:^7.24.7, @babel/plugin-syntax-import-attributes@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/plugin-syntax-import-attributes@npm:7.28.6" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/1be160e2c426faa74e5be2e30e39e8d0d8c543063bd5d06cd804f8751b8fbcb82ce824ca7f9ce4b09c003693f6c06a11ce503b7e34d85e1a259631e4c3f72ad2 + languageName: node + linkType: hard + +"@babel/plugin-syntax-import-meta@npm:^7.10.4": + version: 7.10.4 + resolution: "@babel/plugin-syntax-import-meta@npm:7.10.4" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.10.4" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/0b08b5e4c3128523d8e346f8cfc86824f0da2697b1be12d71af50a31aff7a56ceb873ed28779121051475010c28d6146a6bfea8518b150b71eeb4e46190172ee + languageName: node + linkType: hard + +"@babel/plugin-syntax-json-strings@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-json-strings@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.8.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/e98f31b2ec406c57757d115aac81d0336e8434101c224edd9a5c93cefa53faf63eacc69f3138960c8b25401315af03df37f68d316c151c4b933136716ed6906e + languageName: node + linkType: hard + +"@babel/plugin-syntax-jsx@npm:^7.27.1, @babel/plugin-syntax-jsx@npm:^7.7.2": + version: 7.28.6 + resolution: "@babel/plugin-syntax-jsx@npm:7.28.6" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/b98fc3cd75e4ca3d5ca1162f610c286e14ede1486e0d297c13a5eb0ac85680ac9656d17d348bddd9160a54d797a08cea5eaac02b9330ddebb7b26732b7b99fb5 + languageName: node + linkType: hard + +"@babel/plugin-syntax-logical-assignment-operators@npm:^7.10.4": + version: 7.10.4 + resolution: "@babel/plugin-syntax-logical-assignment-operators@npm:7.10.4" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.10.4" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/2594cfbe29411ad5bc2ad4058de7b2f6a8c5b86eda525a993959438615479e59c012c14aec979e538d60a584a1a799b60d1b8942c3b18468cb9d99b8fd34cd0b + languageName: node + linkType: hard + +"@babel/plugin-syntax-nullish-coalescing-operator@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-nullish-coalescing-operator@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.8.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/2024fbb1162899094cfc81152449b12bd0cc7053c6d4bda8ac2852545c87d0a851b1b72ed9560673cbf3ef6248257262c3c04aabf73117215c1b9cc7dd2542ce + languageName: node + linkType: hard + +"@babel/plugin-syntax-numeric-separator@npm:^7.10.4": + version: 7.10.4 + resolution: "@babel/plugin-syntax-numeric-separator@npm:7.10.4" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.10.4" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/c55a82b3113480942c6aa2fcbe976ff9caa74b7b1109ff4369641dfbc88d1da348aceb3c31b6ed311c84d1e7c479440b961906c735d0ab494f688bf2fd5b9bb9 + languageName: node + linkType: hard + +"@babel/plugin-syntax-object-rest-spread@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-object-rest-spread@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.8.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/ee1eab52ea6437e3101a0a7018b0da698545230015fc8ab129d292980ec6dff94d265e9e90070e8ae5fed42f08f1622c14c94552c77bcac784b37f503a82ff26 + languageName: node + linkType: hard + +"@babel/plugin-syntax-optional-catch-binding@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-optional-catch-binding@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.8.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/27e2493ab67a8ea6d693af1287f7e9acec206d1213ff107a928e85e173741e1d594196f99fec50e9dde404b09164f39dec5864c767212154ffe1caa6af0bc5af + languageName: node + linkType: hard + +"@babel/plugin-syntax-optional-chaining@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-optional-chaining@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.8.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/46edddf2faa6ebf94147b8e8540dfc60a5ab718e2de4d01b2c0bdf250a4d642c2bd47cbcbb739febcb2bf75514dbcefad3c52208787994b8d0f8822490f55e81 + languageName: node + linkType: hard + +"@babel/plugin-syntax-private-property-in-object@npm:^7.14.5": + version: 7.14.5 + resolution: "@babel/plugin-syntax-private-property-in-object@npm:7.14.5" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.14.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/69822772561706c87f0a65bc92d0772cea74d6bc0911537904a676d5ff496a6d3ac4e05a166d8125fce4a16605bace141afc3611074e170a994e66e5397787f3 + languageName: node + linkType: hard + +"@babel/plugin-syntax-top-level-await@npm:^7.14.5": + version: 7.14.5 + resolution: "@babel/plugin-syntax-top-level-await@npm:7.14.5" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.14.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/14bf6e65d5bc1231ffa9def5f0ef30b19b51c218fcecaa78cd1bdf7939dfdf23f90336080b7f5196916368e399934ce5d581492d8292b46a2fb569d8b2da106f + languageName: node + linkType: hard + +"@babel/plugin-syntax-typescript@npm:^7.27.1, @babel/plugin-syntax-typescript@npm:^7.28.6, @babel/plugin-syntax-typescript@npm:^7.3.3, @babel/plugin-syntax-typescript@npm:^7.7.2": + version: 7.28.6 + resolution: "@babel/plugin-syntax-typescript@npm:7.28.6" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/b0c392a35624883ac480277401ac7d92d8646b66e33639f5d350de7a6723924265985ae11ab9ebd551740ded261c443eaa9a87ea19def9763ca1e0d78c97dea8 + languageName: node + linkType: hard + +"@babel/plugin-syntax-unicode-sets-regex@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-syntax-unicode-sets-regex@npm:7.18.6" + dependencies: + "@babel/helper-create-regexp-features-plugin": "npm:^7.18.6" + "@babel/helper-plugin-utils": "npm:^7.18.6" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/9144e5b02a211a4fb9a0ce91063f94fbe1004e80bde3485a0910c9f14897cf83fabd8c21267907cff25db8e224858178df0517f14333cfcf3380ad9a4139cb50 + languageName: node + linkType: hard + +"@babel/plugin-transform-arrow-functions@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-transform-arrow-functions@npm:7.27.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/19abd7a7d11eef58c9340408a4c2594503f6c4eaea1baa7b0e5fbdda89df097e50663edb3448ad2300170b39efca98a75e5767af05cad3b0facb4944326896a3 + languageName: node + linkType: hard + +"@babel/plugin-transform-async-generator-functions@npm:^7.29.0": + version: 7.29.0 + resolution: "@babel/plugin-transform-async-generator-functions@npm:7.29.0" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.28.6" + "@babel/helper-remap-async-to-generator": "npm:^7.27.1" + "@babel/traverse": "npm:^7.29.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/4080fc5e7dad7761bfebbb4fbe06bdfeb3a8bf0c027bcb4373e59e6b3dc7c5002eca7cbb1afba801d6439df8f92f7bcb3fb862e8fbbe43a9e59bb5653dcc0568 + languageName: node + linkType: hard + +"@babel/plugin-transform-async-to-generator@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/plugin-transform-async-to-generator@npm:7.28.6" + dependencies: + "@babel/helper-module-imports": "npm:^7.28.6" + "@babel/helper-plugin-utils": "npm:^7.28.6" + "@babel/helper-remap-async-to-generator": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/2eb0826248587df6e50038f36194a138771a7df22581020451c7779edeaf9ef39bf47c5b7a20ae2645af6416e8c896feeca273317329652e84abd79a4ab920ad + languageName: node + linkType: hard + +"@babel/plugin-transform-block-scoped-functions@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-transform-block-scoped-functions@npm:7.27.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/3313130ba3bf0699baad0e60da1c8c3c2f0c2c0a7039cd0063e54e72e739c33f1baadfc9d8c73b3fea8c85dd7250c3964fb09c8e1fa62ba0b24a9fefe0a8dbde + languageName: node + linkType: hard + +"@babel/plugin-transform-block-scoping@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/plugin-transform-block-scoping@npm:7.28.6" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/2e3e09e1f9770b56cef4dcbffddf262508fd03416072f815ac66b2b224a3a12cd285cfec12fc067f1add414e7db5ce6dafb5164a6e0fb1a728e6a97d0c6f6e9d + languageName: node + linkType: hard + +"@babel/plugin-transform-class-properties@npm:^7.22.5, @babel/plugin-transform-class-properties@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/plugin-transform-class-properties@npm:7.28.6" + dependencies: + "@babel/helper-create-class-features-plugin": "npm:^7.28.6" + "@babel/helper-plugin-utils": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/c4327fcd730c239d9f173f9b695b57b801729e273b4848aef1f75818069dfd31d985d75175db188d947b9b1bbe5353dae298849042026a5e4fcf07582ff3f9f1 + languageName: node + linkType: hard + +"@babel/plugin-transform-class-static-block@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/plugin-transform-class-static-block@npm:7.28.6" + dependencies: + "@babel/helper-create-class-features-plugin": "npm:^7.28.6" + "@babel/helper-plugin-utils": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.12.0 + checksum: 10c0/dbe9b1fd302ae41b73186e17ac8d8ecf625ebc2416a91f2dc8013977a1bdf21e6ea288a83f084752b412242f3866e789d4fddeb428af323fe35b60e0fae4f98c + languageName: node + linkType: hard + +"@babel/plugin-transform-classes@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/plugin-transform-classes@npm:7.28.6" + dependencies: + "@babel/helper-annotate-as-pure": "npm:^7.27.3" + "@babel/helper-compilation-targets": "npm:^7.28.6" + "@babel/helper-globals": "npm:^7.28.0" + "@babel/helper-plugin-utils": "npm:^7.28.6" + "@babel/helper-replace-supers": "npm:^7.28.6" + "@babel/traverse": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/dc22f1f6eadab17305128fbf9cc5f30e87a51a77dd0a6d5498097994e8a9b9a90ab298c11edf2342acbeaac9edc9c601cad72eedcf4b592cd465a787d7f41490 + languageName: node + linkType: hard + +"@babel/plugin-transform-computed-properties@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/plugin-transform-computed-properties@npm:7.28.6" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.28.6" + "@babel/template": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/1e9893503ae6d651125701cc29450e87c0b873c8febebff19da75da9c40cfb7968c52c28bf948244e461110aeb7b3591f2cc199b7406ff74a24c50c7a5729f39 + languageName: node + linkType: hard + +"@babel/plugin-transform-destructuring@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/plugin-transform-destructuring@npm:7.28.5" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + "@babel/traverse": "npm:^7.28.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/288207f488412b23bb206c7c01ba143714e2506b72a9ec09e993f28366cc8188d121bde714659b3437984a86d2881d9b1b06de3089d5582823ccf2f3b3eaa2c4 + languageName: node + linkType: hard + +"@babel/plugin-transform-dotall-regex@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/plugin-transform-dotall-regex@npm:7.28.6" + dependencies: + "@babel/helper-create-regexp-features-plugin": "npm:^7.28.5" + "@babel/helper-plugin-utils": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/e2fb76b7ae99087cf4212013a3ca9dee07048f90f98fd6264855080fb6c3f169be11c9b8c9d8b26cf9a407e4d0a5fa6e103f7cef433a542b75cf7127c99d4f97 + languageName: node + linkType: hard + +"@babel/plugin-transform-duplicate-keys@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-transform-duplicate-keys@npm:7.27.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/22a822e5342b7066f83eaedc4fd9bb044ac6bc68725484690b33ba04a7104980e43ea3229de439286cb8db8e7db4a865733a3f05123ab58a10f189f03553746f + languageName: node + linkType: hard + +"@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:^7.29.0": + version: 7.29.0 + resolution: "@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:7.29.0" + dependencies: + "@babel/helper-create-regexp-features-plugin": "npm:^7.28.5" + "@babel/helper-plugin-utils": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/6f03d9e5e31a05b28555541be6e283407e08447a36be6ddf8068b3efa970411d832e04b1282e2b894baf89a3864ff7e7f1e36346652a8d983170c6d548555167 + languageName: node + linkType: hard + +"@babel/plugin-transform-dynamic-import@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-transform-dynamic-import@npm:7.27.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/8dcd3087aca134b064fc361d2cc34eec1f900f6be039b6368104afcef10bb75dea726bb18cabd046716b89b0edaa771f50189fa16bc5c5914a38cbcf166350f7 + languageName: node + linkType: hard + +"@babel/plugin-transform-explicit-resource-management@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/plugin-transform-explicit-resource-management@npm:7.28.6" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.28.6" + "@babel/plugin-transform-destructuring": "npm:^7.28.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/e6ea28c26e058fe61ada3e70b0def1992dd5a44f5fc14d8e2c6a3a512fb4d4c6dc96a3e1d0b466d83db32a9101e0b02df94051e48d3140da115b8ea9f8a31f37 + languageName: node + linkType: hard + +"@babel/plugin-transform-exponentiation-operator@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.28.6" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/4572d955a50dbc9a652a19431b4bb822cb479ee6045f4e6df72659c499c13036da0a2adf650b07ca995f2781e80aa868943bea1e7bff1de3169ec3f0a73a902e + languageName: node + linkType: hard + +"@babel/plugin-transform-export-namespace-from@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-transform-export-namespace-from@npm:7.27.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/d7165cad11f571a54c8d9263d6c6bf2b817aff4874f747cb51e6e49efb32f2c9b37a6850cdb5e3b81e0b638141bb77dc782a6ec1a94128859fbdf7767581e07c + languageName: node + linkType: hard + +"@babel/plugin-transform-for-of@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-transform-for-of@npm:7.27.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/4635763173a23aae24480681f2b0996b4f54a0cb2368880301a1801638242e263132d1e8adbe112ab272913d1d900ee0d6f7dea79443aef9d3325168cd88b3fb + languageName: node + linkType: hard + +"@babel/plugin-transform-function-name@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-transform-function-name@npm:7.27.1" + dependencies: + "@babel/helper-compilation-targets": "npm:^7.27.1" + "@babel/helper-plugin-utils": "npm:^7.27.1" + "@babel/traverse": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/5abdc7b5945fbd807269dcc6e76e52b69235056023b0b35d311e8f5dfd6c09d9f225839798998fc3b663f50cf701457ddb76517025a0d7a5474f3fe56e567a4c + languageName: node + linkType: hard + +"@babel/plugin-transform-json-strings@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/plugin-transform-json-strings@npm:7.28.6" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/ab1091798c58e6c0bb8a864ee2b727c400924592c6ed69797a26b4c205f850a935de77ad516570be0419c279a3d9f7740c2aa448762eb8364ea77a6a357a9653 + languageName: node + linkType: hard + +"@babel/plugin-transform-literals@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-transform-literals@npm:7.27.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/c40dc3eb2f45a92ee476412314a40e471af51a0f51a24e91b85cef5fc59f4fe06758088f541643f07f949d2c67ee7bdce10e11c5ec56791ae09b15c3b451eeca + languageName: node + linkType: hard + +"@babel/plugin-transform-logical-assignment-operators@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.28.6" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/4632a35453d2131f0be466681d0a33e3db44d868ff51ec46cd87e0ebd1e47c6a39b894f7d1c9b06f931addf6efa9d30e60c4cdedeb4f69d426f683e11f8490cf + languageName: node + linkType: hard + +"@babel/plugin-transform-member-expression-literals@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-transform-member-expression-literals@npm:7.27.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/0874ccebbd1c6a155e5f6b3b29729fade1221b73152567c1af1e1a7c12848004dffecbd7eded6dc463955120040ae57c17cb586b53fb5a7a27fcd88177034c30 + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-amd@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-transform-modules-amd@npm:7.27.1" + dependencies: + "@babel/helper-module-transforms": "npm:^7.27.1" + "@babel/helper-plugin-utils": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/76e86cd278b6a3c5b8cca8dfb3428e9cd0c81a5df7096e04c783c506696b916a9561386d610a9d846ef64804640e0bd818ea47455fed0ee89b7f66c555b29537 + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-commonjs@npm:^7.27.1, @babel/plugin-transform-modules-commonjs@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/plugin-transform-modules-commonjs@npm:7.28.6" + dependencies: + "@babel/helper-module-transforms": "npm:^7.28.6" + "@babel/helper-plugin-utils": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/7c45992797c6150644c8552feff4a016ba7bd6d59ff2b039ed969a9c5b20a6804cd9d21db5045fc8cca8ca7f08262497e354e93f8f2be6a1cdf3fbfa8c31a9b6 + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-systemjs@npm:^7.29.0": + version: 7.29.0 + resolution: "@babel/plugin-transform-modules-systemjs@npm:7.29.0" + dependencies: + "@babel/helper-module-transforms": "npm:^7.28.6" + "@babel/helper-plugin-utils": "npm:^7.28.6" + "@babel/helper-validator-identifier": "npm:^7.28.5" + "@babel/traverse": "npm:^7.29.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/44ea502f2c990398b7d9adc5b44d9e1810a0a5e86eebc05c92d039458f0b3994fe243efa9353b90f8a648d8a91b79845fb353d8679d7324cc9de0162d732771d + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-umd@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-transform-modules-umd@npm:7.27.1" + dependencies: + "@babel/helper-module-transforms": "npm:^7.27.1" + "@babel/helper-plugin-utils": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/e5962a8874889da2ab1aa32eb93ec21d419c7423c766e4befb39b4bb512b9ad44b47837b6cd1c8f1065445cbbcc6dc2be10298ac6e734e5ca1059fc23698daed + languageName: node + linkType: hard + +"@babel/plugin-transform-named-capturing-groups-regex@npm:^7.29.0": + version: 7.29.0 + resolution: "@babel/plugin-transform-named-capturing-groups-regex@npm:7.29.0" + dependencies: + "@babel/helper-create-regexp-features-plugin": "npm:^7.28.5" + "@babel/helper-plugin-utils": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/1904db22da7f2bc3e380cd2c0786bda330ee1b1b3efa3f5203d980708c4bfeb5daa4dff48d01692193040bcc5f275dbdc0c2eadc8b1eb1b6dfe363564ad6e898 + languageName: node + linkType: hard + +"@babel/plugin-transform-new-target@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-transform-new-target@npm:7.27.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/9b0581412fcc5ab1b9a2d86a0c5407bd959391f0a1e77a46953fef9f7a57f3f4020d75f71098c5f9e5dcc680a87f9fd99b3205ab12e25ef8c19eed038c1e4b28 + languageName: node + linkType: hard + +"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.28.6" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/6607f2201d66ccb688f0b1db09475ef995837df19f14705da41f693b669f834c206147a854864ab107913d7b4f4748878b0cd9fe9ca8bfd1bee0c206fc027b49 + languageName: node + linkType: hard + +"@babel/plugin-transform-numeric-separator@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/plugin-transform-numeric-separator@npm:7.28.6" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/191097d8d2753cdd16d1acca65a945d1645ab20b65655c2f5b030a9e38967a52e093dcb21ebf391e342222705c6ffe5dea15dafd6257f7b51b77fb64a830b637 + languageName: node + linkType: hard + +"@babel/plugin-transform-object-rest-spread@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/plugin-transform-object-rest-spread@npm:7.28.6" + dependencies: + "@babel/helper-compilation-targets": "npm:^7.28.6" + "@babel/helper-plugin-utils": "npm:^7.28.6" + "@babel/plugin-transform-destructuring": "npm:^7.28.5" + "@babel/plugin-transform-parameters": "npm:^7.27.7" + "@babel/traverse": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/f55334352d4fcde385f2e8a58836687e71ff668c9b6e4c34d52575bf2789cdde92d9d3116edba13647ac0bc3e51fb2a6d1e8fb822dce7e8123334b82600bc4c3 + languageName: node + linkType: hard + +"@babel/plugin-transform-object-super@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-transform-object-super@npm:7.27.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + "@babel/helper-replace-supers": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/efa2d092ef55105deb06d30aff4e460c57779b94861188128489b72378bf1f0ab0f06a4a4d68b9ae2a59a79719fbb2d148b9a3dca19ceff9c73b1f1a95e0527c + languageName: node + linkType: hard + +"@babel/plugin-transform-optional-catch-binding@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.28.6" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/36e8face000ee65e478a55febf687ce9be7513ad498c60dfe585851555565e0c28e7cb891b3c59709318539ce46f7697d5f42130eb18f385cd47e47cfa297446 + languageName: node + linkType: hard + +"@babel/plugin-transform-optional-chaining@npm:^7.27.1, @babel/plugin-transform-optional-chaining@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.28.6" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.28.6" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/c159cc74115c2266be21791f192dd079e2aeb65c8731157e53b80fcefa41e8e28ad370021d4dfbdb31f25e5afa0322669a8eb2d032cd96e65ac37e020324c763 + languageName: node + linkType: hard + +"@babel/plugin-transform-parameters@npm:^7.27.7": + version: 7.27.7 + resolution: "@babel/plugin-transform-parameters@npm:7.27.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/f2da3804e047d9f1cfb27be6c014e2c7f6cf5e1e38290d1cb3cb2607859e3d6facb4ee8c8c1e336e9fbb440091a174ce95ce156582d7e8bf9c0e735d11681f0f + languageName: node + linkType: hard + +"@babel/plugin-transform-private-methods@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/plugin-transform-private-methods@npm:7.28.6" + dependencies: + "@babel/helper-create-class-features-plugin": "npm:^7.28.6" + "@babel/helper-plugin-utils": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/fb504e2bfdcf3f734d2a90ab20d61427c58385f57f950d3de6ff4e6d12dd4aa7d552147312d218367e129b7920dccfc3230ba554de861986cda38921bad84067 + languageName: node + linkType: hard + +"@babel/plugin-transform-private-property-in-object@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/plugin-transform-private-property-in-object@npm:7.28.6" + dependencies: + "@babel/helper-annotate-as-pure": "npm:^7.27.3" + "@babel/helper-create-class-features-plugin": "npm:^7.28.6" + "@babel/helper-plugin-utils": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/0f6bbc6ec3f93b556d3de7d56bf49335255fc4c43488e51a5025d6ee0286183fd3cf950ffcac1bbeed8a45777f860a49996455c8d3b4a04c3b1a5f28e697fe31 + languageName: node + linkType: hard + +"@babel/plugin-transform-property-literals@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-transform-property-literals@npm:7.27.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/15713a87edd6db620d6e66eb551b4fbfff5b8232c460c7c76cedf98efdc5cd21080c97040231e19e06594c6d7dfa66e1ab3d0951e29d5814fb25e813f6d6209c + languageName: node + linkType: hard + +"@babel/plugin-transform-regenerator@npm:^7.29.0": + version: 7.29.0 + resolution: "@babel/plugin-transform-regenerator@npm:7.29.0" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/86c7db9b97f85ee47c0fae0528802cbc06e5775e61580ee905335c16bb971270086764a3859873d9adcd7d0f913a5b93eb0dc271aec8fb9e93e090e4ac95e29e + languageName: node + linkType: hard + +"@babel/plugin-transform-regexp-modifiers@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/plugin-transform-regexp-modifiers@npm:7.28.6" + dependencies: + "@babel/helper-create-regexp-features-plugin": "npm:^7.28.5" + "@babel/helper-plugin-utils": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/97e36b086800f71694fa406abc00192e3833662f2bdd5f51c018bd0c95eef247c4ae187417c207d03a9c5374342eac0bb65a39112c431a9b23b09b1eda1562e5 + languageName: node + linkType: hard + +"@babel/plugin-transform-reserved-words@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-transform-reserved-words@npm:7.27.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/e1a87691cce21a644a474d7c9a8107d4486c062957be32042d40f0a3d0cc66e00a3150989655019c255ff020d2640ac16aaf544792717d586f219f3bad295567 + languageName: node + linkType: hard + +"@babel/plugin-transform-runtime@npm:^7.23.2": + version: 7.29.0 + resolution: "@babel/plugin-transform-runtime@npm:7.29.0" + dependencies: + "@babel/helper-module-imports": "npm:^7.28.6" + "@babel/helper-plugin-utils": "npm:^7.28.6" + babel-plugin-polyfill-corejs2: "npm:^0.4.14" + babel-plugin-polyfill-corejs3: "npm:^0.13.0" + babel-plugin-polyfill-regenerator: "npm:^0.6.5" + semver: "npm:^6.3.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/05a451cb96a1e6ccfdd1a123773208615cd14cb156aa0aa99a448d86e4326b36b9ab2be8267037bd27644a5918dac88378b791d020b3c08a4fd8f3415621a006 + languageName: node + linkType: hard + +"@babel/plugin-transform-shorthand-properties@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-transform-shorthand-properties@npm:7.27.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/bd5544b89520a22c41a6df5ddac9039821d3334c0ef364d18b0ba9674c5071c223bcc98be5867dc3865cb10796882b7594e2c40dedaff38e1b1273913fe353e1 + languageName: node + linkType: hard + +"@babel/plugin-transform-spread@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/plugin-transform-spread@npm:7.28.6" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.28.6" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/bcac50e558d6f0c501cbce19ec197af558cef51fe3b3a6eba27276e323e57a5be28109b4264a5425ac12a67bf95d6af9c2a42b05e79c522ce913fb9529259d76 + languageName: node + linkType: hard + +"@babel/plugin-transform-sticky-regex@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-transform-sticky-regex@npm:7.27.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/5698df2d924f0b1b7bdb7ef370e83f99ed3f0964eb3b9c27d774d021bee7f6d45f9a73e2be369d90b4aff1603ce29827f8743f091789960e7669daf9c3cda850 + languageName: node + linkType: hard + +"@babel/plugin-transform-template-literals@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-transform-template-literals@npm:7.27.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/c90f403e42ef062b60654d1c122c70f3ec6f00c2f304b0931ebe6d0b432498ef8a5ef9266ddf00debc535f8390842207e44d3900eff1d2bab0cc1a700f03e083 + languageName: node + linkType: hard + +"@babel/plugin-transform-typeof-symbol@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-transform-typeof-symbol@npm:7.27.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/a13c68015311fefa06a51830bc69d5badd06c881b13d5cf9ba04bf7c73e3fc6311cc889e18d9645ce2a64a79456dc9c7be88476c0b6802f62a686cb6f662ecd6 + languageName: node + linkType: hard + +"@babel/plugin-transform-typescript@npm:^7.28.5": + version: 7.28.6 + resolution: "@babel/plugin-transform-typescript@npm:7.28.6" + dependencies: + "@babel/helper-annotate-as-pure": "npm:^7.27.3" + "@babel/helper-create-class-features-plugin": "npm:^7.28.6" + "@babel/helper-plugin-utils": "npm:^7.28.6" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.27.1" + "@babel/plugin-syntax-typescript": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/72dbfd3e5f71c4e30445e610758ec0eef65347fafd72bd46f4903733df0d537663a72a81c1626f213a0feab7afc68ba83f1648ffece888dd0868115c9cb748f6 + languageName: node + linkType: hard + +"@babel/plugin-transform-unicode-escapes@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-transform-unicode-escapes@npm:7.27.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/a6809e0ca69d77ee9804e0c1164e8a2dea5e40718f6dcf234aeddf7292e7414f7ee331d87f17eb6f160823a329d1d6751bd49b35b392ac4a6efc032e4d3038d8 + languageName: node + linkType: hard + +"@babel/plugin-transform-unicode-property-regex@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/plugin-transform-unicode-property-regex@npm:7.28.6" + dependencies: + "@babel/helper-create-regexp-features-plugin": "npm:^7.28.5" + "@babel/helper-plugin-utils": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/b25f8cde643f4f47e0fa4f7b5c552e2dfbb6ad0ce07cf40f7e8ae40daa9855ad855d76d4d6d010153b74e48c8794685955c92ca637c0da152ce5f0fa9e7c90fa + languageName: node + linkType: hard + +"@babel/plugin-transform-unicode-regex@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-transform-unicode-regex@npm:7.27.1" + dependencies: + "@babel/helper-create-regexp-features-plugin": "npm:^7.27.1" + "@babel/helper-plugin-utils": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/6abda1bcffb79feba6f5c691859cdbe984cc96481ea65d5af5ba97c2e843154005f0886e25006a37a2d213c0243506a06eaeafd93a040dbe1f79539016a0d17a + languageName: node + linkType: hard + +"@babel/plugin-transform-unicode-sets-regex@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/plugin-transform-unicode-sets-regex@npm:7.28.6" + dependencies: + "@babel/helper-create-regexp-features-plugin": "npm:^7.28.5" + "@babel/helper-plugin-utils": "npm:^7.28.6" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/c03c8818736b138db73d1f7a96fbfa22d1994639164d743f0f00e6383d3b7b3144d333de960ff4afad0bddd0baaac257295e3316969eba995b1b6a1b4dec933e + languageName: node + linkType: hard + +"@babel/preset-env@npm:^7.23.2": + version: 7.29.2 + resolution: "@babel/preset-env@npm:7.29.2" + dependencies: + "@babel/compat-data": "npm:^7.29.0" + "@babel/helper-compilation-targets": "npm:^7.28.6" + "@babel/helper-plugin-utils": "npm:^7.28.6" + "@babel/helper-validator-option": "npm:^7.27.1" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "npm:^7.28.5" + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "npm:^7.27.1" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "npm:^7.27.1" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "npm:^7.27.1" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "npm:^7.28.6" + "@babel/plugin-proposal-private-property-in-object": "npm:7.21.0-placeholder-for-preset-env.2" + "@babel/plugin-syntax-import-assertions": "npm:^7.28.6" + "@babel/plugin-syntax-import-attributes": "npm:^7.28.6" + "@babel/plugin-syntax-unicode-sets-regex": "npm:^7.18.6" + "@babel/plugin-transform-arrow-functions": "npm:^7.27.1" + "@babel/plugin-transform-async-generator-functions": "npm:^7.29.0" + "@babel/plugin-transform-async-to-generator": "npm:^7.28.6" + "@babel/plugin-transform-block-scoped-functions": "npm:^7.27.1" + "@babel/plugin-transform-block-scoping": "npm:^7.28.6" + "@babel/plugin-transform-class-properties": "npm:^7.28.6" + "@babel/plugin-transform-class-static-block": "npm:^7.28.6" + "@babel/plugin-transform-classes": "npm:^7.28.6" + "@babel/plugin-transform-computed-properties": "npm:^7.28.6" + "@babel/plugin-transform-destructuring": "npm:^7.28.5" + "@babel/plugin-transform-dotall-regex": "npm:^7.28.6" + "@babel/plugin-transform-duplicate-keys": "npm:^7.27.1" + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "npm:^7.29.0" + "@babel/plugin-transform-dynamic-import": "npm:^7.27.1" + "@babel/plugin-transform-explicit-resource-management": "npm:^7.28.6" + "@babel/plugin-transform-exponentiation-operator": "npm:^7.28.6" + "@babel/plugin-transform-export-namespace-from": "npm:^7.27.1" + "@babel/plugin-transform-for-of": "npm:^7.27.1" + "@babel/plugin-transform-function-name": "npm:^7.27.1" + "@babel/plugin-transform-json-strings": "npm:^7.28.6" + "@babel/plugin-transform-literals": "npm:^7.27.1" + "@babel/plugin-transform-logical-assignment-operators": "npm:^7.28.6" + "@babel/plugin-transform-member-expression-literals": "npm:^7.27.1" + "@babel/plugin-transform-modules-amd": "npm:^7.27.1" + "@babel/plugin-transform-modules-commonjs": "npm:^7.28.6" + "@babel/plugin-transform-modules-systemjs": "npm:^7.29.0" + "@babel/plugin-transform-modules-umd": "npm:^7.27.1" + "@babel/plugin-transform-named-capturing-groups-regex": "npm:^7.29.0" + "@babel/plugin-transform-new-target": "npm:^7.27.1" + "@babel/plugin-transform-nullish-coalescing-operator": "npm:^7.28.6" + "@babel/plugin-transform-numeric-separator": "npm:^7.28.6" + "@babel/plugin-transform-object-rest-spread": "npm:^7.28.6" + "@babel/plugin-transform-object-super": "npm:^7.27.1" + "@babel/plugin-transform-optional-catch-binding": "npm:^7.28.6" + "@babel/plugin-transform-optional-chaining": "npm:^7.28.6" + "@babel/plugin-transform-parameters": "npm:^7.27.7" + "@babel/plugin-transform-private-methods": "npm:^7.28.6" + "@babel/plugin-transform-private-property-in-object": "npm:^7.28.6" + "@babel/plugin-transform-property-literals": "npm:^7.27.1" + "@babel/plugin-transform-regenerator": "npm:^7.29.0" + "@babel/plugin-transform-regexp-modifiers": "npm:^7.28.6" + "@babel/plugin-transform-reserved-words": "npm:^7.27.1" + "@babel/plugin-transform-shorthand-properties": "npm:^7.27.1" + "@babel/plugin-transform-spread": "npm:^7.28.6" + "@babel/plugin-transform-sticky-regex": "npm:^7.27.1" + "@babel/plugin-transform-template-literals": "npm:^7.27.1" + "@babel/plugin-transform-typeof-symbol": "npm:^7.27.1" + "@babel/plugin-transform-unicode-escapes": "npm:^7.27.1" + "@babel/plugin-transform-unicode-property-regex": "npm:^7.28.6" + "@babel/plugin-transform-unicode-regex": "npm:^7.27.1" + "@babel/plugin-transform-unicode-sets-regex": "npm:^7.28.6" + "@babel/preset-modules": "npm:0.1.6-no-external-plugins" + babel-plugin-polyfill-corejs2: "npm:^0.4.15" + babel-plugin-polyfill-corejs3: "npm:^0.14.0" + babel-plugin-polyfill-regenerator: "npm:^0.6.6" + core-js-compat: "npm:^3.48.0" + semver: "npm:^6.3.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/d49cb005f2dbc3f2293ab6d80ee8f1380e6215af5518fe26b087c8961c1ea8ebaa554dfce589abe1fbebac25ad7c2515d943dec3859ea2d4981a3f8f4711c580 + languageName: node + linkType: hard + +"@babel/preset-modules@npm:0.1.6-no-external-plugins": + version: 0.1.6-no-external-plugins + resolution: "@babel/preset-modules@npm:0.1.6-no-external-plugins" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.0.0" + "@babel/types": "npm:^7.4.4" + esutils: "npm:^2.0.2" + peerDependencies: + "@babel/core": ^7.0.0-0 || ^8.0.0-0 <8.0.0 + checksum: 10c0/9d02f70d7052446c5f3a4fb39e6b632695fb6801e46d31d7f7c5001f7c18d31d1ea8369212331ca7ad4e7877b73231f470b0d559162624128f1b80fe591409e6 + languageName: node + linkType: hard + +"@babel/preset-typescript@npm:^7.22.5": + version: 7.28.5 + resolution: "@babel/preset-typescript@npm:7.28.5" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + "@babel/helper-validator-option": "npm:^7.27.1" + "@babel/plugin-syntax-jsx": "npm:^7.27.1" + "@babel/plugin-transform-modules-commonjs": "npm:^7.27.1" + "@babel/plugin-transform-typescript": "npm:^7.28.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/b3d55548854c105085dd80f638147aa8295bc186d70492289242d6c857cb03a6c61ec15186440ea10ed4a71cdde7d495f5eb3feda46273f36b0ac926e8409629 + languageName: node + linkType: hard + +"@babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.22.6": + version: 7.29.2 + resolution: "@babel/runtime@npm:7.29.2" + checksum: 10c0/30b80a0140d16467792e1bbeb06f655b0dab70407da38dfac7fedae9c859f9ae9d846ef14ad77bd3814c064295fe9b1bc551f1541ea14646ae9f22b71a8bc17a + languageName: node + linkType: hard + +"@babel/template@npm:^7.28.6, @babel/template@npm:^7.3.3": + version: 7.28.6 + resolution: "@babel/template@npm:7.28.6" + dependencies: + "@babel/code-frame": "npm:^7.28.6" + "@babel/parser": "npm:^7.28.6" + "@babel/types": "npm:^7.28.6" + checksum: 10c0/66d87225ed0bc77f888181ae2d97845021838c619944877f7c4398c6748bcf611f216dfd6be74d39016af502bca876e6ce6873db3c49e4ac354c56d34d57e9f5 + languageName: node + linkType: hard + +"@babel/traverse@npm:^7.16.0, @babel/traverse@npm:^7.27.1, @babel/traverse@npm:^7.28.5, @babel/traverse@npm:^7.28.6, @babel/traverse@npm:^7.29.0": + version: 7.29.0 + resolution: "@babel/traverse@npm:7.29.0" + dependencies: + "@babel/code-frame": "npm:^7.29.0" + "@babel/generator": "npm:^7.29.0" + "@babel/helper-globals": "npm:^7.28.0" + "@babel/parser": "npm:^7.29.0" + "@babel/template": "npm:^7.28.6" + "@babel/types": "npm:^7.29.0" + debug: "npm:^4.3.1" + checksum: 10c0/f63ef6e58d02a9fbf3c0e2e5f1c877da3e0bc57f91a19d2223d53e356a76859cbaf51171c9211c71816d94a0e69efa2732fd27ffc0e1bbc84b636e60932333eb + languageName: node + linkType: hard + +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.27.1, @babel/types@npm:^7.27.3, @babel/types@npm:^7.28.2, @babel/types@npm:^7.28.5, @babel/types@npm:^7.28.6, @babel/types@npm:^7.29.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4": + version: 7.29.0 + resolution: "@babel/types@npm:7.29.0" + dependencies: + "@babel/helper-string-parser": "npm:^7.27.1" + "@babel/helper-validator-identifier": "npm:^7.28.5" + checksum: 10c0/23cc3466e83bcbfab8b9bd0edaafdb5d4efdb88b82b3be6728bbade5ba2f0996f84f63b1c5f7a8c0d67efded28300898a5f930b171bb40b311bca2029c4e9b4f + languageName: node + linkType: hard + +"@balena/dockerignore@npm:^1.0.2": + version: 1.0.2 + resolution: "@balena/dockerignore@npm:1.0.2" + checksum: 10c0/0bcb067e86f6734ab943ce4ce9a7c8611f2e983a70bccebf9d2309db57695c09dded7faf5be49c929c4c9e9a9174ae55fc625626de0fb9958823c37423d12f4e + languageName: node + linkType: hard + +"@bcoe/v8-coverage@npm:^0.2.3": + version: 0.2.3 + resolution: "@bcoe/v8-coverage@npm:0.2.3" + checksum: 10c0/6b80ae4cb3db53f486da2dc63b6e190a74c8c3cca16bb2733f234a0b6a9382b09b146488ae08e2b22cf00f6c83e20f3e040a2f7894f05c045c946d6a090b1d52 + languageName: node + linkType: hard + +"@borewit/text-codec@npm:^0.2.1": + version: 0.2.2 + resolution: "@borewit/text-codec@npm:0.2.2" + checksum: 10c0/2d3fb132bc6a132914a8fbf8e9ff2fa1ead210ecc395b28bb7355bd7719548a5e351ffe39f21c3bee8048f6cabd99eabd404bb5cc809cad9cba25abed19d271f + languageName: node + linkType: hard + +"@colors/colors@npm:1.6.0, @colors/colors@npm:^1.6.0": + version: 1.6.0 + resolution: "@colors/colors@npm:1.6.0" + checksum: 10c0/9328a0778a5b0db243af54455b79a69e3fb21122d6c15ef9e9fcc94881d8d17352d8b2b2590f9bdd46fac5c2d6c1636dcfc14358a20c70e22daf89e1a759b629 + languageName: node + linkType: hard + +"@cspotcode/source-map-support@npm:^0.8.0": + version: 0.8.1 + resolution: "@cspotcode/source-map-support@npm:0.8.1" + dependencies: + "@jridgewell/trace-mapping": "npm:0.3.9" + checksum: 10c0/05c5368c13b662ee4c122c7bfbe5dc0b613416672a829f3e78bc49a357a197e0218d6e74e7c66cfcd04e15a179acab080bd3c69658c9fbefd0e1ccd950a07fc6 + languageName: node + linkType: hard + +"@dabh/diagnostics@npm:^2.0.8": + version: 2.0.8 + resolution: "@dabh/diagnostics@npm:2.0.8" + dependencies: + "@so-ric/colorspace": "npm:^1.1.6" + enabled: "npm:2.0.x" + kuler: "npm:^2.0.0" + checksum: 10c0/64701c272f7de02800039fea99796507670fe5f67d4eb7718599351ec156936efd123fcab7ee18f9d7874939caaacc08e7c7a6bb05ff8cda6d930ad041cc555c + languageName: node + linkType: hard + +"@emnapi/core@npm:^1.1.0, @emnapi/core@npm:^1.4.3": + version: 1.9.2 + resolution: "@emnapi/core@npm:1.9.2" + dependencies: + "@emnapi/wasi-threads": "npm:1.2.1" + tslib: "npm:^2.4.0" + checksum: 10c0/5500393f953951bad0768fafaa9191f2d938956b20c6d6a79e5ab696a613a25ce6ad23422bc18e86e6ce8deb147619d8d0d7d413a69f84adc01a6633cc353cd9 + languageName: node + linkType: hard + +"@emnapi/runtime@npm:^1.1.0, @emnapi/runtime@npm:^1.4.3": + version: 1.9.2 + resolution: "@emnapi/runtime@npm:1.9.2" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10c0/61c3a59e0c36784558b8d58eb02bd04815aa5fb0dbfbaf84d1b3050a78aa0cc63ea129ae806bd1e48062bfeb7fc36eb0e5431740d62f64ea51bdf426404b8caa + languageName: node + linkType: hard + +"@emnapi/wasi-threads@npm:1.2.1": + version: 1.2.1 + resolution: "@emnapi/wasi-threads@npm:1.2.1" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10c0/32fcfa81ab396533b2ec1f4082b1ff779a05d9c836bbbd3f4398405b0e6814c0d9503b7993130e37bc6941dbc1ded49f55e9700ae9ca4e803bab2b5bc5deb331 + languageName: node + linkType: hard + +"@eslint-community/eslint-utils@npm:^4.8.0, @eslint-community/eslint-utils@npm:^4.9.1": + version: 4.9.1 + resolution: "@eslint-community/eslint-utils@npm:4.9.1" + dependencies: + eslint-visitor-keys: "npm:^3.4.3" + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + checksum: 10c0/dc4ab5e3e364ef27e33666b11f4b86e1a6c1d7cbf16f0c6ff87b1619b3562335e9201a3d6ce806221887ff780ec9d828962a290bb910759fd40a674686503f02 + languageName: node + linkType: hard + +"@eslint-community/regexpp@npm:^4.12.1, @eslint-community/regexpp@npm:^4.12.2": + version: 4.12.2 + resolution: "@eslint-community/regexpp@npm:4.12.2" + checksum: 10c0/fddcbc66851b308478d04e302a4d771d6917a0b3740dc351513c0da9ca2eab8a1adf99f5e0aa7ab8b13fa0df005c81adeee7e63a92f3effd7d367a163b721c2d + languageName: node + linkType: hard + +"@eslint/config-array@npm:^0.21.2": + version: 0.21.2 + resolution: "@eslint/config-array@npm:0.21.2" + dependencies: + "@eslint/object-schema": "npm:^2.1.7" + debug: "npm:^4.3.1" + minimatch: "npm:^3.1.5" + checksum: 10c0/89dfe815d18456177c0a1f238daf4593107fd20298b3598e0103054360d3b8d09d967defd8318f031185d68df1f95cfa68becf1390a9c5c6887665f1475142e3 + languageName: node + linkType: hard + +"@eslint/config-helpers@npm:^0.4.2": + version: 0.4.2 + resolution: "@eslint/config-helpers@npm:0.4.2" + dependencies: + "@eslint/core": "npm:^0.17.0" + checksum: 10c0/92efd7a527b2d17eb1a148409d71d80f9ac160b565ac73ee092252e8bf08ecd08670699f46b306b94f13d22e88ac88a612120e7847570dd7cdc72f234d50dcb4 + languageName: node + linkType: hard + +"@eslint/core@npm:^0.17.0": + version: 0.17.0 + resolution: "@eslint/core@npm:0.17.0" + dependencies: + "@types/json-schema": "npm:^7.0.15" + checksum: 10c0/9a580f2246633bc752298e7440dd942ec421860d1946d0801f0423830e67887e4aeba10ab9a23d281727a978eb93d053d1922a587d502942a713607f40ed704e + languageName: node + linkType: hard + +"@eslint/eslintrc@npm:^3.3.5": + version: 3.3.5 + resolution: "@eslint/eslintrc@npm:3.3.5" + dependencies: + ajv: "npm:^6.14.0" + debug: "npm:^4.3.2" + espree: "npm:^10.0.1" + globals: "npm:^14.0.0" + ignore: "npm:^5.2.0" + import-fresh: "npm:^3.2.1" + js-yaml: "npm:^4.1.1" + minimatch: "npm:^3.1.5" + strip-json-comments: "npm:^3.1.1" + checksum: 10c0/9fb9f1ca65e46d6173966e3aaa5bd353e3a65d7f1f582bebf77f578fab7d7960a399fac1ecfb1e7d52bd61f5cefd6531087ca52a3a3c388f2e1b4f1ebd3da8b7 + languageName: node + linkType: hard + +"@eslint/js@npm:9.39.4": + version: 9.39.4 + resolution: "@eslint/js@npm:9.39.4" + checksum: 10c0/5aa7dea2cbc5decf7f5e3b0c6f86a084ccee0f792d288ca8e839f8bc1b64e03e227068968e49b26096e6f71fd857ab6e42691d1b993826b9a3883f1bdd7a0e46 + languageName: node + linkType: hard + +"@eslint/object-schema@npm:^2.1.7": + version: 2.1.7 + resolution: "@eslint/object-schema@npm:2.1.7" + checksum: 10c0/936b6e499853d1335803f556d526c86f5fe2259ed241bc665000e1d6353828edd913feed43120d150adb75570cae162cf000b5b0dfc9596726761c36b82f4e87 + languageName: node + linkType: hard + +"@eslint/plugin-kit@npm:^0.4.1": + version: 0.4.1 + resolution: "@eslint/plugin-kit@npm:0.4.1" + dependencies: + "@eslint/core": "npm:^0.17.0" + levn: "npm:^0.4.1" + checksum: 10c0/51600f78b798f172a9915dffb295e2ffb44840d583427bc732baf12ecb963eb841b253300e657da91d890f4b323d10a1bd12934bf293e3018d8bb66fdce5217b + languageName: node + linkType: hard + +"@fastify/busboy@npm:^2.0.0": + version: 2.1.1 + resolution: "@fastify/busboy@npm:2.1.1" + checksum: 10c0/6f8027a8cba7f8f7b736718b013f5a38c0476eea67034c94a0d3c375e2b114366ad4419e6a6fa7ffc2ef9c6d3e0435d76dd584a7a1cbac23962fda7650b579e3 + languageName: node + linkType: hard + +"@gar/promise-retry@npm:^1.0.0, @gar/promise-retry@npm:^1.0.2": + version: 1.0.3 + resolution: "@gar/promise-retry@npm:1.0.3" + checksum: 10c0/885b02c8b0d75b2d215da25f3b639158c4fbe8fefe0d79163304534b9a6d0710db4b7699f7cd3cc1a730792bff04cbe19f4850a62d3e105a663eaeec88f38332 + languageName: node + linkType: hard + +"@grpc/grpc-js@npm:^1.11.1, @grpc/grpc-js@npm:^1.14.0, @grpc/grpc-js@npm:^1.9": + version: 1.14.3 + resolution: "@grpc/grpc-js@npm:1.14.3" + dependencies: + "@grpc/proto-loader": "npm:^0.8.0" + "@js-sdsl/ordered-map": "npm:^4.4.2" + checksum: 10c0/f41f06a311b93cca8c472d56e21387e0f7b57bb2337a91d15ea4279bac8ec4fa0de6bd0d881201229ab800c0f0c55277911ecb850e057f20a828d0ddd623551d + languageName: node + linkType: hard + +"@grpc/proto-loader@npm:^0.7.13": + version: 0.7.15 + resolution: "@grpc/proto-loader@npm:0.7.15" + dependencies: + lodash.camelcase: "npm:^4.3.0" + long: "npm:^5.0.0" + protobufjs: "npm:^7.2.5" + yargs: "npm:^17.7.2" + bin: + proto-loader-gen-types: build/bin/proto-loader-gen-types.js + checksum: 10c0/514a134a724b56d73d0a202b7e02c84479da21e364547bacb2f4995ebc0d52412a1a21653add9f004ebd146c1e6eb4bcb0b8846fdfe1bfa8a98ed8f3d203da4a + languageName: node + linkType: hard + +"@grpc/proto-loader@npm:^0.8.0": + version: 0.8.0 + resolution: "@grpc/proto-loader@npm:0.8.0" + dependencies: + lodash.camelcase: "npm:^4.3.0" + long: "npm:^5.0.0" + protobufjs: "npm:^7.5.3" + yargs: "npm:^17.7.2" + bin: + proto-loader-gen-types: build/bin/proto-loader-gen-types.js + checksum: 10c0/a27da3b85d5d17bab956d536786c717287eae46ca264ea9ec774db90ff571955bae2705809f431b4622fbf3be9951d7c7bbb1360b2015ee88abe1587cf3d6fe0 + languageName: node + linkType: hard + +"@hono/node-server@npm:^1.19.9": + version: 1.19.12 + resolution: "@hono/node-server@npm:1.19.12" + peerDependencies: + hono: ^4 + checksum: 10c0/06b5c7ba775d585abebe1ece155f3b00cc9013319818c58bba6f1b1e71df44d1d0d6c6e66cd50350ab6f0b9219a182f83c9fe3074b81a1d1ebb0a1493a73db9e + languageName: node + linkType: hard + +"@humanfs/core@npm:^0.19.1": + version: 0.19.1 + resolution: "@humanfs/core@npm:0.19.1" + checksum: 10c0/aa4e0152171c07879b458d0e8a704b8c3a89a8c0541726c6b65b81e84fd8b7564b5d6c633feadc6598307d34564bd53294b533491424e8e313d7ab6c7bc5dc67 + languageName: node + linkType: hard + +"@humanfs/node@npm:^0.16.6": + version: 0.16.7 + resolution: "@humanfs/node@npm:0.16.7" + dependencies: + "@humanfs/core": "npm:^0.19.1" + "@humanwhocodes/retry": "npm:^0.4.0" + checksum: 10c0/9f83d3cf2cfa37383e01e3cdaead11cd426208e04c44adcdd291aa983aaf72d7d3598844d2fe9ce54896bb1bf8bd4b56883376611c8905a19c44684642823f30 + languageName: node + linkType: hard + +"@humanwhocodes/module-importer@npm:^1.0.1": + version: 1.0.1 + resolution: "@humanwhocodes/module-importer@npm:1.0.1" + checksum: 10c0/909b69c3b86d482c26b3359db16e46a32e0fb30bd306a3c176b8313b9e7313dba0f37f519de6aa8b0a1921349e505f259d19475e123182416a506d7f87e7f529 + languageName: node + linkType: hard + +"@humanwhocodes/retry@npm:^0.4.0, @humanwhocodes/retry@npm:^0.4.2": + version: 0.4.3 + resolution: "@humanwhocodes/retry@npm:0.4.3" + checksum: 10c0/3775bb30087d4440b3f7406d5a057777d90e4b9f435af488a4923ef249e93615fb78565a85f173a186a076c7706a81d0d57d563a2624e4de2c5c9c66c486ce42 + languageName: node + linkType: hard + +"@hutson/parse-repository-url@npm:^3.0.0": + version: 3.0.2 + resolution: "@hutson/parse-repository-url@npm:3.0.2" + checksum: 10c0/d9197757ecad2df18d29d3e1d1fe0716d458fd88b849c71cbec9e78239f911074c97e8d764dfd8ed890431c1137e52dd7a337207fd65be20ce0784f7860ae4d1 + languageName: node + linkType: hard + +"@inquirer/ansi@npm:^1.0.0, @inquirer/ansi@npm:^1.0.2": + version: 1.0.2 + resolution: "@inquirer/ansi@npm:1.0.2" + checksum: 10c0/8e408cc628923aa93402e66657482ccaa2ad5174f9db526d9a8b443f9011e9cd8f70f0f534f5fe3857b8a9df3bce1e25f66c96f666d6750490bd46e2b4f3b829 + languageName: node + linkType: hard + +"@inquirer/checkbox@npm:^4.3.2": + version: 4.3.2 + resolution: "@inquirer/checkbox@npm:4.3.2" + dependencies: + "@inquirer/ansi": "npm:^1.0.2" + "@inquirer/core": "npm:^10.3.2" + "@inquirer/figures": "npm:^1.0.15" + "@inquirer/type": "npm:^3.0.10" + yoctocolors-cjs: "npm:^2.1.3" + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/771d23bc6b16cd5c21a4f1073e98e306147f90c0e2487fe887ee054b8bf86449f1f9e6e6f9c218c1aa45ae3be2533197d53654abe9c0545981aebb0920d5f471 + languageName: node + linkType: hard + +"@inquirer/confirm@npm:^5.1.21": + version: 5.1.21 + resolution: "@inquirer/confirm@npm:5.1.21" + dependencies: + "@inquirer/core": "npm:^10.3.2" + "@inquirer/type": "npm:^3.0.10" + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/a95bbdbb17626c484735a4193ed6b6a6fbb078cf62116ec8e1667f647e534dd6618e688ecc7962585efcc56881b544b8c53db3914599bbf2ab842e7f224b0fca + languageName: node + linkType: hard + +"@inquirer/core@npm:^10.2.2, @inquirer/core@npm:^10.3.2": + version: 10.3.2 + resolution: "@inquirer/core@npm:10.3.2" + dependencies: + "@inquirer/ansi": "npm:^1.0.2" + "@inquirer/figures": "npm:^1.0.15" + "@inquirer/type": "npm:^3.0.10" + cli-width: "npm:^4.1.0" + mute-stream: "npm:^2.0.0" + signal-exit: "npm:^4.1.0" + wrap-ansi: "npm:^6.2.0" + yoctocolors-cjs: "npm:^2.1.3" + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/f0f27e07fe288e01e3949b4ad216c19751f025ce77c610366e08d8b0f7a135d064dc074732031d251584b454c576f1e5c849e4abe259186dd5d4974c8f85c13e + languageName: node + linkType: hard + +"@inquirer/editor@npm:^4.2.23": + version: 4.2.23 + resolution: "@inquirer/editor@npm:4.2.23" + dependencies: + "@inquirer/core": "npm:^10.3.2" + "@inquirer/external-editor": "npm:^1.0.3" + "@inquirer/type": "npm:^3.0.10" + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/aa02028ee35ae039a4857b6a9490d295a1b3558f042e7454dee0aa36fbc83ac25586a2dfe0b46a5ea7ea151e3f5cb97a8ee6229131b4619f3b3466ad74b9519f + languageName: node + linkType: hard + +"@inquirer/expand@npm:^4.0.23": + version: 4.0.23 + resolution: "@inquirer/expand@npm:4.0.23" + dependencies: + "@inquirer/core": "npm:^10.3.2" + "@inquirer/type": "npm:^3.0.10" + yoctocolors-cjs: "npm:^2.1.3" + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/294c92652760c3d1a46c4b900a99fd553ea9e5734ba261d4e71d7b8499d86a8b15e38a2467ddb7c95c197daf7e472bdab209fc3f7c38cbc70842cd291f4ce39d + languageName: node + linkType: hard + +"@inquirer/external-editor@npm:^1.0.3": + version: 1.0.3 + resolution: "@inquirer/external-editor@npm:1.0.3" + dependencies: + chardet: "npm:^2.1.1" + iconv-lite: "npm:^0.7.0" + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/82951cb7f3762dd78cca2ea291396841e3f4adfe26004b5badfed1cec4b6a04bb567dff94d0e41b35c61bdd7957317c64c22f58074d14b238d44e44d9e420019 + languageName: node + linkType: hard + +"@inquirer/figures@npm:^1.0.15": + version: 1.0.15 + resolution: "@inquirer/figures@npm:1.0.15" + checksum: 10c0/6e39a040d260ae234ae220180b7994ff852673e20be925f8aa95e78c7934d732b018cbb4d0ec39e600a410461bcb93dca771e7de23caa10630d255692e440f69 + languageName: node + linkType: hard + +"@inquirer/input@npm:^4.3.1": + version: 4.3.1 + resolution: "@inquirer/input@npm:4.3.1" + dependencies: + "@inquirer/core": "npm:^10.3.2" + "@inquirer/type": "npm:^3.0.10" + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/9e81d6ae56e5b59f96475ae1327e7e7beeef0d917b83762e0c2ed5a75239ad6b1a39fc05553ce45fe6f6de49681dade8704b5f1c11c2f555663a74d0ac998af3 + languageName: node + linkType: hard + +"@inquirer/number@npm:^3.0.23": + version: 3.0.23 + resolution: "@inquirer/number@npm:3.0.23" + dependencies: + "@inquirer/core": "npm:^10.3.2" + "@inquirer/type": "npm:^3.0.10" + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/3944a524be2a2e0834822a0e483f2e2fd56ad597b5feeca2155b956821f88e22e07ce3816f66113b040601636ed7146865aee7d7afb2a06939acc77491330ccc + languageName: node + linkType: hard + +"@inquirer/password@npm:^4.0.23": + version: 4.0.23 + resolution: "@inquirer/password@npm:4.0.23" + dependencies: + "@inquirer/ansi": "npm:^1.0.2" + "@inquirer/core": "npm:^10.3.2" + "@inquirer/type": "npm:^3.0.10" + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/9fd3d0462d02735bb1521c4e221d057a94d9aaac308e9a192e59d6c1e8efc707c2376ab627151d589bc3633f6b14b74b60b91c3d473a32adfd100ef1f6cfdef7 + languageName: node + linkType: hard + +"@inquirer/prompts@npm:^7.8.6": + version: 7.10.1 + resolution: "@inquirer/prompts@npm:7.10.1" + dependencies: + "@inquirer/checkbox": "npm:^4.3.2" + "@inquirer/confirm": "npm:^5.1.21" + "@inquirer/editor": "npm:^4.2.23" + "@inquirer/expand": "npm:^4.0.23" + "@inquirer/input": "npm:^4.3.1" + "@inquirer/number": "npm:^3.0.23" + "@inquirer/password": "npm:^4.0.23" + "@inquirer/rawlist": "npm:^4.1.11" + "@inquirer/search": "npm:^3.2.2" + "@inquirer/select": "npm:^4.4.2" + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/eac309cc75712bc94fc8b6761d6a736786ca1942cf9c90805b2a6049a05ce6131bcfb3aa703d1dbe66874d1b78c2b446044ad9735a2bb76743b8ddcb3dcb4d2a + languageName: node + linkType: hard + +"@inquirer/rawlist@npm:^4.1.11": + version: 4.1.11 + resolution: "@inquirer/rawlist@npm:4.1.11" + dependencies: + "@inquirer/core": "npm:^10.3.2" + "@inquirer/type": "npm:^3.0.10" + yoctocolors-cjs: "npm:^2.1.3" + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/33792b40cd0fbf77f547c9c4805087dd1188342c6a5ca512c73b0b6c4d132225fc5ae8bc4fd5035309484da3698a90fcef17aad100b9ae57624fda7b07d92227 + languageName: node + linkType: hard + +"@inquirer/search@npm:^3.2.2": + version: 3.2.2 + resolution: "@inquirer/search@npm:3.2.2" + dependencies: + "@inquirer/core": "npm:^10.3.2" + "@inquirer/figures": "npm:^1.0.15" + "@inquirer/type": "npm:^3.0.10" + yoctocolors-cjs: "npm:^2.1.3" + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/e7849663a51fe95e3ce99d274c815b8dc8933d6a5ddcaaf6130bf43f5f10316062c9f7a37c2923a14b8dcd09d202b0bb9cc3eaf0adb0336f6a704ea52e03ef8c + languageName: node + linkType: hard + +"@inquirer/select@npm:^4.4.2": + version: 4.4.2 + resolution: "@inquirer/select@npm:4.4.2" + dependencies: + "@inquirer/ansi": "npm:^1.0.2" + "@inquirer/core": "npm:^10.3.2" + "@inquirer/figures": "npm:^1.0.15" + "@inquirer/type": "npm:^3.0.10" + yoctocolors-cjs: "npm:^2.1.3" + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/6978a5a92928b4d439dd6b688f2db51fd49be209f24be224bb81ed8f75b76e0715e79bdb05dab2a33bbdc7091c779a99f8603fe0ca199f059528ca2b1d0d4944 + languageName: node + linkType: hard + +"@inquirer/type@npm:^3.0.10, @inquirer/type@npm:^3.0.8": + version: 3.0.10 + resolution: "@inquirer/type@npm:3.0.10" + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/a846c7a570e3bf2657d489bcc5dcdc3179d24c7323719de1951dcdb722400ac76e5b2bfe9765d0a789bc1921fac810983d7999f021f30a78a6a174c23fc78dc9 + languageName: node + linkType: hard + +"@ioredis/commands@npm:1.5.1": + version: 1.5.1 + resolution: "@ioredis/commands@npm:1.5.1" + checksum: 10c0/cb8f6d13cff0753e3e7ef001fb895491985d9a623248192538f13bc2fd9bfdfde3c18cf2ba6f20ec8ceaa681b0771070d3a09b82eed044c798bcfef5e3ae54b3 + languageName: node + linkType: hard + +"@isaacs/cliui@npm:^8.0.2": + version: 8.0.2 + resolution: "@isaacs/cliui@npm:8.0.2" + dependencies: + string-width: "npm:^5.1.2" + string-width-cjs: "npm:string-width@^4.2.0" + strip-ansi: "npm:^7.0.1" + strip-ansi-cjs: "npm:strip-ansi@^6.0.1" + wrap-ansi: "npm:^8.1.0" + wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" + checksum: 10c0/b1bf42535d49f11dc137f18d5e4e63a28c5569de438a221c369483731e9dac9fb797af554e8bf02b6192d1e5eba6e6402cf93900c3d0ac86391d00d04876789e + languageName: node + linkType: hard + +"@isaacs/cliui@npm:^9.0.0": + version: 9.0.0 + resolution: "@isaacs/cliui@npm:9.0.0" + checksum: 10c0/971063b7296419f85053dacd0a0285dcadaa3dfc139228b23e016c1a9848121ad4aa5e7fcca7522062014e1eb6239a7424188b9f2cba893a79c90aae5710319c + languageName: node + linkType: hard + +"@isaacs/fs-minipass@npm:^4.0.0": + version: 4.0.1 + resolution: "@isaacs/fs-minipass@npm:4.0.1" + dependencies: + minipass: "npm:^7.0.4" + checksum: 10c0/c25b6dc1598790d5b55c0947a9b7d111cfa92594db5296c3b907e2f533c033666f692a3939eadac17b1c7c40d362d0b0635dc874cbfe3e70db7c2b07cc97a5d2 + languageName: node + linkType: hard + +"@isaacs/string-locale-compare@npm:^1.1.0": + version: 1.1.0 + resolution: "@isaacs/string-locale-compare@npm:1.1.0" + checksum: 10c0/d67226ff7ac544a495c77df38187e69e0e3a0783724777f86caadafb306e2155dc3b5787d5927916ddd7fb4a53561ac8f705448ac3235d18ea60da5854829fdf + languageName: node + linkType: hard + +"@istanbuljs/load-nyc-config@npm:^1.0.0": + version: 1.1.0 + resolution: "@istanbuljs/load-nyc-config@npm:1.1.0" + dependencies: + camelcase: "npm:^5.3.1" + find-up: "npm:^4.1.0" + get-package-type: "npm:^0.1.0" + js-yaml: "npm:^3.13.1" + resolve-from: "npm:^5.0.0" + checksum: 10c0/dd2a8b094887da5a1a2339543a4933d06db2e63cbbc2e288eb6431bd832065df0c099d091b6a67436e71b7d6bf85f01ce7c15f9253b4cbebcc3b9a496165ba42 + languageName: node + linkType: hard + +"@istanbuljs/schema@npm:^0.1.2, @istanbuljs/schema@npm:^0.1.3": + version: 0.1.3 + resolution: "@istanbuljs/schema@npm:0.1.3" + checksum: 10c0/61c5286771676c9ca3eb2bd8a7310a9c063fb6e0e9712225c8471c582d157392c88f5353581c8c9adbe0dff98892317d2fdfc56c3499aa42e0194405206a963a + languageName: node + linkType: hard + +"@jest/console@npm:30.3.0": + version: 30.3.0 + resolution: "@jest/console@npm:30.3.0" + dependencies: + "@jest/types": "npm:30.3.0" + "@types/node": "npm:*" + chalk: "npm:^4.1.2" + jest-message-util: "npm:30.3.0" + jest-util: "npm:30.3.0" + slash: "npm:^3.0.0" + checksum: 10c0/5458f26b0591b847b719a707cbd1d6b2b99960784a1480a28d19200a807b6092f066c1bd1810df8c6adebf934a64de7b6022dc35082cd7c8f09f35940da104d9 + languageName: node + linkType: hard + +"@jest/console@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/console@npm:29.7.0" + dependencies: + "@jest/types": "npm:^29.6.3" + "@types/node": "npm:*" + chalk: "npm:^4.0.0" + jest-message-util: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + slash: "npm:^3.0.0" + checksum: 10c0/7be408781d0a6f657e969cbec13b540c329671819c2f57acfad0dae9dbfe2c9be859f38fe99b35dba9ff1536937dc6ddc69fdcd2794812fa3c647a1619797f6c + languageName: node + linkType: hard + +"@jest/core@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/core@npm:29.7.0" + dependencies: + "@jest/console": "npm:^29.7.0" + "@jest/reporters": "npm:^29.7.0" + "@jest/test-result": "npm:^29.7.0" + "@jest/transform": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + "@types/node": "npm:*" + ansi-escapes: "npm:^4.2.1" + chalk: "npm:^4.0.0" + ci-info: "npm:^3.2.0" + exit: "npm:^0.1.2" + graceful-fs: "npm:^4.2.9" + jest-changed-files: "npm:^29.7.0" + jest-config: "npm:^29.7.0" + jest-haste-map: "npm:^29.7.0" + jest-message-util: "npm:^29.7.0" + jest-regex-util: "npm:^29.6.3" + jest-resolve: "npm:^29.7.0" + jest-resolve-dependencies: "npm:^29.7.0" + jest-runner: "npm:^29.7.0" + jest-runtime: "npm:^29.7.0" + jest-snapshot: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + jest-validate: "npm:^29.7.0" + jest-watcher: "npm:^29.7.0" + micromatch: "npm:^4.0.4" + pretty-format: "npm:^29.7.0" + slash: "npm:^3.0.0" + strip-ansi: "npm:^6.0.0" + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + checksum: 10c0/934f7bf73190f029ac0f96662c85cd276ec460d407baf6b0dbaec2872e157db4d55a7ee0b1c43b18874602f662b37cb973dda469a4e6d88b4e4845b521adeeb2 + languageName: node + linkType: hard + +"@jest/diff-sequences@npm:30.3.0": + version: 30.3.0 + resolution: "@jest/diff-sequences@npm:30.3.0" + checksum: 10c0/8922c16a869b839b6c05f677023b3e5a9aa1610ad78a9c5ec8bd6654e35e8136ea1c7b60ad561910e2ad964bfdb0b09b0254ff8dcfacd4562095766f60c63d76 + languageName: node + linkType: hard + +"@jest/environment@npm:30.3.0": + version: 30.3.0 + resolution: "@jest/environment@npm:30.3.0" + dependencies: + "@jest/fake-timers": "npm:30.3.0" + "@jest/types": "npm:30.3.0" + "@types/node": "npm:*" + jest-mock: "npm:30.3.0" + checksum: 10c0/4068ccc2e4761e52909239c21e71f73b57ad087bd120b75d3232c68d911686d68fd0fb20e19725517a624b0aa9d45431b00503bd1d5ab2f4958e1a18d265d8d5 + languageName: node + linkType: hard + +"@jest/environment@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/environment@npm:29.7.0" + dependencies: + "@jest/fake-timers": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + "@types/node": "npm:*" + jest-mock: "npm:^29.7.0" + checksum: 10c0/c7b1b40c618f8baf4d00609022d2afa086d9c6acc706f303a70bb4b67275868f620ad2e1a9efc5edd418906157337cce50589a627a6400bbdf117d351b91ef86 + languageName: node + linkType: hard + +"@jest/expect-utils@npm:30.3.0": + version: 30.3.0 + resolution: "@jest/expect-utils@npm:30.3.0" + dependencies: + "@jest/get-type": "npm:30.1.0" + checksum: 10c0/4bb60fb434cb8ed325735bd39171b61621e110502ecc502089805d203ecb17b9fc5a400aeffb83b41fabcc819628a9c38c955f90a716d6aaff193d10926fc854 + languageName: node + linkType: hard + +"@jest/expect-utils@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/expect-utils@npm:29.7.0" + dependencies: + jest-get-type: "npm:^29.6.3" + checksum: 10c0/60b79d23a5358dc50d9510d726443316253ecda3a7fb8072e1526b3e0d3b14f066ee112db95699b7a43ad3f0b61b750c72e28a5a1cac361d7a2bb34747fa938a + languageName: node + linkType: hard + +"@jest/expect@npm:30.3.0": + version: 30.3.0 + resolution: "@jest/expect@npm:30.3.0" + dependencies: + expect: "npm:30.3.0" + jest-snapshot: "npm:30.3.0" + checksum: 10c0/1e052975fdf2b977a63dc9f3db1de56be9dce8e5cd660d9c72cc25093324b990b3e93318cd0c1ff9df7cb30ec7eef71331bc7e19d39700eb3f4498e17ee4c9e0 + languageName: node + linkType: hard + +"@jest/expect@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/expect@npm:29.7.0" + dependencies: + expect: "npm:^29.7.0" + jest-snapshot: "npm:^29.7.0" + checksum: 10c0/b41f193fb697d3ced134349250aed6ccea075e48c4f803159db102b826a4e473397c68c31118259868fd69a5cba70e97e1c26d2c2ff716ca39dc73a2ccec037e + languageName: node + linkType: hard + +"@jest/fake-timers@npm:30.3.0": + version: 30.3.0 + resolution: "@jest/fake-timers@npm:30.3.0" + dependencies: + "@jest/types": "npm:30.3.0" + "@sinonjs/fake-timers": "npm:^15.0.0" + "@types/node": "npm:*" + jest-message-util: "npm:30.3.0" + jest-mock: "npm:30.3.0" + jest-util: "npm:30.3.0" + checksum: 10c0/114855ca14d6b34c886855445852a5b960bc3df0ef97c4b971b375747fe0206b3111ec60efc6e658565677022f0d790acd7e232e478f3390ea854d04dea0c4d8 + languageName: node + linkType: hard + +"@jest/fake-timers@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/fake-timers@npm:29.7.0" + dependencies: + "@jest/types": "npm:^29.6.3" + "@sinonjs/fake-timers": "npm:^10.0.2" + "@types/node": "npm:*" + jest-message-util: "npm:^29.7.0" + jest-mock: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + checksum: 10c0/cf0a8bcda801b28dc2e2b2ba36302200ee8104a45ad7a21e6c234148932f826cb3bc57c8df3b7b815aeea0861d7b6ca6f0d4778f93b9219398ef28749e03595c + languageName: node + linkType: hard + +"@jest/get-type@npm:30.1.0": + version: 30.1.0 + resolution: "@jest/get-type@npm:30.1.0" + checksum: 10c0/3e65fd5015f551c51ec68fca31bbd25b466be0e8ee8075d9610fa1c686ea1e70a942a0effc7b10f4ea9a338c24337e1ad97ff69d3ebacc4681b7e3e80d1b24ac + languageName: node + linkType: hard + +"@jest/globals@npm:30.3.0": + version: 30.3.0 + resolution: "@jest/globals@npm:30.3.0" + dependencies: + "@jest/environment": "npm:30.3.0" + "@jest/expect": "npm:30.3.0" + "@jest/types": "npm:30.3.0" + jest-mock: "npm:30.3.0" + checksum: 10c0/013554dcbf75867e715801e98a5c6eefbea67cb388efd019be9e0d83979d7354874c4b33bbabc95de698215f5b891e921c26a284841504f9825fd789432b1cd0 + languageName: node + linkType: hard + +"@jest/globals@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/globals@npm:29.7.0" + dependencies: + "@jest/environment": "npm:^29.7.0" + "@jest/expect": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + jest-mock: "npm:^29.7.0" + checksum: 10c0/a385c99396878fe6e4460c43bd7bb0a5cc52befb462cc6e7f2a3810f9e7bcce7cdeb51908fd530391ee452dc856c98baa2c5f5fa8a5b30b071d31ef7f6955cea + languageName: node + linkType: hard + +"@jest/pattern@npm:30.0.1": + version: 30.0.1 + resolution: "@jest/pattern@npm:30.0.1" + dependencies: + "@types/node": "npm:*" + jest-regex-util: "npm:30.0.1" + checksum: 10c0/32c5a7bfb6c591f004dac0ed36d645002ed168971e4c89bd915d1577031672870032594767557b855c5bc330aa1e39a2f54bf150d2ee88a7a0886e9cb65318bc + languageName: node + linkType: hard + +"@jest/reporters@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/reporters@npm:29.7.0" + dependencies: + "@bcoe/v8-coverage": "npm:^0.2.3" + "@jest/console": "npm:^29.7.0" + "@jest/test-result": "npm:^29.7.0" + "@jest/transform": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + "@jridgewell/trace-mapping": "npm:^0.3.18" + "@types/node": "npm:*" + chalk: "npm:^4.0.0" + collect-v8-coverage: "npm:^1.0.0" + exit: "npm:^0.1.2" + glob: "npm:^7.1.3" + graceful-fs: "npm:^4.2.9" + istanbul-lib-coverage: "npm:^3.0.0" + istanbul-lib-instrument: "npm:^6.0.0" + istanbul-lib-report: "npm:^3.0.0" + istanbul-lib-source-maps: "npm:^4.0.0" + istanbul-reports: "npm:^3.1.3" + jest-message-util: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + jest-worker: "npm:^29.7.0" + slash: "npm:^3.0.0" + string-length: "npm:^4.0.1" + strip-ansi: "npm:^6.0.0" + v8-to-istanbul: "npm:^9.0.1" + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + checksum: 10c0/a754402a799541c6e5aff2c8160562525e2a47e7d568f01ebfc4da66522de39cbb809bbb0a841c7052e4270d79214e70aec3c169e4eae42a03bc1a8a20cb9fa2 + languageName: node + linkType: hard + +"@jest/reporters@npm:^30.0.2": + version: 30.3.0 + resolution: "@jest/reporters@npm:30.3.0" + dependencies: + "@bcoe/v8-coverage": "npm:^0.2.3" + "@jest/console": "npm:30.3.0" + "@jest/test-result": "npm:30.3.0" + "@jest/transform": "npm:30.3.0" + "@jest/types": "npm:30.3.0" + "@jridgewell/trace-mapping": "npm:^0.3.25" + "@types/node": "npm:*" + chalk: "npm:^4.1.2" + collect-v8-coverage: "npm:^1.0.2" + exit-x: "npm:^0.2.2" + glob: "npm:^10.5.0" + graceful-fs: "npm:^4.2.11" + istanbul-lib-coverage: "npm:^3.0.0" + istanbul-lib-instrument: "npm:^6.0.0" + istanbul-lib-report: "npm:^3.0.0" + istanbul-lib-source-maps: "npm:^5.0.0" + istanbul-reports: "npm:^3.1.3" + jest-message-util: "npm:30.3.0" + jest-util: "npm:30.3.0" + jest-worker: "npm:30.3.0" + slash: "npm:^3.0.0" + string-length: "npm:^4.0.2" + v8-to-istanbul: "npm:^9.0.1" + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + checksum: 10c0/e1b6fb13df94435d4b8e6f4d4bd1c27dfc572ca7393b0a95d14c98013abe3c962aa28e2c56864f3ddd0894834d21c9a67485d11e6c31532aaaeea66ca6a2a026 + languageName: node + linkType: hard + +"@jest/schemas@npm:30.0.5": + version: 30.0.5 + resolution: "@jest/schemas@npm:30.0.5" + dependencies: + "@sinclair/typebox": "npm:^0.34.0" + checksum: 10c0/449dcd7ec5c6505e9ac3169d1143937e67044ae3e66a729ce4baf31812dfd30535f2b3b2934393c97cfdf5984ff581120e6b38f62b8560c8b5b7cc07f4175f65 + languageName: node + linkType: hard + +"@jest/schemas@npm:^29.6.3": + version: 29.6.3 + resolution: "@jest/schemas@npm:29.6.3" + dependencies: + "@sinclair/typebox": "npm:^0.27.8" + checksum: 10c0/b329e89cd5f20b9278ae1233df74016ebf7b385e0d14b9f4c1ad18d096c4c19d1e687aa113a9c976b16ec07f021ae53dea811fb8c1248a50ac34fbe009fdf6be + languageName: node + linkType: hard + +"@jest/snapshot-utils@npm:30.3.0": + version: 30.3.0 + resolution: "@jest/snapshot-utils@npm:30.3.0" + dependencies: + "@jest/types": "npm:30.3.0" + chalk: "npm:^4.1.2" + graceful-fs: "npm:^4.2.11" + natural-compare: "npm:^1.4.0" + checksum: 10c0/ba4fea05a418b257d128d8f9eb7672a9004952563a45ad577bed80e5b2ea2ec6e6d3a24535781cc6530d9904d8fda7b27d15952d079ccdbe88f87a5e71112df0 + languageName: node + linkType: hard + +"@jest/source-map@npm:30.0.1": + version: 30.0.1 + resolution: "@jest/source-map@npm:30.0.1" + dependencies: + "@jridgewell/trace-mapping": "npm:^0.3.25" + callsites: "npm:^3.1.0" + graceful-fs: "npm:^4.2.11" + checksum: 10c0/e7bda2786fc9f483d9dd7566c58c4bd948830997be862dfe80a3ae5550ff3f84753abb52e705d02ebe9db9f34ba7ebec4c2db11882048cdeef7a66f6332b3897 + languageName: node + linkType: hard + +"@jest/source-map@npm:^29.6.3": + version: 29.6.3 + resolution: "@jest/source-map@npm:29.6.3" + dependencies: + "@jridgewell/trace-mapping": "npm:^0.3.18" + callsites: "npm:^3.0.0" + graceful-fs: "npm:^4.2.9" + checksum: 10c0/a2f177081830a2e8ad3f2e29e20b63bd40bade294880b595acf2fc09ec74b6a9dd98f126a2baa2bf4941acd89b13a4ade5351b3885c224107083a0059b60a219 + languageName: node + linkType: hard + +"@jest/test-result@npm:30.3.0, @jest/test-result@npm:^30.0.2": + version: 30.3.0 + resolution: "@jest/test-result@npm:30.3.0" + dependencies: + "@jest/console": "npm:30.3.0" + "@jest/types": "npm:30.3.0" + "@types/istanbul-lib-coverage": "npm:^2.0.6" + collect-v8-coverage: "npm:^1.0.2" + checksum: 10c0/67bcd405d0a1ac85b55afabf26e0ee0f184f9cfe0e659a44e0e4a4456c1c7fed9d2288f0116b017eaddfa49ded8c44426b8694c44f9a8a2af35be9202b8a9165 + languageName: node + linkType: hard + +"@jest/test-result@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/test-result@npm:29.7.0" + dependencies: + "@jest/console": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + "@types/istanbul-lib-coverage": "npm:^2.0.0" + collect-v8-coverage: "npm:^1.0.0" + checksum: 10c0/7de54090e54a674ca173470b55dc1afdee994f2d70d185c80236003efd3fa2b753fff51ffcdda8e2890244c411fd2267529d42c4a50a8303755041ee493e6a04 + languageName: node + linkType: hard + +"@jest/test-sequencer@npm:30.3.0": + version: 30.3.0 + resolution: "@jest/test-sequencer@npm:30.3.0" + dependencies: + "@jest/test-result": "npm:30.3.0" + graceful-fs: "npm:^4.2.11" + jest-haste-map: "npm:30.3.0" + slash: "npm:^3.0.0" + checksum: 10c0/698be35e7145e79ea9d66071d4ec255f6cef4b5972b5142d299f3edbcbc0428cadf8ddecc6d21e938c98ed72b73b15a6d5f81e7b8b370aaa130d2f6b26fd017c + languageName: node + linkType: hard + +"@jest/test-sequencer@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/test-sequencer@npm:29.7.0" + dependencies: + "@jest/test-result": "npm:^29.7.0" + graceful-fs: "npm:^4.2.9" + jest-haste-map: "npm:^29.7.0" + slash: "npm:^3.0.0" + checksum: 10c0/593a8c4272797bb5628984486080cbf57aed09c7cfdc0a634e8c06c38c6bef329c46c0016e84555ee55d1cd1f381518cf1890990ff845524c1123720c8c1481b + languageName: node + linkType: hard + +"@jest/transform@npm:30.3.0": + version: 30.3.0 + resolution: "@jest/transform@npm:30.3.0" + dependencies: + "@babel/core": "npm:^7.27.4" + "@jest/types": "npm:30.3.0" + "@jridgewell/trace-mapping": "npm:^0.3.25" + babel-plugin-istanbul: "npm:^7.0.1" + chalk: "npm:^4.1.2" + convert-source-map: "npm:^2.0.0" + fast-json-stable-stringify: "npm:^2.1.0" + graceful-fs: "npm:^4.2.11" + jest-haste-map: "npm:30.3.0" + jest-regex-util: "npm:30.0.1" + jest-util: "npm:30.3.0" + pirates: "npm:^4.0.7" + slash: "npm:^3.0.0" + write-file-atomic: "npm:^5.0.1" + checksum: 10c0/5ad0b5361910680b5160e3dc347c0beb75b4edc35a165ef4fc55837d01365179c276dd6f9cc80f7db94048c641b0c188757e1c98c6d4e9b55577956efbc00574 + languageName: node + linkType: hard + +"@jest/transform@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/transform@npm:29.7.0" + dependencies: + "@babel/core": "npm:^7.11.6" + "@jest/types": "npm:^29.6.3" + "@jridgewell/trace-mapping": "npm:^0.3.18" + babel-plugin-istanbul: "npm:^6.1.1" + chalk: "npm:^4.0.0" + convert-source-map: "npm:^2.0.0" + fast-json-stable-stringify: "npm:^2.1.0" + graceful-fs: "npm:^4.2.9" + jest-haste-map: "npm:^29.7.0" + jest-regex-util: "npm:^29.6.3" + jest-util: "npm:^29.7.0" + micromatch: "npm:^4.0.4" + pirates: "npm:^4.0.4" + slash: "npm:^3.0.0" + write-file-atomic: "npm:^4.0.2" + checksum: 10c0/7f4a7f73dcf45dfdf280c7aa283cbac7b6e5a904813c3a93ead7e55873761fc20d5c4f0191d2019004fac6f55f061c82eb3249c2901164ad80e362e7a7ede5a6 + languageName: node + linkType: hard + +"@jest/types@npm:30.3.0": + version: 30.3.0 + resolution: "@jest/types@npm:30.3.0" + dependencies: + "@jest/pattern": "npm:30.0.1" + "@jest/schemas": "npm:30.0.5" + "@types/istanbul-lib-coverage": "npm:^2.0.6" + "@types/istanbul-reports": "npm:^3.0.4" + "@types/node": "npm:*" + "@types/yargs": "npm:^17.0.33" + chalk: "npm:^4.1.2" + checksum: 10c0/c3e3f4de0b77a7ced345f47d3687b1094c1b6c1521529a7ca66a76f9a80194f79179a1dbc32d6761a5b67914a8f78be1e65d1408107efcb1f252c4a63b5ddd92 + languageName: node + linkType: hard + +"@jest/types@npm:^29.6.3": + version: 29.6.3 + resolution: "@jest/types@npm:29.6.3" + dependencies: + "@jest/schemas": "npm:^29.6.3" + "@types/istanbul-lib-coverage": "npm:^2.0.0" + "@types/istanbul-reports": "npm:^3.0.0" + "@types/node": "npm:*" + "@types/yargs": "npm:^17.0.8" + chalk: "npm:^4.0.0" + checksum: 10c0/ea4e493dd3fb47933b8ccab201ae573dcc451f951dc44ed2a86123cd8541b82aa9d2b1031caf9b1080d6673c517e2dcc25a44b2dc4f3fbc37bfc965d444888c0 + languageName: node + linkType: hard + +"@jridgewell/gen-mapping@npm:^0.3.12, @jridgewell/gen-mapping@npm:^0.3.5": + version: 0.3.13 + resolution: "@jridgewell/gen-mapping@npm:0.3.13" + dependencies: + "@jridgewell/sourcemap-codec": "npm:^1.5.0" + "@jridgewell/trace-mapping": "npm:^0.3.24" + checksum: 10c0/9a7d65fb13bd9aec1fbab74cda08496839b7e2ceb31f5ab922b323e94d7c481ce0fc4fd7e12e2610915ed8af51178bdc61e168e92a8c8b8303b030b03489b13b + languageName: node + linkType: hard + +"@jridgewell/remapping@npm:^2.3.5": + version: 2.3.5 + resolution: "@jridgewell/remapping@npm:2.3.5" + dependencies: + "@jridgewell/gen-mapping": "npm:^0.3.5" + "@jridgewell/trace-mapping": "npm:^0.3.24" + checksum: 10c0/3de494219ffeb2c5c38711d0d7bb128097edf91893090a2dbc8ee0b55d092bb7347b1fd0f478486c5eab010e855c73927b1666f2107516d472d24a73017d1194 + languageName: node + linkType: hard + +"@jridgewell/resolve-uri@npm:^3.0.3, @jridgewell/resolve-uri@npm:^3.1.0": + version: 3.1.2 + resolution: "@jridgewell/resolve-uri@npm:3.1.2" + checksum: 10c0/d502e6fb516b35032331406d4e962c21fe77cdf1cbdb49c6142bcbd9e30507094b18972778a6e27cbad756209cfe34b1a27729e6fa08a2eb92b33943f680cf1e + languageName: node + linkType: hard + +"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.5.0": + version: 1.5.5 + resolution: "@jridgewell/sourcemap-codec@npm:1.5.5" + checksum: 10c0/f9e538f302b63c0ebc06eecb1dd9918dd4289ed36147a0ddce35d6ea4d7ebbda243cda7b2213b6a5e1d8087a298d5cf630fb2bd39329cdecb82017023f6081a0 + languageName: node + linkType: hard + +"@jridgewell/trace-mapping@npm:0.3.9": + version: 0.3.9 + resolution: "@jridgewell/trace-mapping@npm:0.3.9" + dependencies: + "@jridgewell/resolve-uri": "npm:^3.0.3" + "@jridgewell/sourcemap-codec": "npm:^1.4.10" + checksum: 10c0/fa425b606d7c7ee5bfa6a31a7b050dd5814b4082f318e0e4190f991902181b4330f43f4805db1dd4f2433fd0ed9cc7a7b9c2683f1deeab1df1b0a98b1e24055b + languageName: node + linkType: hard + +"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.18, @jridgewell/trace-mapping@npm:^0.3.23, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25, @jridgewell/trace-mapping@npm:^0.3.28": + version: 0.3.31 + resolution: "@jridgewell/trace-mapping@npm:0.3.31" + dependencies: + "@jridgewell/resolve-uri": "npm:^3.1.0" + "@jridgewell/sourcemap-codec": "npm:^1.4.14" + checksum: 10c0/4b30ec8cd56c5fd9a661f088230af01e0c1a3888d11ffb6b47639700f71225be21d1f7e168048d6d4f9449207b978a235c07c8f15c07705685d16dc06280e9d9 + languageName: node + linkType: hard + +"@js-sdsl/ordered-map@npm:^4.4.2": + version: 4.4.2 + resolution: "@js-sdsl/ordered-map@npm:4.4.2" + checksum: 10c0/cc7e15dc4acf6d9ef663757279600bab70533d847dcc1ab01332e9e680bd30b77cdf9ad885cc774276f51d98b05a013571c940e5b360985af5eb798dc1a2ee2b + languageName: node + linkType: hard + +"@kwsites/file-exists@npm:^1.1.1": + version: 1.1.1 + resolution: "@kwsites/file-exists@npm:1.1.1" + dependencies: + debug: "npm:^4.1.1" + checksum: 10c0/39e693239a72ccd8408bb618a0200e4a8d61682057ca7ae2c87668d7e69196e8d7e2c9cde73db6b23b3b0230169a15e5f1bfe086539f4be43e767b2db68e8ee4 + languageName: node + linkType: hard + +"@ltd/j-toml@npm:^1.38.0": + version: 1.38.0 + resolution: "@ltd/j-toml@npm:1.38.0" + checksum: 10c0/6db2b203e21c6bc2e781ad76f3e798ae9c4b9d83205070f482602a30f3d1c37dde8c8c72575bdc505c1b8c228c5e81171a4557f0d76b814da0fb91cdd21f6194 + languageName: node + linkType: hard + +"@lukeed/csprng@npm:^1.0.0": + version: 1.1.0 + resolution: "@lukeed/csprng@npm:1.1.0" + checksum: 10c0/5d6dcf478af732972083ab2889c294b57f1028fa13c2c240d7a4aaa079c2c75df7ef0dcbdda5419147fc6704b4adf96b2de92f1a9a72ac21c6350c4014fffe6c + languageName: node + linkType: hard + +"@modelcontextprotocol/sdk@npm:^1.25.2": + version: 1.29.0 + resolution: "@modelcontextprotocol/sdk@npm:1.29.0" + dependencies: + "@hono/node-server": "npm:^1.19.9" + ajv: "npm:^8.17.1" + ajv-formats: "npm:^3.0.1" + content-type: "npm:^1.0.5" + cors: "npm:^2.8.5" + cross-spawn: "npm:^7.0.5" + eventsource: "npm:^3.0.2" + eventsource-parser: "npm:^3.0.0" + express: "npm:^5.2.1" + express-rate-limit: "npm:^8.2.1" + hono: "npm:^4.11.4" + jose: "npm:^6.1.3" + json-schema-typed: "npm:^8.0.2" + pkce-challenge: "npm:^5.0.0" + raw-body: "npm:^3.0.0" + zod: "npm:^3.25 || ^4.0" + zod-to-json-schema: "npm:^3.25.1" + peerDependencies: + "@cfworker/json-schema": ^4.1.1 + zod: ^3.25 || ^4.0 + peerDependenciesMeta: + "@cfworker/json-schema": + optional: true + zod: + optional: false + checksum: 10c0/7c4bc339205b1652330cd4e6b121cc859079655f2b9c0506bbb15563ba0d07924bda3d949705530532db7f4d2cb86d633dc8f92bc32803d97c7bece2ac63e29f + languageName: node + linkType: hard + +"@msgpackr-extract/msgpackr-extract-darwin-arm64@npm:3.0.3": + version: 3.0.3 + resolution: "@msgpackr-extract/msgpackr-extract-darwin-arm64@npm:3.0.3" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@msgpackr-extract/msgpackr-extract-darwin-x64@npm:3.0.3": + version: 3.0.3 + resolution: "@msgpackr-extract/msgpackr-extract-darwin-x64@npm:3.0.3" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@msgpackr-extract/msgpackr-extract-linux-arm64@npm:3.0.3": + version: 3.0.3 + resolution: "@msgpackr-extract/msgpackr-extract-linux-arm64@npm:3.0.3" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + +"@msgpackr-extract/msgpackr-extract-linux-arm@npm:3.0.3": + version: 3.0.3 + resolution: "@msgpackr-extract/msgpackr-extract-linux-arm@npm:3.0.3" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@msgpackr-extract/msgpackr-extract-linux-x64@npm:3.0.3": + version: 3.0.3 + resolution: "@msgpackr-extract/msgpackr-extract-linux-x64@npm:3.0.3" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + +"@msgpackr-extract/msgpackr-extract-win32-x64@npm:3.0.3": + version: 3.0.3 + resolution: "@msgpackr-extract/msgpackr-extract-win32-x64@npm:3.0.3" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@napi-rs/wasm-runtime@npm:0.2.4": + version: 0.2.4 + resolution: "@napi-rs/wasm-runtime@npm:0.2.4" + dependencies: + "@emnapi/core": "npm:^1.1.0" + "@emnapi/runtime": "npm:^1.1.0" + "@tybys/wasm-util": "npm:^0.9.0" + checksum: 10c0/1040de49b2ef509db207e2517465dbf7fb3474f20e8ec32897672a962ff4f59872385666dac61dc9dbeae3cae5dad265d8dc3865da756adeb07d1634c67b03a1 + languageName: node + linkType: hard + +"@napi-rs/wasm-runtime@npm:^0.2.11": + version: 0.2.12 + resolution: "@napi-rs/wasm-runtime@npm:0.2.12" + dependencies: + "@emnapi/core": "npm:^1.4.3" + "@emnapi/runtime": "npm:^1.4.3" + "@tybys/wasm-util": "npm:^0.10.0" + checksum: 10c0/6d07922c0613aab30c6a497f4df297ca7c54e5b480e00035e0209b872d5c6aab7162fc49477267556109c2c7ed1eb9c65a174e27e9b87568106a87b0a6e3ca7d + languageName: node + linkType: hard + +"@nestjs/common@npm:^10": + version: 10.4.22 + resolution: "@nestjs/common@npm:10.4.22" + dependencies: + file-type: "npm:20.4.1" + iterare: "npm:1.2.1" + tslib: "npm:2.8.1" + uid: "npm:2.0.2" + peerDependencies: + class-transformer: "*" + class-validator: "*" + reflect-metadata: ^0.1.12 || ^0.2.0 + rxjs: ^7.1.0 + peerDependenciesMeta: + class-transformer: + optional: true + class-validator: + optional: true + checksum: 10c0/6b31315b173361af069ef7b79023f25eb1b8c0ed95cf453339b69a967c923961e56b2976493421ff7f055feb46f500ed42497dcf7c9a599731c9cf4c504e84d7 + languageName: node + linkType: hard + +"@nestjs/core@npm:^10": + version: 10.4.22 + resolution: "@nestjs/core@npm:10.4.22" + dependencies: + "@nuxtjs/opencollective": "npm:0.3.2" + fast-safe-stringify: "npm:2.1.1" + iterare: "npm:1.2.1" + path-to-regexp: "npm:3.3.0" + tslib: "npm:2.8.1" + uid: "npm:2.0.2" + peerDependencies: + "@nestjs/common": ^10.0.0 + "@nestjs/microservices": ^10.0.0 + "@nestjs/platform-express": ^10.0.0 + "@nestjs/websockets": ^10.0.0 + reflect-metadata: ^0.1.12 || ^0.2.0 + rxjs: ^7.1.0 + peerDependenciesMeta: + "@nestjs/microservices": + optional: true + "@nestjs/platform-express": + optional: true + "@nestjs/websockets": + optional: true + checksum: 10c0/026393ca7d09bc80f2a2b2f0813092a9af964f2f4ecfc6a01a6cc89e8dfd107d0df8c839d373c53a9b300db954b81ed2967a56dc289785d98d897090ca66268e + languageName: node + linkType: hard + +"@nestjs/platform-express@npm:^10": + version: 10.4.22 + resolution: "@nestjs/platform-express@npm:10.4.22" + dependencies: + body-parser: "npm:1.20.4" + cors: "npm:2.8.5" + express: "npm:4.22.1" + multer: "npm:2.0.2" + tslib: "npm:2.8.1" + peerDependencies: + "@nestjs/common": ^10.0.0 + "@nestjs/core": ^10.0.0 + checksum: 10c0/7bddcba7b66d19f14fe4c15f21b21dd819fe0340fa57db35dcdcf7fb344ce682aa494363b182574885413d22c7fbee5fcef6f9d2189f419d4983cb71be1f4d28 + languageName: node + linkType: hard + +"@nestjs/testing@npm:^11.1.18": + version: 11.1.18 + resolution: "@nestjs/testing@npm:11.1.18" + dependencies: + tslib: "npm:2.8.1" + peerDependencies: + "@nestjs/common": ^11.0.0 + "@nestjs/core": ^11.0.0 + "@nestjs/microservices": ^11.0.0 + "@nestjs/platform-express": ^11.0.0 + peerDependenciesMeta: + "@nestjs/microservices": + optional: true + "@nestjs/platform-express": + optional: true + checksum: 10c0/49addd548fbf8881181b4e467a713835190cb79e24cd3a9ad643d6c7b7bca1688547ce0a7dffe453d811fb85f5aad75d247d6d04bbceb36136dd3724d1e8509f + languageName: node + linkType: hard + +"@npmcli/agent@npm:^4.0.0": + version: 4.0.0 + resolution: "@npmcli/agent@npm:4.0.0" + dependencies: + agent-base: "npm:^7.1.0" + http-proxy-agent: "npm:^7.0.0" + https-proxy-agent: "npm:^7.0.1" + lru-cache: "npm:^11.2.1" + socks-proxy-agent: "npm:^8.0.3" + checksum: 10c0/f7b5ce0f3dd42c3f8c6546e8433573d8049f67ef11ec22aa4704bc41483122f68bf97752e06302c455ead667af5cb753e6a09bff06632bc465c1cfd4c4b75a53 + languageName: node + linkType: hard + +"@npmcli/arborist@npm:9.1.6": + version: 9.1.6 + resolution: "@npmcli/arborist@npm:9.1.6" + dependencies: + "@isaacs/string-locale-compare": "npm:^1.1.0" + "@npmcli/fs": "npm:^4.0.0" + "@npmcli/installed-package-contents": "npm:^3.0.0" + "@npmcli/map-workspaces": "npm:^5.0.0" + "@npmcli/metavuln-calculator": "npm:^9.0.2" + "@npmcli/name-from-folder": "npm:^3.0.0" + "@npmcli/node-gyp": "npm:^4.0.0" + "@npmcli/package-json": "npm:^7.0.0" + "@npmcli/query": "npm:^4.0.0" + "@npmcli/redact": "npm:^3.0.0" + "@npmcli/run-script": "npm:^10.0.0" + bin-links: "npm:^5.0.0" + cacache: "npm:^20.0.1" + common-ancestor-path: "npm:^1.0.1" + hosted-git-info: "npm:^9.0.0" + json-stringify-nice: "npm:^1.1.4" + lru-cache: "npm:^11.2.1" + minimatch: "npm:^10.0.3" + nopt: "npm:^8.0.0" + npm-install-checks: "npm:^7.1.0" + npm-package-arg: "npm:^13.0.0" + npm-pick-manifest: "npm:^11.0.1" + npm-registry-fetch: "npm:^19.0.0" + pacote: "npm:^21.0.2" + parse-conflict-json: "npm:^4.0.0" + proc-log: "npm:^5.0.0" + proggy: "npm:^3.0.0" + promise-all-reject-late: "npm:^1.0.0" + promise-call-limit: "npm:^3.0.1" + semver: "npm:^7.3.7" + ssri: "npm:^12.0.0" + treeverse: "npm:^3.0.0" + walk-up-path: "npm:^4.0.0" + bin: + arborist: bin/index.js + checksum: 10c0/359e2a278fda83e60bdfdc410c1d439753d8d390a475e934d31d3fd250a3f2b0693dc7c64f6e9ed9cc5bd0186b21b50c3fc1c5befc0c6ff4996d332477dbe1b1 + languageName: node + linkType: hard + +"@npmcli/fs@npm:^4.0.0": + version: 4.0.0 + resolution: "@npmcli/fs@npm:4.0.0" + dependencies: + semver: "npm:^7.3.5" + checksum: 10c0/c90935d5ce670c87b6b14fab04a965a3b8137e585f8b2a6257263bd7f97756dd736cb165bb470e5156a9e718ecd99413dccc54b1138c1a46d6ec7cf325982fe5 + languageName: node + linkType: hard + +"@npmcli/fs@npm:^5.0.0": + version: 5.0.0 + resolution: "@npmcli/fs@npm:5.0.0" + dependencies: + semver: "npm:^7.3.5" + checksum: 10c0/26e376d780f60ff16e874a0ac9bc3399186846baae0b6e1352286385ac134d900cc5dafaded77f38d77f86898fc923ae1cee9d7399f0275b1aa24878915d722b + languageName: node + linkType: hard + +"@npmcli/git@npm:^6.0.0": + version: 6.0.3 + resolution: "@npmcli/git@npm:6.0.3" + dependencies: + "@npmcli/promise-spawn": "npm:^8.0.0" + ini: "npm:^5.0.0" + lru-cache: "npm:^10.0.1" + npm-pick-manifest: "npm:^10.0.0" + proc-log: "npm:^5.0.0" + promise-retry: "npm:^2.0.1" + semver: "npm:^7.3.5" + which: "npm:^5.0.0" + checksum: 10c0/a8ff1d5f997f7bfdc149fbe7478017b100efe3d08bd566df6b5ac716fd630d2eff0f7feebc6705831a3a7072a67a955a339a8fea8551ce4faffafa9526306e05 + languageName: node + linkType: hard + +"@npmcli/git@npm:^7.0.0": + version: 7.0.2 + resolution: "@npmcli/git@npm:7.0.2" + dependencies: + "@gar/promise-retry": "npm:^1.0.0" + "@npmcli/promise-spawn": "npm:^9.0.0" + ini: "npm:^6.0.0" + lru-cache: "npm:^11.2.1" + npm-pick-manifest: "npm:^11.0.1" + proc-log: "npm:^6.0.0" + semver: "npm:^7.3.5" + which: "npm:^6.0.0" + checksum: 10c0/1936471c3188aa470d0c0dd4d49724bf144e381d122252d001475d69a96cd9de950936f55fec8c6a673a47cf607b11a662fc8b8a45c67d5c37c795b07d2be8e9 + languageName: node + linkType: hard + +"@npmcli/installed-package-contents@npm:^3.0.0": + version: 3.0.0 + resolution: "@npmcli/installed-package-contents@npm:3.0.0" + dependencies: + npm-bundled: "npm:^4.0.0" + npm-normalize-package-bin: "npm:^4.0.0" + bin: + installed-package-contents: bin/index.js + checksum: 10c0/8bb361251cd13b91ae2d04bfcc59b52ffb8cd475d074259c143b3c29a0c4c0ae90d76cfb2cab00ff61cc76bd0c38591b530ce1bdbbc8a61d60ddc6c9ecbf169b + languageName: node + linkType: hard + +"@npmcli/installed-package-contents@npm:^4.0.0": + version: 4.0.0 + resolution: "@npmcli/installed-package-contents@npm:4.0.0" + dependencies: + npm-bundled: "npm:^5.0.0" + npm-normalize-package-bin: "npm:^5.0.0" + bin: + installed-package-contents: bin/index.js + checksum: 10c0/297f32afc350e92c85981c1c793358af19e63c64d090f4e09997393fa2471f92da52317cb551356dc13594f2bdfad32d02c78bc2c664e2b7e0109d0d8713b39e + languageName: node + linkType: hard + +"@npmcli/map-workspaces@npm:^5.0.0": + version: 5.0.3 + resolution: "@npmcli/map-workspaces@npm:5.0.3" + dependencies: + "@npmcli/name-from-folder": "npm:^4.0.0" + "@npmcli/package-json": "npm:^7.0.0" + glob: "npm:^13.0.0" + minimatch: "npm:^10.0.3" + checksum: 10c0/975c3f94f9bc9e646b28ddabea2eebd11e6528241f7f7621cdfc083311c91b608a7b9647797e07a18bb8ce775e54a80d361800fffa3ced22803c5140f0a50553 + languageName: node + linkType: hard + +"@npmcli/metavuln-calculator@npm:^9.0.2": + version: 9.0.3 + resolution: "@npmcli/metavuln-calculator@npm:9.0.3" + dependencies: + cacache: "npm:^20.0.0" + json-parse-even-better-errors: "npm:^5.0.0" + pacote: "npm:^21.0.0" + proc-log: "npm:^6.0.0" + semver: "npm:^7.3.5" + checksum: 10c0/cc5905788b0dbd2372beff690566ed917be8643b8c24352e669339f6ee66a6edf4a82ba22c7b88b8fa0c52589556c6aa4613a47825ab3727caee6ae8451ab09a + languageName: node + linkType: hard + +"@npmcli/name-from-folder@npm:^3.0.0": + version: 3.0.0 + resolution: "@npmcli/name-from-folder@npm:3.0.0" + checksum: 10c0/d6a508c5b4920fb28c752718b906b36fc2374873eba804668afdac8b3c322e8b97a5f1a74f3448d847c615a10828446821d90caf7cdf603d424a9f40f3a733df + languageName: node + linkType: hard + +"@npmcli/name-from-folder@npm:^4.0.0": + version: 4.0.0 + resolution: "@npmcli/name-from-folder@npm:4.0.0" + checksum: 10c0/edaeb4a4098f920e373cddd7f765347f1013e3a84e1cdb16da4b83144bc377fe7cd4fa37562596a53a9e46dfca381c2b8706c2661014921bc1bf710303dff713 + languageName: node + linkType: hard + +"@npmcli/node-gyp@npm:^4.0.0": + version: 4.0.0 + resolution: "@npmcli/node-gyp@npm:4.0.0" + checksum: 10c0/58422c2ce0693f519135dd32b5c5bcbb441823f08f9294d5ec19d9a22925ba1a5ec04a1b96f606f2ab09a5f5db56e704f6e201a485198ce9d11fb6b2705e6e79 + languageName: node + linkType: hard + +"@npmcli/node-gyp@npm:^5.0.0": + version: 5.0.0 + resolution: "@npmcli/node-gyp@npm:5.0.0" + checksum: 10c0/dc78219a848a30d26d46cd174816bdf21936aaee15469888cbd04433981ef866b35611275a1f94a31d68ea60cc18747d0d02430e4ce59f8a5c2423ec35b1bbed + languageName: node + linkType: hard + +"@npmcli/package-json@npm:7.0.2": + version: 7.0.2 + resolution: "@npmcli/package-json@npm:7.0.2" + dependencies: + "@npmcli/git": "npm:^7.0.0" + glob: "npm:^11.0.3" + hosted-git-info: "npm:^9.0.0" + json-parse-even-better-errors: "npm:^5.0.0" + proc-log: "npm:^6.0.0" + semver: "npm:^7.5.3" + validate-npm-package-license: "npm:^3.0.4" + checksum: 10c0/2901c648c80b4805c3c17ca30c76217858b348b20aab1ddf83b30240ed1d32257284545a9c78a8eb1c6d1a5dd7d5c61b430bfc5bc9ae409c989abafe54b6d4e3 + languageName: node + linkType: hard + +"@npmcli/package-json@npm:^7.0.0": + version: 7.0.5 + resolution: "@npmcli/package-json@npm:7.0.5" + dependencies: + "@npmcli/git": "npm:^7.0.0" + glob: "npm:^13.0.0" + hosted-git-info: "npm:^9.0.0" + json-parse-even-better-errors: "npm:^5.0.0" + proc-log: "npm:^6.0.0" + semver: "npm:^7.5.3" + spdx-expression-parse: "npm:^4.0.0" + checksum: 10c0/4a04af494cd7273d4a5e930f53f30217dad389c7eaeb4de667aca84be27e668ebd8b16a6923ce58dc3090030f9126885b4cfc790517050acf179d0d9e0ca6de1 + languageName: node + linkType: hard + +"@npmcli/promise-spawn@npm:^8.0.0": + version: 8.0.3 + resolution: "@npmcli/promise-spawn@npm:8.0.3" + dependencies: + which: "npm:^5.0.0" + checksum: 10c0/596b8f626d3764c761cb931982546b8a94ceedcb6d62884b90118be1b06c7e33b3f5890f4946e29d4b913ec3089384b13c3957d8b58e33ceb6ac4daf786e84a0 + languageName: node + linkType: hard + +"@npmcli/promise-spawn@npm:^9.0.0": + version: 9.0.1 + resolution: "@npmcli/promise-spawn@npm:9.0.1" + dependencies: + which: "npm:^6.0.0" + checksum: 10c0/361872192934bda684f590f140a2edd68add90d5936ca9a2e8792435447847adb59e249d5976950e20bbf213898c04da1b51b62fbc8f258b2fa8601af37fa0e2 + languageName: node + linkType: hard + +"@npmcli/query@npm:^4.0.0": + version: 4.0.1 + resolution: "@npmcli/query@npm:4.0.1" + dependencies: + postcss-selector-parser: "npm:^7.0.0" + checksum: 10c0/ac88b1eb255e00f80be210f8641678a2d695a80b5935e60922fc523d3e19a9e4523accd38b0fa9d9c39a60e6eea3385b4a7161773950896f7e89ebd741dc542b + languageName: node + linkType: hard + +"@npmcli/redact@npm:^3.0.0": + version: 3.2.2 + resolution: "@npmcli/redact@npm:3.2.2" + checksum: 10c0/4cfb43a5de22114eee40d3ca4f4dc6a4e0f0315e3427938b7e43dfc16684a54844d202b171cee3ec99852eb2ada22fb874a4fe61ad22399fd98897326b1cc7d7 + languageName: node + linkType: hard + +"@npmcli/redact@npm:^4.0.0": + version: 4.0.0 + resolution: "@npmcli/redact@npm:4.0.0" + checksum: 10c0/a1e9ba9c70a6b40e175bda2c3dd8cfdaf096e6b7f7a132c855c083c8dfe545c3237cd56702e2e6627a580b1d63373599d49a1192c4078a85bf47bbde824df31c + languageName: node + linkType: hard + +"@npmcli/run-script@npm:10.0.3": + version: 10.0.3 + resolution: "@npmcli/run-script@npm:10.0.3" + dependencies: + "@npmcli/node-gyp": "npm:^5.0.0" + "@npmcli/package-json": "npm:^7.0.0" + "@npmcli/promise-spawn": "npm:^9.0.0" + node-gyp: "npm:^12.1.0" + proc-log: "npm:^6.0.0" + which: "npm:^6.0.0" + checksum: 10c0/227483417d1f36011d35d1b868cd7a9c615553f195a86a282ca3c273e89f38f172fc1fcbb8f1635d419c861679570887874a37f9f21350e0b6fc813930224358 + languageName: node + linkType: hard + +"@npmcli/run-script@npm:^10.0.0": + version: 10.0.4 + resolution: "@npmcli/run-script@npm:10.0.4" + dependencies: + "@npmcli/node-gyp": "npm:^5.0.0" + "@npmcli/package-json": "npm:^7.0.0" + "@npmcli/promise-spawn": "npm:^9.0.0" + node-gyp: "npm:^12.1.0" + proc-log: "npm:^6.0.0" + checksum: 10c0/4d65682491ce7462c6a16a3d20511f70074a0ab384e4e08786ff6c2df9630ad29caa564b5ace49ec3ba5a7f483dfbd13168da903c433a48e59c73189306b1a2f + languageName: node + linkType: hard + +"@nuxtjs/opencollective@npm:0.3.2": + version: 0.3.2 + resolution: "@nuxtjs/opencollective@npm:0.3.2" + dependencies: + chalk: "npm:^4.1.0" + consola: "npm:^2.15.0" + node-fetch: "npm:^2.6.1" + bin: + opencollective: bin/opencollective.js + checksum: 10c0/540268687af3289ff107585484d42201b404cdbb98b3a512487c12a6b180a8f0e1df0d701df47d3d9e0d5c0f6eb3252d80535562aedca9edf52cf7fd17ae4601 + languageName: node + linkType: hard + +"@nx/devkit@npm:22.6.4, @nx/devkit@npm:>=21.5.2 < 23.0.0": + version: 22.6.4 + resolution: "@nx/devkit@npm:22.6.4" + dependencies: + "@zkochan/js-yaml": "npm:0.0.7" + ejs: "npm:^3.1.7" + enquirer: "npm:~2.3.6" + minimatch: "npm:10.2.4" + semver: "npm:^7.6.3" + tslib: "npm:^2.3.0" + yargs-parser: "npm:21.1.1" + peerDependencies: + nx: ">= 21 <= 23 || ^22.0.0-0" + checksum: 10c0/1484e229eded11c0f125f566fd96e47c845dc47692070892faaea02c91db4db62335268c7e59d42032c66f00f5fd08cdef513b6d6f12ddae2f41a79291843422 + languageName: node + linkType: hard + +"@nx/eslint@npm:^22.6.4": + version: 22.6.4 + resolution: "@nx/eslint@npm:22.6.4" + dependencies: + "@nx/devkit": "npm:22.6.4" + "@nx/js": "npm:22.6.4" + semver: "npm:^7.6.3" + tslib: "npm:^2.3.0" + typescript: "npm:~5.9.2" + peerDependencies: + "@zkochan/js-yaml": 0.0.7 + eslint: ^8.0.0 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + "@zkochan/js-yaml": + optional: true + checksum: 10c0/a1da4abb86327882e0ca315d45fa4bd73156643719520a0e2f64dc7942e3f1f3d6c77985cc50be4c12f00f460c7893a2daf588621bfe18f9e56e0fac2546403c + languageName: node + linkType: hard + +"@nx/jest@npm:^22.6.4": + version: 22.6.4 + resolution: "@nx/jest@npm:22.6.4" + dependencies: + "@jest/reporters": "npm:^30.0.2" + "@jest/test-result": "npm:^30.0.2" + "@nx/devkit": "npm:22.6.4" + "@nx/js": "npm:22.6.4" + "@phenomnomnominal/tsquery": "npm:~6.1.4" + identity-obj-proxy: "npm:3.0.0" + jest-config: "npm:^30.0.2" + jest-resolve: "npm:^30.0.2" + jest-util: "npm:^30.0.2" + minimatch: "npm:10.2.4" + picocolors: "npm:^1.1.0" + resolve.exports: "npm:2.0.3" + semver: "npm:^7.6.3" + tslib: "npm:^2.3.0" + yargs-parser: "npm:21.1.1" + checksum: 10c0/3ec599c18d2a38a9b49cb876f7df53edbc70f9e3a49f6d4f972da0e966a38e1450f2cc7e6c8cb909530d00b43646b0574af6e60e161873bc3211f2a122df37a0 + languageName: node + linkType: hard + +"@nx/js@npm:22.6.4, @nx/js@npm:^22.6.4": + version: 22.6.4 + resolution: "@nx/js@npm:22.6.4" + dependencies: + "@babel/core": "npm:^7.23.2" + "@babel/plugin-proposal-decorators": "npm:^7.22.7" + "@babel/plugin-transform-class-properties": "npm:^7.22.5" + "@babel/plugin-transform-runtime": "npm:^7.23.2" + "@babel/preset-env": "npm:^7.23.2" + "@babel/preset-typescript": "npm:^7.22.5" + "@babel/runtime": "npm:^7.22.6" + "@nx/devkit": "npm:22.6.4" + "@nx/workspace": "npm:22.6.4" + "@zkochan/js-yaml": "npm:0.0.7" + babel-plugin-const-enum: "npm:^1.0.1" + babel-plugin-macros: "npm:^3.1.0" + babel-plugin-transform-typescript-metadata: "npm:^0.3.1" + chalk: "npm:^4.1.0" + columnify: "npm:^1.6.0" + detect-port: "npm:^1.5.1" + ignore: "npm:^5.0.4" + js-tokens: "npm:^4.0.0" + jsonc-parser: "npm:3.2.0" + npm-run-path: "npm:^4.0.1" + picocolors: "npm:^1.1.0" + picomatch: "npm:4.0.4" + semver: "npm:^7.6.3" + source-map-support: "npm:0.5.19" + tinyglobby: "npm:^0.2.12" + tslib: "npm:^2.3.0" + peerDependencies: + verdaccio: ^6.0.5 + peerDependenciesMeta: + verdaccio: + optional: true + checksum: 10c0/5608b3a2f5134508671e05f51ce0250fd63e3402596e3efac2560a9927781eef52c7458191c09f1fe76a05e3f65c557aadd3a83c8f288c501bdf9504bf7a676e + languageName: node + linkType: hard + +"@nx/nx-darwin-arm64@npm:22.6.4": + version: 22.6.4 + resolution: "@nx/nx-darwin-arm64@npm:22.6.4" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@nx/nx-darwin-x64@npm:22.6.4": + version: 22.6.4 + resolution: "@nx/nx-darwin-x64@npm:22.6.4" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@nx/nx-freebsd-x64@npm:22.6.4": + version: 22.6.4 + resolution: "@nx/nx-freebsd-x64@npm:22.6.4" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@nx/nx-linux-arm-gnueabihf@npm:22.6.4": + version: 22.6.4 + resolution: "@nx/nx-linux-arm-gnueabihf@npm:22.6.4" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@nx/nx-linux-arm64-gnu@npm:22.6.4": + version: 22.6.4 + resolution: "@nx/nx-linux-arm64-gnu@npm:22.6.4" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@nx/nx-linux-arm64-musl@npm:22.6.4": + version: 22.6.4 + resolution: "@nx/nx-linux-arm64-musl@npm:22.6.4" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@nx/nx-linux-x64-gnu@npm:22.6.4": + version: 22.6.4 + resolution: "@nx/nx-linux-x64-gnu@npm:22.6.4" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@nx/nx-linux-x64-musl@npm:22.6.4": + version: 22.6.4 + resolution: "@nx/nx-linux-x64-musl@npm:22.6.4" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@nx/nx-win32-arm64-msvc@npm:22.6.4": + version: 22.6.4 + resolution: "@nx/nx-win32-arm64-msvc@npm:22.6.4" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@nx/nx-win32-x64-msvc@npm:22.6.4": + version: 22.6.4 + resolution: "@nx/nx-win32-x64-msvc@npm:22.6.4" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@nx/workspace@npm:22.6.4": + version: 22.6.4 + resolution: "@nx/workspace@npm:22.6.4" + dependencies: + "@nx/devkit": "npm:22.6.4" + "@zkochan/js-yaml": "npm:0.0.7" + chalk: "npm:^4.1.0" + enquirer: "npm:~2.3.6" + nx: "npm:22.6.4" + picomatch: "npm:4.0.4" + semver: "npm:^7.6.3" + tslib: "npm:^2.3.0" + yargs-parser: "npm:21.1.1" + checksum: 10c0/7982c937915181a5f6c6070056a69dff8f2463faca43903a46aefdc7f79075e1f588ec3c9b3031533afe2bf2aeb0f9abca7cf8478297d19b5a237d67c556ca55 + languageName: node + linkType: hard + +"@octokit/auth-token@npm:^4.0.0": + version: 4.0.0 + resolution: "@octokit/auth-token@npm:4.0.0" + checksum: 10c0/57acaa6c394c5abab2f74e8e1dcf4e7a16b236f713c77a54b8f08e2d14114de94b37946259e33ec2aab0566b26f724c2b71d2602352b59e541a9854897618f3c + languageName: node + linkType: hard + +"@octokit/core@npm:^5.0.2": + version: 5.2.2 + resolution: "@octokit/core@npm:5.2.2" + dependencies: + "@octokit/auth-token": "npm:^4.0.0" + "@octokit/graphql": "npm:^7.1.0" + "@octokit/request": "npm:^8.4.1" + "@octokit/request-error": "npm:^5.1.1" + "@octokit/types": "npm:^13.0.0" + before-after-hook: "npm:^2.2.0" + universal-user-agent: "npm:^6.0.0" + checksum: 10c0/b4484d85552303b839613e2133dcd064fa06a7c10fe0ebd11ba8f67cb8e3384e48983c589f4d1dc0fa3754857784e3d90ff4eab9782e118baf13ddd1b834957c + languageName: node + linkType: hard + +"@octokit/endpoint@npm:^9.0.6": + version: 9.0.6 + resolution: "@octokit/endpoint@npm:9.0.6" + dependencies: + "@octokit/types": "npm:^13.1.0" + universal-user-agent: "npm:^6.0.0" + checksum: 10c0/8e06197b21869aeb498e0315093ca6fbee12bd1bdcfc1667fcd7d79d827d84f2c5a30702ffd28bba7879780e367d14c30df5b20d47fcaed5de5fdc05f5d4e013 + languageName: node + linkType: hard + +"@octokit/graphql@npm:^7.1.0": + version: 7.1.1 + resolution: "@octokit/graphql@npm:7.1.1" + dependencies: + "@octokit/request": "npm:^8.4.1" + "@octokit/types": "npm:^13.0.0" + universal-user-agent: "npm:^6.0.0" + checksum: 10c0/c27216200f3f4ce7ce2a694fb7ea43f8ea4a807fbee3a423c41ed137dd7948dfc0bbf6ea1656f029a7625c84b583acdef740a7032266d0eff55305c91c3a1ed6 + languageName: node + linkType: hard + +"@octokit/openapi-types@npm:^24.2.0": + version: 24.2.0 + resolution: "@octokit/openapi-types@npm:24.2.0" + checksum: 10c0/8f47918b35e9b7f6109be6f7c8fc3a64ad13a48233112b29e92559e64a564b810eb3ebf81b4cd0af1bb2989d27b9b95cca96e841ec4e23a3f68703cefe62fd9e + languageName: node + linkType: hard + +"@octokit/plugin-enterprise-rest@npm:6.0.1": + version: 6.0.1 + resolution: "@octokit/plugin-enterprise-rest@npm:6.0.1" + checksum: 10c0/26bd0a30582954efcd29b41e16698db79e9d20e3f88c4069b43b183223cee69862621f18b6a7a1c9257b1cd07c24477e403b75c74688660ecf31d467b9d8fd9e + languageName: node + linkType: hard + +"@octokit/plugin-paginate-rest@npm:11.4.4-cjs.2": + version: 11.4.4-cjs.2 + resolution: "@octokit/plugin-paginate-rest@npm:11.4.4-cjs.2" + dependencies: + "@octokit/types": "npm:^13.7.0" + peerDependencies: + "@octokit/core": 5 + checksum: 10c0/1d61a63c98a18c171bccdc6cf63ffe279fe852e8bdc9db6647ffcb27f4ea485fdab78fb71b552ed0f2186785cf5264f8ed3f9a8f33061e4697b5f73b097accb1 + languageName: node + linkType: hard + +"@octokit/plugin-request-log@npm:^4.0.0": + version: 4.0.1 + resolution: "@octokit/plugin-request-log@npm:4.0.1" + peerDependencies: + "@octokit/core": 5 + checksum: 10c0/6f556f86258c5fbff9b1821075dc91137b7499f2ad0fd12391f0876064a6daa88abe1748336b2d483516505771d358aa15cb4bcdabc348a79e3d951fe9726798 + languageName: node + linkType: hard + +"@octokit/plugin-rest-endpoint-methods@npm:13.3.2-cjs.1": + version: 13.3.2-cjs.1 + resolution: "@octokit/plugin-rest-endpoint-methods@npm:13.3.2-cjs.1" + dependencies: + "@octokit/types": "npm:^13.8.0" + peerDependencies: + "@octokit/core": ^5 + checksum: 10c0/810fe5cb1861386746bf0218ea969d87c56e553ff339490526483b4b66f53c4b4c6092034bec30c5d453172eb6f33e75b5748ade1b401b76774b5a994e2c10b0 + languageName: node + linkType: hard + +"@octokit/request-error@npm:^5.1.1": + version: 5.1.1 + resolution: "@octokit/request-error@npm:5.1.1" + dependencies: + "@octokit/types": "npm:^13.1.0" + deprecation: "npm:^2.0.0" + once: "npm:^1.4.0" + checksum: 10c0/dc9fc76ea5e4199273e4665ce9ddf345fe8f25578d9999c9a16f276298e61ee6fe0e6f5a6147b91ba3b34fdf5b9e6b7af6ae13d6333175e95b30c574088f7a2d + languageName: node + linkType: hard + +"@octokit/request@npm:^8.4.1": + version: 8.4.1 + resolution: "@octokit/request@npm:8.4.1" + dependencies: + "@octokit/endpoint": "npm:^9.0.6" + "@octokit/request-error": "npm:^5.1.1" + "@octokit/types": "npm:^13.1.0" + universal-user-agent: "npm:^6.0.0" + checksum: 10c0/1a69dcb7336de708a296db9e9a58040e5b284a87495a63112f80eb0007da3fc96a9fadecb9e875fc63cf179c23a0f81031fbef2a6f610a219e45805ead03fcf3 + languageName: node + linkType: hard + +"@octokit/rest@npm:20.1.2": + version: 20.1.2 + resolution: "@octokit/rest@npm:20.1.2" + dependencies: + "@octokit/core": "npm:^5.0.2" + "@octokit/plugin-paginate-rest": "npm:11.4.4-cjs.2" + "@octokit/plugin-request-log": "npm:^4.0.0" + "@octokit/plugin-rest-endpoint-methods": "npm:13.3.2-cjs.1" + checksum: 10c0/712e08c43c7af37c5c219f95ae289b3ac2646270be4e8a7141fa2aa9340ed8f7134f117c9467e89206c5a9797c49c8d2c039b884d4865bb3bde91bc5adb3c38c + languageName: node + linkType: hard + +"@octokit/types@npm:^13.0.0, @octokit/types@npm:^13.1.0, @octokit/types@npm:^13.7.0, @octokit/types@npm:^13.8.0": + version: 13.10.0 + resolution: "@octokit/types@npm:13.10.0" + dependencies: + "@octokit/openapi-types": "npm:^24.2.0" + checksum: 10c0/f66a401b89d653ec28e5c1529abdb7965752db4d9d40fa54c80e900af4c6bf944af6bd0a83f5b4f1eecb72e3d646899dfb27ffcf272ac243552de7e3b97a038d + languageName: node + linkType: hard + +"@openai/agents-core@npm:0.3.9": + version: 0.3.9 + resolution: "@openai/agents-core@npm:0.3.9" + dependencies: + "@modelcontextprotocol/sdk": "npm:^1.25.2" + debug: "npm:^4.4.0" + openai: "npm:^6" + peerDependencies: + zod: ^3.25.40 || ^4.0 + dependenciesMeta: + "@modelcontextprotocol/sdk": + optional: true + peerDependenciesMeta: + zod: + optional: true + checksum: 10c0/8cf01b89ac906c0328778a3067eb0a112f3b42df88d2fcb7691292d45e78523bcbc2f9f7a27daabdf4d101bc56b48ae41d69cc7dd5d37376b32e9cd3f297e745 + languageName: node + linkType: hard + +"@openai/agents-openai@npm:0.3.9": + version: 0.3.9 + resolution: "@openai/agents-openai@npm:0.3.9" + dependencies: + "@openai/agents-core": "npm:0.3.9" + debug: "npm:^4.4.0" + openai: "npm:^6" + peerDependencies: + zod: ^3.25.40 || ^4.0 + checksum: 10c0/f6be0d93e4de925d40da9ae2bd95eea154171911ec33342be0fd3cdb4cbc397202f5856e649894e0f13c3cf58c568c06deb50e02ee17c6a8f9061c13b952f5e1 + languageName: node + linkType: hard + +"@openai/agents-realtime@npm:0.3.9": + version: 0.3.9 + resolution: "@openai/agents-realtime@npm:0.3.9" + dependencies: + "@openai/agents-core": "npm:0.3.9" + "@types/ws": "npm:^8.18.1" + debug: "npm:^4.4.0" + ws: "npm:^8.18.1" + peerDependencies: + zod: ^3.25.40 || ^4.0 + checksum: 10c0/3bf61704cb48f108efdbc43154226be2cacd379edadaf75d68e074f5e62377836598d62f846697d302cb6d4a97c4cf13f864062238f1a2a442a6d605e2441791 + languageName: node + linkType: hard + +"@openai/agents@npm:^0.3.0": + version: 0.3.9 + resolution: "@openai/agents@npm:0.3.9" + dependencies: + "@openai/agents-core": "npm:0.3.9" + "@openai/agents-openai": "npm:0.3.9" + "@openai/agents-realtime": "npm:0.3.9" + debug: "npm:^4.4.0" + openai: "npm:^6" + peerDependencies: + zod: ^3.25.40 || ^4.0 + checksum: 10c0/b353021372a760b87f4bab71bee9072791c3778d4320508834e8de746fa1442cc1d01d93bdd1ce1e158b5e74e42644e58ed9c60d48bec023a4c4ce670d542ad6 + languageName: node + linkType: hard + +"@phenomnomnominal/tsquery@npm:~6.1.4": + version: 6.1.4 + resolution: "@phenomnomnominal/tsquery@npm:6.1.4" + dependencies: + "@types/esquery": "npm:^1.5.0" + esquery: "npm:^1.5.0" + peerDependencies: + typescript: ^3 || ^4 || ^5 + checksum: 10c0/6bff27df57d4f710c8488f31405b3ad79e5dbc41db5cf1d0ff0f116cfcff49dca364cf15586fe020d48b4e7c2a976497260894ad01a35aed5187279b620c9d74 + languageName: node + linkType: hard + +"@pkgjs/parseargs@npm:^0.11.0": + version: 0.11.0 + resolution: "@pkgjs/parseargs@npm:0.11.0" + checksum: 10c0/5bd7576bb1b38a47a7fc7b51ac9f38748e772beebc56200450c4a817d712232b8f1d3ef70532c80840243c657d491cf6a6be1e3a214cff907645819fdc34aadd + languageName: node + linkType: hard + +"@pkgr/core@npm:^0.2.9": + version: 0.2.9 + resolution: "@pkgr/core@npm:0.2.9" + checksum: 10c0/ac8e4e8138b1a7a4ac6282873aef7389c352f1f8b577b4850778f5182e4a39a5241facbe48361fec817f56d02b51691b383010843fb08b34a8e8ea3614688fd5 + languageName: node + linkType: hard + +"@protobufjs/aspromise@npm:^1.1.1, @protobufjs/aspromise@npm:^1.1.2": + version: 1.1.2 + resolution: "@protobufjs/aspromise@npm:1.1.2" + checksum: 10c0/a83343a468ff5b5ec6bff36fd788a64c839e48a07ff9f4f813564f58caf44d011cd6504ed2147bf34835bd7a7dd2107052af755961c6b098fd8902b4f6500d0f + languageName: node + linkType: hard + +"@protobufjs/base64@npm:^1.1.2": + version: 1.1.2 + resolution: "@protobufjs/base64@npm:1.1.2" + checksum: 10c0/eec925e681081af190b8ee231f9bad3101e189abbc182ff279da6b531e7dbd2a56f1f306f37a80b1be9e00aa2d271690d08dcc5f326f71c9eed8546675c8caf6 + languageName: node + linkType: hard + +"@protobufjs/codegen@npm:^2.0.4": + version: 2.0.4 + resolution: "@protobufjs/codegen@npm:2.0.4" + checksum: 10c0/26ae337c5659e41f091606d16465bbcc1df1f37cc1ed462438b1f67be0c1e28dfb2ca9f294f39100c52161aef82edf758c95d6d75650a1ddf31f7ddee1440b43 + languageName: node + linkType: hard + +"@protobufjs/eventemitter@npm:^1.1.0": + version: 1.1.0 + resolution: "@protobufjs/eventemitter@npm:1.1.0" + checksum: 10c0/1eb0a75180e5206d1033e4138212a8c7089a3d418c6dfa5a6ce42e593a4ae2e5892c4ef7421f38092badba4040ea6a45f0928869989411001d8c1018ea9a6e70 + languageName: node + linkType: hard + +"@protobufjs/fetch@npm:^1.1.0": + version: 1.1.0 + resolution: "@protobufjs/fetch@npm:1.1.0" + dependencies: + "@protobufjs/aspromise": "npm:^1.1.1" + "@protobufjs/inquire": "npm:^1.1.0" + checksum: 10c0/cda6a3dc2d50a182c5865b160f72077aac197046600091dbb005dd0a66db9cce3c5eaed6d470ac8ed49d7bcbeef6ee5f0bc288db5ff9a70cbd003e5909065233 + languageName: node + linkType: hard + +"@protobufjs/float@npm:^1.0.2": + version: 1.0.2 + resolution: "@protobufjs/float@npm:1.0.2" + checksum: 10c0/18f2bdede76ffcf0170708af15c9c9db6259b771e6b84c51b06df34a9c339dbbeec267d14ce0bddd20acc142b1d980d983d31434398df7f98eb0c94a0eb79069 + languageName: node + linkType: hard + +"@protobufjs/inquire@npm:^1.1.0": + version: 1.1.0 + resolution: "@protobufjs/inquire@npm:1.1.0" + checksum: 10c0/64372482efcba1fb4d166a2664a6395fa978b557803857c9c03500e0ac1013eb4b1aacc9ed851dd5fc22f81583670b4f4431bae186f3373fedcfde863ef5921a + languageName: node + linkType: hard + +"@protobufjs/path@npm:^1.1.2": + version: 1.1.2 + resolution: "@protobufjs/path@npm:1.1.2" + checksum: 10c0/cece0a938e7f5dfd2fa03f8c14f2f1cf8b0d6e13ac7326ff4c96ea311effd5fb7ae0bba754fbf505312af2e38500250c90e68506b97c02360a43793d88a0d8b4 + languageName: node + linkType: hard + +"@protobufjs/pool@npm:^1.1.0": + version: 1.1.0 + resolution: "@protobufjs/pool@npm:1.1.0" + checksum: 10c0/eda2718b7f222ac6e6ad36f758a92ef90d26526026a19f4f17f668f45e0306a5bd734def3f48f51f8134ae0978b6262a5c517c08b115a551756d1a3aadfcf038 + languageName: node + linkType: hard + +"@protobufjs/utf8@npm:^1.1.0": + version: 1.1.0 + resolution: "@protobufjs/utf8@npm:1.1.0" + checksum: 10c0/a3fe31fe3fa29aa3349e2e04ee13dc170cc6af7c23d92ad49e3eeaf79b9766264544d3da824dba93b7855bd6a2982fb40032ef40693da98a136d835752beb487 + languageName: node + linkType: hard + +"@redis/bloom@npm:1.2.0": + version: 1.2.0 + resolution: "@redis/bloom@npm:1.2.0" + peerDependencies: + "@redis/client": ^1.0.0 + checksum: 10c0/7dde8e67188164e96226c8a5c78ebd2801f1662947371e78fb95fb180c1e9ddff8d237012eb5e9182775be61cb546f67f759927cdaee0d178d863ee290e1fb27 + languageName: node + linkType: hard + +"@redis/client@npm:1.6.1": + version: 1.6.1 + resolution: "@redis/client@npm:1.6.1" + dependencies: + cluster-key-slot: "npm:1.1.2" + generic-pool: "npm:3.9.0" + yallist: "npm:4.0.0" + checksum: 10c0/216c61f5aa2fef212386c2ef5b5f6d10f44244f6928682f370e190402d23338e11260377c08e87dd6d678408fa7c0a6b7bb5571ecadb830abfa3d7355b9eff1e + languageName: node + linkType: hard + +"@redis/graph@npm:1.1.1": + version: 1.1.1 + resolution: "@redis/graph@npm:1.1.1" + peerDependencies: + "@redis/client": ^1.0.0 + checksum: 10c0/64199db2cb3669c4911af8aba3b7116c4c2c1df37ca74b2a65555e62c863935a0cea74bc41bd92acf2e551074eb2a30c75f54a9f439b40e0f9bb67fc5fb66614 + languageName: node + linkType: hard + +"@redis/json@npm:1.0.7": + version: 1.0.7 + resolution: "@redis/json@npm:1.0.7" + peerDependencies: + "@redis/client": ^1.0.0 + checksum: 10c0/cef473711d66f7568a16edbd728acca7d237cfeaa15e0326b5b628dfab4afc0c76c7354e7f8efad6ecc64a1cb774e4aa060ee46497b633e18ba0a2f0aace1cc4 + languageName: node + linkType: hard + +"@redis/search@npm:1.2.0": + version: 1.2.0 + resolution: "@redis/search@npm:1.2.0" + peerDependencies: + "@redis/client": ^1.0.0 + checksum: 10c0/01d57ac10d2c5698e04e4a2f945440db3087e8834643ca950c099879dbcd77526604ca6f5c2ee883dfd4b337b0a24cb7d81ac56845aa83f89a4f161362a08dc6 + languageName: node + linkType: hard + +"@redis/time-series@npm:1.1.0": + version: 1.1.0 + resolution: "@redis/time-series@npm:1.1.0" + peerDependencies: + "@redis/client": ^1.0.0 + checksum: 10c0/503d0d5cbc9113d26666bb7b4dea57619badbcdfeee0369abf647250f26c5482ed5827c83f88f9f0cf22e021e3e7cb562459669d733fac05652972e208d6ba0f + languageName: node + linkType: hard + +"@sigstore/bundle@npm:^4.0.0": + version: 4.0.0 + resolution: "@sigstore/bundle@npm:4.0.0" + dependencies: + "@sigstore/protobuf-specs": "npm:^0.5.0" + checksum: 10c0/0606ed6274f8e042298cdbcbef293d57de7dc00082e6ab076c8bda9c1765dc502e160aecaa034c112c1f1d08266dd7376437a86e7ecab03e3865cb4e03ee24c2 + languageName: node + linkType: hard + +"@sigstore/core@npm:^3.1.0, @sigstore/core@npm:^3.2.0": + version: 3.2.0 + resolution: "@sigstore/core@npm:3.2.0" + checksum: 10c0/64a4abe361af3b56fd1689e195516759d8124b3033cd182888d007db0be9adc8825c5af350040b6a8eceeebe79c1296149c4d3afce7effca4a93fc00bb9373dc + languageName: node + linkType: hard + +"@sigstore/protobuf-specs@npm:^0.5.0": + version: 0.5.0 + resolution: "@sigstore/protobuf-specs@npm:0.5.0" + checksum: 10c0/03c188ce9943a8a89fb5b0257556dcfa9bb4b0bd70c9fa1ab19d26c378870e02d295ba024b89b8c80dc7e856dee046cdd25f6a94473d14d2b383d7b905d62de8 + languageName: node + linkType: hard + +"@sigstore/sign@npm:^4.1.0": + version: 4.1.1 + resolution: "@sigstore/sign@npm:4.1.1" + dependencies: + "@gar/promise-retry": "npm:^1.0.2" + "@sigstore/bundle": "npm:^4.0.0" + "@sigstore/core": "npm:^3.2.0" + "@sigstore/protobuf-specs": "npm:^0.5.0" + make-fetch-happen: "npm:^15.0.4" + proc-log: "npm:^6.1.0" + checksum: 10c0/88a6e5d2ce49477a52574d5dd5f4531cbb3472435fad29730969b77988efb23bdd5ce031a74f738da5b24c950f99030704b75b8cc65d5179b56ce9ede9711784 + languageName: node + linkType: hard + +"@sigstore/tuf@npm:^4.0.1": + version: 4.0.2 + resolution: "@sigstore/tuf@npm:4.0.2" + dependencies: + "@sigstore/protobuf-specs": "npm:^0.5.0" + tuf-js: "npm:^4.1.0" + checksum: 10c0/eb7ba5b9d4859948bfd5552a1c6d93f0d05b9482bf21dede53779ea429f833dcd13c3a52524596c556729d75d85326ce0a7d0857d3d23ef99784b0e94e948818 + languageName: node + linkType: hard + +"@sigstore/verify@npm:^3.1.0": + version: 3.1.0 + resolution: "@sigstore/verify@npm:3.1.0" + dependencies: + "@sigstore/bundle": "npm:^4.0.0" + "@sigstore/core": "npm:^3.1.0" + "@sigstore/protobuf-specs": "npm:^0.5.0" + checksum: 10c0/09745156daa109556750b0a57b076d6d813628f207d2db9425495a443a9b5e4bf378eb6904a0e3d6cd7f2c1382e80f136f29f3aed87eede2747d4f244aeb2075 + languageName: node + linkType: hard + +"@sinclair/typebox@npm:^0.27.8": + version: 0.27.10 + resolution: "@sinclair/typebox@npm:0.27.10" + checksum: 10c0/ca42a02817656dbdae464ed4bb8aca6ad4718d7618e270760fea84a834ad0ecc1a22eba51421f09e5047174571131356ff3b5d80d609ced775d631df7b404b0d + languageName: node + linkType: hard + +"@sinclair/typebox@npm:^0.34.0": + version: 0.34.49 + resolution: "@sinclair/typebox@npm:0.34.49" + checksum: 10c0/16b7d87f039a49b68c10bb4cdcae2ce5242b2472228851fd6483731616aba4ef977690aa517b230a8d20da8185bb416eb34e326f30568b3963c1cf26b05d1ad8 + languageName: node + linkType: hard + +"@sinonjs/commons@npm:^3.0.0, @sinonjs/commons@npm:^3.0.1": + version: 3.0.1 + resolution: "@sinonjs/commons@npm:3.0.1" + dependencies: + type-detect: "npm:4.0.8" + checksum: 10c0/1227a7b5bd6c6f9584274db996d7f8cee2c8c350534b9d0141fc662eaf1f292ea0ae3ed19e5e5271c8fd390d27e492ca2803acd31a1978be2cdc6be0da711403 + languageName: node + linkType: hard + +"@sinonjs/fake-timers@npm:^10.0.2": + version: 10.3.0 + resolution: "@sinonjs/fake-timers@npm:10.3.0" + dependencies: + "@sinonjs/commons": "npm:^3.0.0" + checksum: 10c0/2e2fb6cc57f227912814085b7b01fede050cd4746ea8d49a1e44d5a0e56a804663b0340ae2f11af7559ea9bf4d087a11f2f646197a660ea3cb04e19efc04aa63 + languageName: node + linkType: hard + +"@sinonjs/fake-timers@npm:^15.0.0": + version: 15.3.0 + resolution: "@sinonjs/fake-timers@npm:15.3.0" + dependencies: + "@sinonjs/commons": "npm:^3.0.1" + checksum: 10c0/172d21f5200069727f2aa90b35ab60068c1f0652c7d2a43f03bd6c2c2d75b87f4daa9fc7f1402f8c10e0849bb888d15d3364a194339b62307abd3a60cefbb929 + languageName: node + linkType: hard + +"@so-ric/colorspace@npm:^1.1.6": + version: 1.1.6 + resolution: "@so-ric/colorspace@npm:1.1.6" + dependencies: + color: "npm:^5.0.2" + text-hex: "npm:1.0.x" + checksum: 10c0/f3ad26afefbb8d6101ea7c385cd5f402d4291c2ffc9cabe37030d5fdb8bda980ee534a0d7c250f8233fc3a59b99272410177cd98b219f6b3770f91a0fdb6eb3e + languageName: node + linkType: hard + +"@tavily/core@npm:^0.6.0": + version: 0.6.4 + resolution: "@tavily/core@npm:0.6.4" + dependencies: + axios: "npm:^1.7.7" + https-proxy-agent: "npm:^7.0.6" + js-tiktoken: "npm:^1.0.14" + checksum: 10c0/20e09ec47f458dc883cdbd35c7056d8e886abc9fe6329ce0f2e9ebc56b7ee91f02d0e6cb56f44acb8d5b028496cd4590c54ea9874437f07d11b735db83c630af + languageName: node + linkType: hard + +"@tokenizer/inflate@npm:^0.2.6": + version: 0.2.7 + resolution: "@tokenizer/inflate@npm:0.2.7" + dependencies: + debug: "npm:^4.4.0" + fflate: "npm:^0.8.2" + token-types: "npm:^6.0.0" + checksum: 10c0/75bd0c510810dfd62be9d963216b5852cde021e1f8aab43b37662bc6aa75e65fd7277fcab7d463186b55cee36a5b61129916161bdb2a7d18064016156c7daf4f + languageName: node + linkType: hard + +"@tokenizer/token@npm:^0.3.0": + version: 0.3.0 + resolution: "@tokenizer/token@npm:0.3.0" + checksum: 10c0/7ab9a822d4b5ff3f5bca7f7d14d46bdd8432528e028db4a52be7fbf90c7f495cc1af1324691dda2813c6af8dc4b8eb29de3107d4508165f9aa5b53e7d501f155 + languageName: node + linkType: hard + +"@tsconfig/node10@npm:^1.0.7": + version: 1.0.12 + resolution: "@tsconfig/node10@npm:1.0.12" + checksum: 10c0/7bbbd7408cfaced86387a9b1b71cebc91c6fd701a120369735734da8eab1a4773fc079abd9f40c9e0b049e12586c8ac0e13f0da596bfd455b9b4c3faa813ebc5 + languageName: node + linkType: hard + +"@tsconfig/node12@npm:^1.0.7": + version: 1.0.11 + resolution: "@tsconfig/node12@npm:1.0.11" + checksum: 10c0/dddca2b553e2bee1308a056705103fc8304e42bb2d2cbd797b84403a223b25c78f2c683ec3e24a095e82cd435387c877239bffcb15a590ba817cd3f6b9a99fd9 + languageName: node + linkType: hard + +"@tsconfig/node14@npm:^1.0.0": + version: 1.0.3 + resolution: "@tsconfig/node14@npm:1.0.3" + checksum: 10c0/67c1316d065fdaa32525bc9449ff82c197c4c19092b9663b23213c8cbbf8d88b6ed6a17898e0cbc2711950fbfaf40388938c1c748a2ee89f7234fc9e7fe2bf44 + languageName: node + linkType: hard + +"@tsconfig/node16@npm:^1.0.2": + version: 1.0.4 + resolution: "@tsconfig/node16@npm:1.0.4" + checksum: 10c0/05f8f2734e266fb1839eb1d57290df1664fe2aa3b0fdd685a9035806daa635f7519bf6d5d9b33f6e69dd545b8c46bd6e2b5c79acb2b1f146e885f7f11a42a5bb + languageName: node + linkType: hard + +"@tufjs/canonical-json@npm:2.0.0": + version: 2.0.0 + resolution: "@tufjs/canonical-json@npm:2.0.0" + checksum: 10c0/52c5ffaef1483ed5c3feedfeba26ca9142fa386eea54464e70ff515bd01c5e04eab05d01eff8c2593291dcaf2397ca7d9c512720e11f52072b04c47a5c279415 + languageName: node + linkType: hard + +"@tufjs/models@npm:4.1.0": + version: 4.1.0 + resolution: "@tufjs/models@npm:4.1.0" + dependencies: + "@tufjs/canonical-json": "npm:2.0.0" + minimatch: "npm:^10.1.1" + checksum: 10c0/0a4ab524061c97bb43ccd3ffaaaed224eb41469fa2b748f66599d298798f7556e7158a12a9cbdfb89476df0ae538ca562292ac10909e411aa17f81f72b3e8931 + languageName: node + linkType: hard + +"@tybys/wasm-util@npm:^0.10.0": + version: 0.10.1 + resolution: "@tybys/wasm-util@npm:0.10.1" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10c0/b255094f293794c6d2289300c5fbcafbb5532a3aed3a5ffd2f8dc1828e639b88d75f6a376dd8f94347a44813fd7a7149d8463477a9a49525c8b2dcaa38c2d1e8 + languageName: node + linkType: hard + +"@tybys/wasm-util@npm:^0.9.0": + version: 0.9.0 + resolution: "@tybys/wasm-util@npm:0.9.0" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10c0/f9fde5c554455019f33af6c8215f1a1435028803dc2a2825b077d812bed4209a1a64444a4ca0ce2ea7e1175c8d88e2f9173a36a33c199e8a5c671aa31de8242d + languageName: node + linkType: hard + +"@types/babel__core@npm:^7.1.14, @types/babel__core@npm:^7.20.5": + version: 7.20.5 + resolution: "@types/babel__core@npm:7.20.5" + dependencies: + "@babel/parser": "npm:^7.20.7" + "@babel/types": "npm:^7.20.7" + "@types/babel__generator": "npm:*" + "@types/babel__template": "npm:*" + "@types/babel__traverse": "npm:*" + checksum: 10c0/bdee3bb69951e833a4b811b8ee9356b69a61ed5b7a23e1a081ec9249769117fa83aaaf023bb06562a038eb5845155ff663e2d5c75dd95c1d5ccc91db012868ff + languageName: node + linkType: hard + +"@types/babel__generator@npm:*": + version: 7.27.0 + resolution: "@types/babel__generator@npm:7.27.0" + dependencies: + "@babel/types": "npm:^7.0.0" + checksum: 10c0/9f9e959a8792df208a9d048092fda7e1858bddc95c6314857a8211a99e20e6830bdeb572e3587ae8be5429e37f2a96fcf222a9f53ad232f5537764c9e13a2bbd + languageName: node + linkType: hard + +"@types/babel__template@npm:*": + version: 7.4.4 + resolution: "@types/babel__template@npm:7.4.4" + dependencies: + "@babel/parser": "npm:^7.1.0" + "@babel/types": "npm:^7.0.0" + checksum: 10c0/cc84f6c6ab1eab1427e90dd2b76ccee65ce940b778a9a67be2c8c39e1994e6f5bbc8efa309f6cea8dc6754994524cd4d2896558df76d92e7a1f46ecffee7112b + languageName: node + linkType: hard + +"@types/babel__traverse@npm:*, @types/babel__traverse@npm:^7.0.6": + version: 7.28.0 + resolution: "@types/babel__traverse@npm:7.28.0" + dependencies: + "@babel/types": "npm:^7.28.2" + checksum: 10c0/b52d7d4e8fc6a9018fe7361c4062c1c190f5778cf2466817cb9ed19d69fbbb54f9a85ffedeb748ed8062d2cf7d4cc088ee739848f47c57740de1c48cbf0d0994 + languageName: node + linkType: hard + +"@types/bcrypt@npm:^6.0.0": + version: 6.0.0 + resolution: "@types/bcrypt@npm:6.0.0" + dependencies: + "@types/node": "npm:*" + checksum: 10c0/48b66408838f5eb59791da5a77260cef59a5291ce0945f2caa3b5a6158c44b321b684b4aa7dce771852c63271c766cadd587374273451b300377a17015c1d51d + languageName: node + linkType: hard + +"@types/debug@npm:^4.1.8": + version: 4.1.13 + resolution: "@types/debug@npm:4.1.13" + dependencies: + "@types/ms": "npm:*" + checksum: 10c0/e5e124021bbdb23a82727eee0a726ae0fc8a3ae1f57253cbcc47497f259afb357de7f6941375e773e1abbfa1604c1555b901a409d762ec2bb4c1612131d4afb7 + languageName: node + linkType: hard + +"@types/docker-modem@npm:*": + version: 3.0.6 + resolution: "@types/docker-modem@npm:3.0.6" + dependencies: + "@types/node": "npm:*" + "@types/ssh2": "npm:*" + checksum: 10c0/d3ffd273148bc883ff9b1a972b1f84c1add6d9a197d2f4fc9774db4c814f39c2e51cc649385b55d781c790c16fb0bf9c1f4c62499bd0f372a4b920190919445d + languageName: node + linkType: hard + +"@types/dockerode@npm:^3.3.35": + version: 3.3.47 + resolution: "@types/dockerode@npm:3.3.47" + dependencies: + "@types/docker-modem": "npm:*" + "@types/node": "npm:*" + "@types/ssh2": "npm:*" + checksum: 10c0/165746fdeceab022608ec28a6021c7d6835d6b164847f5d3cda63e721da4e6e3f1bcf72bb6f9c266117991f9d8038332a0d69d2a8d73ef02a4874bc0853d214c + languageName: node + linkType: hard + +"@types/dockerode@npm:^4.0.1": + version: 4.0.1 + resolution: "@types/dockerode@npm:4.0.1" + dependencies: + "@types/docker-modem": "npm:*" + "@types/node": "npm:*" + "@types/ssh2": "npm:*" + checksum: 10c0/d504d5568624e629663633da9df4a88757d55548e399f2001c478bcdc55ee2e2a4c2fc8a903c4616ebe820a411e256ad5a5caa9c0fb244dca0a5dbc0eb333e45 + languageName: node + linkType: hard + +"@types/esquery@npm:^1.5.0": + version: 1.5.4 + resolution: "@types/esquery@npm:1.5.4" + dependencies: + "@types/estree": "npm:*" + checksum: 10c0/a9fdd09d42ce2e94a8bcb59fbeb56e87f65c0c140747a64e70f55ceb8cd41b12f0ee5daf6c1e6eee51bc05b7d90e51cebc607dab22c3657d4b9aa299bf4e9873 + languageName: node + linkType: hard + +"@types/estree@npm:*, @types/estree@npm:^1.0.6": + version: 1.0.8 + resolution: "@types/estree@npm:1.0.8" + checksum: 10c0/39d34d1afaa338ab9763f37ad6066e3f349444f9052b9676a7cc0252ef9485a41c6d81c9c4e0d26e9077993354edf25efc853f3224dd4b447175ef62bdcc86a5 + languageName: node + linkType: hard + +"@types/graceful-fs@npm:^4.1.3": + version: 4.1.9 + resolution: "@types/graceful-fs@npm:4.1.9" + dependencies: + "@types/node": "npm:*" + checksum: 10c0/235d2fc69741448e853333b7c3d1180a966dd2b8972c8cbcd6b2a0c6cd7f8d582ab2b8e58219dbc62cce8f1b40aa317ff78ea2201cdd8249da5025adebed6f0b + languageName: node + linkType: hard + +"@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1, @types/istanbul-lib-coverage@npm:^2.0.6": + version: 2.0.6 + resolution: "@types/istanbul-lib-coverage@npm:2.0.6" + checksum: 10c0/3948088654f3eeb45363f1db158354fb013b362dba2a5c2c18c559484d5eb9f6fd85b23d66c0a7c2fcfab7308d0a585b14dadaca6cc8bf89ebfdc7f8f5102fb7 + languageName: node + linkType: hard + +"@types/istanbul-lib-report@npm:*": + version: 3.0.3 + resolution: "@types/istanbul-lib-report@npm:3.0.3" + dependencies: + "@types/istanbul-lib-coverage": "npm:*" + checksum: 10c0/247e477bbc1a77248f3c6de5dadaae85ff86ac2d76c5fc6ab1776f54512a745ff2a5f791d22b942e3990ddbd40f3ef5289317c4fca5741bedfaa4f01df89051c + languageName: node + linkType: hard + +"@types/istanbul-reports@npm:^3.0.0, @types/istanbul-reports@npm:^3.0.4": + version: 3.0.4 + resolution: "@types/istanbul-reports@npm:3.0.4" + dependencies: + "@types/istanbul-lib-report": "npm:*" + checksum: 10c0/1647fd402aced5b6edac87274af14ebd6b3a85447ef9ad11853a70fd92a98d35f81a5d3ea9fcb5dbb5834e800c6e35b64475e33fcae6bfa9acc70d61497c54ee + languageName: node + linkType: hard + +"@types/jest@npm:^29": + version: 29.5.14 + resolution: "@types/jest@npm:29.5.14" + dependencies: + expect: "npm:^29.0.0" + pretty-format: "npm:^29.0.0" + checksum: 10c0/18e0712d818890db8a8dab3d91e9ea9f7f19e3f83c2e50b312f557017dc81466207a71f3ed79cf4428e813ba939954fa26ffa0a9a7f153181ba174581b1c2aed + languageName: node + linkType: hard + +"@types/js-yaml@npm:^4.0.9": + version: 4.0.9 + resolution: "@types/js-yaml@npm:4.0.9" + checksum: 10c0/24de857aa8d61526bbfbbaa383aa538283ad17363fcd5bb5148e2c7f604547db36646440e739d78241ed008702a8920665d1add5618687b6743858fae00da211 + languageName: node + linkType: hard + +"@types/json-schema@npm:^7.0.15": + version: 7.0.15 + resolution: "@types/json-schema@npm:7.0.15" + checksum: 10c0/a996a745e6c5d60292f36731dd41341339d4eeed8180bb09226e5c8d23759067692b1d88e5d91d72ee83dfc00d3aca8e7bd43ea120516c17922cbcb7c3e252db + languageName: node + linkType: hard + +"@types/luxon@npm:^3.7.1": + version: 3.7.1 + resolution: "@types/luxon@npm:3.7.1" + checksum: 10c0/2db30c13b58adcd86daa447faa3ba59515fe907ead8ee3e6bb716d662812af0619d712f6c1eb190cdd7f9d2c00444c3ecd80af0f36e8143eb0c5e7339d6b2aca + languageName: node + linkType: hard + +"@types/minimist@npm:^1.2.0": + version: 1.2.5 + resolution: "@types/minimist@npm:1.2.5" + checksum: 10c0/3f791258d8e99a1d7d0ca2bda1ca6ea5a94e5e7b8fc6cde84dd79b0552da6fb68ade750f0e17718f6587783c24254bbca0357648dd59dc3812c150305cabdc46 + languageName: node + linkType: hard + +"@types/ms@npm:*": + version: 2.1.0 + resolution: "@types/ms@npm:2.1.0" + checksum: 10c0/5ce692ffe1549e1b827d99ef8ff71187457e0eb44adbae38fdf7b9a74bae8d20642ee963c14516db1d35fa2652e65f47680fdf679dcbde52bbfadd021f497225 + languageName: node + linkType: hard + +"@types/node-fetch@npm:^2.6.4": + version: 2.6.13 + resolution: "@types/node-fetch@npm:2.6.13" + dependencies: + "@types/node": "npm:*" + form-data: "npm:^4.0.4" + checksum: 10c0/6313c89f62c50bd0513a6839cdff0a06727ac5495ccbb2eeda51bb2bbbc4f3c0a76c0393a491b7610af703d3d2deb6cf60e37e59c81ceeca803ffde745dbf309 + languageName: node + linkType: hard + +"@types/node@npm:*, @types/node@npm:>=13.7.0": + version: 25.5.2 + resolution: "@types/node@npm:25.5.2" + dependencies: + undici-types: "npm:~7.18.0" + checksum: 10c0/11e41a85401724cd1a4de6fb7bd4264ec46db10c09fc8cf8d41de4ede0a7063db458348f859ead4ec0929906aa26aaf45a5fef3aa59742ca0521cda9cee52377 + languageName: node + linkType: hard + +"@types/node@npm:^18.11.18": + version: 18.19.130 + resolution: "@types/node@npm:18.19.130" + dependencies: + undici-types: "npm:~5.26.4" + checksum: 10c0/22ba2bc9f8863101a7e90a56aaeba1eb3ebdc51e847cef4a6d188967ab1acbce9b4f92251372fd0329ecb924bbf610509e122c3dfe346c04dbad04013d4ad7d0 + languageName: node + linkType: hard + +"@types/node@npm:^22": + version: 22.19.17 + resolution: "@types/node@npm:22.19.17" + dependencies: + undici-types: "npm:~6.21.0" + checksum: 10c0/b66c484c0a9f6d88b1ef360b0f487717234ee1a482cb2551ff73d9f3c43a42a777daf4c8a5eee970960728f8fe1f3877d3d8c6ffabcbca74cb401a59db700fa4 + languageName: node + linkType: hard + +"@types/normalize-package-data@npm:^2.4.0": + version: 2.4.4 + resolution: "@types/normalize-package-data@npm:2.4.4" + checksum: 10c0/aef7bb9b015883d6f4119c423dd28c4bdc17b0e8a0ccf112c78b4fe0e91fbc4af7c6204b04bba0e199a57d2f3fbbd5b4a14bf8739bf9d2a39b2a0aad545e0f86 + languageName: node + linkType: hard + +"@types/parse-json@npm:^4.0.0": + version: 4.0.2 + resolution: "@types/parse-json@npm:4.0.2" + checksum: 10c0/b1b863ac34a2c2172fbe0807a1ec4d5cb684e48d422d15ec95980b81475fac4fdb3768a8b13eef39130203a7c04340fc167bae057c7ebcafd7dec9fe6c36aeb1 + languageName: node + linkType: hard + +"@types/randomstring@npm:^1.3.0": + version: 1.3.0 + resolution: "@types/randomstring@npm:1.3.0" + checksum: 10c0/f7f8ba9c6b793c467e98193fccc2b17778c9cbb5e9da81b6f466c2f2b5089d37f4923b4b02d0e10d5cf2b6bb7a5d0db6ca9aecb93d20835e478a6c1050dbb1f3 + languageName: node + linkType: hard + +"@types/ssh2-streams@npm:*": + version: 0.1.13 + resolution: "@types/ssh2-streams@npm:0.1.13" + dependencies: + "@types/node": "npm:*" + checksum: 10c0/c0734417ae1d964bcc0681e4cd45f6d25d49e87c1eba54a934dc9a78c40bf76ba4935a414561b6dec5fe0c9c42fe7ad94ef79a4e1592940d934f9c75a704ebb0 + languageName: node + linkType: hard + +"@types/ssh2@npm:*": + version: 1.15.5 + resolution: "@types/ssh2@npm:1.15.5" + dependencies: + "@types/node": "npm:^18.11.18" + checksum: 10c0/750e402ce60d6dd67011bf1a811dcbbe638da14baca30c0952b50bad646c4ef8d6fc400894e20f5d2f8882e38b4c35eb6d4f5fe2ecd1d1b1a2f9efef9cf6e773 + languageName: node + linkType: hard + +"@types/ssh2@npm:^0.5.48": + version: 0.5.52 + resolution: "@types/ssh2@npm:0.5.52" + dependencies: + "@types/node": "npm:*" + "@types/ssh2-streams": "npm:*" + checksum: 10c0/95c52fd3438dedae6a59ca87b6558cb36568db6b9144c6c8a28c168739e04c51e27c02908aae14950b7b5020e1c40fea039b1203ae2734c356a40a050fd51c84 + languageName: node + linkType: hard + +"@types/stack-utils@npm:^2.0.0, @types/stack-utils@npm:^2.0.3": + version: 2.0.3 + resolution: "@types/stack-utils@npm:2.0.3" + checksum: 10c0/1f4658385ae936330581bcb8aa3a066df03867d90281cdf89cc356d404bd6579be0f11902304e1f775d92df22c6dd761d4451c804b0a4fba973e06211e9bd77c + languageName: node + linkType: hard + +"@types/triple-beam@npm:^1.3.2": + version: 1.3.5 + resolution: "@types/triple-beam@npm:1.3.5" + checksum: 10c0/d5d7f25da612f6d79266f4f1bb9c1ef8f1684e9f60abab251e1261170631062b656ba26ff22631f2760caeafd372abc41e64867cde27fba54fafb73a35b9056a + languageName: node + linkType: hard + +"@types/validator@npm:^13.15.3, @types/validator@npm:^13.7.17": + version: 13.15.10 + resolution: "@types/validator@npm:13.15.10" + checksum: 10c0/3e2e65fcd37dd6961ca3fd0535293d0c42f5911dc3ca44b96f458835e6db2392b678ccbb0c9815d8c0a14e653439e6c62c7b8758a6cd1d6e390551c9e56618ac + languageName: node + linkType: hard + +"@types/ws@npm:^8.18.1": + version: 8.18.1 + resolution: "@types/ws@npm:8.18.1" + dependencies: + "@types/node": "npm:*" + checksum: 10c0/61aff1129143fcc4312f083bc9e9e168aa3026b7dd6e70796276dcfb2c8211c4292603f9c4864fae702f2ed86e4abd4d38aa421831c2fd7f856c931a481afbab + languageName: node + linkType: hard + +"@types/yargs-parser@npm:*": + version: 21.0.3 + resolution: "@types/yargs-parser@npm:21.0.3" + checksum: 10c0/e71c3bd9d0b73ca82e10bee2064c384ab70f61034bbfb78e74f5206283fc16a6d85267b606b5c22cb2a3338373586786fed595b2009825d6a9115afba36560a0 + languageName: node + linkType: hard + +"@types/yargs@npm:^17.0.33, @types/yargs@npm:^17.0.8": + version: 17.0.35 + resolution: "@types/yargs@npm:17.0.35" + dependencies: + "@types/yargs-parser": "npm:*" + checksum: 10c0/609557826a6b85e73ccf587923f6429850d6dc70e420b455bab4601b670bfadf684b09ae288bccedab042c48ba65f1666133cf375814204b544009f57d6eef63 + languageName: node + linkType: hard + +"@typescript-eslint/eslint-plugin@npm:^8": + version: 8.58.0 + resolution: "@typescript-eslint/eslint-plugin@npm:8.58.0" + dependencies: + "@eslint-community/regexpp": "npm:^4.12.2" + "@typescript-eslint/scope-manager": "npm:8.58.0" + "@typescript-eslint/type-utils": "npm:8.58.0" + "@typescript-eslint/utils": "npm:8.58.0" + "@typescript-eslint/visitor-keys": "npm:8.58.0" + ignore: "npm:^7.0.5" + natural-compare: "npm:^1.4.0" + ts-api-utils: "npm:^2.5.0" + peerDependencies: + "@typescript-eslint/parser": ^8.58.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: ">=4.8.4 <6.1.0" + checksum: 10c0/ac45c30f6ba9e188a01144708aa845e7ee8bb8a4d4f9aa6d2dce7784852d0821d42b031fee6832069935c3b885feff6d4014e30145b99693d25d7f563266a9f8 + languageName: node + linkType: hard + +"@typescript-eslint/parser@npm:^8": + version: 8.58.0 + resolution: "@typescript-eslint/parser@npm:8.58.0" + dependencies: + "@typescript-eslint/scope-manager": "npm:8.58.0" + "@typescript-eslint/types": "npm:8.58.0" + "@typescript-eslint/typescript-estree": "npm:8.58.0" + "@typescript-eslint/visitor-keys": "npm:8.58.0" + debug: "npm:^4.4.3" + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: ">=4.8.4 <6.1.0" + checksum: 10c0/56c7ec21675cec4730760bfa37c29e42e80b4d6444e2beca55fad9ef53731392270d142797482ea798405be0d7e28ec6c9c16a1ee2ee1c94f73d3bf0ed29763c + languageName: node + linkType: hard + +"@typescript-eslint/project-service@npm:8.58.0": + version: 8.58.0 + resolution: "@typescript-eslint/project-service@npm:8.58.0" + dependencies: + "@typescript-eslint/tsconfig-utils": "npm:^8.58.0" + "@typescript-eslint/types": "npm:^8.58.0" + debug: "npm:^4.4.3" + peerDependencies: + typescript: ">=4.8.4 <6.1.0" + checksum: 10c0/e6d0cb2f7708ccb31a2ff9eb35817d4999c26e1f1cd3c607539e21d0c73a234daa77c73ee1163bc4e8b139252d619823c444759f1ddabdd138cab4885e9c9794 + languageName: node + linkType: hard + +"@typescript-eslint/scope-manager@npm:8.58.0": + version: 8.58.0 + resolution: "@typescript-eslint/scope-manager@npm:8.58.0" + dependencies: + "@typescript-eslint/types": "npm:8.58.0" + "@typescript-eslint/visitor-keys": "npm:8.58.0" + checksum: 10c0/bd5c16780f22d62359af0f69909f38a15fa3c55e609124a7cd5c2a04322fe41e586d81066f3ad1dcc3c1eff24dbcb48b78d099626d611fbd680c20c005d48f1d + languageName: node + linkType: hard + +"@typescript-eslint/tsconfig-utils@npm:8.58.0, @typescript-eslint/tsconfig-utils@npm:^8.58.0": + version: 8.58.0 + resolution: "@typescript-eslint/tsconfig-utils@npm:8.58.0" + peerDependencies: + typescript: ">=4.8.4 <6.1.0" + checksum: 10c0/0a07fe1a28b2513e625882bc8d4c4e0c5a105cdbcb987beae12fc66dbe71dc9638013e4d1fa8ad10d828a2acd5e3fed987c189c00d41fed0e880009f99adf1b2 + languageName: node + linkType: hard + +"@typescript-eslint/type-utils@npm:8.58.0": + version: 8.58.0 + resolution: "@typescript-eslint/type-utils@npm:8.58.0" + dependencies: + "@typescript-eslint/types": "npm:8.58.0" + "@typescript-eslint/typescript-estree": "npm:8.58.0" + "@typescript-eslint/utils": "npm:8.58.0" + debug: "npm:^4.4.3" + ts-api-utils: "npm:^2.5.0" + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: ">=4.8.4 <6.1.0" + checksum: 10c0/1223733d41f8463be92ef1ad048d546f9663152212b22dc968abbd9f8e4486bd4082e16baa51d2d281e0d4815563bc4b1ecf01684e2940b7897ba17aa26d1196 + languageName: node + linkType: hard + +"@typescript-eslint/types@npm:8.58.0, @typescript-eslint/types@npm:^8.58.0": + version: 8.58.0 + resolution: "@typescript-eslint/types@npm:8.58.0" + checksum: 10c0/f2fe1321758a04591c20d77caba956ae76b77cff0b976a0224b37077d80b1ebd826874d15ec79c3a3b7d57ee5679e5d10756db1b082bde3d51addbd3a8431d38 + languageName: node + linkType: hard + +"@typescript-eslint/typescript-estree@npm:8.58.0": + version: 8.58.0 + resolution: "@typescript-eslint/typescript-estree@npm:8.58.0" + dependencies: + "@typescript-eslint/project-service": "npm:8.58.0" + "@typescript-eslint/tsconfig-utils": "npm:8.58.0" + "@typescript-eslint/types": "npm:8.58.0" + "@typescript-eslint/visitor-keys": "npm:8.58.0" + debug: "npm:^4.4.3" + minimatch: "npm:^10.2.2" + semver: "npm:^7.7.3" + tinyglobby: "npm:^0.2.15" + ts-api-utils: "npm:^2.5.0" + peerDependencies: + typescript: ">=4.8.4 <6.1.0" + checksum: 10c0/a8cb94cb765b27740a54f9b5378bd8f0dc49e301ceed99a0791dc9d1f61c2a54e3212f7ed9120c8c2df80104ad3117150cf5e7fe8a0b7eec3ed04969a79b103e + languageName: node + linkType: hard + +"@typescript-eslint/utils@npm:8.58.0": + version: 8.58.0 + resolution: "@typescript-eslint/utils@npm:8.58.0" + dependencies: + "@eslint-community/eslint-utils": "npm:^4.9.1" + "@typescript-eslint/scope-manager": "npm:8.58.0" + "@typescript-eslint/types": "npm:8.58.0" + "@typescript-eslint/typescript-estree": "npm:8.58.0" + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: ">=4.8.4 <6.1.0" + checksum: 10c0/457e01a6e6d954dbfe13c49ece3cf8a55e5d8cf19ea9ae7086c0e205d89e3cdbb91153062ab440d2e78ad3f077b174adc42bfb1b6fc24299020a0733e7f9c11c + languageName: node + linkType: hard + +"@typescript-eslint/visitor-keys@npm:8.58.0": + version: 8.58.0 + resolution: "@typescript-eslint/visitor-keys@npm:8.58.0" + dependencies: + "@typescript-eslint/types": "npm:8.58.0" + eslint-visitor-keys: "npm:^5.0.0" + checksum: 10c0/75f3c9c097a308cc6450822a0f81d44c8b79b524e99dd2c41ded347b12f148ab3bd459ce9cc6bd00f8f0725c5831baab6d2561596ead3394ab76dddbeb32cce1 + languageName: node + linkType: hard + +"@ungap/structured-clone@npm:^1.3.0": + version: 1.3.0 + resolution: "@ungap/structured-clone@npm:1.3.0" + checksum: 10c0/0fc3097c2540ada1fc340ee56d58d96b5b536a2a0dab6e3ec17d4bfc8c4c86db345f61a375a8185f9da96f01c69678f836a2b57eeaa9e4b8eeafd26428e57b0a + languageName: node + linkType: hard + +"@unrs/resolver-binding-android-arm-eabi@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-android-arm-eabi@npm:1.11.1" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@unrs/resolver-binding-android-arm64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-android-arm64@npm:1.11.1" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-darwin-arm64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-darwin-arm64@npm:1.11.1" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-darwin-x64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-darwin-x64@npm:1.11.1" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-freebsd-x64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-freebsd-x64@npm:1.11.1" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.11.1" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm-musleabihf@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm-musleabihf@npm:1.11.1" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm64-gnu@npm:1.11.1" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm64-musl@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm64-musl@npm:1.11.1" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-ppc64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-ppc64-gnu@npm:1.11.1" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-riscv64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-riscv64-gnu@npm:1.11.1" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-riscv64-musl@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-riscv64-musl@npm:1.11.1" + conditions: os=linux & cpu=riscv64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-s390x-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-s390x-gnu@npm:1.11.1" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-x64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-x64-gnu@npm:1.11.1" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-x64-musl@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-x64-musl@npm:1.11.1" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-wasm32-wasi@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-wasm32-wasi@npm:1.11.1" + dependencies: + "@napi-rs/wasm-runtime": "npm:^0.2.11" + conditions: cpu=wasm32 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-arm64-msvc@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-win32-arm64-msvc@npm:1.11.1" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-ia32-msvc@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-win32-ia32-msvc@npm:1.11.1" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-x64-msvc@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-win32-x64-msvc@npm:1.11.1" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@yarnpkg/lockfile@npm:^1.1.0": + version: 1.1.0 + resolution: "@yarnpkg/lockfile@npm:1.1.0" + checksum: 10c0/0bfa50a3d756623d1f3409bc23f225a1d069424dbc77c6fd2f14fb377390cd57ec703dc70286e081c564be9051ead9ba85d81d66a3e68eeb6eb506d4e0c0fbda + languageName: node + linkType: hard + +"@yarnpkg/parsers@npm:3.0.2": + version: 3.0.2 + resolution: "@yarnpkg/parsers@npm:3.0.2" + dependencies: + js-yaml: "npm:^3.10.0" + tslib: "npm:^2.4.0" + checksum: 10c0/a0c340e13129643162423d7e666061c0b39b143bfad3fc5a74c7d92a30fd740f6665d41cd4e61832c20375889d793eea1d1d103cacb39ed68f7acd168add8c53 + languageName: node + linkType: hard + +"@zeroshotbuilders/agentic-workflows@workspace:packages/agentic-workflows": + version: 0.0.0-use.local + resolution: "@zeroshotbuilders/agentic-workflows@workspace:packages/agentic-workflows" + dependencies: + "@openai/agents": "npm:^0.3.0" + openai: "npm:^4.77.0" + peerDependencies: + "@nestjs/common": ">=10.0.0" + "@nestjs/core": ">=10.0.0" + "@zeroshotbuilders/commons": ">=0.0.1" + languageName: unknown + linkType: soft + +"@zeroshotbuilders/commons-testing@workspace:packages/commons-testing": + version: 0.0.0-use.local + resolution: "@zeroshotbuilders/commons-testing@workspace:packages/commons-testing" + dependencies: + testcontainers: "npm:^10.24.0" + peerDependencies: + "@zeroshotbuilders/commons": ">=0.0.1" + languageName: unknown + linkType: soft + +"@zeroshotbuilders/commons@workspace:packages/commons": + version: 0.0.0-use.local + resolution: "@zeroshotbuilders/commons@workspace:packages/commons" + dependencies: + abort-controller-x: "npm:^0.4.0" + bullmq: "npm:^5.0.0" + class-transformer: "npm:^0.5.0" + class-validator: "npm:^0.14.0" + immutable: "npm:^4.3.0" + js-yaml: "npm:^4.1.0" + luxon: "npm:^3.6.0" + nice-grpc: "npm:^2.1.0" + randomstring: "npm:^1.3.0" + redis: "npm:^4.7.0" + reflect-metadata: "npm:^0.2.0" + sequelize: "npm:^6.37.0" + ts-pattern: "npm:^5.0.0" + uuid: "npm:^11.0.0" + winston: "npm:^3.17.0" + peerDependencies: + "@grpc/grpc-js": ">=1.9.0" + "@nestjs/common": ">=10.0.0" + "@nestjs/core": ">=10.0.0" + "@nestjs/platform-express": ">=10.0.0" + languageName: unknown + linkType: soft + +"@zeroshotbuilders/openai-utils@workspace:packages/openai-utils": + version: 0.0.0-use.local + resolution: "@zeroshotbuilders/openai-utils@workspace:packages/openai-utils" + dependencies: + openai: "npm:^4.77.0" + peerDependencies: + "@nestjs/common": ">=10.0.0" + "@zeroshotbuilders/commons": ">=0.0.1" + languageName: unknown + linkType: soft + +"@zeroshotbuilders/sql-decorators@workspace:packages/sql-decorators": + version: 0.0.0-use.local + resolution: "@zeroshotbuilders/sql-decorators@workspace:packages/sql-decorators" + dependencies: + reflect-metadata: "npm:^0.2.0" + sequelize: "npm:^6.37.0" + peerDependencies: + "@zeroshotbuilders/commons": ">=0.0.1" + languageName: unknown + linkType: soft + +"@zeroshotbuilders/tavily-utils@workspace:packages/tavily-utils": + version: 0.0.0-use.local + resolution: "@zeroshotbuilders/tavily-utils@workspace:packages/tavily-utils" + dependencies: + "@tavily/core": "npm:^0.6.0" + peerDependencies: + "@nestjs/common": ">=10.0.0" + "@openai/agents": ">=0.3.0" + "@zeroshotbuilders/commons": ">=0.0.1" + languageName: unknown + linkType: soft + +"@zkochan/js-yaml@npm:0.0.7": + version: 0.0.7 + resolution: "@zkochan/js-yaml@npm:0.0.7" + dependencies: + argparse: "npm:^2.0.1" + bin: + js-yaml: bin/js-yaml.js + checksum: 10c0/c8b3525717912811f9422ed50e94c5751ed6f771eb1b7e5cde097f14835654931e2bdaecb1e5fc37b51cf8d822410a307f16dd1581d46149398c30215f3f9bac + languageName: node + linkType: hard + +"JSONStream@npm:^1.3.5": + version: 1.3.5 + resolution: "JSONStream@npm:1.3.5" + dependencies: + jsonparse: "npm:^1.2.0" + through: "npm:>=2.2.7 <3" + bin: + JSONStream: ./bin.js + checksum: 10c0/0f54694da32224d57b715385d4a6b668d2117379d1f3223dc758459246cca58fdc4c628b83e8a8883334e454a0a30aa198ede77c788b55537c1844f686a751f2 + languageName: node + linkType: hard + +"abbrev@npm:^3.0.0": + version: 3.0.1 + resolution: "abbrev@npm:3.0.1" + checksum: 10c0/21ba8f574ea57a3106d6d35623f2c4a9111d9ee3e9a5be47baed46ec2457d2eac46e07a5c4a60186f88cb98abbe3e24f2d4cca70bc2b12f1692523e2209a9ccf + languageName: node + linkType: hard + +"abbrev@npm:^4.0.0": + version: 4.0.0 + resolution: "abbrev@npm:4.0.0" + checksum: 10c0/b4cc16935235e80702fc90192e349e32f8ef0ed151ef506aa78c81a7c455ec18375c4125414b99f84b2e055199d66383e787675f0bcd87da7a4dbd59f9eac1d5 + languageName: node + linkType: hard + +"abort-controller-x@npm:^0.4.0": + version: 0.4.3 + resolution: "abort-controller-x@npm:0.4.3" + checksum: 10c0/8091b5c9279c304890e4e9cc90601947790846b7b2c149bb322a25e873eb3db060ef3da74a93b6fe40ccea41c3962fc4b175468a0ecdf4c4bb6421023ad9d71e + languageName: node + linkType: hard + +"abort-controller@npm:^3.0.0": + version: 3.0.0 + resolution: "abort-controller@npm:3.0.0" + dependencies: + event-target-shim: "npm:^5.0.0" + checksum: 10c0/90ccc50f010250152509a344eb2e71977fbf8db0ab8f1061197e3275ddf6c61a41a6edfd7b9409c664513131dd96e962065415325ef23efa5db931b382d24ca5 + languageName: node + linkType: hard + +"accepts@npm:^2.0.0": + version: 2.0.0 + resolution: "accepts@npm:2.0.0" + dependencies: + mime-types: "npm:^3.0.0" + negotiator: "npm:^1.0.0" + checksum: 10c0/98374742097e140891546076215f90c32644feacf652db48412329de4c2a529178a81aa500fbb13dd3e6cbf6e68d829037b123ac037fc9a08bcec4b87b358eef + languageName: node + linkType: hard + +"accepts@npm:~1.3.8": + version: 1.3.8 + resolution: "accepts@npm:1.3.8" + dependencies: + mime-types: "npm:~2.1.34" + negotiator: "npm:0.6.3" + checksum: 10c0/3a35c5f5586cfb9a21163ca47a5f77ac34fa8ceb5d17d2fa2c0d81f41cbd7f8c6fa52c77e2c039acc0f4d09e71abdc51144246900f6bef5e3c4b333f77d89362 + languageName: node + linkType: hard + +"acorn-jsx@npm:^5.3.2": + version: 5.3.2 + resolution: "acorn-jsx@npm:5.3.2" + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + checksum: 10c0/4c54868fbef3b8d58927d5e33f0a4de35f59012fe7b12cf9dfbb345fb8f46607709e1c4431be869a23fb63c151033d84c4198fa9f79385cec34fcb1dd53974c1 + languageName: node + linkType: hard + +"acorn-walk@npm:^8.1.1": + version: 8.3.5 + resolution: "acorn-walk@npm:8.3.5" + dependencies: + acorn: "npm:^8.11.0" + checksum: 10c0/e31bf5b5423ed1349437029d66d708b9fbd1b77a644b031501e2c753b028d13b56348210ed901d5b1d0d86eb3381c0a0fc0d0998511a9d546d1194936266a332 + languageName: node + linkType: hard + +"acorn@npm:^8.11.0, acorn@npm:^8.15.0, acorn@npm:^8.4.1": + version: 8.16.0 + resolution: "acorn@npm:8.16.0" + bin: + acorn: bin/acorn + checksum: 10c0/c9c52697227661b68d0debaf972222d4f622aa06b185824164e153438afa7b08273432ca43ea792cadb24dada1d46f6f6bb1ef8de9956979288cc1b96bf9914e + languageName: node + linkType: hard + +"add-stream@npm:^1.0.0": + version: 1.0.0 + resolution: "add-stream@npm:1.0.0" + checksum: 10c0/985014a14e76ca4cb24e0fc58bb1556794cf38c5c8937de335a10584f50a371dc48e1c34a59391c7eb9c1fc908b4b86764df5d2756f701df6ba95d1ca2f63ddc + languageName: node + linkType: hard + +"address@npm:^1.0.1": + version: 1.2.2 + resolution: "address@npm:1.2.2" + checksum: 10c0/1c8056b77fb124456997b78ed682ecc19d2fd7ea8bd5850a2aa8c3e3134c913847c57bcae418622efd32ba858fa1e242a40a251ac31da0515664fc0ac03a047d + languageName: node + linkType: hard + +"agent-base@npm:^7.1.0, agent-base@npm:^7.1.2": + version: 7.1.4 + resolution: "agent-base@npm:7.1.4" + checksum: 10c0/c2c9ab7599692d594b6a161559ada307b7a624fa4c7b03e3afdb5a5e31cd0e53269115b620fcab024c5ac6a6f37fa5eb2e004f076ad30f5f7e6b8b671f7b35fe + languageName: node + linkType: hard + +"agentkeepalive@npm:^4.2.1": + version: 4.6.0 + resolution: "agentkeepalive@npm:4.6.0" + dependencies: + humanize-ms: "npm:^1.2.1" + checksum: 10c0/235c182432f75046835b05f239708107138a40103deee23b6a08caee5136873709155753b394ec212e49e60e94a378189562cb01347765515cff61b692c69187 + languageName: node + linkType: hard + +"aggregate-error@npm:^3.0.0": + version: 3.1.0 + resolution: "aggregate-error@npm:3.1.0" + dependencies: + clean-stack: "npm:^2.0.0" + indent-string: "npm:^4.0.0" + checksum: 10c0/a42f67faa79e3e6687a4923050e7c9807db3848a037076f791d10e092677d65c1d2d863b7848560699f40fc0502c19f40963fb1cd1fb3d338a7423df8e45e039 + languageName: node + linkType: hard + +"ajv-formats@npm:^3.0.1": + version: 3.0.1 + resolution: "ajv-formats@npm:3.0.1" + dependencies: + ajv: "npm:^8.0.0" + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + checksum: 10c0/168d6bca1ea9f163b41c8147bae537e67bd963357a5488a1eaf3abe8baa8eec806d4e45f15b10767e6020679315c7e1e5e6803088dfb84efa2b4e9353b83dd0a + languageName: node + linkType: hard + +"ajv@npm:^6.14.0": + version: 6.14.0 + resolution: "ajv@npm:6.14.0" + dependencies: + fast-deep-equal: "npm:^3.1.1" + fast-json-stable-stringify: "npm:^2.0.0" + json-schema-traverse: "npm:^0.4.1" + uri-js: "npm:^4.2.2" + checksum: 10c0/a2bc39b0555dc9802c899f86990eb8eed6e366cddbf65be43d5aa7e4f3c4e1a199d5460fd7ca4fb3d864000dbbc049253b72faa83b3b30e641ca52cb29a68c22 + languageName: node + linkType: hard + +"ajv@npm:^8.0.0, ajv@npm:^8.17.1": + version: 8.18.0 + resolution: "ajv@npm:8.18.0" + dependencies: + fast-deep-equal: "npm:^3.1.3" + fast-uri: "npm:^3.0.1" + json-schema-traverse: "npm:^1.0.0" + require-from-string: "npm:^2.0.2" + checksum: 10c0/e7517c426173513a07391be951879932bdf3348feaebd2199f5b901c20f99d60db8cd1591502d4d551dc82f594e82a05c4fe1c70139b15b8937f7afeaed9532f + languageName: node + linkType: hard + +"ansi-colors@npm:^4.1.1": + version: 4.1.3 + resolution: "ansi-colors@npm:4.1.3" + checksum: 10c0/ec87a2f59902f74e61eada7f6e6fe20094a628dab765cfdbd03c3477599368768cffccdb5d3bb19a1b6c99126783a143b1fee31aab729b31ffe5836c7e5e28b9 + languageName: node + linkType: hard + +"ansi-escapes@npm:^4.2.1, ansi-escapes@npm:^4.3.2": + version: 4.3.2 + resolution: "ansi-escapes@npm:4.3.2" + dependencies: + type-fest: "npm:^0.21.3" + checksum: 10c0/da917be01871525a3dfcf925ae2977bc59e8c513d4423368645634bf5d4ceba5401574eb705c1e92b79f7292af5a656f78c5725a4b0e1cec97c4b413705c1d50 + languageName: node + linkType: hard + +"ansi-regex@npm:^5.0.1": + version: 5.0.1 + resolution: "ansi-regex@npm:5.0.1" + checksum: 10c0/9a64bb8627b434ba9327b60c027742e5d17ac69277960d041898596271d992d4d52ba7267a63ca10232e29f6107fc8a835f6ce8d719b88c5f8493f8254813737 + languageName: node + linkType: hard + +"ansi-regex@npm:^6.2.2": + version: 6.2.2 + resolution: "ansi-regex@npm:6.2.2" + checksum: 10c0/05d4acb1d2f59ab2cf4b794339c7b168890d44dda4bf0ce01152a8da0213aca207802f930442ce8cd22d7a92f44907664aac6508904e75e038fa944d2601b30f + languageName: node + linkType: hard + +"ansi-styles@npm:^4.0.0, ansi-styles@npm:^4.1.0": + version: 4.3.0 + resolution: "ansi-styles@npm:4.3.0" + dependencies: + color-convert: "npm:^2.0.1" + checksum: 10c0/895a23929da416f2bd3de7e9cb4eabd340949328ab85ddd6e484a637d8f6820d485f53933446f5291c3b760cbc488beb8e88573dd0f9c7daf83dccc8fe81b041 + languageName: node + linkType: hard + +"ansi-styles@npm:^5.0.0, ansi-styles@npm:^5.2.0": + version: 5.2.0 + resolution: "ansi-styles@npm:5.2.0" + checksum: 10c0/9c4ca80eb3c2fb7b33841c210d2f20807f40865d27008d7c3f707b7f95cab7d67462a565e2388ac3285b71cb3d9bb2173de8da37c57692a362885ec34d6e27df + languageName: node + linkType: hard + +"ansi-styles@npm:^6.1.0": + version: 6.2.3 + resolution: "ansi-styles@npm:6.2.3" + checksum: 10c0/23b8a4ce14e18fb854693b95351e286b771d23d8844057ed2e7d083cd3e708376c3323707ec6a24365f7d7eda3ca00327fe04092e29e551499ec4c8b7bfac868 + languageName: node + linkType: hard + +"anymatch@npm:^3.0.3, anymatch@npm:^3.1.3": + version: 3.1.3 + resolution: "anymatch@npm:3.1.3" + dependencies: + normalize-path: "npm:^3.0.0" + picomatch: "npm:^2.0.4" + checksum: 10c0/57b06ae984bc32a0d22592c87384cd88fe4511b1dd7581497831c56d41939c8a001b28e7b853e1450f2bf61992dfcaa8ae2d0d161a0a90c4fb631ef07098fbac + languageName: node + linkType: hard + +"append-field@npm:^1.0.0": + version: 1.0.0 + resolution: "append-field@npm:1.0.0" + checksum: 10c0/1b5abcc227e5179936a9e4f7e2af4769fa1f00eda85bbaed907f7964b0fd1f7d61f0f332b35337f391389ff13dd5310c2546ba670f8e5a743b23ec85185c73ef + languageName: node + linkType: hard + +"aproba@npm:2.0.0": + version: 2.0.0 + resolution: "aproba@npm:2.0.0" + checksum: 10c0/d06e26384a8f6245d8c8896e138c0388824e259a329e0c9f196b4fa533c82502a6fd449586e3604950a0c42921832a458bb3aa0aa9f0ba449cfd4f50fd0d09b5 + languageName: node + linkType: hard + +"archiver-utils@npm:^5.0.0, archiver-utils@npm:^5.0.2": + version: 5.0.2 + resolution: "archiver-utils@npm:5.0.2" + dependencies: + glob: "npm:^10.0.0" + graceful-fs: "npm:^4.2.0" + is-stream: "npm:^2.0.1" + lazystream: "npm:^1.0.0" + lodash: "npm:^4.17.15" + normalize-path: "npm:^3.0.0" + readable-stream: "npm:^4.0.0" + checksum: 10c0/3782c5fa9922186aa1a8e41ed0c2867569faa5f15c8e5e6418ea4c1b730b476e21bd68270b3ea457daf459ae23aaea070b2b9f90cf90a59def8dc79b9e4ef538 + languageName: node + linkType: hard + +"archiver@npm:^7.0.1": + version: 7.0.1 + resolution: "archiver@npm:7.0.1" + dependencies: + archiver-utils: "npm:^5.0.2" + async: "npm:^3.2.4" + buffer-crc32: "npm:^1.0.0" + readable-stream: "npm:^4.0.0" + readdir-glob: "npm:^1.1.2" + tar-stream: "npm:^3.0.0" + zip-stream: "npm:^6.0.1" + checksum: 10c0/02afd87ca16f6184f752db8e26884e6eff911c476812a0e7f7b26c4beb09f06119807f388a8e26ed2558aa8ba9db28646ebd147a4f99e46813b8b43158e1438e + languageName: node + linkType: hard + +"arg@npm:^4.1.0": + version: 4.1.3 + resolution: "arg@npm:4.1.3" + checksum: 10c0/070ff801a9d236a6caa647507bdcc7034530604844d64408149a26b9e87c2f97650055c0f049abd1efc024b334635c01f29e0b632b371ac3f26130f4cf65997a + languageName: node + linkType: hard + +"argparse@npm:^1.0.7": + version: 1.0.10 + resolution: "argparse@npm:1.0.10" + dependencies: + sprintf-js: "npm:~1.0.2" + checksum: 10c0/b2972c5c23c63df66bca144dbc65d180efa74f25f8fd9b7d9a0a6c88ae839db32df3d54770dcb6460cf840d232b60695d1a6b1053f599d84e73f7437087712de + languageName: node + linkType: hard + +"argparse@npm:^2.0.1": + version: 2.0.1 + resolution: "argparse@npm:2.0.1" + checksum: 10c0/c5640c2d89045371c7cedd6a70212a04e360fd34d6edeae32f6952c63949e3525ea77dbec0289d8213a99bbaeab5abfa860b5c12cf88a2e6cf8106e90dd27a7e + languageName: node + linkType: hard + +"array-flatten@npm:1.1.1": + version: 1.1.1 + resolution: "array-flatten@npm:1.1.1" + checksum: 10c0/806966c8abb2f858b08f5324d9d18d7737480610f3bd5d3498aaae6eb5efdc501a884ba019c9b4a8f02ff67002058749d05548fd42fa8643f02c9c7f22198b91 + languageName: node + linkType: hard + +"array-ify@npm:^1.0.0": + version: 1.0.0 + resolution: "array-ify@npm:1.0.0" + checksum: 10c0/75c9c072faac47bd61779c0c595e912fe660d338504ac70d10e39e1b8a4a0c9c87658703d619b9d1b70d324177ae29dc8d07dda0d0a15d005597bc4c5a59c70c + languageName: node + linkType: hard + +"arrify@npm:^1.0.1": + version: 1.0.1 + resolution: "arrify@npm:1.0.1" + checksum: 10c0/c35c8d1a81bcd5474c0c57fe3f4bad1a4d46a5fa353cedcff7a54da315df60db71829e69104b859dff96c5d68af46bd2be259fe5e50dc6aa9df3b36bea0383ab + languageName: node + linkType: hard + +"asn1@npm:^0.2.6": + version: 0.2.6 + resolution: "asn1@npm:0.2.6" + dependencies: + safer-buffer: "npm:~2.1.0" + checksum: 10c0/00c8a06c37e548762306bcb1488388d2f76c74c36f70c803f0c081a01d3bdf26090fc088cd812afc5e56a6d49e33765d451a5f8a68ab9c2b087eba65d2e980e0 + languageName: node + linkType: hard + +"async-lock@npm:^1.4.1": + version: 1.4.1 + resolution: "async-lock@npm:1.4.1" + checksum: 10c0/f696991c7d894af1dc91abc81cc4f14b3785190a35afb1646d8ab91138238d55cabd83bfdd56c42663a008d72b3dc39493ff83797e550effc577d1ccbde254af + languageName: node + linkType: hard + +"async@npm:^3.2.3, async@npm:^3.2.4, async@npm:^3.2.6": + version: 3.2.6 + resolution: "async@npm:3.2.6" + checksum: 10c0/36484bb15ceddf07078688d95e27076379cc2f87b10c03b6dd8a83e89475a3c8df5848859dd06a4c95af1e4c16fc973de0171a77f18ea00be899aca2a4f85e70 + languageName: node + linkType: hard + +"asynckit@npm:^0.4.0": + version: 0.4.0 + resolution: "asynckit@npm:0.4.0" + checksum: 10c0/d73e2ddf20c4eb9337e1b3df1a0f6159481050a5de457c55b14ea2e5cb6d90bb69e004c9af54737a5ee0917fcf2c9e25de67777bbe58261847846066ba75bc9d + languageName: node + linkType: hard + +"axios@npm:1.12.0": + version: 1.12.0 + resolution: "axios@npm:1.12.0" + dependencies: + follow-redirects: "npm:^1.15.6" + form-data: "npm:^4.0.4" + proxy-from-env: "npm:^1.1.0" + checksum: 10c0/44a1e4cfb69a2d59aa12bbc441a336e5c18e87c02b904c509fd33607d94e8cb8cc221c17e9d53f67841a4efe13abf1aa1497c85df390cdb8681ee723998d11b0 + languageName: node + linkType: hard + +"axios@npm:^1.7.7": + version: 1.14.0 + resolution: "axios@npm:1.14.0" + dependencies: + follow-redirects: "npm:^1.15.11" + form-data: "npm:^4.0.5" + proxy-from-env: "npm:^2.1.0" + checksum: 10c0/2541f4aa215a7d1842429dad006fc682d82bc0e74bd14500823f7d8cce3bbae0e0a8c328c8538946718f366ab8ce5a4c12e9ad40e5a0f3482ff8bff0cd115d45 + languageName: node + linkType: hard + +"b4a@npm:^1.6.4": + version: 1.8.0 + resolution: "b4a@npm:1.8.0" + peerDependencies: + react-native-b4a: "*" + peerDependenciesMeta: + react-native-b4a: + optional: true + checksum: 10c0/27eab5c50ea1f1314f36256f160d2e6d6950f55f02ee4942732ecafd8bcc4b3a2ed209fab532b288770d41df2befa97a2745175c06471875b716eb87abf31519 + languageName: node + linkType: hard + +"babel-jest@npm:30.3.0": + version: 30.3.0 + resolution: "babel-jest@npm:30.3.0" + dependencies: + "@jest/transform": "npm:30.3.0" + "@types/babel__core": "npm:^7.20.5" + babel-plugin-istanbul: "npm:^7.0.1" + babel-preset-jest: "npm:30.3.0" + chalk: "npm:^4.1.2" + graceful-fs: "npm:^4.2.11" + slash: "npm:^3.0.0" + peerDependencies: + "@babel/core": ^7.11.0 || ^8.0.0-0 + checksum: 10c0/5e41e124a404ddb78aa37a20336d7c883feab5ad9c4f4c72ae26db71be2fcca345874b9a7fef97d9c5f64f144a264b247ebde8acfe493578320f314ca581bac3 + languageName: node + linkType: hard + +"babel-jest@npm:^29.7.0": + version: 29.7.0 + resolution: "babel-jest@npm:29.7.0" + dependencies: + "@jest/transform": "npm:^29.7.0" + "@types/babel__core": "npm:^7.1.14" + babel-plugin-istanbul: "npm:^6.1.1" + babel-preset-jest: "npm:^29.6.3" + chalk: "npm:^4.0.0" + graceful-fs: "npm:^4.2.9" + slash: "npm:^3.0.0" + peerDependencies: + "@babel/core": ^7.8.0 + checksum: 10c0/2eda9c1391e51936ca573dd1aedfee07b14c59b33dbe16ef347873ddd777bcf6e2fc739681e9e9661ab54ef84a3109a03725be2ac32cd2124c07ea4401cbe8c1 + languageName: node + linkType: hard + +"babel-plugin-const-enum@npm:^1.0.1": + version: 1.2.0 + resolution: "babel-plugin-const-enum@npm:1.2.0" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.0.0" + "@babel/plugin-syntax-typescript": "npm:^7.3.3" + "@babel/traverse": "npm:^7.16.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/53fef408995add80e615773ff3609169c327bd671990c5ff3b59d275595aad0caa269ac7fdf1b1f691fa13f0d7c03c7fa3d3552cfbf4573912f0eef0bd52f751 + languageName: node + linkType: hard + +"babel-plugin-istanbul@npm:^6.1.1": + version: 6.1.1 + resolution: "babel-plugin-istanbul@npm:6.1.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.0.0" + "@istanbuljs/load-nyc-config": "npm:^1.0.0" + "@istanbuljs/schema": "npm:^0.1.2" + istanbul-lib-instrument: "npm:^5.0.4" + test-exclude: "npm:^6.0.0" + checksum: 10c0/1075657feb705e00fd9463b329921856d3775d9867c5054b449317d39153f8fbcebd3e02ebf00432824e647faff3683a9ca0a941325ef1afe9b3c4dd51b24beb + languageName: node + linkType: hard + +"babel-plugin-istanbul@npm:^7.0.1": + version: 7.0.1 + resolution: "babel-plugin-istanbul@npm:7.0.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.0.0" + "@istanbuljs/load-nyc-config": "npm:^1.0.0" + "@istanbuljs/schema": "npm:^0.1.3" + istanbul-lib-instrument: "npm:^6.0.2" + test-exclude: "npm:^6.0.0" + checksum: 10c0/92975e3df12503b168695463b451468da0c20e117807221652eb8e33a26c160f3b9d4c5c4e65495657420e871c6a54e5e31f539e2e1da37ef2261d7ddd4b1dfd + languageName: node + linkType: hard + +"babel-plugin-jest-hoist@npm:30.3.0": + version: 30.3.0 + resolution: "babel-plugin-jest-hoist@npm:30.3.0" + dependencies: + "@types/babel__core": "npm:^7.20.5" + checksum: 10c0/5e15900a6487356131e084970f4a9ebe24b702d74930f786e897d4fab90b0987054f66661a3570ea692f429dcd158c2214c97ecf08f7356cbc60029d7b277c74 + languageName: node + linkType: hard + +"babel-plugin-jest-hoist@npm:^29.6.3": + version: 29.6.3 + resolution: "babel-plugin-jest-hoist@npm:29.6.3" + dependencies: + "@babel/template": "npm:^7.3.3" + "@babel/types": "npm:^7.3.3" + "@types/babel__core": "npm:^7.1.14" + "@types/babel__traverse": "npm:^7.0.6" + checksum: 10c0/7e6451caaf7dce33d010b8aafb970e62f1b0c0b57f4978c37b0d457bbcf0874d75a395a102daf0bae0bd14eafb9f6e9a165ee5e899c0a4f1f3bb2e07b304ed2e + languageName: node + linkType: hard + +"babel-plugin-macros@npm:^3.1.0": + version: 3.1.0 + resolution: "babel-plugin-macros@npm:3.1.0" + dependencies: + "@babel/runtime": "npm:^7.12.5" + cosmiconfig: "npm:^7.0.0" + resolve: "npm:^1.19.0" + checksum: 10c0/c6dfb15de96f67871d95bd2e8c58b0c81edc08b9b087dc16755e7157f357dc1090a8dc60ebab955e92587a9101f02eba07e730adc253a1e4cf593ca3ebd3839c + languageName: node + linkType: hard + +"babel-plugin-polyfill-corejs2@npm:^0.4.14, babel-plugin-polyfill-corejs2@npm:^0.4.15": + version: 0.4.17 + resolution: "babel-plugin-polyfill-corejs2@npm:0.4.17" + dependencies: + "@babel/compat-data": "npm:^7.28.6" + "@babel/helper-define-polyfill-provider": "npm:^0.6.8" + semver: "npm:^6.3.1" + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: 10c0/1284960ea403c63b0dd598f338666c4b17d489aefee30b4da6a7313eff1d91edffb0ccf26341a6e5d94231684b74e016eade66b3921ea112f8b0e4980fa08a5c + languageName: node + linkType: hard + +"babel-plugin-polyfill-corejs3@npm:^0.13.0": + version: 0.13.0 + resolution: "babel-plugin-polyfill-corejs3@npm:0.13.0" + dependencies: + "@babel/helper-define-polyfill-provider": "npm:^0.6.5" + core-js-compat: "npm:^3.43.0" + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: 10c0/5d8e228da425edc040d8c868486fd01ba10b0440f841156a30d9f8986f330f723e2ee61553c180929519563ef5b64acce2caac36a5a847f095d708dda5d8206d + languageName: node + linkType: hard + +"babel-plugin-polyfill-corejs3@npm:^0.14.0": + version: 0.14.2 + resolution: "babel-plugin-polyfill-corejs3@npm:0.14.2" + dependencies: + "@babel/helper-define-polyfill-provider": "npm:^0.6.8" + core-js-compat: "npm:^3.48.0" + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: 10c0/32f70442f142d0f5607f4b57c121c573b106e09da8659c0f03108a85bf1d09ba5bdc89595a82b34ff76c19f1faf3d1c831b56166f03babf69c024f36da77c3bf + languageName: node + linkType: hard + +"babel-plugin-polyfill-regenerator@npm:^0.6.5, babel-plugin-polyfill-regenerator@npm:^0.6.6": + version: 0.6.8 + resolution: "babel-plugin-polyfill-regenerator@npm:0.6.8" + dependencies: + "@babel/helper-define-polyfill-provider": "npm:^0.6.8" + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: 10c0/7c8b2497c29fa880e0acdc8e7b93e29b81b154179b83beb0476eb2c4e7a78b6b42fc35c2554ca250c9bd6d39941eaf75416254b8592ce50979f9a12e1d51c049 + languageName: node + linkType: hard + +"babel-plugin-transform-typescript-metadata@npm:^0.3.1": + version: 0.3.2 + resolution: "babel-plugin-transform-typescript-metadata@npm:0.3.2" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.0.0" + checksum: 10c0/3a44874122e696416e4bc01a7973f38b07cf6bfd2e366026960a16f85d64ab41b735f408a045cbcfe651dadda52802c9fb992ee8229b1d7731fad56cc4346f57 + languageName: node + linkType: hard + +"babel-preset-current-node-syntax@npm:^1.0.0, babel-preset-current-node-syntax@npm:^1.2.0": + version: 1.2.0 + resolution: "babel-preset-current-node-syntax@npm:1.2.0" + dependencies: + "@babel/plugin-syntax-async-generators": "npm:^7.8.4" + "@babel/plugin-syntax-bigint": "npm:^7.8.3" + "@babel/plugin-syntax-class-properties": "npm:^7.12.13" + "@babel/plugin-syntax-class-static-block": "npm:^7.14.5" + "@babel/plugin-syntax-import-attributes": "npm:^7.24.7" + "@babel/plugin-syntax-import-meta": "npm:^7.10.4" + "@babel/plugin-syntax-json-strings": "npm:^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators": "npm:^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator": "npm:^7.8.3" + "@babel/plugin-syntax-numeric-separator": "npm:^7.10.4" + "@babel/plugin-syntax-object-rest-spread": "npm:^7.8.3" + "@babel/plugin-syntax-optional-catch-binding": "npm:^7.8.3" + "@babel/plugin-syntax-optional-chaining": "npm:^7.8.3" + "@babel/plugin-syntax-private-property-in-object": "npm:^7.14.5" + "@babel/plugin-syntax-top-level-await": "npm:^7.14.5" + peerDependencies: + "@babel/core": ^7.0.0 || ^8.0.0-0 + checksum: 10c0/94a4f81cddf9b051045d08489e4fff7336292016301664c138cfa3d9ffe3fe2ba10a24ad6ae589fd95af1ac72ba0216e1653555c187e694d7b17be0c002bea10 + languageName: node + linkType: hard + +"babel-preset-jest@npm:30.3.0": + version: 30.3.0 + resolution: "babel-preset-jest@npm:30.3.0" + dependencies: + babel-plugin-jest-hoist: "npm:30.3.0" + babel-preset-current-node-syntax: "npm:^1.2.0" + peerDependencies: + "@babel/core": ^7.11.0 || ^8.0.0-beta.1 + checksum: 10c0/a6839a1527d254bf04e82c0cf61a6a2aa283123a74f0a552e6fce462cb990abebab75a13ec3e9c58b09a865d4d2dfbac710c2d3975ae3ce6f2707cb314915c66 + languageName: node + linkType: hard + +"babel-preset-jest@npm:^29.6.3": + version: 29.6.3 + resolution: "babel-preset-jest@npm:29.6.3" + dependencies: + babel-plugin-jest-hoist: "npm:^29.6.3" + babel-preset-current-node-syntax: "npm:^1.0.0" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/ec5fd0276b5630b05f0c14bb97cc3815c6b31600c683ebb51372e54dcb776cff790bdeeabd5b8d01ede375a040337ccbf6a3ccd68d3a34219125945e167ad943 + languageName: node + linkType: hard + +"balanced-match@npm:^1.0.0": + version: 1.0.2 + resolution: "balanced-match@npm:1.0.2" + checksum: 10c0/9308baf0a7e4838a82bbfd11e01b1cb0f0cf2893bc1676c27c2a8c0e70cbae1c59120c3268517a8ae7fb6376b4639ef81ca22582611dbee4ed28df945134aaee + languageName: node + linkType: hard + +"balanced-match@npm:^4.0.2": + version: 4.0.4 + resolution: "balanced-match@npm:4.0.4" + checksum: 10c0/07e86102a3eb2ee2a6a1a89164f29d0dbaebd28f2ca3f5ca786f36b8b23d9e417eb3be45a4acf754f837be5ac0a2317de90d3fcb7f4f4dc95720a1f36b26a17b + languageName: node + linkType: hard + +"bare-events@npm:^2.5.4, bare-events@npm:^2.7.0": + version: 2.8.2 + resolution: "bare-events@npm:2.8.2" + peerDependencies: + bare-abort-controller: "*" + peerDependenciesMeta: + bare-abort-controller: + optional: true + checksum: 10c0/53fef240cf2cdcca62f78b6eead90ddb5a59b0929f414b13a63764c2b4f9de98ea8a578d033b04d64bb7b86dfbc402e937984e69950855cc3754c7b63da7db21 + languageName: node + linkType: hard + +"bare-fs@npm:^4.0.1, bare-fs@npm:^4.5.5": + version: 4.6.0 + resolution: "bare-fs@npm:4.6.0" + dependencies: + bare-events: "npm:^2.5.4" + bare-path: "npm:^3.0.0" + bare-stream: "npm:^2.6.4" + bare-url: "npm:^2.2.2" + fast-fifo: "npm:^1.3.2" + peerDependencies: + bare-buffer: "*" + peerDependenciesMeta: + bare-buffer: + optional: true + checksum: 10c0/fe7fce0c2b8f269ec1ff55d034b39201e4cd3100d9808950a267158603e1a85b37bda54c83237b3828ec6989094bef025ac4f44177d72a3d2ce26d69daff81d5 + languageName: node + linkType: hard + +"bare-os@npm:^3.0.1": + version: 3.8.7 + resolution: "bare-os@npm:3.8.7" + checksum: 10c0/6541b223a196a58b52e1103ef1f04d35018c1b56b6c250410fc54680767624273691ece741eb88502c95b058ab90b632972348a9231410df05c5df61a62c9c08 + languageName: node + linkType: hard + +"bare-path@npm:^3.0.0": + version: 3.0.0 + resolution: "bare-path@npm:3.0.0" + dependencies: + bare-os: "npm:^3.0.1" + checksum: 10c0/56a3ca82a9f808f4976cb1188640ac206546ce0ddff582afafc7bd2a6a5b31c3bd16422653aec656eeada2830cfbaa433c6cbf6d6b4d9eba033d5e06d60d9a68 + languageName: node + linkType: hard + +"bare-stream@npm:^2.6.4": + version: 2.12.0 + resolution: "bare-stream@npm:2.12.0" + dependencies: + streamx: "npm:^2.25.0" + teex: "npm:^1.0.1" + peerDependencies: + bare-abort-controller: "*" + bare-buffer: "*" + bare-events: "*" + peerDependenciesMeta: + bare-abort-controller: + optional: true + bare-buffer: + optional: true + bare-events: + optional: true + checksum: 10c0/b2f306e2f23f8a53572c8df90ad71dda0d1565a7de70fef14c95259fe93421de20dfb9420b382698468cfbac4010fc260ba5bd75cca3965ebe47695d1679ad82 + languageName: node + linkType: hard + +"bare-url@npm:^2.2.2": + version: 2.4.0 + resolution: "bare-url@npm:2.4.0" + dependencies: + bare-path: "npm:^3.0.0" + checksum: 10c0/b349bf4d3826d6e9fea40aae0b8aaba6e7e83af89feac93ad0b87721c11e0dd84eb651549275242c5ae07a3a21d24620b76bf59c434db65e9605a6e3180f8af2 + languageName: node + linkType: hard + +"base64-js@npm:^1.3.1, base64-js@npm:^1.5.1": + version: 1.5.1 + resolution: "base64-js@npm:1.5.1" + checksum: 10c0/f23823513b63173a001030fae4f2dabe283b99a9d324ade3ad3d148e218134676f1ee8568c877cd79ec1c53158dcf2d2ba527a97c606618928ba99dd930102bf + languageName: node + linkType: hard + +"baseline-browser-mapping@npm:^2.10.12": + version: 2.10.15 + resolution: "baseline-browser-mapping@npm:2.10.15" + bin: + baseline-browser-mapping: dist/cli.cjs + checksum: 10c0/0bbcdefe842e79a1bcded41f7ffd6cca7a89edc035cfabae84ed80f19a0318de3f909ee64e184c39165cef12213eba89335745b101eeace2a4eaf290680d3af2 + languageName: node + linkType: hard + +"bcrypt-pbkdf@npm:^1.0.2": + version: 1.0.2 + resolution: "bcrypt-pbkdf@npm:1.0.2" + dependencies: + tweetnacl: "npm:^0.14.3" + checksum: 10c0/ddfe85230b32df25aeebfdccfbc61d3bc493ace49c884c9c68575de1f5dcf733a5d7de9def3b0f318b786616b8d85bad50a28b1da1750c43e0012c93badcc148 + languageName: node + linkType: hard + +"bcrypt@npm:^6.0.0": + version: 6.0.0 + resolution: "bcrypt@npm:6.0.0" + dependencies: + node-addon-api: "npm:^8.3.0" + node-gyp: "npm:latest" + node-gyp-build: "npm:^4.8.4" + checksum: 10c0/006e69d4b3f0f021051fa9d998a768721a51dde28e7848e3e775ab608ba3476b25fa9262a7082ececbb0d493b0b6ca83673a6f3810b114fe90ec1bc6ae4b35b2 + languageName: node + linkType: hard + +"before-after-hook@npm:^2.2.0": + version: 2.2.3 + resolution: "before-after-hook@npm:2.2.3" + checksum: 10c0/0488c4ae12df758ca9d49b3bb27b47fd559677965c52cae7b335784724fb8bf96c42b6e5ba7d7afcbc31facb0e294c3ef717cc41c5bc2f7bd9e76f8b90acd31c + languageName: node + linkType: hard + +"bin-links@npm:^5.0.0": + version: 5.0.0 + resolution: "bin-links@npm:5.0.0" + dependencies: + cmd-shim: "npm:^7.0.0" + npm-normalize-package-bin: "npm:^4.0.0" + proc-log: "npm:^5.0.0" + read-cmd-shim: "npm:^5.0.0" + write-file-atomic: "npm:^6.0.0" + checksum: 10c0/7ef087164b13df1810bf087146880a5d43d7d0beb95c51ec0664224f9371e1ca0de70c813306de6de173fb1a3fd0ca49e636ba80c951a70ce6bd7cbf48daf075 + languageName: node + linkType: hard + +"bl@npm:^4.0.3": + version: 4.1.0 + resolution: "bl@npm:4.1.0" + dependencies: + buffer: "npm:^5.5.0" + inherits: "npm:^2.0.4" + readable-stream: "npm:^3.4.0" + checksum: 10c0/02847e1d2cb089c9dc6958add42e3cdeaf07d13f575973963335ac0fdece563a50ac770ac4c8fa06492d2dd276f6cc3b7f08c7cd9c7a7ad0f8d388b2a28def5f + languageName: node + linkType: hard + +"body-parser@npm:1.20.4, body-parser@npm:~1.20.3": + version: 1.20.4 + resolution: "body-parser@npm:1.20.4" + dependencies: + bytes: "npm:~3.1.2" + content-type: "npm:~1.0.5" + debug: "npm:2.6.9" + depd: "npm:2.0.0" + destroy: "npm:~1.2.0" + http-errors: "npm:~2.0.1" + iconv-lite: "npm:~0.4.24" + on-finished: "npm:~2.4.1" + qs: "npm:~6.14.0" + raw-body: "npm:~2.5.3" + type-is: "npm:~1.6.18" + unpipe: "npm:~1.0.0" + checksum: 10c0/569c1e896297d1fcd8f34026c8d0ab70b90d45343c15c5d8dff5de2bad08125fc1e2f8c2f3f4c1ac6c0caaad115218202594d37dcb8d89d9b5dcae1c2b736aa9 + languageName: node + linkType: hard + +"body-parser@npm:^2.2.1": + version: 2.2.2 + resolution: "body-parser@npm:2.2.2" + dependencies: + bytes: "npm:^3.1.2" + content-type: "npm:^1.0.5" + debug: "npm:^4.4.3" + http-errors: "npm:^2.0.0" + iconv-lite: "npm:^0.7.0" + on-finished: "npm:^2.4.1" + qs: "npm:^6.14.1" + raw-body: "npm:^3.0.1" + type-is: "npm:^2.0.1" + checksum: 10c0/95a830a003b38654b75166ca765358aa92ee3d561bf0e41d6ccdde0e1a0c9783cab6b90b20eb635d23172c010b59d3563a137a738e74da4ba714463510d05137 + languageName: node + linkType: hard + +"brace-expansion@npm:^1.1.7": + version: 1.1.13 + resolution: "brace-expansion@npm:1.1.13" + dependencies: + balanced-match: "npm:^1.0.0" + concat-map: "npm:0.0.1" + checksum: 10c0/384c61bb329b6adfdcc0cbbdd108dc19fb5f3e84ae15a02a74f94c6c791b5a9b035aae73b2a51929a8a478e2f0f212a771eb6a8b5b514cccfb8d0c9f2ce8cbd8 + languageName: node + linkType: hard + +"brace-expansion@npm:^2.0.1, brace-expansion@npm:^2.0.2": + version: 2.0.3 + resolution: "brace-expansion@npm:2.0.3" + dependencies: + balanced-match: "npm:^1.0.0" + checksum: 10c0/468436c9b2fa6f9e64d0cff8784b21300677571a7196e258593e95e7c3db9973a80fbafdb0f01404d5d298a04dc666eae1fc3c9052e2edbb9f2510541deeddfe + languageName: node + linkType: hard + +"brace-expansion@npm:^5.0.2, brace-expansion@npm:^5.0.5": + version: 5.0.5 + resolution: "brace-expansion@npm:5.0.5" + dependencies: + balanced-match: "npm:^4.0.2" + checksum: 10c0/4d238e14ed4f5cc9c07285550a41cef23121ca08ba99fa9eb5b55b580dcb6bf868b8210aa10526bdc9f8dc97f33ca2a7259039c4cc131a93042beddb424c48e3 + languageName: node + linkType: hard + +"braces@npm:^3.0.3": + version: 3.0.3 + resolution: "braces@npm:3.0.3" + dependencies: + fill-range: "npm:^7.1.1" + checksum: 10c0/7c6dfd30c338d2997ba77500539227b9d1f85e388a5f43220865201e407e076783d0881f2d297b9f80951b4c957fcf0b51c1d2d24227631643c3f7c284b0aa04 + languageName: node + linkType: hard + +"browserslist@npm:^4.24.0, browserslist@npm:^4.28.1": + version: 4.28.2 + resolution: "browserslist@npm:4.28.2" + dependencies: + baseline-browser-mapping: "npm:^2.10.12" + caniuse-lite: "npm:^1.0.30001782" + electron-to-chromium: "npm:^1.5.328" + node-releases: "npm:^2.0.36" + update-browserslist-db: "npm:^1.2.3" + bin: + browserslist: cli.js + checksum: 10c0/c0228b6330f785b7fa59d2d360124ec6d9322f96ed9f3ee1f873e33ecc9503a6f0ffc3b71191a28c4ff6e930b753b30043da1c33844a9548f3018d491f09ce60 + languageName: node + linkType: hard + +"bs-logger@npm:^0.2.6": + version: 0.2.6 + resolution: "bs-logger@npm:0.2.6" + dependencies: + fast-json-stable-stringify: "npm:2.x" + checksum: 10c0/80e89aaaed4b68e3374ce936f2eb097456a0dddbf11f75238dbd53140b1e39259f0d248a5089ed456f1158984f22191c3658d54a713982f676709fbe1a6fa5a0 + languageName: node + linkType: hard + +"bser@npm:2.1.1": + version: 2.1.1 + resolution: "bser@npm:2.1.1" + dependencies: + node-int64: "npm:^0.4.0" + checksum: 10c0/24d8dfb7b6d457d73f32744e678a60cc553e4ec0e9e1a01cf614b44d85c3c87e188d3cc78ef0442ce5032ee6818de20a0162ba1074725c0d08908f62ea979227 + languageName: node + linkType: hard + +"buffer-crc32@npm:^1.0.0": + version: 1.0.0 + resolution: "buffer-crc32@npm:1.0.0" + checksum: 10c0/8b86e161cee4bb48d5fa622cbae4c18f25e4857e5203b89e23de59e627ab26beb82d9d7999f2b8de02580165f61f83f997beaf02980cdf06affd175b651921ab + languageName: node + linkType: hard + +"buffer-from@npm:^1.0.0": + version: 1.1.2 + resolution: "buffer-from@npm:1.1.2" + checksum: 10c0/124fff9d66d691a86d3b062eff4663fe437a9d9ee4b47b1b9e97f5a5d14f6d5399345db80f796827be7c95e70a8e765dd404b7c3ff3b3324f98e9b0c8826cc34 + languageName: node + linkType: hard + +"buffer@npm:^5.5.0": + version: 5.7.1 + resolution: "buffer@npm:5.7.1" + dependencies: + base64-js: "npm:^1.3.1" + ieee754: "npm:^1.1.13" + checksum: 10c0/27cac81cff434ed2876058d72e7c4789d11ff1120ef32c9de48f59eab58179b66710c488987d295ae89a228f835fc66d088652dffeb8e3ba8659f80eb091d55e + languageName: node + linkType: hard + +"buffer@npm:^6.0.3": + version: 6.0.3 + resolution: "buffer@npm:6.0.3" + dependencies: + base64-js: "npm:^1.3.1" + ieee754: "npm:^1.2.1" + checksum: 10c0/2a905fbbcde73cc5d8bd18d1caa23715d5f83a5935867c2329f0ac06104204ba7947be098fe1317fbd8830e26090ff8e764f08cd14fefc977bb248c3487bcbd0 + languageName: node + linkType: hard + +"build-kit@workspace:.": + version: 0.0.0-use.local + resolution: "build-kit@workspace:." + dependencies: + "@grpc/grpc-js": "npm:^1.9" + "@nestjs/common": "npm:^10" + "@nestjs/core": "npm:^10" + "@nestjs/platform-express": "npm:^10" + "@nestjs/testing": "npm:^11.1.18" + "@nx/eslint": "npm:^22.6.4" + "@nx/jest": "npm:^22.6.4" + "@nx/js": "npm:^22.6.4" + "@types/bcrypt": "npm:^6.0.0" + "@types/jest": "npm:^29" + "@types/js-yaml": "npm:^4.0.9" + "@types/luxon": "npm:^3.7.1" + "@types/node": "npm:^22" + "@types/randomstring": "npm:^1.3.0" + "@typescript-eslint/eslint-plugin": "npm:^8" + "@typescript-eslint/parser": "npm:^8" + bcrypt: "npm:^6.0.0" + eslint: "npm:^9" + eslint-config-prettier: "npm:^10.1.8" + eslint-plugin-prettier: "npm:^5.5.5" + jest: "npm:^29" + jest-environment-node: "npm:^29" + lerna: "npm:^9.0.7" + nx: "npm:^22.6.4" + pg: "npm:^8.20.0" + prettier: "npm:^3.8.1" + rxjs: "npm:^7.8.2" + testcontainers: "npm:^11.13.0" + ts-jest: "npm:^29" + ts-node: "npm:^10.9.2" + typescript: "npm:~5.8" + languageName: unknown + linkType: soft + +"buildcheck@npm:~0.0.6": + version: 0.0.7 + resolution: "buildcheck@npm:0.0.7" + checksum: 10c0/987c605267b1b6311bb2ac0638b073d322370267445a6d059da27985fce0b41f85a59d3a9aa9af839e8ac2d63da8af07be6dc737f8bd5323e1dfe6779ad67228 + languageName: node + linkType: hard + +"bullmq@npm:^5.0.0": + version: 5.73.0 + resolution: "bullmq@npm:5.73.0" + dependencies: + cron-parser: "npm:4.9.0" + ioredis: "npm:5.10.1" + msgpackr: "npm:1.11.5" + node-abort-controller: "npm:3.1.1" + semver: "npm:7.7.4" + tslib: "npm:2.8.1" + uuid: "npm:11.1.0" + checksum: 10c0/15da7665438ade0664ea4dd493cb7b991b077396e3ed26d43edf84a9230aab051ce424e87fc9863e822f3e6e3a5c7066648c486f468fe9813c8fb00ec69f31ce + languageName: node + linkType: hard + +"busboy@npm:^1.6.0": + version: 1.6.0 + resolution: "busboy@npm:1.6.0" + dependencies: + streamsearch: "npm:^1.1.0" + checksum: 10c0/fa7e836a2b82699b6e074393428b91ae579d4f9e21f5ac468e1b459a244341d722d2d22d10920cdd849743dbece6dca11d72de939fb75a7448825cf2babfba1f + languageName: node + linkType: hard + +"byline@npm:^5.0.0": + version: 5.0.0 + resolution: "byline@npm:5.0.0" + checksum: 10c0/33fb64cd84440b3652a99a68d732c56ef18a748ded495ba38e7756a242fab0d4654b9b8ce269fd0ac14c5f97aa4e3c369613672b280a1f60b559b34223105c85 + languageName: node + linkType: hard + +"byte-size@npm:8.1.1": + version: 8.1.1 + resolution: "byte-size@npm:8.1.1" + checksum: 10c0/83170a16820fde48ebaef93bf6b2e86c5f72041f76e44eba1f3c738cceb699aeadf11088198944d5d7c6f970b465ab1e3dddc2e60bfb49a74374f3447a8db5b9 + languageName: node + linkType: hard + +"bytes@npm:^3.1.2, bytes@npm:~3.1.2": + version: 3.1.2 + resolution: "bytes@npm:3.1.2" + checksum: 10c0/76d1c43cbd602794ad8ad2ae94095cddeb1de78c5dddaa7005c51af10b0176c69971a6d88e805a90c2b6550d76636e43c40d8427a808b8645ede885de4a0358e + languageName: node + linkType: hard + +"cacache@npm:^20.0.0, cacache@npm:^20.0.1": + version: 20.0.4 + resolution: "cacache@npm:20.0.4" + dependencies: + "@npmcli/fs": "npm:^5.0.0" + fs-minipass: "npm:^3.0.0" + glob: "npm:^13.0.0" + lru-cache: "npm:^11.1.0" + minipass: "npm:^7.0.3" + minipass-collect: "npm:^2.0.1" + minipass-flush: "npm:^1.0.5" + minipass-pipeline: "npm:^1.2.4" + p-map: "npm:^7.0.2" + ssri: "npm:^13.0.0" + checksum: 10c0/539bf4020e44ba9ca5afc2ec435623ed7e0dd80c020097677e6b4a0545df5cc9d20b473212d01209c8b4aea43c0d095af0bb6da97bcb991642ea6fac0d7c462b + languageName: node + linkType: hard + +"call-bind-apply-helpers@npm:^1.0.1, call-bind-apply-helpers@npm:^1.0.2": + version: 1.0.2 + resolution: "call-bind-apply-helpers@npm:1.0.2" + dependencies: + es-errors: "npm:^1.3.0" + function-bind: "npm:^1.1.2" + checksum: 10c0/47bd9901d57b857590431243fea704ff18078b16890a6b3e021e12d279bbf211d039155e27d7566b374d49ee1f8189344bac9833dec7a20cdec370506361c938 + languageName: node + linkType: hard + +"call-bound@npm:^1.0.2": + version: 1.0.4 + resolution: "call-bound@npm:1.0.4" + dependencies: + call-bind-apply-helpers: "npm:^1.0.2" + get-intrinsic: "npm:^1.3.0" + checksum: 10c0/f4796a6a0941e71c766aea672f63b72bc61234c4f4964dc6d7606e3664c307e7d77845328a8f3359ce39ddb377fed67318f9ee203dea1d47e46165dcf2917644 + languageName: node + linkType: hard + +"callsites@npm:^3.0.0, callsites@npm:^3.1.0": + version: 3.1.0 + resolution: "callsites@npm:3.1.0" + checksum: 10c0/fff92277400eb06c3079f9e74f3af120db9f8ea03bad0e84d9aede54bbe2d44a56cccb5f6cf12211f93f52306df87077ecec5b712794c5a9b5dac6d615a3f301 + languageName: node + linkType: hard + +"camelcase-keys@npm:^6.2.2": + version: 6.2.2 + resolution: "camelcase-keys@npm:6.2.2" + dependencies: + camelcase: "npm:^5.3.1" + map-obj: "npm:^4.0.0" + quick-lru: "npm:^4.0.1" + checksum: 10c0/bf1a28348c0f285c6c6f68fb98a9d088d3c0269fed0cdff3ea680d5a42df8a067b4de374e7a33e619eb9d5266a448fe66c2dd1f8e0c9209ebc348632882a3526 + languageName: node + linkType: hard + +"camelcase@npm:^5.3.1": + version: 5.3.1 + resolution: "camelcase@npm:5.3.1" + checksum: 10c0/92ff9b443bfe8abb15f2b1513ca182d16126359ad4f955ebc83dc4ddcc4ef3fdd2c078bc223f2673dc223488e75c99b16cc4d056624374b799e6a1555cf61b23 + languageName: node + linkType: hard + +"camelcase@npm:^6.2.0, camelcase@npm:^6.3.0": + version: 6.3.0 + resolution: "camelcase@npm:6.3.0" + checksum: 10c0/0d701658219bd3116d12da3eab31acddb3f9440790c0792e0d398f0a520a6a4058018e546862b6fba89d7ae990efaeb97da71e1913e9ebf5a8b5621a3d55c710 + languageName: node + linkType: hard + +"caniuse-lite@npm:^1.0.30001782": + version: 1.0.30001785 + resolution: "caniuse-lite@npm:1.0.30001785" + checksum: 10c0/c537e35063f857d3266375d60ed89d46258a912d4b562e7768fb1b02bbc4c36982d4ec7d25451c41e3565640d926a968869e12d9eac3caf444564d857f1f674c + languageName: node + linkType: hard + +"chalk@npm:4.1.0": + version: 4.1.0 + resolution: "chalk@npm:4.1.0" + dependencies: + ansi-styles: "npm:^4.1.0" + supports-color: "npm:^7.1.0" + checksum: 10c0/3787bd65ecd98ab3a1acc3b4f71d006268a675875e49ee6ea75fb54ba73d268b97544368358c18c42445e408e076ae8ad5cec8fbad36942a2c7ac654883dc61e + languageName: node + linkType: hard + +"chalk@npm:^4.0.0, chalk@npm:^4.1.0, chalk@npm:^4.1.2": + version: 4.1.2 + resolution: "chalk@npm:4.1.2" + dependencies: + ansi-styles: "npm:^4.1.0" + supports-color: "npm:^7.1.0" + checksum: 10c0/4a3fef5cc34975c898ffe77141450f679721df9dde00f6c304353fa9c8b571929123b26a0e4617bde5018977eb655b31970c297b91b63ee83bb82aeb04666880 + languageName: node + linkType: hard + +"char-regex@npm:^1.0.2": + version: 1.0.2 + resolution: "char-regex@npm:1.0.2" + checksum: 10c0/57a09a86371331e0be35d9083ba429e86c4f4648ecbe27455dbfb343037c16ee6fdc7f6b61f433a57cc5ded5561d71c56a150e018f40c2ffb7bc93a26dae341e + languageName: node + linkType: hard + +"chardet@npm:^2.1.1": + version: 2.1.1 + resolution: "chardet@npm:2.1.1" + checksum: 10c0/d8391dd412338442b3de0d3a488aa9327f8bcf74b62b8723d6bd0b85c4084d50b731320e0a7c710edb1d44de75969995d2784b80e4c13b004a6c7a0db4c6e793 + languageName: node + linkType: hard + +"chownr@npm:^1.1.1": + version: 1.1.4 + resolution: "chownr@npm:1.1.4" + checksum: 10c0/ed57952a84cc0c802af900cf7136de643d3aba2eecb59d29344bc2f3f9bf703a301b9d84cdc71f82c3ffc9ccde831b0d92f5b45f91727d6c9da62f23aef9d9db + languageName: node + linkType: hard + +"chownr@npm:^3.0.0": + version: 3.0.0 + resolution: "chownr@npm:3.0.0" + checksum: 10c0/43925b87700f7e3893296c8e9c56cc58f926411cce3a6e5898136daaf08f08b9a8eb76d37d3267e707d0dcc17aed2e2ebdf5848c0c3ce95cf910a919935c1b10 + languageName: node + linkType: hard + +"ci-info@npm:4.3.1": + version: 4.3.1 + resolution: "ci-info@npm:4.3.1" + checksum: 10c0/7dd82000f514d76ddfe7775e4cb0d66e5c638f5fa0e2a3be29557e898da0d32ac04f231217d414d07fb968b1fbc6d980ee17ddde0d2c516f23da9cfff608f6c1 + languageName: node + linkType: hard + +"ci-info@npm:^3.2.0": + version: 3.9.0 + resolution: "ci-info@npm:3.9.0" + checksum: 10c0/6f0109e36e111684291d46123d491bc4e7b7a1934c3a20dea28cba89f1d4a03acd892f5f6a81ed3855c38647e285a150e3c9ba062e38943bef57fee6c1554c3a + languageName: node + linkType: hard + +"ci-info@npm:^4.0.0, ci-info@npm:^4.2.0": + version: 4.4.0 + resolution: "ci-info@npm:4.4.0" + checksum: 10c0/44156201545b8dde01aa8a09ee2fe9fc7a73b1bef9adbd4606c9f61c8caeeb73fb7a575c88b0443f7b4edb5ee45debaa59ed54ba5f99698339393ca01349eb3a + languageName: node + linkType: hard + +"cjs-module-lexer@npm:^1.0.0": + version: 1.4.3 + resolution: "cjs-module-lexer@npm:1.4.3" + checksum: 10c0/076b3af85adc4d65dbdab1b5b240fe5b45d44fcf0ef9d429044dd94d19be5589376805c44fb2d4b3e684e5fe6a9b7cf3e426476a6507c45283c5fc6ff95240be + languageName: node + linkType: hard + +"cjs-module-lexer@npm:^2.1.0": + version: 2.2.0 + resolution: "cjs-module-lexer@npm:2.2.0" + checksum: 10c0/aec4ca58f87145fac221386790ecaae8b012f2e2359a45acb61d8c75ea4fa84f6ea869f17abc1a7e91a808eff0fed581209632f03540de16f72f0a28f5fd35ac + languageName: node + linkType: hard + +"class-transformer@npm:^0.5.0": + version: 0.5.1 + resolution: "class-transformer@npm:0.5.1" + checksum: 10c0/19809914e51c6db42c036166839906420bb60367df14e15f49c45c8c1231bf25ae661ebe94736ee29cc688b77101ef851a8acca299375cc52fc141b64acde18a + languageName: node + linkType: hard + +"class-validator@npm:^0.14.0": + version: 0.14.4 + resolution: "class-validator@npm:0.14.4" + dependencies: + "@types/validator": "npm:^13.15.3" + libphonenumber-js: "npm:^1.11.1" + validator: "npm:^13.15.22" + checksum: 10c0/1d415261aad7bdd72528db76e814195ca627a9d33f159752554dbbf71b8360359d3061a8edd16ac951a9a4fb86e0495cdf8badf82ec44e2dcc187ab496f37c5a + languageName: node + linkType: hard + +"clean-stack@npm:^2.0.0": + version: 2.2.0 + resolution: "clean-stack@npm:2.2.0" + checksum: 10c0/1f90262d5f6230a17e27d0c190b09d47ebe7efdd76a03b5a1127863f7b3c9aec4c3e6c8bb3a7bbf81d553d56a1fd35728f5a8ef4c63f867ac8d690109742a8c1 + languageName: node + linkType: hard + +"cli-cursor@npm:3.1.0, cli-cursor@npm:^3.1.0": + version: 3.1.0 + resolution: "cli-cursor@npm:3.1.0" + dependencies: + restore-cursor: "npm:^3.1.0" + checksum: 10c0/92a2f98ff9037d09be3dfe1f0d749664797fb674bf388375a2207a1203b69d41847abf16434203e0089212479e47a358b13a0222ab9fccfe8e2644a7ccebd111 + languageName: node + linkType: hard + +"cli-spinners@npm:2.6.1": + version: 2.6.1 + resolution: "cli-spinners@npm:2.6.1" + checksum: 10c0/6abcdfef59aa68e6b51376d87d257f9120a0a7120a39dd21633702d24797decb6dc747dff2217c88732710db892b5053c5c672d221b6c4d13bbcb5372e203596 + languageName: node + linkType: hard + +"cli-spinners@npm:^2.5.0": + version: 2.9.2 + resolution: "cli-spinners@npm:2.9.2" + checksum: 10c0/907a1c227ddf0d7a101e7ab8b300affc742ead4b4ebe920a5bf1bc6d45dce2958fcd195eb28fa25275062fe6fa9b109b93b63bc8033396ed3bcb50297008b3a3 + languageName: node + linkType: hard + +"cli-width@npm:^4.1.0": + version: 4.1.0 + resolution: "cli-width@npm:4.1.0" + checksum: 10c0/1fbd56413578f6117abcaf858903ba1f4ad78370a4032f916745fa2c7e390183a9d9029cf837df320b0fdce8137668e522f60a30a5f3d6529ff3872d265a955f + languageName: node + linkType: hard + +"cliui@npm:^7.0.2": + version: 7.0.4 + resolution: "cliui@npm:7.0.4" + dependencies: + string-width: "npm:^4.2.0" + strip-ansi: "npm:^6.0.0" + wrap-ansi: "npm:^7.0.0" + checksum: 10c0/6035f5daf7383470cef82b3d3db00bec70afb3423538c50394386ffbbab135e26c3689c41791f911fa71b62d13d3863c712fdd70f0fbdffd938a1e6fd09aac00 + languageName: node + linkType: hard + +"cliui@npm:^8.0.1": + version: 8.0.1 + resolution: "cliui@npm:8.0.1" + dependencies: + string-width: "npm:^4.2.0" + strip-ansi: "npm:^6.0.1" + wrap-ansi: "npm:^7.0.0" + checksum: 10c0/4bda0f09c340cbb6dfdc1ed508b3ca080f12992c18d68c6be4d9cf51756033d5266e61ec57529e610dacbf4da1c634423b0c1b11037709cc6b09045cbd815df5 + languageName: node + linkType: hard + +"clone@npm:^1.0.2": + version: 1.0.4 + resolution: "clone@npm:1.0.4" + checksum: 10c0/2176952b3649293473999a95d7bebfc9dc96410f6cbd3d2595cf12fd401f63a4bf41a7adbfd3ab2ff09ed60cb9870c58c6acdd18b87767366fabfc163700f13b + languageName: node + linkType: hard + +"cluster-key-slot@npm:1.1.2, cluster-key-slot@npm:^1.1.0": + version: 1.1.2 + resolution: "cluster-key-slot@npm:1.1.2" + checksum: 10c0/d7d39ca28a8786e9e801eeb8c770e3c3236a566625d7299a47bb71113fb2298ce1039596acb82590e598c52dbc9b1f088c8f587803e697cb58e1867a95ff94d3 + languageName: node + linkType: hard + +"cmd-shim@npm:6.0.3": + version: 6.0.3 + resolution: "cmd-shim@npm:6.0.3" + checksum: 10c0/dc09fe0bf39e86250529456d9a87dd6d5208d053e449101a600e96dc956c100e0bc312cdb413a91266201f3bd8057d4abf63875cafb99039553a1937d8f3da36 + languageName: node + linkType: hard + +"cmd-shim@npm:^7.0.0": + version: 7.0.0 + resolution: "cmd-shim@npm:7.0.0" + checksum: 10c0/f2a14eccea9d29ac39f5182b416af60b2d4ad13ef96c541580175a394c63192aeaa53a3edfc73c7f988685574623465304b80c417dde4049d6ad7370a78dc792 + languageName: node + linkType: hard + +"co@npm:^4.6.0": + version: 4.6.0 + resolution: "co@npm:4.6.0" + checksum: 10c0/c0e85ea0ca8bf0a50cbdca82efc5af0301240ca88ebe3644a6ffb8ffe911f34d40f8fbcf8f1d52c5ddd66706abd4d3bfcd64259f1e8e2371d4f47573b0dc8c28 + languageName: node + linkType: hard + +"collect-v8-coverage@npm:^1.0.0, collect-v8-coverage@npm:^1.0.2": + version: 1.0.3 + resolution: "collect-v8-coverage@npm:1.0.3" + checksum: 10c0/bc62ba251bcce5e3354a8f88fa6442bee56e3e612fec08d4dfcf66179b41ea0bf544b0f78c4ebc0f8050871220af95bb5c5578a6aef346feea155640582f09dc + languageName: node + linkType: hard + +"color-convert@npm:^2.0.1": + version: 2.0.1 + resolution: "color-convert@npm:2.0.1" + dependencies: + color-name: "npm:~1.1.4" + checksum: 10c0/37e1150172f2e311fe1b2df62c6293a342ee7380da7b9cfdba67ea539909afbd74da27033208d01d6d5cfc65ee7868a22e18d7e7648e004425441c0f8a15a7d7 + languageName: node + linkType: hard + +"color-convert@npm:^3.1.3": + version: 3.1.3 + resolution: "color-convert@npm:3.1.3" + dependencies: + color-name: "npm:^2.0.0" + checksum: 10c0/427648b442c6ea6dab5ba03f4962201ee59f128c80b25d5a0f7d9aab0ef52519a9db8a9bb3cf40b73f86eb19b5ca6aeb0ab930665f3d14973ce776d7d0448a15 + languageName: node + linkType: hard + +"color-name@npm:^2.0.0": + version: 2.1.0 + resolution: "color-name@npm:2.1.0" + checksum: 10c0/9c953caba99557fce472232ded438c56b902c569cb15d66fcfbdf6374206126eef52ab66459f3984d4074b4aa8ab95e6f4b31a8e4f228dea57d0afecf94281fa + languageName: node + linkType: hard + +"color-name@npm:~1.1.4": + version: 1.1.4 + resolution: "color-name@npm:1.1.4" + checksum: 10c0/a1a3f914156960902f46f7f56bc62effc6c94e84b2cae157a526b1c1f74b677a47ec602bf68a61abfa2b42d15b7c5651c6dbe72a43af720bc588dff885b10f95 + languageName: node + linkType: hard + +"color-string@npm:^2.1.3": + version: 2.1.4 + resolution: "color-string@npm:2.1.4" + dependencies: + color-name: "npm:^2.0.0" + checksum: 10c0/18a9fefec153d885e0dbfb076f3a65cdcd19f52d96c719f2f261e90e5b7dafd13c51baac399d7099eac290f004d340045ab9467312dcc8afefe6f877ec5c4428 + languageName: node + linkType: hard + +"color-support@npm:1.1.3": + version: 1.1.3 + resolution: "color-support@npm:1.1.3" + bin: + color-support: bin.js + checksum: 10c0/8ffeaa270a784dc382f62d9be0a98581db43e11eee301af14734a6d089bd456478b1a8b3e7db7ca7dc5b18a75f828f775c44074020b51c05fc00e6d0992b1cc6 + languageName: node + linkType: hard + +"color@npm:^5.0.2": + version: 5.0.3 + resolution: "color@npm:5.0.3" + dependencies: + color-convert: "npm:^3.1.3" + color-string: "npm:^2.1.3" + checksum: 10c0/f08a03c5113ae4aa36dba9d2438596b194b897e18b961310643cb63872add1da507cd238df264eb434bbdbe3a377ec41f90d877531acca611523cfcd365db1b6 + languageName: node + linkType: hard + +"columnify@npm:1.6.0, columnify@npm:^1.6.0": + version: 1.6.0 + resolution: "columnify@npm:1.6.0" + dependencies: + strip-ansi: "npm:^6.0.1" + wcwidth: "npm:^1.0.0" + checksum: 10c0/25b90b59129331bbb8b0c838f8df69924349b83e8eab9549f431062a20a39094b8d744bb83265be38fd5d03140ce4bfbd85837c293f618925e83157ae9535f1d + languageName: node + linkType: hard + +"combined-stream@npm:^1.0.8": + version: 1.0.8 + resolution: "combined-stream@npm:1.0.8" + dependencies: + delayed-stream: "npm:~1.0.0" + checksum: 10c0/0dbb829577e1b1e839fa82b40c07ffaf7de8a09b935cadd355a73652ae70a88b4320db322f6634a4ad93424292fa80973ac6480986247f1734a1137debf271d5 + languageName: node + linkType: hard + +"common-ancestor-path@npm:^1.0.1": + version: 1.0.1 + resolution: "common-ancestor-path@npm:1.0.1" + checksum: 10c0/390c08d2a67a7a106d39499c002d827d2874966d938012453fd7ca34cd306881e2b9d604f657fa7a8e6e4896d67f39ebc09bf1bfd8da8ff318e0fb7a8752c534 + languageName: node + linkType: hard + +"compare-func@npm:^2.0.0": + version: 2.0.0 + resolution: "compare-func@npm:2.0.0" + dependencies: + array-ify: "npm:^1.0.0" + dot-prop: "npm:^5.1.0" + checksum: 10c0/78bd4dd4ed311a79bd264c9e13c36ed564cde657f1390e699e0f04b8eee1fc06ffb8698ce2dfb5fbe7342d509579c82d4e248f08915b708f77f7b72234086cc3 + languageName: node + linkType: hard + +"compress-commons@npm:^6.0.2": + version: 6.0.2 + resolution: "compress-commons@npm:6.0.2" + dependencies: + crc-32: "npm:^1.2.0" + crc32-stream: "npm:^6.0.0" + is-stream: "npm:^2.0.1" + normalize-path: "npm:^3.0.0" + readable-stream: "npm:^4.0.0" + checksum: 10c0/2347031b7c92c8ed5011b07b93ec53b298fa2cd1800897532ac4d4d1aeae06567883f481b6e35f13b65fc31b190c751df6635434d525562f0203fde76f1f0814 + languageName: node + linkType: hard + +"concat-map@npm:0.0.1": + version: 0.0.1 + resolution: "concat-map@npm:0.0.1" + checksum: 10c0/c996b1cfdf95b6c90fee4dae37e332c8b6eb7d106430c17d538034c0ad9a1630cb194d2ab37293b1bdd4d779494beee7786d586a50bd9376fd6f7bcc2bd4c98f + languageName: node + linkType: hard + +"concat-stream@npm:^2.0.0": + version: 2.0.0 + resolution: "concat-stream@npm:2.0.0" + dependencies: + buffer-from: "npm:^1.0.0" + inherits: "npm:^2.0.3" + readable-stream: "npm:^3.0.2" + typedarray: "npm:^0.0.6" + checksum: 10c0/29565dd9198fe1d8cf57f6cc71527dbc6ad67e12e4ac9401feb389c53042b2dceedf47034cbe702dfc4fd8df3ae7e6bfeeebe732cc4fa2674e484c13f04c219a + languageName: node + linkType: hard + +"consola@npm:^2.15.0": + version: 2.15.3 + resolution: "consola@npm:2.15.3" + checksum: 10c0/34a337e6b4a1349ee4d7b4c568484344418da8fdb829d7d71bfefcd724f608f273987633b6eef465e8de510929907a092e13cb7a28a5d3acb3be446fcc79fd5e + languageName: node + linkType: hard + +"console-control-strings@npm:^1.1.0": + version: 1.1.0 + resolution: "console-control-strings@npm:1.1.0" + checksum: 10c0/7ab51d30b52d461412cd467721bb82afe695da78fff8f29fe6f6b9cbaac9a2328e27a22a966014df9532100f6dd85370460be8130b9c677891ba36d96a343f50 + languageName: node + linkType: hard + +"content-disposition@npm:^1.0.0": + version: 1.0.1 + resolution: "content-disposition@npm:1.0.1" + checksum: 10c0/bd7ff1fe8d2542d3a2b9a29428cc3591f6ac27bb5595bba2c69664408a68f9538b14cbd92479796ea835b317a09a527c8c7209c4200381dedb0c34d3b658849e + languageName: node + linkType: hard + +"content-disposition@npm:~0.5.4": + version: 0.5.4 + resolution: "content-disposition@npm:0.5.4" + dependencies: + safe-buffer: "npm:5.2.1" + checksum: 10c0/bac0316ebfeacb8f381b38285dc691c9939bf0a78b0b7c2d5758acadad242d04783cee5337ba7d12a565a19075af1b3c11c728e1e4946de73c6ff7ce45f3f1bb + languageName: node + linkType: hard + +"content-type@npm:^1.0.5, content-type@npm:~1.0.4, content-type@npm:~1.0.5": + version: 1.0.5 + resolution: "content-type@npm:1.0.5" + checksum: 10c0/b76ebed15c000aee4678c3707e0860cb6abd4e680a598c0a26e17f0bfae723ec9cc2802f0ff1bc6e4d80603719010431d2231018373d4dde10f9ccff9dadf5af + languageName: node + linkType: hard + +"conventional-changelog-angular@npm:7.0.0": + version: 7.0.0 + resolution: "conventional-changelog-angular@npm:7.0.0" + dependencies: + compare-func: "npm:^2.0.0" + checksum: 10c0/90e73e25e224059b02951b6703b5f8742dc2a82c1fea62163978e6735fd3ab04350897a8fc6f443ec6b672d6b66e28a0820e833e544a0101f38879e5e6289b7e + languageName: node + linkType: hard + +"conventional-changelog-core@npm:5.0.1": + version: 5.0.1 + resolution: "conventional-changelog-core@npm:5.0.1" + dependencies: + add-stream: "npm:^1.0.0" + conventional-changelog-writer: "npm:^6.0.0" + conventional-commits-parser: "npm:^4.0.0" + dateformat: "npm:^3.0.3" + get-pkg-repo: "npm:^4.2.1" + git-raw-commits: "npm:^3.0.0" + git-remote-origin-url: "npm:^2.0.0" + git-semver-tags: "npm:^5.0.0" + normalize-package-data: "npm:^3.0.3" + read-pkg: "npm:^3.0.0" + read-pkg-up: "npm:^3.0.0" + checksum: 10c0/c026da415ea58346c167e58f8dd717592e92afc897aa604189a6d69f48b6943e7a656b2c83433810feea32dda117b0914a7f5860ed338a21f6ee9b0f56788b37 + languageName: node + linkType: hard + +"conventional-changelog-preset-loader@npm:^3.0.0": + version: 3.0.0 + resolution: "conventional-changelog-preset-loader@npm:3.0.0" + checksum: 10c0/5de23c4aa8b8526c3542fd5abe9758d56eed79821f32cc16d1fdf480cecc44855edbe4680113f229509dcaf4b97cc41e786ac8e3b0822b44fd9d0b98542ed0e0 + languageName: node + linkType: hard + +"conventional-changelog-writer@npm:^6.0.0": + version: 6.0.1 + resolution: "conventional-changelog-writer@npm:6.0.1" + dependencies: + conventional-commits-filter: "npm:^3.0.0" + dateformat: "npm:^3.0.3" + handlebars: "npm:^4.7.7" + json-stringify-safe: "npm:^5.0.1" + meow: "npm:^8.1.2" + semver: "npm:^7.0.0" + split: "npm:^1.0.1" + bin: + conventional-changelog-writer: cli.js + checksum: 10c0/50790b0d92e06c5ab1c02cc4eb2ecd74575244d31cfacea1885d7c8afeae1bc7bbc169140fe062f2438b9952400762240b796e59521c0246278859296b323338 + languageName: node + linkType: hard + +"conventional-commits-filter@npm:^3.0.0": + version: 3.0.0 + resolution: "conventional-commits-filter@npm:3.0.0" + dependencies: + lodash.ismatch: "npm:^4.4.0" + modify-values: "npm:^1.0.1" + checksum: 10c0/9d43cf9029bf39b70b394c551846a57b6f0473028ba5628c38bd447672655cc27bb80ba502d9a7e41335f63ad62b754cb26579f3d4bae7398dfc092acbb32578 + languageName: node + linkType: hard + +"conventional-commits-parser@npm:^4.0.0": + version: 4.0.0 + resolution: "conventional-commits-parser@npm:4.0.0" + dependencies: + JSONStream: "npm:^1.3.5" + is-text-path: "npm:^1.0.1" + meow: "npm:^8.1.2" + split2: "npm:^3.2.2" + bin: + conventional-commits-parser: cli.js + checksum: 10c0/12e390cc80ad8a825c5775a329b95e11cf47a6df7b8a3875d375e28b8cb27c4f32955842ea73e4e357cff9757a6be99fdffe4fda87a23e9d8e73f983425537a0 + languageName: node + linkType: hard + +"conventional-recommended-bump@npm:7.0.1": + version: 7.0.1 + resolution: "conventional-recommended-bump@npm:7.0.1" + dependencies: + concat-stream: "npm:^2.0.0" + conventional-changelog-preset-loader: "npm:^3.0.0" + conventional-commits-filter: "npm:^3.0.0" + conventional-commits-parser: "npm:^4.0.0" + git-raw-commits: "npm:^3.0.0" + git-semver-tags: "npm:^5.0.0" + meow: "npm:^8.1.2" + bin: + conventional-recommended-bump: cli.js + checksum: 10c0/ff751a256ddfbec62efd5a32de059b01659e945073793c6766143a8242864fd8099804a90bbf1e6a61928ade3d12292d6f66f721a113630de392d54eb7f0b0c3 + languageName: node + linkType: hard + +"convert-source-map@npm:^2.0.0": + version: 2.0.0 + resolution: "convert-source-map@npm:2.0.0" + checksum: 10c0/8f2f7a27a1a011cc6cc88cc4da2d7d0cfa5ee0369508baae3d98c260bb3ac520691464e5bbe4ae7cdf09860c1d69ecc6f70c63c6e7c7f7e3f18ec08484dc7d9b + languageName: node + linkType: hard + +"cookie-signature@npm:^1.2.1": + version: 1.2.2 + resolution: "cookie-signature@npm:1.2.2" + checksum: 10c0/54e05df1a293b3ce81589b27dddc445f462f6fa6812147c033350cd3561a42bc14481674e05ed14c7bd0ce1e8bb3dc0e40851bad75415733711294ddce0b7bc6 + languageName: node + linkType: hard + +"cookie-signature@npm:~1.0.6": + version: 1.0.7 + resolution: "cookie-signature@npm:1.0.7" + checksum: 10c0/e7731ad2995ae2efeed6435ec1e22cdd21afef29d300c27281438b1eab2bae04ef0d1a203928c0afec2cee72aa36540b8747406ebe308ad23c8e8cc3c26c9c51 + languageName: node + linkType: hard + +"cookie@npm:^0.7.1, cookie@npm:~0.7.1": + version: 0.7.2 + resolution: "cookie@npm:0.7.2" + checksum: 10c0/9596e8ccdbf1a3a88ae02cf5ee80c1c50959423e1022e4e60b91dd87c622af1da309253d8abdb258fb5e3eacb4f08e579dc58b4897b8087574eee0fd35dfa5d2 + languageName: node + linkType: hard + +"core-js-compat@npm:^3.43.0, core-js-compat@npm:^3.48.0": + version: 3.49.0 + resolution: "core-js-compat@npm:3.49.0" + dependencies: + browserslist: "npm:^4.28.1" + checksum: 10c0/546e64b7ce45f724825bc13c1347f35c0459a6e71c0dcccff3ec21fbff463f5b0b97fc1220e6d90302153863489301793276fe2bf96f46001ff555ead4140308 + languageName: node + linkType: hard + +"core-util-is@npm:~1.0.0": + version: 1.0.3 + resolution: "core-util-is@npm:1.0.3" + checksum: 10c0/90a0e40abbddfd7618f8ccd63a74d88deea94e77d0e8dbbea059fa7ebebb8fbb4e2909667fe26f3a467073de1a542ebe6ae4c73a73745ac5833786759cd906c9 + languageName: node + linkType: hard + +"cors@npm:2.8.5": + version: 2.8.5 + resolution: "cors@npm:2.8.5" + dependencies: + object-assign: "npm:^4" + vary: "npm:^1" + checksum: 10c0/373702b7999409922da80de4a61938aabba6929aea5b6fd9096fefb9e8342f626c0ebd7507b0e8b0b311380744cc985f27edebc0a26e0ddb784b54e1085de761 + languageName: node + linkType: hard + +"cors@npm:^2.8.5": + version: 2.8.6 + resolution: "cors@npm:2.8.6" + dependencies: + object-assign: "npm:^4" + vary: "npm:^1" + checksum: 10c0/ab2bc57b8af8ef8476682a59647f7c55c1a7d406b559ac06119aa1c5f70b96d35036864d197b24cf86e228e4547231088f1f94ca05061dbb14d89cc0bc9d4cab + languageName: node + linkType: hard + +"cosmiconfig@npm:9.0.0": + version: 9.0.0 + resolution: "cosmiconfig@npm:9.0.0" + dependencies: + env-paths: "npm:^2.2.1" + import-fresh: "npm:^3.3.0" + js-yaml: "npm:^4.1.0" + parse-json: "npm:^5.2.0" + peerDependencies: + typescript: ">=4.9.5" + peerDependenciesMeta: + typescript: + optional: true + checksum: 10c0/1c1703be4f02a250b1d6ca3267e408ce16abfe8364193891afc94c2d5c060b69611fdc8d97af74b7e6d5d1aac0ab2fb94d6b079573146bc2d756c2484ce5f0ee + languageName: node + linkType: hard + +"cosmiconfig@npm:^7.0.0": + version: 7.1.0 + resolution: "cosmiconfig@npm:7.1.0" + dependencies: + "@types/parse-json": "npm:^4.0.0" + import-fresh: "npm:^3.2.1" + parse-json: "npm:^5.0.0" + path-type: "npm:^4.0.0" + yaml: "npm:^1.10.0" + checksum: 10c0/b923ff6af581638128e5f074a5450ba12c0300b71302398ea38dbeabd33bbcaa0245ca9adbedfcf284a07da50f99ede5658c80bb3e39e2ce770a99d28a21ef03 + languageName: node + linkType: hard + +"cpu-features@npm:~0.0.10": + version: 0.0.10 + resolution: "cpu-features@npm:0.0.10" + dependencies: + buildcheck: "npm:~0.0.6" + nan: "npm:^2.19.0" + node-gyp: "npm:latest" + checksum: 10c0/0c4a12904657b22477ffbcfd2b4b2bdd45b174f283616b18d9e1ade495083f9f6098493feb09f4ae2d0b36b240f9ecd32cfb4afe210cf0d0f8f0cc257bd58e54 + languageName: node + linkType: hard + +"crc-32@npm:^1.2.0": + version: 1.2.2 + resolution: "crc-32@npm:1.2.2" + bin: + crc32: bin/crc32.njs + checksum: 10c0/11dcf4a2e77ee793835d49f2c028838eae58b44f50d1ff08394a610bfd817523f105d6ae4d9b5bef0aad45510f633eb23c903e9902e4409bed1ce70cb82b9bf0 + languageName: node + linkType: hard + +"crc32-stream@npm:^6.0.0": + version: 6.0.0 + resolution: "crc32-stream@npm:6.0.0" + dependencies: + crc-32: "npm:^1.2.0" + readable-stream: "npm:^4.0.0" + checksum: 10c0/bf9c84571ede2d119c2b4f3a9ef5eeb9ff94b588493c0d3862259af86d3679dcce1c8569dd2b0a6eff2f35f5e2081cc1263b846d2538d4054da78cf34f262a3d + languageName: node + linkType: hard + +"create-jest@npm:^29.7.0": + version: 29.7.0 + resolution: "create-jest@npm:29.7.0" + dependencies: + "@jest/types": "npm:^29.6.3" + chalk: "npm:^4.0.0" + exit: "npm:^0.1.2" + graceful-fs: "npm:^4.2.9" + jest-config: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + prompts: "npm:^2.0.1" + bin: + create-jest: bin/create-jest.js + checksum: 10c0/e7e54c280692470d3398f62a6238fd396327e01c6a0757002833f06d00afc62dd7bfe04ff2b9cd145264460e6b4d1eb8386f2925b7e567f97939843b7b0e812f + languageName: node + linkType: hard + +"create-require@npm:^1.1.0": + version: 1.1.1 + resolution: "create-require@npm:1.1.1" + checksum: 10c0/157cbc59b2430ae9a90034a5f3a1b398b6738bf510f713edc4d4e45e169bc514d3d99dd34d8d01ca7ae7830b5b8b537e46ae8f3c8f932371b0875c0151d7ec91 + languageName: node + linkType: hard + +"cron-parser@npm:4.9.0": + version: 4.9.0 + resolution: "cron-parser@npm:4.9.0" + dependencies: + luxon: "npm:^3.2.1" + checksum: 10c0/348622bdcd1a15695b61fc33af8a60133e5913a85cf99f6344367579e7002896514ba3b0a9d6bb569b02667d6b06836722bf2295fcd101b3de378f71d37bed0b + languageName: node + linkType: hard + +"cross-spawn@npm:^7.0.3, cross-spawn@npm:^7.0.5, cross-spawn@npm:^7.0.6": + version: 7.0.6 + resolution: "cross-spawn@npm:7.0.6" + dependencies: + path-key: "npm:^3.1.0" + shebang-command: "npm:^2.0.0" + which: "npm:^2.0.1" + checksum: 10c0/053ea8b2135caff68a9e81470e845613e374e7309a47731e81639de3eaeb90c3d01af0e0b44d2ab9d50b43467223b88567dfeb3262db942dc063b9976718ffc1 + languageName: node + linkType: hard + +"cssesc@npm:^3.0.0": + version: 3.0.0 + resolution: "cssesc@npm:3.0.0" + bin: + cssesc: bin/cssesc + checksum: 10c0/6bcfd898662671be15ae7827120472c5667afb3d7429f1f917737f3bf84c4176003228131b643ae74543f17a394446247df090c597bb9a728cce298606ed0aa7 + languageName: node + linkType: hard + +"dargs@npm:^7.0.0": + version: 7.0.0 + resolution: "dargs@npm:7.0.0" + checksum: 10c0/ec7f6a8315a8fa2f8b12d39207615bdf62b4d01f631b96fbe536c8ad5469ab9ed710d55811e564d0d5c1d548fc8cb6cc70bf0939f2415790159f5a75e0f96c92 + languageName: node + linkType: hard + +"dateformat@npm:^3.0.3": + version: 3.0.3 + resolution: "dateformat@npm:3.0.3" + checksum: 10c0/2effb8bef52ff912f87a05e4adbeacff46353e91313ad1ea9ed31412db26849f5a0fcc7e3ce36dbfb84fc6c881a986d5694f84838ad0da7000d5150693e78678 + languageName: node + linkType: hard + +"debug@npm:2.6.9": + version: 2.6.9 + resolution: "debug@npm:2.6.9" + dependencies: + ms: "npm:2.0.0" + checksum: 10c0/121908fb839f7801180b69a7e218a40b5a0b718813b886b7d6bdb82001b931c938e2941d1e4450f33a1b1df1da653f5f7a0440c197f29fbf8a6e9d45ff6ef589 + languageName: node + linkType: hard + +"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.3.5, debug@npm:^4.4.0, debug@npm:^4.4.3": + version: 4.4.3 + resolution: "debug@npm:4.4.3" + dependencies: + ms: "npm:^2.1.3" + peerDependenciesMeta: + supports-color: + optional: true + checksum: 10c0/d79136ec6c83ecbefd0f6a5593da6a9c91ec4d7ddc4b54c883d6e71ec9accb5f67a1a5e96d00a328196b5b5c86d365e98d8a3a70856aaf16b4e7b1985e67f5a6 + languageName: node + linkType: hard + +"decamelize-keys@npm:^1.1.0": + version: 1.1.1 + resolution: "decamelize-keys@npm:1.1.1" + dependencies: + decamelize: "npm:^1.1.0" + map-obj: "npm:^1.0.0" + checksum: 10c0/4ca385933127437658338c65fb9aead5f21b28d3dd3ccd7956eb29aab0953b5d3c047fbc207111672220c71ecf7a4d34f36c92851b7bbde6fca1a02c541bdd7d + languageName: node + linkType: hard + +"decamelize@npm:^1.1.0": + version: 1.2.0 + resolution: "decamelize@npm:1.2.0" + checksum: 10c0/85c39fe8fbf0482d4a1e224ef0119db5c1897f8503bcef8b826adff7a1b11414972f6fef2d7dec2ee0b4be3863cf64ac1439137ae9e6af23a3d8dcbe26a5b4b2 + languageName: node + linkType: hard + +"dedent@npm:1.5.3": + version: 1.5.3 + resolution: "dedent@npm:1.5.3" + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + checksum: 10c0/d94bde6e6f780be4da4fd760288fcf755ec368872f4ac5218197200d86430aeb8d90a003a840bff1c20221188e3f23adced0119cb811c6873c70d0ac66d12832 + languageName: node + linkType: hard + +"dedent@npm:^1.0.0, dedent@npm:^1.6.0": + version: 1.7.2 + resolution: "dedent@npm:1.7.2" + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + checksum: 10c0/acaff07cac355b93f17b1b17ebbb84d3cc55af6ab4b7814c3f505e061903e168bc6bf9ddce331552d64dee1525f0b4c549c9ade46aebfac6f69caaed74e90751 + languageName: node + linkType: hard + +"deep-is@npm:^0.1.3": + version: 0.1.4 + resolution: "deep-is@npm:0.1.4" + checksum: 10c0/7f0ee496e0dff14a573dc6127f14c95061b448b87b995fc96c017ce0a1e66af1675e73f1d6064407975bc4ea6ab679497a29fff7b5b9c4e99cb10797c1ad0b4c + languageName: node + linkType: hard + +"deepmerge@npm:^4.2.2, deepmerge@npm:^4.3.1": + version: 4.3.1 + resolution: "deepmerge@npm:4.3.1" + checksum: 10c0/e53481aaf1aa2c4082b5342be6b6d8ad9dfe387bc92ce197a66dea08bd4265904a087e75e464f14d1347cf2ac8afe1e4c16b266e0561cc5df29382d3c5f80044 + languageName: node + linkType: hard + +"defaults@npm:^1.0.3": + version: 1.0.4 + resolution: "defaults@npm:1.0.4" + dependencies: + clone: "npm:^1.0.2" + checksum: 10c0/9cfbe498f5c8ed733775db62dfd585780387d93c17477949e1670bfcfb9346e0281ce8c4bf9f4ac1fc0f9b851113bd6dc9e41182ea1644ccd97de639fa13c35a + languageName: node + linkType: hard + +"define-lazy-prop@npm:^2.0.0": + version: 2.0.0 + resolution: "define-lazy-prop@npm:2.0.0" + checksum: 10c0/db6c63864a9d3b7dc9def55d52764968a5af296de87c1b2cc71d8be8142e445208071953649e0386a8cc37cfcf9a2067a47207f1eb9ff250c2a269658fdae422 + languageName: node + linkType: hard + +"delayed-stream@npm:~1.0.0": + version: 1.0.0 + resolution: "delayed-stream@npm:1.0.0" + checksum: 10c0/d758899da03392e6712f042bec80aa293bbe9e9ff1b2634baae6a360113e708b91326594c8a486d475c69d6259afb7efacdc3537bfcda1c6c648e390ce601b19 + languageName: node + linkType: hard + +"denque@npm:^2.1.0": + version: 2.1.0 + resolution: "denque@npm:2.1.0" + checksum: 10c0/f9ef81aa0af9c6c614a727cb3bd13c5d7db2af1abf9e6352045b86e85873e629690f6222f4edd49d10e4ccf8f078bbeec0794fafaf61b659c0589d0c511ec363 + languageName: node + linkType: hard + +"depd@npm:2.0.0, depd@npm:^2.0.0, depd@npm:~2.0.0": + version: 2.0.0 + resolution: "depd@npm:2.0.0" + checksum: 10c0/58bd06ec20e19529b06f7ad07ddab60e504d9e0faca4bd23079fac2d279c3594334d736508dc350e06e510aba5e22e4594483b3a6562ce7c17dd797f4cc4ad2c + languageName: node + linkType: hard + +"deprecation@npm:^2.0.0": + version: 2.3.1 + resolution: "deprecation@npm:2.3.1" + checksum: 10c0/23d688ba66b74d09b908c40a76179418acbeeb0bfdf218c8075c58ad8d0c315130cb91aa3dffb623aa3a411a3569ce56c6460de6c8d69071c17fe6dd2442f032 + languageName: node + linkType: hard + +"destroy@npm:1.2.0, destroy@npm:~1.2.0": + version: 1.2.0 + resolution: "destroy@npm:1.2.0" + checksum: 10c0/bd7633942f57418f5a3b80d5cb53898127bcf53e24cdf5d5f4396be471417671f0fee48a4ebe9a1e9defbde2a31280011af58a57e090ff822f589b443ed4e643 + languageName: node + linkType: hard + +"detect-libc@npm:^2.0.1": + version: 2.1.2 + resolution: "detect-libc@npm:2.1.2" + checksum: 10c0/acc675c29a5649fa1fb6e255f993b8ee829e510b6b56b0910666949c80c364738833417d0edb5f90e4e46be17228b0f2b66a010513984e18b15deeeac49369c4 + languageName: node + linkType: hard + +"detect-newline@npm:^3.0.0, detect-newline@npm:^3.1.0": + version: 3.1.0 + resolution: "detect-newline@npm:3.1.0" + checksum: 10c0/c38cfc8eeb9fda09febb44bcd85e467c970d4e3bf526095394e5a4f18bc26dd0cf6b22c69c1fa9969261521c593836db335c2795218f6d781a512aea2fb8209d + languageName: node + linkType: hard + +"detect-port@npm:^1.5.1": + version: 1.6.1 + resolution: "detect-port@npm:1.6.1" + dependencies: + address: "npm:^1.0.1" + debug: "npm:4" + bin: + detect: bin/detect-port.js + detect-port: bin/detect-port.js + checksum: 10c0/4ea9eb46a637cb21220dd0a62b6074792894fc77b2cacbc9de533d1908b2eedafa7bfd7547baaa2ac1e9c7ba7c289b34b17db896dca6da142f4fc6e2060eee17 + languageName: node + linkType: hard + +"diff-sequences@npm:^29.6.3": + version: 29.6.3 + resolution: "diff-sequences@npm:29.6.3" + checksum: 10c0/32e27ac7dbffdf2fb0eb5a84efd98a9ad084fbabd5ac9abb8757c6770d5320d2acd172830b28c4add29bb873d59420601dfc805ac4064330ce59b1adfd0593b2 + languageName: node + linkType: hard + +"diff@npm:^4.0.1": + version: 4.0.4 + resolution: "diff@npm:4.0.4" + checksum: 10c0/855fb70b093d1d9643ddc12ea76dca90dc9d9cdd7f82c08ee8b9325c0dc5748faf3c82e2047ced5dcaa8b26e58f7903900be2628d0380a222c02d79d8de385df + languageName: node + linkType: hard + +"docker-compose@npm:^0.24.8": + version: 0.24.8 + resolution: "docker-compose@npm:0.24.8" + dependencies: + yaml: "npm:^2.2.2" + checksum: 10c0/1494389e554fed8aabf9fef24210a641cd2442028b1462d7f68186919f5e75045f7bfb4ccaf47c94ed879dcb63e4d82885c389399f531550c4b244920740b2b3 + languageName: node + linkType: hard + +"docker-compose@npm:^1.3.2": + version: 1.4.2 + resolution: "docker-compose@npm:1.4.2" + dependencies: + yaml: "npm:^2.2.2" + checksum: 10c0/2cd9182dafeac8ac3fed57e5aac85be5dec18eaa0241026d202e418577bfe185ab97ae2e066be01ade4ae55ffdcab04f4b40c754f3b2d11c314d6ca0117b51fa + languageName: node + linkType: hard + +"docker-modem@npm:^5.0.7": + version: 5.0.7 + resolution: "docker-modem@npm:5.0.7" + dependencies: + debug: "npm:^4.1.1" + readable-stream: "npm:^3.5.0" + split-ca: "npm:^1.0.1" + ssh2: "npm:^1.15.0" + checksum: 10c0/987dd7b04de57241d4e0fbdb5c44d41f898f5f520a3f6dbc6542c27cf9e84c91c44bf0c1bee2469be83096cb2941ea5e4a1bd3f57f60eb508c1d790d27ada8f9 + languageName: node + linkType: hard + +"dockerode@npm:^4.0.5, dockerode@npm:^4.0.9": + version: 4.0.10 + resolution: "dockerode@npm:4.0.10" + dependencies: + "@balena/dockerignore": "npm:^1.0.2" + "@grpc/grpc-js": "npm:^1.11.1" + "@grpc/proto-loader": "npm:^0.7.13" + docker-modem: "npm:^5.0.7" + protobufjs: "npm:^7.3.2" + tar-fs: "npm:^2.1.4" + uuid: "npm:^10.0.0" + checksum: 10c0/064930c4446ee833227417952ee9450b6f2a0045bfb93041ce36dd3f831fd6f24b7f87b44b6ff067782d0f121e5e530044e7e9ef538ef0c83133928a486d2d47 + languageName: node + linkType: hard + +"dot-prop@npm:^5.1.0": + version: 5.3.0 + resolution: "dot-prop@npm:5.3.0" + dependencies: + is-obj: "npm:^2.0.0" + checksum: 10c0/93f0d343ef87fe8869320e62f2459f7e70f49c6098d948cc47e060f4a3f827d0ad61e83cb82f2bd90cd5b9571b8d334289978a43c0f98fea4f0e99ee8faa0599 + languageName: node + linkType: hard + +"dotenv-expand@npm:~11.0.6": + version: 11.0.7 + resolution: "dotenv-expand@npm:11.0.7" + dependencies: + dotenv: "npm:^16.4.5" + checksum: 10c0/d80b8a7be085edf351270b96ac0e794bc3ddd7f36157912939577cb4d33ba6492ebee349d59798b71b90e36f498d24a2a564fb4aa00073b2ef4c2a3a49c467b1 + languageName: node + linkType: hard + +"dotenv@npm:^16.4.5": + version: 16.6.1 + resolution: "dotenv@npm:16.6.1" + checksum: 10c0/15ce56608326ea0d1d9414a5c8ee6dcf0fffc79d2c16422b4ac2268e7e2d76ff5a572d37ffe747c377de12005f14b3cc22361e79fc7f1061cce81f77d2c973dc + languageName: node + linkType: hard + +"dotenv@npm:~16.4.5": + version: 16.4.7 + resolution: "dotenv@npm:16.4.7" + checksum: 10c0/be9f597e36a8daf834452daa1f4cc30e5375a5968f98f46d89b16b983c567398a330580c88395069a77473943c06b877d1ca25b4afafcdd6d4adb549e8293462 + languageName: node + linkType: hard + +"dottie@npm:^2.0.6": + version: 2.0.7 + resolution: "dottie@npm:2.0.7" + checksum: 10c0/ba21bbc9b632aa33efa969bde514446a9ec0db4d43d79cac449c1ed17da10f0cb63da7e3d9fcd11935bf95882387ea9b3bf80c58479f2f8c97b318c2a8bcf54d + languageName: node + linkType: hard + +"dunder-proto@npm:^1.0.1": + version: 1.0.1 + resolution: "dunder-proto@npm:1.0.1" + dependencies: + call-bind-apply-helpers: "npm:^1.0.1" + es-errors: "npm:^1.3.0" + gopd: "npm:^1.2.0" + checksum: 10c0/199f2a0c1c16593ca0a145dbf76a962f8033ce3129f01284d48c45ed4e14fea9bbacd7b3610b6cdc33486cef20385ac054948fefc6272fcce645c09468f93031 + languageName: node + linkType: hard + +"eastasianwidth@npm:^0.2.0": + version: 0.2.0 + resolution: "eastasianwidth@npm:0.2.0" + checksum: 10c0/26f364ebcdb6395f95124fda411f63137a4bfb5d3a06453f7f23dfe52502905bd84e0488172e0f9ec295fdc45f05c23d5d91baf16bd26f0fe9acd777a188dc39 + languageName: node + linkType: hard + +"ee-first@npm:1.1.1": + version: 1.1.1 + resolution: "ee-first@npm:1.1.1" + checksum: 10c0/b5bb125ee93161bc16bfe6e56c6b04de5ad2aa44234d8f644813cc95d861a6910903132b05093706de2b706599367c4130eb6d170f6b46895686b95f87d017b7 + languageName: node + linkType: hard + +"ejs@npm:^3.1.7": + version: 3.1.10 + resolution: "ejs@npm:3.1.10" + dependencies: + jake: "npm:^10.8.5" + bin: + ejs: bin/cli.js + checksum: 10c0/52eade9e68416ed04f7f92c492183340582a36482836b11eab97b159fcdcfdedc62233a1bf0bf5e5e1851c501f2dca0e2e9afd111db2599e4e7f53ee29429ae1 + languageName: node + linkType: hard + +"electron-to-chromium@npm:^1.5.328": + version: 1.5.331 + resolution: "electron-to-chromium@npm:1.5.331" + checksum: 10c0/a7687f3bb4df4640bfeac08d1586531624917452bbbbeb67ccf2b07f111e584321e60945da080df664cbb57f272307d7867c8b93e279150ce8385f13d5178c96 + languageName: node + linkType: hard + +"emittery@npm:^0.13.1": + version: 0.13.1 + resolution: "emittery@npm:0.13.1" + checksum: 10c0/1573d0ae29ab34661b6c63251ff8f5facd24ccf6a823f19417ae8ba8c88ea450325788c67f16c99edec8de4b52ce93a10fe441ece389fd156e88ee7dab9bfa35 + languageName: node + linkType: hard + +"emoji-regex@npm:^8.0.0": + version: 8.0.0 + resolution: "emoji-regex@npm:8.0.0" + checksum: 10c0/b6053ad39951c4cf338f9092d7bfba448cdfd46fe6a2a034700b149ac9ffbc137e361cbd3c442297f86bed2e5f7576c1b54cc0a6bf8ef5106cc62f496af35010 + languageName: node + linkType: hard + +"emoji-regex@npm:^9.2.2": + version: 9.2.2 + resolution: "emoji-regex@npm:9.2.2" + checksum: 10c0/af014e759a72064cf66e6e694a7fc6b0ed3d8db680427b021a89727689671cefe9d04151b2cad51dbaf85d5ba790d061cd167f1cf32eb7b281f6368b3c181639 + languageName: node + linkType: hard + +"enabled@npm:2.0.x": + version: 2.0.0 + resolution: "enabled@npm:2.0.0" + checksum: 10c0/3b2c2af9bc7f8b9e291610f2dde4a75cf6ee52a68f4dd585482fbdf9a55d65388940e024e56d40bb03e05ef6671f5f53021fa8b72a20e954d7066ec28166713f + languageName: node + linkType: hard + +"encodeurl@npm:^2.0.0, encodeurl@npm:~2.0.0": + version: 2.0.0 + resolution: "encodeurl@npm:2.0.0" + checksum: 10c0/5d317306acb13e6590e28e27924c754163946a2480de11865c991a3a7eed4315cd3fba378b543ca145829569eefe9b899f3d84bb09870f675ae60bc924b01ceb + languageName: node + linkType: hard + +"encoding@npm:^0.1.13": + version: 0.1.13 + resolution: "encoding@npm:0.1.13" + dependencies: + iconv-lite: "npm:^0.6.2" + checksum: 10c0/36d938712ff00fe1f4bac88b43bcffb5930c1efa57bbcdca9d67e1d9d6c57cfb1200fb01efe0f3109b2ce99b231f90779532814a81370a1bd3274a0f58585039 + languageName: node + linkType: hard + +"end-of-stream@npm:^1.1.0, end-of-stream@npm:^1.4.1": + version: 1.4.5 + resolution: "end-of-stream@npm:1.4.5" + dependencies: + once: "npm:^1.4.0" + checksum: 10c0/b0701c92a10b89afb1cb45bf54a5292c6f008d744eb4382fa559d54775ff31617d1d7bc3ef617575f552e24fad2c7c1a1835948c66b3f3a4be0a6c1f35c883d8 + languageName: node + linkType: hard + +"enquirer@npm:~2.3.6": + version: 2.3.6 + resolution: "enquirer@npm:2.3.6" + dependencies: + ansi-colors: "npm:^4.1.1" + checksum: 10c0/8e070e052c2c64326a2803db9084d21c8aaa8c688327f133bf65c4a712586beb126fd98c8a01cfb0433e82a4bd3b6262705c55a63e0f7fb91d06b9cedbde9a11 + languageName: node + linkType: hard + +"env-paths@npm:^2.2.0, env-paths@npm:^2.2.1": + version: 2.2.1 + resolution: "env-paths@npm:2.2.1" + checksum: 10c0/285325677bf00e30845e330eec32894f5105529db97496ee3f598478e50f008c5352a41a30e5e72ec9de8a542b5a570b85699cd63bd2bc646dbcb9f311d83bc4 + languageName: node + linkType: hard + +"envinfo@npm:7.13.0": + version: 7.13.0 + resolution: "envinfo@npm:7.13.0" + bin: + envinfo: dist/cli.js + checksum: 10c0/9c279213cbbb353b3171e8e333fd2ed564054abade08ab3d735fe136e10a0e14e0588e1ce77e6f01285f2462eaca945d64f0778be5ae3d9e82804943e36a4411 + languageName: node + linkType: hard + +"err-code@npm:^2.0.2": + version: 2.0.3 + resolution: "err-code@npm:2.0.3" + checksum: 10c0/b642f7b4dd4a376e954947550a3065a9ece6733ab8e51ad80db727aaae0817c2e99b02a97a3d6cecc648a97848305e728289cf312d09af395403a90c9d4d8a66 + languageName: node + linkType: hard + +"error-ex@npm:^1.3.1": + version: 1.3.4 + resolution: "error-ex@npm:1.3.4" + dependencies: + is-arrayish: "npm:^0.2.1" + checksum: 10c0/b9e34ff4778b8f3b31a8377e1c654456f4c41aeaa3d10a1138c3b7635d8b7b2e03eb2475d46d8ae055c1f180a1063e100bffabf64ea7e7388b37735df5328664 + languageName: node + linkType: hard + +"es-define-property@npm:^1.0.1": + version: 1.0.1 + resolution: "es-define-property@npm:1.0.1" + checksum: 10c0/3f54eb49c16c18707949ff25a1456728c883e81259f045003499efba399c08bad00deebf65cccde8c0e07908c1a225c9d472b7107e558f2a48e28d530e34527c + languageName: node + linkType: hard + +"es-errors@npm:^1.3.0": + version: 1.3.0 + resolution: "es-errors@npm:1.3.0" + checksum: 10c0/0a61325670072f98d8ae3b914edab3559b6caa980f08054a3b872052640d91da01d38df55df797fcc916389d77fc92b8d5906cf028f4db46d7e3003abecbca85 + languageName: node + linkType: hard + +"es-object-atoms@npm:^1.0.0, es-object-atoms@npm:^1.1.1": + version: 1.1.1 + resolution: "es-object-atoms@npm:1.1.1" + dependencies: + es-errors: "npm:^1.3.0" + checksum: 10c0/65364812ca4daf48eb76e2a3b7a89b3f6a2e62a1c420766ce9f692665a29d94fe41fe88b65f24106f449859549711e4b40d9fb8002d862dfd7eb1c512d10be0c + languageName: node + linkType: hard + +"es-set-tostringtag@npm:^2.1.0": + version: 2.1.0 + resolution: "es-set-tostringtag@npm:2.1.0" + dependencies: + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.6" + has-tostringtag: "npm:^1.0.2" + hasown: "npm:^2.0.2" + checksum: 10c0/ef2ca9ce49afe3931cb32e35da4dcb6d86ab02592cfc2ce3e49ced199d9d0bb5085fc7e73e06312213765f5efa47cc1df553a6a5154584b21448e9fb8355b1af + languageName: node + linkType: hard + +"escalade@npm:^3.1.1, escalade@npm:^3.2.0": + version: 3.2.0 + resolution: "escalade@npm:3.2.0" + checksum: 10c0/ced4dd3a78e15897ed3be74e635110bbf3b08877b0a41be50dcb325ee0e0b5f65fc2d50e9845194d7c4633f327e2e1c6cce00a71b617c5673df0374201d67f65 + languageName: node + linkType: hard + +"escape-html@npm:^1.0.3, escape-html@npm:~1.0.3": + version: 1.0.3 + resolution: "escape-html@npm:1.0.3" + checksum: 10c0/524c739d776b36c3d29fa08a22e03e8824e3b2fd57500e5e44ecf3cc4707c34c60f9ca0781c0e33d191f2991161504c295e98f68c78fe7baa6e57081ec6ac0a3 + languageName: node + linkType: hard + +"escape-string-regexp@npm:^1.0.5": + version: 1.0.5 + resolution: "escape-string-regexp@npm:1.0.5" + checksum: 10c0/a968ad453dd0c2724e14a4f20e177aaf32bb384ab41b674a8454afe9a41c5e6fe8903323e0a1052f56289d04bd600f81278edf140b0fcc02f5cac98d0f5b5371 + languageName: node + linkType: hard + +"escape-string-regexp@npm:^2.0.0": + version: 2.0.0 + resolution: "escape-string-regexp@npm:2.0.0" + checksum: 10c0/2530479fe8db57eace5e8646c9c2a9c80fa279614986d16dcc6bcaceb63ae77f05a851ba6c43756d816c61d7f4534baf56e3c705e3e0d884818a46808811c507 + languageName: node + linkType: hard + +"escape-string-regexp@npm:^4.0.0": + version: 4.0.0 + resolution: "escape-string-regexp@npm:4.0.0" + checksum: 10c0/9497d4dd307d845bd7f75180d8188bb17ea8c151c1edbf6b6717c100e104d629dc2dfb687686181b0f4b7d732c7dfdc4d5e7a8ff72de1b0ca283a75bbb3a9cd9 + languageName: node + linkType: hard + +"eslint-config-prettier@npm:^10.1.8": + version: 10.1.8 + resolution: "eslint-config-prettier@npm:10.1.8" + peerDependencies: + eslint: ">=7.0.0" + bin: + eslint-config-prettier: bin/cli.js + checksum: 10c0/e1bcfadc9eccd526c240056b1e59c5cd26544fe59feb85f38f4f1f116caed96aea0b3b87868e68b3099e55caaac3f2e5b9f58110f85db893e83a332751192682 + languageName: node + linkType: hard + +"eslint-plugin-prettier@npm:^5.5.5": + version: 5.5.5 + resolution: "eslint-plugin-prettier@npm:5.5.5" + dependencies: + prettier-linter-helpers: "npm:^1.0.1" + synckit: "npm:^0.11.12" + peerDependencies: + "@types/eslint": ">=8.0.0" + eslint: ">=8.0.0" + eslint-config-prettier: ">= 7.0.0 <10.0.0 || >=10.1.0" + prettier: ">=3.0.0" + peerDependenciesMeta: + "@types/eslint": + optional: true + eslint-config-prettier: + optional: true + checksum: 10c0/091449b28c77ab2efbbf674e977181f2c8453d95a4df68218bddd87a4dfaa9ecc4eda60164e416f5986fb5d577e66e8d8e1e23d81e8555f8d735375598b03257 + languageName: node + linkType: hard + +"eslint-scope@npm:^8.4.0": + version: 8.4.0 + resolution: "eslint-scope@npm:8.4.0" + dependencies: + esrecurse: "npm:^4.3.0" + estraverse: "npm:^5.2.0" + checksum: 10c0/407f6c600204d0f3705bd557f81bd0189e69cd7996f408f8971ab5779c0af733d1af2f1412066b40ee1588b085874fc37a2333986c6521669cdbdd36ca5058e0 + languageName: node + linkType: hard + +"eslint-visitor-keys@npm:^3.4.3": + version: 3.4.3 + resolution: "eslint-visitor-keys@npm:3.4.3" + checksum: 10c0/92708e882c0a5ffd88c23c0b404ac1628cf20104a108c745f240a13c332a11aac54f49a22d5762efbffc18ecbc9a580d1b7ad034bf5f3cc3307e5cbff2ec9820 + languageName: node + linkType: hard + +"eslint-visitor-keys@npm:^4.2.1": + version: 4.2.1 + resolution: "eslint-visitor-keys@npm:4.2.1" + checksum: 10c0/fcd43999199d6740db26c58dbe0c2594623e31ca307e616ac05153c9272f12f1364f5a0b1917a8e962268fdecc6f3622c1c2908b4fcc2e047a106fe6de69dc43 + languageName: node + linkType: hard + +"eslint-visitor-keys@npm:^5.0.0": + version: 5.0.1 + resolution: "eslint-visitor-keys@npm:5.0.1" + checksum: 10c0/16190bdf2cbae40a1109384c94450c526a79b0b9c3cb21e544256ed85ac48a4b84db66b74a6561d20fe6ab77447f150d711c2ad5ad74df4fcc133736bce99678 + languageName: node + linkType: hard + +"eslint@npm:^9": + version: 9.39.4 + resolution: "eslint@npm:9.39.4" + dependencies: + "@eslint-community/eslint-utils": "npm:^4.8.0" + "@eslint-community/regexpp": "npm:^4.12.1" + "@eslint/config-array": "npm:^0.21.2" + "@eslint/config-helpers": "npm:^0.4.2" + "@eslint/core": "npm:^0.17.0" + "@eslint/eslintrc": "npm:^3.3.5" + "@eslint/js": "npm:9.39.4" + "@eslint/plugin-kit": "npm:^0.4.1" + "@humanfs/node": "npm:^0.16.6" + "@humanwhocodes/module-importer": "npm:^1.0.1" + "@humanwhocodes/retry": "npm:^0.4.2" + "@types/estree": "npm:^1.0.6" + ajv: "npm:^6.14.0" + chalk: "npm:^4.0.0" + cross-spawn: "npm:^7.0.6" + debug: "npm:^4.3.2" + escape-string-regexp: "npm:^4.0.0" + eslint-scope: "npm:^8.4.0" + eslint-visitor-keys: "npm:^4.2.1" + espree: "npm:^10.4.0" + esquery: "npm:^1.5.0" + esutils: "npm:^2.0.2" + fast-deep-equal: "npm:^3.1.3" + file-entry-cache: "npm:^8.0.0" + find-up: "npm:^5.0.0" + glob-parent: "npm:^6.0.2" + ignore: "npm:^5.2.0" + imurmurhash: "npm:^0.1.4" + is-glob: "npm:^4.0.0" + json-stable-stringify-without-jsonify: "npm:^1.0.1" + lodash.merge: "npm:^4.6.2" + minimatch: "npm:^3.1.5" + natural-compare: "npm:^1.4.0" + optionator: "npm:^0.9.3" + peerDependencies: + jiti: "*" + peerDependenciesMeta: + jiti: + optional: true + bin: + eslint: bin/eslint.js + checksum: 10c0/1955067c2d991f0c84f4c4abfafe31bb47fa3b717a7fd3e43fe1e511c6f859d7700cbca969f85661dc4c130f7aeced5e5444884314198a54428f5e5141db9337 + languageName: node + linkType: hard + +"espree@npm:^10.0.1, espree@npm:^10.4.0": + version: 10.4.0 + resolution: "espree@npm:10.4.0" + dependencies: + acorn: "npm:^8.15.0" + acorn-jsx: "npm:^5.3.2" + eslint-visitor-keys: "npm:^4.2.1" + checksum: 10c0/c63fe06131c26c8157b4083313cb02a9a54720a08e21543300e55288c40e06c3fc284bdecf108d3a1372c5934a0a88644c98714f38b6ae8ed272b40d9ea08d6b + languageName: node + linkType: hard + +"esprima@npm:^4.0.0": + version: 4.0.1 + resolution: "esprima@npm:4.0.1" + bin: + esparse: ./bin/esparse.js + esvalidate: ./bin/esvalidate.js + checksum: 10c0/ad4bab9ead0808cf56501750fd9d3fb276f6b105f987707d059005d57e182d18a7c9ec7f3a01794ebddcca676773e42ca48a32d67a250c9d35e009ca613caba3 + languageName: node + linkType: hard + +"esquery@npm:^1.5.0": + version: 1.7.0 + resolution: "esquery@npm:1.7.0" + dependencies: + estraverse: "npm:^5.1.0" + checksum: 10c0/77d5173db450b66f3bc685d11af4c90cffeedb340f34a39af96d43509a335ce39c894fd79233df32d38f5e4e219fa0f7076f6ec90bae8320170ba082c0db4793 + languageName: node + linkType: hard + +"esrecurse@npm:^4.3.0": + version: 4.3.0 + resolution: "esrecurse@npm:4.3.0" + dependencies: + estraverse: "npm:^5.2.0" + checksum: 10c0/81a37116d1408ded88ada45b9fb16dbd26fba3aadc369ce50fcaf82a0bac12772ebd7b24cd7b91fc66786bf2c1ac7b5f196bc990a473efff972f5cb338877cf5 + languageName: node + linkType: hard + +"estraverse@npm:^5.1.0, estraverse@npm:^5.2.0": + version: 5.3.0 + resolution: "estraverse@npm:5.3.0" + checksum: 10c0/1ff9447b96263dec95d6d67431c5e0771eb9776427421260a3e2f0fdd5d6bd4f8e37a7338f5ad2880c9f143450c9b1e4fc2069060724570a49cf9cf0312bd107 + languageName: node + linkType: hard + +"esutils@npm:^2.0.2": + version: 2.0.3 + resolution: "esutils@npm:2.0.3" + checksum: 10c0/9a2fe69a41bfdade834ba7c42de4723c97ec776e40656919c62cbd13607c45e127a003f05f724a1ea55e5029a4cf2de444b13009f2af71271e42d93a637137c7 + languageName: node + linkType: hard + +"etag@npm:^1.8.1, etag@npm:~1.8.1": + version: 1.8.1 + resolution: "etag@npm:1.8.1" + checksum: 10c0/12be11ef62fb9817314d790089a0a49fae4e1b50594135dcb8076312b7d7e470884b5100d249b28c18581b7fd52f8b485689ffae22a11ed9ec17377a33a08f84 + languageName: node + linkType: hard + +"event-target-shim@npm:^5.0.0": + version: 5.0.1 + resolution: "event-target-shim@npm:5.0.1" + checksum: 10c0/0255d9f936215fd206156fd4caa9e8d35e62075d720dc7d847e89b417e5e62cf1ce6c9b4e0a1633a9256de0efefaf9f8d26924b1f3c8620cffb9db78e7d3076b + languageName: node + linkType: hard + +"eventemitter3@npm:^4.0.4": + version: 4.0.7 + resolution: "eventemitter3@npm:4.0.7" + checksum: 10c0/5f6d97cbcbac47be798e6355e3a7639a84ee1f7d9b199a07017f1d2f1e2fe236004d14fa5dfaeba661f94ea57805385e326236a6debbc7145c8877fbc0297c6b + languageName: node + linkType: hard + +"events-universal@npm:^1.0.0": + version: 1.0.1 + resolution: "events-universal@npm:1.0.1" + dependencies: + bare-events: "npm:^2.7.0" + checksum: 10c0/a1d9a5e9f95843650f8ec240dd1221454c110189a9813f32cdf7185759b43f1f964367ac7dca4ebc69150b59043f2d77c7e122b0d03abf7c25477ea5494785a5 + languageName: node + linkType: hard + +"events@npm:^3.3.0": + version: 3.3.0 + resolution: "events@npm:3.3.0" + checksum: 10c0/d6b6f2adbccbcda74ddbab52ed07db727ef52e31a61ed26db9feb7dc62af7fc8e060defa65e5f8af9449b86b52cc1a1f6a79f2eafcf4e62add2b7a1fa4a432f6 + languageName: node + linkType: hard + +"eventsource-parser@npm:^3.0.0, eventsource-parser@npm:^3.0.1": + version: 3.0.6 + resolution: "eventsource-parser@npm:3.0.6" + checksum: 10c0/70b8ccec7dac767ef2eca43f355e0979e70415701691382a042a2df8d6a68da6c2fca35363669821f3da876d29c02abe9b232964637c1b6635c940df05ada78a + languageName: node + linkType: hard + +"eventsource@npm:^3.0.2": + version: 3.0.7 + resolution: "eventsource@npm:3.0.7" + dependencies: + eventsource-parser: "npm:^3.0.1" + checksum: 10c0/c48a73c38f300e33e9f11375d4ee969f25cbb0519608a12378a38068055ae8b55b6e0e8a49c3f91c784068434efe1d9f01eb49b6315b04b0da9157879ce2f67d + languageName: node + linkType: hard + +"execa@npm:5.0.0": + version: 5.0.0 + resolution: "execa@npm:5.0.0" + dependencies: + cross-spawn: "npm:^7.0.3" + get-stream: "npm:^6.0.0" + human-signals: "npm:^2.1.0" + is-stream: "npm:^2.0.0" + merge-stream: "npm:^2.0.0" + npm-run-path: "npm:^4.0.1" + onetime: "npm:^5.1.2" + signal-exit: "npm:^3.0.3" + strip-final-newline: "npm:^2.0.0" + checksum: 10c0/e110add7ca0de63aea415385ebad7236c8de281d5d9a916dbd69f59009dac3d5d631e6252c2ea5d0258220b0d22acf25649b2caf05fa162eaa1401339fc69ba4 + languageName: node + linkType: hard + +"execa@npm:^5.0.0": + version: 5.1.1 + resolution: "execa@npm:5.1.1" + dependencies: + cross-spawn: "npm:^7.0.3" + get-stream: "npm:^6.0.0" + human-signals: "npm:^2.1.0" + is-stream: "npm:^2.0.0" + merge-stream: "npm:^2.0.0" + npm-run-path: "npm:^4.0.1" + onetime: "npm:^5.1.2" + signal-exit: "npm:^3.0.3" + strip-final-newline: "npm:^2.0.0" + checksum: 10c0/c8e615235e8de4c5addf2fa4c3da3e3aa59ce975a3e83533b4f6a71750fb816a2e79610dc5f1799b6e28976c9ae86747a36a606655bf8cb414a74d8d507b304f + languageName: node + linkType: hard + +"exit-x@npm:^0.2.2": + version: 0.2.2 + resolution: "exit-x@npm:0.2.2" + checksum: 10c0/212a7a095ca5540e9581f1ef2d1d6a40df7a6027c8cc96e78ce1d16b86d1a88326d4a0eff8dff2b5ec1e68bb0c1edd5d0dfdde87df1869bf7514d4bc6a5cbd72 + languageName: node + linkType: hard + +"exit@npm:^0.1.2": + version: 0.1.2 + resolution: "exit@npm:0.1.2" + checksum: 10c0/71d2ad9b36bc25bb8b104b17e830b40a08989be7f7d100b13269aaae7c3784c3e6e1e88a797e9e87523993a25ba27c8958959a554535370672cfb4d824af8989 + languageName: node + linkType: hard + +"expect@npm:30.3.0": + version: 30.3.0 + resolution: "expect@npm:30.3.0" + dependencies: + "@jest/expect-utils": "npm:30.3.0" + "@jest/get-type": "npm:30.1.0" + jest-matcher-utils: "npm:30.3.0" + jest-message-util: "npm:30.3.0" + jest-mock: "npm:30.3.0" + jest-util: "npm:30.3.0" + checksum: 10c0/a07a157a0c8b3f1e29bfe5ccbf03a3add2c69fe60d1af8a0980053bb6403d721d5f5e4616f1ea5833b747913f8c880c79ce4d98c23a71a2f0c27cf7273892576 + languageName: node + linkType: hard + +"expect@npm:^29.0.0, expect@npm:^29.7.0": + version: 29.7.0 + resolution: "expect@npm:29.7.0" + dependencies: + "@jest/expect-utils": "npm:^29.7.0" + jest-get-type: "npm:^29.6.3" + jest-matcher-utils: "npm:^29.7.0" + jest-message-util: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + checksum: 10c0/2eddeace66e68b8d8ee5f7be57f3014b19770caaf6815c7a08d131821da527fb8c8cb7b3dcd7c883d2d3d8d184206a4268984618032d1e4b16dc8d6596475d41 + languageName: node + linkType: hard + +"exponential-backoff@npm:^3.1.1": + version: 3.1.3 + resolution: "exponential-backoff@npm:3.1.3" + checksum: 10c0/77e3ae682b7b1f4972f563c6dbcd2b0d54ac679e62d5d32f3e5085feba20483cf28bd505543f520e287a56d4d55a28d7874299941faf637e779a1aa5994d1267 + languageName: node + linkType: hard + +"express-rate-limit@npm:^8.2.1": + version: 8.3.2 + resolution: "express-rate-limit@npm:8.3.2" + dependencies: + ip-address: "npm:10.1.0" + peerDependencies: + express: ">= 4.11" + checksum: 10c0/5b64d0691071086cdb8cfc6bcd5e761f5687cf4fabdebfe2a043ea5b4d31443637181e7be71e7ffabce76aee816daee62c1ca83250045847957da408a129f650 + languageName: node + linkType: hard + +"express@npm:4.22.1": + version: 4.22.1 + resolution: "express@npm:4.22.1" + dependencies: + accepts: "npm:~1.3.8" + array-flatten: "npm:1.1.1" + body-parser: "npm:~1.20.3" + content-disposition: "npm:~0.5.4" + content-type: "npm:~1.0.4" + cookie: "npm:~0.7.1" + cookie-signature: "npm:~1.0.6" + debug: "npm:2.6.9" + depd: "npm:2.0.0" + encodeurl: "npm:~2.0.0" + escape-html: "npm:~1.0.3" + etag: "npm:~1.8.1" + finalhandler: "npm:~1.3.1" + fresh: "npm:~0.5.2" + http-errors: "npm:~2.0.0" + merge-descriptors: "npm:1.0.3" + methods: "npm:~1.1.2" + on-finished: "npm:~2.4.1" + parseurl: "npm:~1.3.3" + path-to-regexp: "npm:~0.1.12" + proxy-addr: "npm:~2.0.7" + qs: "npm:~6.14.0" + range-parser: "npm:~1.2.1" + safe-buffer: "npm:5.2.1" + send: "npm:~0.19.0" + serve-static: "npm:~1.16.2" + setprototypeof: "npm:1.2.0" + statuses: "npm:~2.0.1" + type-is: "npm:~1.6.18" + utils-merge: "npm:1.0.1" + vary: "npm:~1.1.2" + checksum: 10c0/ea57f512ab1e05e26b53a14fd432f65a10ec735ece342b37d0b63a7bcb8d337ffbb830ecb8ca15bcdfe423fbff88cea09786277baff200e8cde3ab40faa665cd + languageName: node + linkType: hard + +"express@npm:^5.2.1": + version: 5.2.1 + resolution: "express@npm:5.2.1" + dependencies: + accepts: "npm:^2.0.0" + body-parser: "npm:^2.2.1" + content-disposition: "npm:^1.0.0" + content-type: "npm:^1.0.5" + cookie: "npm:^0.7.1" + cookie-signature: "npm:^1.2.1" + debug: "npm:^4.4.0" + depd: "npm:^2.0.0" + encodeurl: "npm:^2.0.0" + escape-html: "npm:^1.0.3" + etag: "npm:^1.8.1" + finalhandler: "npm:^2.1.0" + fresh: "npm:^2.0.0" + http-errors: "npm:^2.0.0" + merge-descriptors: "npm:^2.0.0" + mime-types: "npm:^3.0.0" + on-finished: "npm:^2.4.1" + once: "npm:^1.4.0" + parseurl: "npm:^1.3.3" + proxy-addr: "npm:^2.0.7" + qs: "npm:^6.14.0" + range-parser: "npm:^1.2.1" + router: "npm:^2.2.0" + send: "npm:^1.1.0" + serve-static: "npm:^2.2.0" + statuses: "npm:^2.0.1" + type-is: "npm:^2.0.1" + vary: "npm:^1.1.2" + checksum: 10c0/45e8c841ad188a41402ddcd1294901e861ee0819f632fb494f2ed344ef9c43315d294d443fb48d594e6586a3b779785120f43321417adaef8567316a55072949 + languageName: node + linkType: hard + +"fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": + version: 3.1.3 + resolution: "fast-deep-equal@npm:3.1.3" + checksum: 10c0/40dedc862eb8992c54579c66d914635afbec43350afbbe991235fdcb4e3a8d5af1b23ae7e79bef7d4882d0ecee06c3197488026998fb19f72dc95acff1d1b1d0 + languageName: node + linkType: hard + +"fast-diff@npm:^1.1.2": + version: 1.3.0 + resolution: "fast-diff@npm:1.3.0" + checksum: 10c0/5c19af237edb5d5effda008c891a18a585f74bf12953be57923f17a3a4d0979565fc64dbc73b9e20926b9d895f5b690c618cbb969af0cf022e3222471220ad29 + languageName: node + linkType: hard + +"fast-fifo@npm:^1.2.0, fast-fifo@npm:^1.3.2": + version: 1.3.2 + resolution: "fast-fifo@npm:1.3.2" + checksum: 10c0/d53f6f786875e8b0529f784b59b4b05d4b5c31c651710496440006a398389a579c8dbcd2081311478b5bf77f4b0b21de69109c5a4eabea9d8e8783d1eb864e4c + languageName: node + linkType: hard + +"fast-json-stable-stringify@npm:2.x, fast-json-stable-stringify@npm:^2.0.0, fast-json-stable-stringify@npm:^2.1.0": + version: 2.1.0 + resolution: "fast-json-stable-stringify@npm:2.1.0" + checksum: 10c0/7f081eb0b8a64e0057b3bb03f974b3ef00135fbf36c1c710895cd9300f13c94ba809bb3a81cf4e1b03f6e5285610a61abbd7602d0652de423144dfee5a389c9b + languageName: node + linkType: hard + +"fast-levenshtein@npm:^2.0.6": + version: 2.0.6 + resolution: "fast-levenshtein@npm:2.0.6" + checksum: 10c0/111972b37338bcb88f7d9e2c5907862c280ebf4234433b95bc611e518d192ccb2d38119c4ac86e26b668d75f7f3894f4ff5c4982899afced7ca78633b08287c4 + languageName: node + linkType: hard + +"fast-safe-stringify@npm:2.1.1": + version: 2.1.1 + resolution: "fast-safe-stringify@npm:2.1.1" + checksum: 10c0/d90ec1c963394919828872f21edaa3ad6f1dddd288d2bd4e977027afff09f5db40f94e39536d4646f7e01761d704d72d51dce5af1b93717f3489ef808f5f4e4d + languageName: node + linkType: hard + +"fast-uri@npm:^3.0.1": + version: 3.1.0 + resolution: "fast-uri@npm:3.1.0" + checksum: 10c0/44364adca566f70f40d1e9b772c923138d47efeac2ae9732a872baafd77061f26b097ba2f68f0892885ad177becd065520412b8ffeec34b16c99433c5b9e2de7 + languageName: node + linkType: hard + +"fb-watchman@npm:^2.0.0, fb-watchman@npm:^2.0.2": + version: 2.0.2 + resolution: "fb-watchman@npm:2.0.2" + dependencies: + bser: "npm:2.1.1" + checksum: 10c0/feae89ac148adb8f6ae8ccd87632e62b13563e6fb114cacb5265c51f585b17e2e268084519fb2edd133872f1d47a18e6bfd7e5e08625c0d41b93149694187581 + languageName: node + linkType: hard + +"fdir@npm:^6.4.3, fdir@npm:^6.5.0": + version: 6.5.0 + resolution: "fdir@npm:6.5.0" + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + checksum: 10c0/e345083c4306b3aed6cb8ec551e26c36bab5c511e99ea4576a16750ddc8d3240e63826cc624f5ae17ad4dc82e68a253213b60d556c11bfad064b7607847ed07f + languageName: node + linkType: hard + +"fecha@npm:^4.2.0": + version: 4.2.3 + resolution: "fecha@npm:4.2.3" + checksum: 10c0/0e895965959cf6a22bb7b00f0bf546f2783836310f510ddf63f463e1518d4c96dec61ab33fdfd8e79a71b4856a7c865478ce2ee8498d560fe125947703c9b1cf + languageName: node + linkType: hard + +"fflate@npm:^0.8.2": + version: 0.8.2 + resolution: "fflate@npm:0.8.2" + checksum: 10c0/03448d630c0a583abea594835a9fdb2aaf7d67787055a761515bf4ed862913cfd693b4c4ffd5c3f3b355a70cf1e19033e9ae5aedcca103188aaff91b8bd6e293 + languageName: node + linkType: hard + +"figures@npm:3.2.0": + version: 3.2.0 + resolution: "figures@npm:3.2.0" + dependencies: + escape-string-regexp: "npm:^1.0.5" + checksum: 10c0/9c421646ede432829a50bc4e55c7a4eb4bcb7cc07b5bab2f471ef1ab9a344595bbebb6c5c21470093fbb730cd81bbca119624c40473a125293f656f49cb47629 + languageName: node + linkType: hard + +"file-entry-cache@npm:^8.0.0": + version: 8.0.0 + resolution: "file-entry-cache@npm:8.0.0" + dependencies: + flat-cache: "npm:^4.0.0" + checksum: 10c0/9e2b5938b1cd9b6d7e3612bdc533afd4ac17b2fc646569e9a8abbf2eb48e5eb8e316bc38815a3ef6a1b456f4107f0d0f055a614ca613e75db6bf9ff4d72c1638 + languageName: node + linkType: hard + +"file-type@npm:20.4.1": + version: 20.4.1 + resolution: "file-type@npm:20.4.1" + dependencies: + "@tokenizer/inflate": "npm:^0.2.6" + strtok3: "npm:^10.2.0" + token-types: "npm:^6.0.0" + uint8array-extras: "npm:^1.4.0" + checksum: 10c0/ae6f65e537205a9a3e07ae574de74ed5210aa78899d6478351a466f97e3f17096b93d74cb97f3fce7488bc8486a21e449ab076ec358ed06984f4a9a8f48a9f55 + languageName: node + linkType: hard + +"filelist@npm:^1.0.4": + version: 1.0.6 + resolution: "filelist@npm:1.0.6" + dependencies: + minimatch: "npm:^5.0.1" + checksum: 10c0/6ee725bec3e1936d680a45f14439b224d9f7c71658c145addcf551dd82f03d608522eb6b191aa086b392bc3e52ed4ce0ed8d78e24b203e6c5e867560a05d1121 + languageName: node + linkType: hard + +"fill-range@npm:^7.1.1": + version: 7.1.1 + resolution: "fill-range@npm:7.1.1" + dependencies: + to-regex-range: "npm:^5.0.1" + checksum: 10c0/b75b691bbe065472f38824f694c2f7449d7f5004aa950426a2c28f0306c60db9b880c0b0e4ed819997ffb882d1da02cfcfc819bddc94d71627f5269682edf018 + languageName: node + linkType: hard + +"finalhandler@npm:^2.1.0": + version: 2.1.1 + resolution: "finalhandler@npm:2.1.1" + dependencies: + debug: "npm:^4.4.0" + encodeurl: "npm:^2.0.0" + escape-html: "npm:^1.0.3" + on-finished: "npm:^2.4.1" + parseurl: "npm:^1.3.3" + statuses: "npm:^2.0.1" + checksum: 10c0/6bd664e21b7b2e79efcaace7d1a427169f61cce048fae68eb56290e6934e676b78e55d89f5998c5508871345bc59a61f47002dc505dc7288be68cceac1b701e2 + languageName: node + linkType: hard + +"finalhandler@npm:~1.3.1": + version: 1.3.2 + resolution: "finalhandler@npm:1.3.2" + dependencies: + debug: "npm:2.6.9" + encodeurl: "npm:~2.0.0" + escape-html: "npm:~1.0.3" + on-finished: "npm:~2.4.1" + parseurl: "npm:~1.3.3" + statuses: "npm:~2.0.2" + unpipe: "npm:~1.0.0" + checksum: 10c0/435a4fd65e4e4e4c71bb5474980090b73c353a123dd415583f67836bdd6516e528cf07298e219a82b94631dee7830eae5eece38d3c178073cf7df4e8c182f413 + languageName: node + linkType: hard + +"find-up@npm:^2.0.0": + version: 2.1.0 + resolution: "find-up@npm:2.1.0" + dependencies: + locate-path: "npm:^2.0.0" + checksum: 10c0/c080875c9fe28eb1962f35cbe83c683796a0321899f1eed31a37577800055539815de13d53495049697d3ba313013344f843bb9401dd337a1b832be5edfc6840 + languageName: node + linkType: hard + +"find-up@npm:^4.0.0, find-up@npm:^4.1.0": + version: 4.1.0 + resolution: "find-up@npm:4.1.0" + dependencies: + locate-path: "npm:^5.0.0" + path-exists: "npm:^4.0.0" + checksum: 10c0/0406ee89ebeefa2d507feb07ec366bebd8a6167ae74aa4e34fb4c4abd06cf782a3ce26ae4194d70706f72182841733f00551c209fe575cb00bd92104056e78c1 + languageName: node + linkType: hard + +"find-up@npm:^5.0.0": + version: 5.0.0 + resolution: "find-up@npm:5.0.0" + dependencies: + locate-path: "npm:^6.0.0" + path-exists: "npm:^4.0.0" + checksum: 10c0/062c5a83a9c02f53cdd6d175a37ecf8f87ea5bbff1fdfb828f04bfa021441bc7583e8ebc0872a4c1baab96221fb8a8a275a19809fb93fbc40bd69ec35634069a + languageName: node + linkType: hard + +"flat-cache@npm:^4.0.0": + version: 4.0.1 + resolution: "flat-cache@npm:4.0.1" + dependencies: + flatted: "npm:^3.2.9" + keyv: "npm:^4.5.4" + checksum: 10c0/2c59d93e9faa2523e4fda6b4ada749bed432cfa28c8e251f33b25795e426a1c6dbada777afb1f74fcfff33934fdbdea921ee738fcc33e71adc9d6eca984a1cfc + languageName: node + linkType: hard + +"flat@npm:^5.0.2": + version: 5.0.2 + resolution: "flat@npm:5.0.2" + bin: + flat: cli.js + checksum: 10c0/f178b13482f0cd80c7fede05f4d10585b1f2fdebf26e12edc138e32d3150c6ea6482b7f12813a1091143bad52bb6d3596bca51a162257a21163c0ff438baa5fe + languageName: node + linkType: hard + +"flatted@npm:^3.2.9": + version: 3.4.2 + resolution: "flatted@npm:3.4.2" + checksum: 10c0/a65b67aae7172d6cdf63691be7de6c5cd5adbdfdfe2e9da1a09b617c9512ed794037741ee53d93114276bff3f93cd3b0d97d54f9b316e1e4885dde6e9ffdf7ed + languageName: node + linkType: hard + +"fn.name@npm:1.x.x": + version: 1.1.0 + resolution: "fn.name@npm:1.1.0" + checksum: 10c0/8ad62aa2d4f0b2a76d09dba36cfec61c540c13a0fd72e5d94164e430f987a7ce6a743112bbeb14877c810ef500d1f73d7f56e76d029d2e3413f20d79e3460a9a + languageName: node + linkType: hard + +"follow-redirects@npm:^1.15.11, follow-redirects@npm:^1.15.6": + version: 1.15.11 + resolution: "follow-redirects@npm:1.15.11" + peerDependenciesMeta: + debug: + optional: true + checksum: 10c0/d301f430542520a54058d4aeeb453233c564aaccac835d29d15e050beb33f339ad67d9bddbce01739c5dc46a6716dbe3d9d0d5134b1ca203effa11a7ef092343 + languageName: node + linkType: hard + +"foreground-child@npm:^3.1.0, foreground-child@npm:^3.3.1": + version: 3.3.1 + resolution: "foreground-child@npm:3.3.1" + dependencies: + cross-spawn: "npm:^7.0.6" + signal-exit: "npm:^4.0.1" + checksum: 10c0/8986e4af2430896e65bc2788d6679067294d6aee9545daefc84923a0a4b399ad9c7a3ea7bd8c0b2b80fdf4a92de4c69df3f628233ff3224260e9c1541a9e9ed3 + languageName: node + linkType: hard + +"form-data-encoder@npm:1.7.2": + version: 1.7.2 + resolution: "form-data-encoder@npm:1.7.2" + checksum: 10c0/56553768037b6d55d9de524f97fe70555f0e415e781cb56fc457a68263de3d40fadea2304d4beef2d40b1a851269bd7854e42c362107071892cb5238debe9464 + languageName: node + linkType: hard + +"form-data@npm:^4.0.4, form-data@npm:^4.0.5": + version: 4.0.5 + resolution: "form-data@npm:4.0.5" + dependencies: + asynckit: "npm:^0.4.0" + combined-stream: "npm:^1.0.8" + es-set-tostringtag: "npm:^2.1.0" + hasown: "npm:^2.0.2" + mime-types: "npm:^2.1.12" + checksum: 10c0/dd6b767ee0bbd6d84039db12a0fa5a2028160ffbfaba1800695713b46ae974a5f6e08b3356c3195137f8530dcd9dfcb5d5ae1eeff53d0db1e5aad863b619ce3b + languageName: node + linkType: hard + +"formdata-node@npm:^4.3.2": + version: 4.4.1 + resolution: "formdata-node@npm:4.4.1" + dependencies: + node-domexception: "npm:1.0.0" + web-streams-polyfill: "npm:4.0.0-beta.3" + checksum: 10c0/74151e7b228ffb33b565cec69182694ad07cc3fdd9126a8240468bb70a8ba66e97e097072b60bcb08729b24c7ce3fd3e0bd7f1f80df6f9f662b9656786e76f6a + languageName: node + linkType: hard + +"forwarded@npm:0.2.0": + version: 0.2.0 + resolution: "forwarded@npm:0.2.0" + checksum: 10c0/9b67c3fac86acdbc9ae47ba1ddd5f2f81526fa4c8226863ede5600a3f7c7416ef451f6f1e240a3cc32d0fd79fcfe6beb08fd0da454f360032bde70bf80afbb33 + languageName: node + linkType: hard + +"fresh@npm:^2.0.0": + version: 2.0.0 + resolution: "fresh@npm:2.0.0" + checksum: 10c0/0557548194cb9a809a435bf92bcfbc20c89e8b5eb38861b73ced36750437251e39a111fc3a18b98531be9dd91fe1411e4969f229dc579ec0251ce6c5d4900bbc + languageName: node + linkType: hard + +"fresh@npm:~0.5.2": + version: 0.5.2 + resolution: "fresh@npm:0.5.2" + checksum: 10c0/c6d27f3ed86cc5b601404822f31c900dd165ba63fff8152a3ef714e2012e7535027063bc67ded4cb5b3a49fa596495d46cacd9f47d6328459cf570f08b7d9e5a + languageName: node + linkType: hard + +"front-matter@npm:^4.0.2": + version: 4.0.2 + resolution: "front-matter@npm:4.0.2" + dependencies: + js-yaml: "npm:^3.13.1" + checksum: 10c0/7a0df5ca37428dd563c057bc17a8940481fe53876609bcdc443a02ce463c70f1842c7cb4628b80916de46a253732794b36fb6a31105db0f185698a93acee4011 + languageName: node + linkType: hard + +"fs-constants@npm:^1.0.0": + version: 1.0.0 + resolution: "fs-constants@npm:1.0.0" + checksum: 10c0/a0cde99085f0872f4d244e83e03a46aa387b74f5a5af750896c6b05e9077fac00e9932fdf5aef84f2f16634cd473c63037d7a512576da7d5c2b9163d1909f3a8 + languageName: node + linkType: hard + +"fs-extra@npm:^11.2.0": + version: 11.3.4 + resolution: "fs-extra@npm:11.3.4" + dependencies: + graceful-fs: "npm:^4.2.0" + jsonfile: "npm:^6.0.1" + universalify: "npm:^2.0.0" + checksum: 10c0/e08276f767a62496ae97d711aaa692c6a478177f24a85979b6a2881c9db9c68b8c2ad5da0bcf92c0b2a474cea6e935ec245656441527958fd8372cb647087df0 + languageName: node + linkType: hard + +"fs-minipass@npm:^3.0.0": + version: 3.0.3 + resolution: "fs-minipass@npm:3.0.3" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10c0/63e80da2ff9b621e2cb1596abcb9207f1cf82b968b116ccd7b959e3323144cce7fb141462200971c38bbf2ecca51695069db45265705bed09a7cd93ae5b89f94 + languageName: node + linkType: hard + +"fs.realpath@npm:^1.0.0": + version: 1.0.0 + resolution: "fs.realpath@npm:1.0.0" + checksum: 10c0/444cf1291d997165dfd4c0d58b69f0e4782bfd9149fd72faa4fe299e68e0e93d6db941660b37dd29153bf7186672ececa3b50b7e7249477b03fdf850f287c948 + languageName: node + linkType: hard + +"fsevents@npm:^2.3.2, fsevents@npm:^2.3.3": + version: 2.3.3 + resolution: "fsevents@npm:2.3.3" + dependencies: + node-gyp: "npm:latest" + checksum: 10c0/a1f0c44595123ed717febbc478aa952e47adfc28e2092be66b8ab1635147254ca6cfe1df792a8997f22716d4cbafc73309899ff7bfac2ac3ad8cf2e4ecc3ec60 + conditions: os=darwin + languageName: node + linkType: hard + +"fsevents@patch:fsevents@npm%3A^2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A^2.3.3#optional!builtin": + version: 2.3.3 + resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" + dependencies: + node-gyp: "npm:latest" + conditions: os=darwin + languageName: node + linkType: hard + +"function-bind@npm:^1.1.2": + version: 1.1.2 + resolution: "function-bind@npm:1.1.2" + checksum: 10c0/d8680ee1e5fcd4c197e4ac33b2b4dce03c71f4d91717292785703db200f5c21f977c568d28061226f9b5900cbcd2c84463646134fd5337e7925e0942bc3f46d5 + languageName: node + linkType: hard + +"generic-pool@npm:3.9.0": + version: 3.9.0 + resolution: "generic-pool@npm:3.9.0" + checksum: 10c0/6b314d0d71170d5cbaf7162c423f53f8d6556b2135626a65bcdc03c089840b0a2f59eeb2d907939b8200e945eaf71ceb6630426f22d2128a1d242aec4b232aa7 + languageName: node + linkType: hard + +"gensync@npm:^1.0.0-beta.2": + version: 1.0.0-beta.2 + resolution: "gensync@npm:1.0.0-beta.2" + checksum: 10c0/782aba6cba65b1bb5af3b095d96249d20edbe8df32dbf4696fd49be2583faf676173bf4809386588828e4dd76a3354fcbeb577bab1c833ccd9fc4577f26103f8 + languageName: node + linkType: hard + +"get-caller-file@npm:^2.0.5": + version: 2.0.5 + resolution: "get-caller-file@npm:2.0.5" + checksum: 10c0/c6c7b60271931fa752aeb92f2b47e355eac1af3a2673f47c9589e8f8a41adc74d45551c1bc57b5e66a80609f10ffb72b6f575e4370d61cc3f7f3aaff01757cde + languageName: node + linkType: hard + +"get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.3.0": + version: 1.3.0 + resolution: "get-intrinsic@npm:1.3.0" + dependencies: + call-bind-apply-helpers: "npm:^1.0.2" + es-define-property: "npm:^1.0.1" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.1.1" + function-bind: "npm:^1.1.2" + get-proto: "npm:^1.0.1" + gopd: "npm:^1.2.0" + has-symbols: "npm:^1.1.0" + hasown: "npm:^2.0.2" + math-intrinsics: "npm:^1.1.0" + checksum: 10c0/52c81808af9a8130f581e6a6a83e1ba4a9f703359e7a438d1369a5267a25412322f03dcbd7c549edaef0b6214a0630a28511d7df0130c93cfd380f4fa0b5b66a + languageName: node + linkType: hard + +"get-package-type@npm:^0.1.0": + version: 0.1.0 + resolution: "get-package-type@npm:0.1.0" + checksum: 10c0/e34cdf447fdf1902a1f6d5af737eaadf606d2ee3518287abde8910e04159368c268568174b2e71102b87b26c2020486f126bfca9c4fb1ceb986ff99b52ecd1be + languageName: node + linkType: hard + +"get-pkg-repo@npm:^4.2.1": + version: 4.2.1 + resolution: "get-pkg-repo@npm:4.2.1" + dependencies: + "@hutson/parse-repository-url": "npm:^3.0.0" + hosted-git-info: "npm:^4.0.0" + through2: "npm:^2.0.0" + yargs: "npm:^16.2.0" + bin: + get-pkg-repo: src/cli.js + checksum: 10c0/1338d2e048a594da4a34e7dd69d909376d72784f5ba50963a242b4b35db77533786f618b3f6a9effdee2af20af4917a3b7cf12533b4575d7f9c163886be1fb62 + languageName: node + linkType: hard + +"get-port@npm:^7.1.0": + version: 7.2.0 + resolution: "get-port@npm:7.2.0" + checksum: 10c0/4ed741d9008ad15a24e2098c8971918025cc8241624245e704ecc62bb65160db5c79de5d7112acdaabccbe0714cd0704008c74d43a1f7a24a5875e58b84621be + languageName: node + linkType: hard + +"get-proto@npm:^1.0.1": + version: 1.0.1 + resolution: "get-proto@npm:1.0.1" + dependencies: + dunder-proto: "npm:^1.0.1" + es-object-atoms: "npm:^1.0.0" + checksum: 10c0/9224acb44603c5526955e83510b9da41baf6ae73f7398875fba50edc5e944223a89c4a72b070fcd78beb5f7bdda58ecb6294adc28f7acfc0da05f76a2399643c + languageName: node + linkType: hard + +"get-stream@npm:6.0.0": + version: 6.0.0 + resolution: "get-stream@npm:6.0.0" + checksum: 10c0/7cd835cb9180041e7be2cc3de236e5db9f2144515921aeb60ae78d3a46f9944439d654c2aae5b0191e41eb6e2500f0237494a2e6c0790367183f788d1c9f6dd6 + languageName: node + linkType: hard + +"get-stream@npm:^6.0.0": + version: 6.0.1 + resolution: "get-stream@npm:6.0.1" + checksum: 10c0/49825d57d3fd6964228e6200a58169464b8e8970489b3acdc24906c782fb7f01f9f56f8e6653c4a50713771d6658f7cfe051e5eb8c12e334138c9c918b296341 + languageName: node + linkType: hard + +"git-raw-commits@npm:^3.0.0": + version: 3.0.0 + resolution: "git-raw-commits@npm:3.0.0" + dependencies: + dargs: "npm:^7.0.0" + meow: "npm:^8.1.2" + split2: "npm:^3.2.2" + bin: + git-raw-commits: cli.js + checksum: 10c0/2a5db2e4b5b1ef7b6ecbdc175e559920a5400cbdb8d36f130aaef3588bfd74d8650b354a51ff89e0929eadbb265a00078a6291ff26248a525f0b2f079b001bf6 + languageName: node + linkType: hard + +"git-remote-origin-url@npm:^2.0.0": + version: 2.0.0 + resolution: "git-remote-origin-url@npm:2.0.0" + dependencies: + gitconfiglocal: "npm:^1.0.0" + pify: "npm:^2.3.0" + checksum: 10c0/3a846ce98ed36b2d0b801e8ec1ab299a236cfc6fa264bfdf9f42301abfdfd8715c946507fd83a10b9db449eb609ac6f8a2a341daf52e3af0000367487f486355 + languageName: node + linkType: hard + +"git-semver-tags@npm:^5.0.0": + version: 5.0.1 + resolution: "git-semver-tags@npm:5.0.1" + dependencies: + meow: "npm:^8.1.2" + semver: "npm:^7.0.0" + bin: + git-semver-tags: cli.js + checksum: 10c0/7cacba2f4ac19c0ccb8e6bb7301409376e5a2cc178692667afff453e6fe81f79b5f3f5040343e2be127a2f34977528d354de2aa32430917e90b64884debd3102 + languageName: node + linkType: hard + +"git-up@npm:^7.0.0": + version: 7.0.0 + resolution: "git-up@npm:7.0.0" + dependencies: + is-ssh: "npm:^1.4.0" + parse-url: "npm:^8.1.0" + checksum: 10c0/a3fa02e1a63c7c824b5ebbf23f4a9a6b34dd80031114c5dd8adb7ef53493642e39d3d80dfef4025a452128400c35c2c138d20a0f6ae5d7d7ef70d9ba13083d34 + languageName: node + linkType: hard + +"git-url-parse@npm:14.0.0": + version: 14.0.0 + resolution: "git-url-parse@npm:14.0.0" + dependencies: + git-up: "npm:^7.0.0" + checksum: 10c0/d360cf23c6278e302b74603f3dc490c3fe22e533d58b7f35e0295fad9af209ce5046a55950ccbf2f0d18de7931faefb4353e3f3fd3dda87fce77b409d48e0ba9 + languageName: node + linkType: hard + +"gitconfiglocal@npm:^1.0.0": + version: 1.0.0 + resolution: "gitconfiglocal@npm:1.0.0" + dependencies: + ini: "npm:^1.3.2" + checksum: 10c0/cfcb16344834113199f209f2758ced778dc30e075ddb49b5dde659b4dd2deadee824db0a1b77e1303cb594d9e8b2240da18c67705f657aa76affb444aa349005 + languageName: node + linkType: hard + +"glob-parent@npm:6.0.2, glob-parent@npm:^6.0.2": + version: 6.0.2 + resolution: "glob-parent@npm:6.0.2" + dependencies: + is-glob: "npm:^4.0.3" + checksum: 10c0/317034d88654730230b3f43bb7ad4f7c90257a426e872ea0bf157473ac61c99bf5d205fad8f0185f989be8d2fa6d3c7dce1645d99d545b6ea9089c39f838e7f8 + languageName: node + linkType: hard + +"glob@npm:^10.0.0, glob@npm:^10.5.0": + version: 10.5.0 + resolution: "glob@npm:10.5.0" + dependencies: + foreground-child: "npm:^3.1.0" + jackspeak: "npm:^3.1.2" + minimatch: "npm:^9.0.4" + minipass: "npm:^7.1.2" + package-json-from-dist: "npm:^1.0.0" + path-scurry: "npm:^1.11.1" + bin: + glob: dist/esm/bin.mjs + checksum: 10c0/100705eddbde6323e7b35e1d1ac28bcb58322095bd8e63a7d0bef1a2cdafe0d0f7922a981b2b48369a4f8c1b077be5c171804534c3509dfe950dde15fbe6d828 + languageName: node + linkType: hard + +"glob@npm:^11.0.3": + version: 11.1.0 + resolution: "glob@npm:11.1.0" + dependencies: + foreground-child: "npm:^3.3.1" + jackspeak: "npm:^4.1.1" + minimatch: "npm:^10.1.1" + minipass: "npm:^7.1.2" + package-json-from-dist: "npm:^1.0.0" + path-scurry: "npm:^2.0.0" + bin: + glob: dist/esm/bin.mjs + checksum: 10c0/1ceae07f23e316a6fa74581d9a74be6e8c2e590d2f7205034dd5c0435c53f5f7b712c2be00c3b65bf0a49294a1c6f4b98cd84c7637e29453b5aa13b79f1763a2 + languageName: node + linkType: hard + +"glob@npm:^13.0.0": + version: 13.0.6 + resolution: "glob@npm:13.0.6" + dependencies: + minimatch: "npm:^10.2.2" + minipass: "npm:^7.1.3" + path-scurry: "npm:^2.0.2" + checksum: 10c0/269c236f11a9b50357fe7a8c6aadac667e01deb5242b19c84975628f05f4438d8ee1354bb62c5d6c10f37fd59911b54d7799730633a2786660d8c69f1d18120a + languageName: node + linkType: hard + +"glob@npm:^7.1.3, glob@npm:^7.1.4": + version: 7.2.3 + resolution: "glob@npm:7.2.3" + dependencies: + fs.realpath: "npm:^1.0.0" + inflight: "npm:^1.0.4" + inherits: "npm:2" + minimatch: "npm:^3.1.1" + once: "npm:^1.3.0" + path-is-absolute: "npm:^1.0.0" + checksum: 10c0/65676153e2b0c9095100fe7f25a778bf45608eeb32c6048cf307f579649bcc30353277b3b898a3792602c65764e5baa4f643714dfbdfd64ea271d210c7a425fe + languageName: node + linkType: hard + +"globals@npm:^14.0.0": + version: 14.0.0 + resolution: "globals@npm:14.0.0" + checksum: 10c0/b96ff42620c9231ad468d4c58ff42afee7777ee1c963013ff8aabe095a451d0ceeb8dcd8ef4cbd64d2538cef45f787a78ba3a9574f4a634438963e334471302d + languageName: node + linkType: hard + +"gopd@npm:^1.2.0": + version: 1.2.0 + resolution: "gopd@npm:1.2.0" + checksum: 10c0/50fff1e04ba2b7737c097358534eacadad1e68d24cccee3272e04e007bed008e68d2614f3987788428fd192a5ae3889d08fb2331417e4fc4a9ab366b2043cead + languageName: node + linkType: hard + +"graceful-fs@npm:^4.1.15, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": + version: 4.2.11 + resolution: "graceful-fs@npm:4.2.11" + checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 + languageName: node + linkType: hard + +"handlebars@npm:^4.7.7, handlebars@npm:^4.7.9": + version: 4.7.9 + resolution: "handlebars@npm:4.7.9" + dependencies: + minimist: "npm:^1.2.5" + neo-async: "npm:^2.6.2" + source-map: "npm:^0.6.1" + uglify-js: "npm:^3.1.4" + wordwrap: "npm:^1.0.0" + dependenciesMeta: + uglify-js: + optional: true + bin: + handlebars: bin/handlebars + checksum: 10c0/22f8105a7e68e81aff2662bb434edf05f757d21d850731d71cec886d69c10cd33d3c43e34b2892968ec62de8241611851d3d0674c8ef324ea3e01dc66262faa9 + languageName: node + linkType: hard + +"hard-rejection@npm:^2.1.0": + version: 2.1.0 + resolution: "hard-rejection@npm:2.1.0" + checksum: 10c0/febc3343a1ad575aedcc112580835b44a89a89e01f400b4eda6e8110869edfdab0b00cd1bd4c3bfec9475a57e79e0b355aecd5be46454b6a62b9a359af60e564 + languageName: node + linkType: hard + +"harmony-reflect@npm:^1.4.6": + version: 1.6.2 + resolution: "harmony-reflect@npm:1.6.2" + checksum: 10c0/fa5b251fbeff0e2d925f0bfb5ffe39e0627639e998c453562d6a39e41789c15499649dc022178c807cf99bfb97e7b974bbbc031ba82078a26be7b098b9bc2b1a + languageName: node + linkType: hard + +"has-flag@npm:^4.0.0": + version: 4.0.0 + resolution: "has-flag@npm:4.0.0" + checksum: 10c0/2e789c61b7888d66993e14e8331449e525ef42aac53c627cc53d1c3334e768bcb6abdc4f5f0de1478a25beec6f0bd62c7549058b7ac53e924040d4f301f02fd1 + languageName: node + linkType: hard + +"has-symbols@npm:^1.0.3, has-symbols@npm:^1.1.0": + version: 1.1.0 + resolution: "has-symbols@npm:1.1.0" + checksum: 10c0/dde0a734b17ae51e84b10986e651c664379018d10b91b6b0e9b293eddb32f0f069688c841fb40f19e9611546130153e0a2a48fd7f512891fb000ddfa36f5a20e + languageName: node + linkType: hard + +"has-tostringtag@npm:^1.0.2": + version: 1.0.2 + resolution: "has-tostringtag@npm:1.0.2" + dependencies: + has-symbols: "npm:^1.0.3" + checksum: 10c0/a8b166462192bafe3d9b6e420a1d581d93dd867adb61be223a17a8d6dad147aa77a8be32c961bb2f27b3ef893cae8d36f564ab651f5e9b7938ae86f74027c48c + languageName: node + linkType: hard + +"has-unicode@npm:2.0.1": + version: 2.0.1 + resolution: "has-unicode@npm:2.0.1" + checksum: 10c0/ebdb2f4895c26bb08a8a100b62d362e49b2190bcfd84b76bc4be1a3bd4d254ec52d0dd9f2fbcc093fc5eb878b20c52146f9dfd33e2686ed28982187be593b47c + languageName: node + linkType: hard + +"hasown@npm:^2.0.2": + version: 2.0.2 + resolution: "hasown@npm:2.0.2" + dependencies: + function-bind: "npm:^1.1.2" + checksum: 10c0/3769d434703b8ac66b209a4cca0737519925bbdb61dd887f93a16372b14694c63ff4e797686d87c90f08168e81082248b9b028bad60d4da9e0d1148766f56eb9 + languageName: node + linkType: hard + +"hono@npm:^4.11.4": + version: 4.12.10 + resolution: "hono@npm:4.12.10" + checksum: 10c0/3fed7c0c0847968ae51910dd06bc4b64cc336af24ee913efdc105de80b467ddaa9e4f03a2814cb73771622eabbe3e7699998dc0536fe35acb0bac9f5d0e67aa1 + languageName: node + linkType: hard + +"hosted-git-info@npm:^2.1.4": + version: 2.8.9 + resolution: "hosted-git-info@npm:2.8.9" + checksum: 10c0/317cbc6b1bbbe23c2a40ae23f3dafe9fa349ce42a89a36f930e3f9c0530c179a3882d2ef1e4141a4c3674d6faaea862138ec55b43ad6f75e387fda2483a13c70 + languageName: node + linkType: hard + +"hosted-git-info@npm:^4.0.0, hosted-git-info@npm:^4.0.1": + version: 4.1.0 + resolution: "hosted-git-info@npm:4.1.0" + dependencies: + lru-cache: "npm:^6.0.0" + checksum: 10c0/150fbcb001600336d17fdbae803264abed013548eea7946c2264c49ebe2ebd8c4441ba71dd23dd8e18c65de79d637f98b22d4760ba5fb2e0b15d62543d0fff07 + languageName: node + linkType: hard + +"hosted-git-info@npm:^8.0.0": + version: 8.1.0 + resolution: "hosted-git-info@npm:8.1.0" + dependencies: + lru-cache: "npm:^10.0.1" + checksum: 10c0/53cc838ecaa7d4aa69a81d9d8edc362c9d415f67b76ad38cdd781d2a2f5b45ad0aa9f9b013fb4ea54a9f64fd2365d0b6386b5a24bdf4cb90c80477cf3175aaa2 + languageName: node + linkType: hard + +"hosted-git-info@npm:^9.0.0": + version: 9.0.2 + resolution: "hosted-git-info@npm:9.0.2" + dependencies: + lru-cache: "npm:^11.1.0" + checksum: 10c0/6c616339b61a103e3de4fef2776bc2b797767c3ed58fc2e3bb2e3b49294740c8c5ec3dde2d6440b09729e5a1d661dab6bacf54fdec46d1c466407a8df045d7a1 + languageName: node + linkType: hard + +"html-escaper@npm:^2.0.0": + version: 2.0.2 + resolution: "html-escaper@npm:2.0.2" + checksum: 10c0/208e8a12de1a6569edbb14544f4567e6ce8ecc30b9394fcaa4e7bb1e60c12a7c9a1ed27e31290817157e8626f3a4f29e76c8747030822eb84a6abb15c255f0a0 + languageName: node + linkType: hard + +"http-cache-semantics@npm:^4.1.1": + version: 4.2.0 + resolution: "http-cache-semantics@npm:4.2.0" + checksum: 10c0/45b66a945cf13ec2d1f29432277201313babf4a01d9e52f44b31ca923434083afeca03f18417f599c9ab3d0e7b618ceb21257542338b57c54b710463b4a53e37 + languageName: node + linkType: hard + +"http-errors@npm:^2.0.0, http-errors@npm:^2.0.1, http-errors@npm:~2.0.0, http-errors@npm:~2.0.1": + version: 2.0.1 + resolution: "http-errors@npm:2.0.1" + dependencies: + depd: "npm:~2.0.0" + inherits: "npm:~2.0.4" + setprototypeof: "npm:~1.2.0" + statuses: "npm:~2.0.2" + toidentifier: "npm:~1.0.1" + checksum: 10c0/fb38906cef4f5c83952d97661fe14dc156cb59fe54812a42cd448fa57b5c5dfcb38a40a916957737bd6b87aab257c0648d63eb5b6a9ca9f548e105b6072712d4 + languageName: node + linkType: hard + +"http-proxy-agent@npm:^7.0.0": + version: 7.0.2 + resolution: "http-proxy-agent@npm:7.0.2" + dependencies: + agent-base: "npm:^7.1.0" + debug: "npm:^4.3.4" + checksum: 10c0/4207b06a4580fb85dd6dff521f0abf6db517489e70863dca1a0291daa7f2d3d2d6015a57bd702af068ea5cf9f1f6ff72314f5f5b4228d299c0904135d2aef921 + languageName: node + linkType: hard + +"https-proxy-agent@npm:^7.0.1, https-proxy-agent@npm:^7.0.6": + version: 7.0.6 + resolution: "https-proxy-agent@npm:7.0.6" + dependencies: + agent-base: "npm:^7.1.2" + debug: "npm:4" + checksum: 10c0/f729219bc735edb621fa30e6e84e60ee5d00802b8247aac0d7b79b0bd6d4b3294737a337b93b86a0bd9e68099d031858a39260c976dc14cdbba238ba1f8779ac + languageName: node + linkType: hard + +"human-signals@npm:^2.1.0": + version: 2.1.0 + resolution: "human-signals@npm:2.1.0" + checksum: 10c0/695edb3edfcfe9c8b52a76926cd31b36978782062c0ed9b1192b36bebc75c4c87c82e178dfcb0ed0fc27ca59d434198aac0bd0be18f5781ded775604db22304a + languageName: node + linkType: hard + +"humanize-ms@npm:^1.2.1": + version: 1.2.1 + resolution: "humanize-ms@npm:1.2.1" + dependencies: + ms: "npm:^2.0.0" + checksum: 10c0/f34a2c20161d02303c2807badec2f3b49cbfbbb409abd4f95a07377ae01cfe6b59e3d15ac609cffcd8f2521f0eb37b7e1091acf65da99aa2a4f1ad63c21e7e7a + languageName: node + linkType: hard + +"iconv-lite@npm:^0.6.2": + version: 0.6.3 + resolution: "iconv-lite@npm:0.6.3" + dependencies: + safer-buffer: "npm:>= 2.1.2 < 3.0.0" + checksum: 10c0/98102bc66b33fcf5ac044099d1257ba0b7ad5e3ccd3221f34dd508ab4070edff183276221684e1e0555b145fce0850c9f7d2b60a9fcac50fbb4ea0d6e845a3b1 + languageName: node + linkType: hard + +"iconv-lite@npm:^0.7.0, iconv-lite@npm:^0.7.2, iconv-lite@npm:~0.7.0": + version: 0.7.2 + resolution: "iconv-lite@npm:0.7.2" + dependencies: + safer-buffer: "npm:>= 2.1.2 < 3.0.0" + checksum: 10c0/3c228920f3bd307f56bf8363706a776f4a060eb042f131cd23855ceca962951b264d0997ab38a1ad340e1c5df8499ed26e1f4f0db6b2a2ad9befaff22f14b722 + languageName: node + linkType: hard + +"iconv-lite@npm:~0.4.24": + version: 0.4.24 + resolution: "iconv-lite@npm:0.4.24" + dependencies: + safer-buffer: "npm:>= 2.1.2 < 3" + checksum: 10c0/c6886a24cc00f2a059767440ec1bc00d334a89f250db8e0f7feb4961c8727118457e27c495ba94d082e51d3baca378726cd110aaf7ded8b9bbfd6a44760cf1d4 + languageName: node + linkType: hard + +"identity-obj-proxy@npm:3.0.0": + version: 3.0.0 + resolution: "identity-obj-proxy@npm:3.0.0" + dependencies: + harmony-reflect: "npm:^1.4.6" + checksum: 10c0/a3fc4de0042d7b45bf8652d5596c80b42139d8625c9cd6a8834e29e1b6dce8fccabd1228e08744b78677a19ceed7201a32fed8ca3dc3e4852e8fee24360a6cfc + languageName: node + linkType: hard + +"ieee754@npm:^1.1.13, ieee754@npm:^1.2.1": + version: 1.2.1 + resolution: "ieee754@npm:1.2.1" + checksum: 10c0/b0782ef5e0935b9f12883a2e2aa37baa75da6e66ce6515c168697b42160807d9330de9a32ec1ed73149aea02e0d822e572bca6f1e22bdcbd2149e13b050b17bb + languageName: node + linkType: hard + +"ignore-walk@npm:^8.0.0": + version: 8.0.0 + resolution: "ignore-walk@npm:8.0.0" + dependencies: + minimatch: "npm:^10.0.3" + checksum: 10c0/fec71d904adaaf233f2f5a67cc547857d960abe1f41a8b43f675617a322aabe9401fb9afa13aba825d21d91c454d5cad72ecba156e69443f3df40288d6ebd058 + languageName: node + linkType: hard + +"ignore@npm:^5.0.4, ignore@npm:^5.2.0": + version: 5.3.2 + resolution: "ignore@npm:5.3.2" + checksum: 10c0/f9f652c957983634ded1e7f02da3b559a0d4cc210fca3792cb67f1b153623c9c42efdc1c4121af171e295444459fc4a9201101fb041b1104a3c000bccb188337 + languageName: node + linkType: hard + +"ignore@npm:^7.0.5": + version: 7.0.5 + resolution: "ignore@npm:7.0.5" + checksum: 10c0/ae00db89fe873064a093b8999fe4cc284b13ef2a178636211842cceb650b9c3e390d3339191acb145d81ed5379d2074840cf0c33a20bdbd6f32821f79eb4ad5d + languageName: node + linkType: hard + +"immutable@npm:^4.3.0": + version: 4.3.8 + resolution: "immutable@npm:4.3.8" + checksum: 10c0/3de58996305a0faf6ef3fc0685f996c42653ad757760214f5aec7d4a6b59ea7abb882522c5f9a61776fae88c0b45e08eb77cbded5a4f57745ec7c63f9642e44b + languageName: node + linkType: hard + +"import-fresh@npm:^3.2.1, import-fresh@npm:^3.3.0": + version: 3.3.1 + resolution: "import-fresh@npm:3.3.1" + dependencies: + parent-module: "npm:^1.0.0" + resolve-from: "npm:^4.0.0" + checksum: 10c0/bf8cc494872fef783249709385ae883b447e3eb09db0ebd15dcead7d9afe7224dad7bd7591c6b73b0b19b3c0f9640eb8ee884f01cfaf2887ab995b0b36a0cbec + languageName: node + linkType: hard + +"import-local@npm:3.1.0": + version: 3.1.0 + resolution: "import-local@npm:3.1.0" + dependencies: + pkg-dir: "npm:^4.2.0" + resolve-cwd: "npm:^3.0.0" + bin: + import-local-fixture: fixtures/cli.js + checksum: 10c0/c67ecea72f775fe8684ca3d057e54bdb2ae28c14bf261d2607c269c18ea0da7b730924c06262eca9aed4b8ab31e31d65bc60b50e7296c85908a56e2f7d41ecd2 + languageName: node + linkType: hard + +"import-local@npm:^3.0.2": + version: 3.2.0 + resolution: "import-local@npm:3.2.0" + dependencies: + pkg-dir: "npm:^4.2.0" + resolve-cwd: "npm:^3.0.0" + bin: + import-local-fixture: fixtures/cli.js + checksum: 10c0/94cd6367a672b7e0cb026970c85b76902d2710a64896fa6de93bd5c571dd03b228c5759308959de205083e3b1c61e799f019c9e36ee8e9c523b993e1057f0433 + languageName: node + linkType: hard + +"imurmurhash@npm:^0.1.4": + version: 0.1.4 + resolution: "imurmurhash@npm:0.1.4" + checksum: 10c0/8b51313850dd33605c6c9d3fd9638b714f4c4c40250cff658209f30d40da60f78992fb2df5dabee4acf589a6a82bbc79ad5486550754bd9ec4e3fc0d4a57d6a6 + languageName: node + linkType: hard + +"indent-string@npm:^4.0.0": + version: 4.0.0 + resolution: "indent-string@npm:4.0.0" + checksum: 10c0/1e1904ddb0cb3d6cce7cd09e27a90184908b7a5d5c21b92e232c93579d314f0b83c246ffb035493d0504b1e9147ba2c9b21df0030f48673fba0496ecd698161f + languageName: node + linkType: hard + +"inflection@npm:^1.13.4": + version: 1.13.4 + resolution: "inflection@npm:1.13.4" + checksum: 10c0/4c579b9ca0079d3f1ae5bca106f009553db3178e5ca46ff6872b270c07fa0a826787be6c50367a2186a578bc9a321d3071fcb5d8ca6d0c63eb8ecbb34f4fdee2 + languageName: node + linkType: hard + +"inflight@npm:^1.0.4": + version: 1.0.6 + resolution: "inflight@npm:1.0.6" + dependencies: + once: "npm:^1.3.0" + wrappy: "npm:1" + checksum: 10c0/7faca22584600a9dc5b9fca2cd5feb7135ac8c935449837b315676b4c90aa4f391ec4f42240178244b5a34e8bede1948627fda392ca3191522fc46b34e985ab2 + languageName: node + linkType: hard + +"inherits@npm:2, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3, inherits@npm:~2.0.4": + version: 2.0.4 + resolution: "inherits@npm:2.0.4" + checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 + languageName: node + linkType: hard + +"ini@npm:^1.3.2, ini@npm:^1.3.8": + version: 1.3.8 + resolution: "ini@npm:1.3.8" + checksum: 10c0/ec93838d2328b619532e4f1ff05df7909760b6f66d9c9e2ded11e5c1897d6f2f9980c54dd638f88654b00919ce31e827040631eab0a3969e4d1abefa0719516a + languageName: node + linkType: hard + +"ini@npm:^5.0.0": + version: 5.0.0 + resolution: "ini@npm:5.0.0" + checksum: 10c0/657491ce766cbb4b335ab221ee8f72b9654d9f0e35c32fe5ff2eb7ab8c5ce72237ff6456555b50cde88e6507a719a70e28e327b450782b4fc20c90326ec8c1a8 + languageName: node + linkType: hard + +"ini@npm:^6.0.0": + version: 6.0.0 + resolution: "ini@npm:6.0.0" + checksum: 10c0/9a7f55f306e2b25b41ae67c8b526e8f4673f057b70852b9025816ef4f15f07bf1ba35ed68ea4471ff7b31718f7ef1bc50d709f8d03cb012e10a3135eb99c7206 + languageName: node + linkType: hard + +"init-package-json@npm:8.2.2": + version: 8.2.2 + resolution: "init-package-json@npm:8.2.2" + dependencies: + "@npmcli/package-json": "npm:^7.0.0" + npm-package-arg: "npm:^13.0.0" + promzard: "npm:^2.0.0" + read: "npm:^4.0.0" + semver: "npm:^7.7.2" + validate-npm-package-license: "npm:^3.0.4" + validate-npm-package-name: "npm:^6.0.2" + checksum: 10c0/e4c1f2d4cf22d58fe6fc9b917d597337041ec0ac6e5c45bd164456b1db4f8a9b5dbb17bdf375e4b6eee3e527817e01ed8010f748d8ebeed8a7c9bf50a9e8ff1a + languageName: node + linkType: hard + +"inquirer@npm:12.9.6": + version: 12.9.6 + resolution: "inquirer@npm:12.9.6" + dependencies: + "@inquirer/ansi": "npm:^1.0.0" + "@inquirer/core": "npm:^10.2.2" + "@inquirer/prompts": "npm:^7.8.6" + "@inquirer/type": "npm:^3.0.8" + mute-stream: "npm:^2.0.0" + run-async: "npm:^4.0.5" + rxjs: "npm:^7.8.2" + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/068d9acbfab5e0c19d68603f86e296d00a8c797b6c2d7f2e659dfc557176e9247c2313beaf79d5557deb7d76a514cf9a75835c7928094b8759570b7a4e3f909f + languageName: node + linkType: hard + +"ioredis@npm:5.10.1": + version: 5.10.1 + resolution: "ioredis@npm:5.10.1" + dependencies: + "@ioredis/commands": "npm:1.5.1" + cluster-key-slot: "npm:^1.1.0" + debug: "npm:^4.3.4" + denque: "npm:^2.1.0" + lodash.defaults: "npm:^4.2.0" + lodash.isarguments: "npm:^3.1.0" + redis-errors: "npm:^1.2.0" + redis-parser: "npm:^3.0.0" + standard-as-callback: "npm:^2.1.0" + checksum: 10c0/d0507b52520d3bdd5dacaa33aed9dd3133794d8633b43a6b7fc3199a5e73f92cb77409f6904abe68e3221a95a630d97073b8c1c9e2c0c7613124db67e97c0eb0 + languageName: node + linkType: hard + +"ip-address@npm:10.1.0, ip-address@npm:^10.0.1": + version: 10.1.0 + resolution: "ip-address@npm:10.1.0" + checksum: 10c0/0103516cfa93f6433b3bd7333fa876eb21263912329bfa47010af5e16934eeeff86f3d2ae700a3744a137839ddfad62b900c7a445607884a49b5d1e32a3d7566 + languageName: node + linkType: hard + +"ipaddr.js@npm:1.9.1": + version: 1.9.1 + resolution: "ipaddr.js@npm:1.9.1" + checksum: 10c0/0486e775047971d3fdb5fb4f063829bac45af299ae0b82dcf3afa2145338e08290563a2a70f34b732d795ecc8311902e541a8530eeb30d75860a78ff4e94ce2a + languageName: node + linkType: hard + +"is-arrayish@npm:^0.2.1": + version: 0.2.1 + resolution: "is-arrayish@npm:0.2.1" + checksum: 10c0/e7fb686a739068bb70f860b39b67afc62acc62e36bb61c5f965768abce1873b379c563e61dd2adad96ebb7edf6651111b385e490cf508378959b0ed4cac4e729 + languageName: node + linkType: hard + +"is-ci@npm:3.0.1": + version: 3.0.1 + resolution: "is-ci@npm:3.0.1" + dependencies: + ci-info: "npm:^3.2.0" + bin: + is-ci: bin.js + checksum: 10c0/0e81caa62f4520d4088a5bef6d6337d773828a88610346c4b1119fb50c842587ed8bef1e5d9a656835a599e7209405b5761ddf2339668f2d0f4e889a92fe6051 + languageName: node + linkType: hard + +"is-core-module@npm:^2.16.1, is-core-module@npm:^2.5.0": + version: 2.16.1 + resolution: "is-core-module@npm:2.16.1" + dependencies: + hasown: "npm:^2.0.2" + checksum: 10c0/898443c14780a577e807618aaae2b6f745c8538eca5c7bc11388a3f2dc6de82b9902bcc7eb74f07be672b11bbe82dd6a6edded44a00cb3d8f933d0459905eedd + languageName: node + linkType: hard + +"is-docker@npm:^2.0.0, is-docker@npm:^2.1.1": + version: 2.2.1 + resolution: "is-docker@npm:2.2.1" + bin: + is-docker: cli.js + checksum: 10c0/e828365958d155f90c409cdbe958f64051d99e8aedc2c8c4cd7c89dcf35329daed42f7b99346f7828df013e27deb8f721cf9408ba878c76eb9e8290235fbcdcc + languageName: node + linkType: hard + +"is-extglob@npm:^2.1.1": + version: 2.1.1 + resolution: "is-extglob@npm:2.1.1" + checksum: 10c0/5487da35691fbc339700bbb2730430b07777a3c21b9ebaecb3072512dfd7b4ba78ac2381a87e8d78d20ea08affb3f1971b4af629173a6bf435ff8a4c47747912 + languageName: node + linkType: hard + +"is-fullwidth-code-point@npm:^3.0.0": + version: 3.0.0 + resolution: "is-fullwidth-code-point@npm:3.0.0" + checksum: 10c0/bb11d825e049f38e04c06373a8d72782eee0205bda9d908cc550ccb3c59b99d750ff9537982e01733c1c94a58e35400661f57042158ff5e8f3e90cf936daf0fc + languageName: node + linkType: hard + +"is-generator-fn@npm:^2.0.0, is-generator-fn@npm:^2.1.0": + version: 2.1.0 + resolution: "is-generator-fn@npm:2.1.0" + checksum: 10c0/2957cab387997a466cd0bf5c1b6047bd21ecb32bdcfd8996b15747aa01002c1c88731802f1b3d34ac99f4f6874b626418bd118658cf39380fe5fff32a3af9c4d + languageName: node + linkType: hard + +"is-glob@npm:^4.0.0, is-glob@npm:^4.0.3": + version: 4.0.3 + resolution: "is-glob@npm:4.0.3" + dependencies: + is-extglob: "npm:^2.1.1" + checksum: 10c0/17fb4014e22be3bbecea9b2e3a76e9e34ff645466be702f1693e8f1ee1adac84710d0be0bd9f967d6354036fd51ab7c2741d954d6e91dae6bb69714de92c197a + languageName: node + linkType: hard + +"is-interactive@npm:^1.0.0": + version: 1.0.0 + resolution: "is-interactive@npm:1.0.0" + checksum: 10c0/dd47904dbf286cd20aa58c5192161be1a67138485b9836d5a70433b21a45442e9611b8498b8ab1f839fc962c7620667a50535fdfb4a6bc7989b8858645c06b4d + languageName: node + linkType: hard + +"is-number@npm:^7.0.0": + version: 7.0.0 + resolution: "is-number@npm:7.0.0" + checksum: 10c0/b4686d0d3053146095ccd45346461bc8e53b80aeb7671cc52a4de02dbbf7dc0d1d2a986e2fe4ae206984b4d34ef37e8b795ebc4f4295c978373e6575e295d811 + languageName: node + linkType: hard + +"is-obj@npm:^2.0.0": + version: 2.0.0 + resolution: "is-obj@npm:2.0.0" + checksum: 10c0/85044ed7ba8bd169e2c2af3a178cacb92a97aa75de9569d02efef7f443a824b5e153eba72b9ae3aca6f8ce81955271aa2dc7da67a8b720575d3e38104208cb4e + languageName: node + linkType: hard + +"is-plain-obj@npm:^1.1.0": + version: 1.1.0 + resolution: "is-plain-obj@npm:1.1.0" + checksum: 10c0/daaee1805add26f781b413fdf192fc91d52409583be30ace35c82607d440da63cc4cac0ac55136716688d6c0a2c6ef3edb2254fecbd1fe06056d6bd15975ee8c + languageName: node + linkType: hard + +"is-promise@npm:^4.0.0": + version: 4.0.0 + resolution: "is-promise@npm:4.0.0" + checksum: 10c0/ebd5c672d73db781ab33ccb155fb9969d6028e37414d609b115cc534654c91ccd061821d5b987eefaa97cf4c62f0b909bb2f04db88306de26e91bfe8ddc01503 + languageName: node + linkType: hard + +"is-ssh@npm:^1.4.0": + version: 1.4.1 + resolution: "is-ssh@npm:1.4.1" + dependencies: + protocols: "npm:^2.0.1" + checksum: 10c0/021a7355cb032625d58db3cc8266ad9aa698cbabf460b71376a0307405577fd7d3aa0826c0bf1951d7809f134c0ee80403306f6d7633db94a5a3600a0106b398 + languageName: node + linkType: hard + +"is-stream@npm:^2.0.0, is-stream@npm:^2.0.1": + version: 2.0.1 + resolution: "is-stream@npm:2.0.1" + checksum: 10c0/7c284241313fc6efc329b8d7f08e16c0efeb6baab1b4cd0ba579eb78e5af1aa5da11e68559896a2067cd6c526bd29241dda4eb1225e627d5aa1a89a76d4635a5 + languageName: node + linkType: hard + +"is-text-path@npm:^1.0.1": + version: 1.0.1 + resolution: "is-text-path@npm:1.0.1" + dependencies: + text-extensions: "npm:^1.0.0" + checksum: 10c0/61c8650c29548febb6bf69e9541fc11abbbb087a0568df7bc471ba264e95fb254def4e610631cbab4ddb0a1a07949d06416f4ebeaf37875023fb184cdb87ee84 + languageName: node + linkType: hard + +"is-unicode-supported@npm:^0.1.0": + version: 0.1.0 + resolution: "is-unicode-supported@npm:0.1.0" + checksum: 10c0/00cbe3455c3756be68d2542c416cab888aebd5012781d6819749fefb15162ff23e38501fe681b3d751c73e8ff561ac09a5293eba6f58fdf0178462ce6dcb3453 + languageName: node + linkType: hard + +"is-wsl@npm:^2.2.0": + version: 2.2.0 + resolution: "is-wsl@npm:2.2.0" + dependencies: + is-docker: "npm:^2.0.0" + checksum: 10c0/a6fa2d370d21be487c0165c7a440d567274fbba1a817f2f0bfa41cc5e3af25041d84267baa22df66696956038a43973e72fca117918c91431920bdef490fa25e + languageName: node + linkType: hard + +"isarray@npm:~1.0.0": + version: 1.0.0 + resolution: "isarray@npm:1.0.0" + checksum: 10c0/18b5be6669be53425f0b84098732670ed4e727e3af33bc7f948aac01782110eb9a18b3b329c5323bcdd3acdaae547ee077d3951317e7f133bff7105264b3003d + languageName: node + linkType: hard + +"isexe@npm:^2.0.0": + version: 2.0.0 + resolution: "isexe@npm:2.0.0" + checksum: 10c0/228cfa503fadc2c31596ab06ed6aa82c9976eec2bfd83397e7eaf06d0ccf42cd1dfd6743bf9aeb01aebd4156d009994c5f76ea898d2832c1fe342da923ca457d + languageName: node + linkType: hard + +"isexe@npm:^3.1.1": + version: 3.1.5 + resolution: "isexe@npm:3.1.5" + checksum: 10c0/8be2973a09f2f804ea1f34bfccfd5ea219ef48083bdb12107fe5bcf96b3e36b85084409e1b09ddaf2fae8927fdd9f6d70d90baadb78caa1ca7c530935706c8a4 + languageName: node + linkType: hard + +"isexe@npm:^4.0.0": + version: 4.0.0 + resolution: "isexe@npm:4.0.0" + checksum: 10c0/5884815115bceac452877659a9c7726382531592f43dc29e5d48b7c4100661aed54018cb90bd36cb2eaeba521092570769167acbb95c18d39afdccbcca06c5ce + languageName: node + linkType: hard + +"istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.0": + version: 3.2.2 + resolution: "istanbul-lib-coverage@npm:3.2.2" + checksum: 10c0/6c7ff2106769e5f592ded1fb418f9f73b4411fd5a084387a5410538332b6567cd1763ff6b6cadca9b9eb2c443cce2f7ea7d7f1b8d315f9ce58539793b1e0922b + languageName: node + linkType: hard + +"istanbul-lib-instrument@npm:^5.0.4": + version: 5.2.1 + resolution: "istanbul-lib-instrument@npm:5.2.1" + dependencies: + "@babel/core": "npm:^7.12.3" + "@babel/parser": "npm:^7.14.7" + "@istanbuljs/schema": "npm:^0.1.2" + istanbul-lib-coverage: "npm:^3.2.0" + semver: "npm:^6.3.0" + checksum: 10c0/8a1bdf3e377dcc0d33ec32fe2b6ecacdb1e4358fd0eb923d4326bb11c67622c0ceb99600a680f3dad5d29c66fc1991306081e339b4d43d0b8a2ab2e1d910a6ee + languageName: node + linkType: hard + +"istanbul-lib-instrument@npm:^6.0.0, istanbul-lib-instrument@npm:^6.0.2": + version: 6.0.3 + resolution: "istanbul-lib-instrument@npm:6.0.3" + dependencies: + "@babel/core": "npm:^7.23.9" + "@babel/parser": "npm:^7.23.9" + "@istanbuljs/schema": "npm:^0.1.3" + istanbul-lib-coverage: "npm:^3.2.0" + semver: "npm:^7.5.4" + checksum: 10c0/a1894e060dd2a3b9f046ffdc87b44c00a35516f5e6b7baf4910369acca79e506fc5323a816f811ae23d82334b38e3ddeb8b3b331bd2c860540793b59a8689128 + languageName: node + linkType: hard + +"istanbul-lib-report@npm:^3.0.0": + version: 3.0.1 + resolution: "istanbul-lib-report@npm:3.0.1" + dependencies: + istanbul-lib-coverage: "npm:^3.0.0" + make-dir: "npm:^4.0.0" + supports-color: "npm:^7.1.0" + checksum: 10c0/84323afb14392de8b6a5714bd7e9af845cfbd56cfe71ed276cda2f5f1201aea673c7111901227ee33e68e4364e288d73861eb2ed48f6679d1e69a43b6d9b3ba7 + languageName: node + linkType: hard + +"istanbul-lib-source-maps@npm:^4.0.0": + version: 4.0.1 + resolution: "istanbul-lib-source-maps@npm:4.0.1" + dependencies: + debug: "npm:^4.1.1" + istanbul-lib-coverage: "npm:^3.0.0" + source-map: "npm:^0.6.1" + checksum: 10c0/19e4cc405016f2c906dff271a76715b3e881fa9faeb3f09a86cb99b8512b3a5ed19cadfe0b54c17ca0e54c1142c9c6de9330d65506e35873994e06634eebeb66 + languageName: node + linkType: hard + +"istanbul-lib-source-maps@npm:^5.0.0": + version: 5.0.6 + resolution: "istanbul-lib-source-maps@npm:5.0.6" + dependencies: + "@jridgewell/trace-mapping": "npm:^0.3.23" + debug: "npm:^4.1.1" + istanbul-lib-coverage: "npm:^3.0.0" + checksum: 10c0/ffe75d70b303a3621ee4671554f306e0831b16f39ab7f4ab52e54d356a5d33e534d97563e318f1333a6aae1d42f91ec49c76b6cd3f3fb378addcb5c81da0255f + languageName: node + linkType: hard + +"istanbul-reports@npm:^3.1.3": + version: 3.2.0 + resolution: "istanbul-reports@npm:3.2.0" + dependencies: + html-escaper: "npm:^2.0.0" + istanbul-lib-report: "npm:^3.0.0" + checksum: 10c0/d596317cfd9c22e1394f22a8d8ba0303d2074fe2e971887b32d870e4b33f8464b10f8ccbe6847808f7db485f084eba09e6c2ed706b3a978e4b52f07085b8f9bc + languageName: node + linkType: hard + +"iterare@npm:1.2.1": + version: 1.2.1 + resolution: "iterare@npm:1.2.1" + checksum: 10c0/02667d486e3e83ead028ba8484d927498c2ceab7e8c6a69dd881fd02abc4114f00b13abb36b592252fbb578b6e6f99ca1dfc2835408b9158c9a112a9964f453f + languageName: node + linkType: hard + +"jackspeak@npm:^3.1.2": + version: 3.4.3 + resolution: "jackspeak@npm:3.4.3" + dependencies: + "@isaacs/cliui": "npm:^8.0.2" + "@pkgjs/parseargs": "npm:^0.11.0" + dependenciesMeta: + "@pkgjs/parseargs": + optional: true + checksum: 10c0/6acc10d139eaefdbe04d2f679e6191b3abf073f111edf10b1de5302c97ec93fffeb2fdd8681ed17f16268aa9dd4f8c588ed9d1d3bffbbfa6e8bf897cbb3149b9 + languageName: node + linkType: hard + +"jackspeak@npm:^4.1.1": + version: 4.2.3 + resolution: "jackspeak@npm:4.2.3" + dependencies: + "@isaacs/cliui": "npm:^9.0.0" + checksum: 10c0/b5c0c414f1607c2aa0597f4bf2c03b8443897fccd5fd3c2b3e4f77d556b2bc7c3d3413828ba91e0789f6fb40ad90242f7f89fb20aee9e9d705bc1681f7564f67 + languageName: node + linkType: hard + +"jake@npm:^10.8.5": + version: 10.9.4 + resolution: "jake@npm:10.9.4" + dependencies: + async: "npm:^3.2.6" + filelist: "npm:^1.0.4" + picocolors: "npm:^1.1.1" + bin: + jake: bin/cli.js + checksum: 10c0/bb52f000340d4a32f1a3893b9abe56ef2b77c25da4dbf2c0c874a8159d082dddda50a5ad10e26060198bd645b928ba8dba3b362710f46a247e335321188c5a9c + languageName: node + linkType: hard + +"jest-changed-files@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-changed-files@npm:29.7.0" + dependencies: + execa: "npm:^5.0.0" + jest-util: "npm:^29.7.0" + p-limit: "npm:^3.1.0" + checksum: 10c0/e071384d9e2f6bb462231ac53f29bff86f0e12394c1b49ccafbad225ce2ab7da226279a8a94f421949920bef9be7ef574fd86aee22e8adfa149be73554ab828b + languageName: node + linkType: hard + +"jest-circus@npm:30.3.0": + version: 30.3.0 + resolution: "jest-circus@npm:30.3.0" + dependencies: + "@jest/environment": "npm:30.3.0" + "@jest/expect": "npm:30.3.0" + "@jest/test-result": "npm:30.3.0" + "@jest/types": "npm:30.3.0" + "@types/node": "npm:*" + chalk: "npm:^4.1.2" + co: "npm:^4.6.0" + dedent: "npm:^1.6.0" + is-generator-fn: "npm:^2.1.0" + jest-each: "npm:30.3.0" + jest-matcher-utils: "npm:30.3.0" + jest-message-util: "npm:30.3.0" + jest-runtime: "npm:30.3.0" + jest-snapshot: "npm:30.3.0" + jest-util: "npm:30.3.0" + p-limit: "npm:^3.1.0" + pretty-format: "npm:30.3.0" + pure-rand: "npm:^7.0.0" + slash: "npm:^3.0.0" + stack-utils: "npm:^2.0.6" + checksum: 10c0/a3a0eb973699b400fb6de4207a7fbc5b33f51523e5e94f954d0e6e60418ea95099883614495fce54d805a321cb65e883592048b73203a59b8f4e53d1bb975a07 + languageName: node + linkType: hard + +"jest-circus@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-circus@npm:29.7.0" + dependencies: + "@jest/environment": "npm:^29.7.0" + "@jest/expect": "npm:^29.7.0" + "@jest/test-result": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + "@types/node": "npm:*" + chalk: "npm:^4.0.0" + co: "npm:^4.6.0" + dedent: "npm:^1.0.0" + is-generator-fn: "npm:^2.0.0" + jest-each: "npm:^29.7.0" + jest-matcher-utils: "npm:^29.7.0" + jest-message-util: "npm:^29.7.0" + jest-runtime: "npm:^29.7.0" + jest-snapshot: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + p-limit: "npm:^3.1.0" + pretty-format: "npm:^29.7.0" + pure-rand: "npm:^6.0.0" + slash: "npm:^3.0.0" + stack-utils: "npm:^2.0.3" + checksum: 10c0/8d15344cf7a9f14e926f0deed64ed190c7a4fa1ed1acfcd81e4cc094d3cc5bf7902ebb7b874edc98ada4185688f90c91e1747e0dfd7ac12463b097968ae74b5e + languageName: node + linkType: hard + +"jest-cli@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-cli@npm:29.7.0" + dependencies: + "@jest/core": "npm:^29.7.0" + "@jest/test-result": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + chalk: "npm:^4.0.0" + create-jest: "npm:^29.7.0" + exit: "npm:^0.1.2" + import-local: "npm:^3.0.2" + jest-config: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + jest-validate: "npm:^29.7.0" + yargs: "npm:^17.3.1" + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + bin: + jest: bin/jest.js + checksum: 10c0/a658fd55050d4075d65c1066364595962ead7661711495cfa1dfeecf3d6d0a8ffec532f3dbd8afbb3e172dd5fd2fb2e813c5e10256e7cf2fea766314942fb43a + languageName: node + linkType: hard + +"jest-config@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-config@npm:29.7.0" + dependencies: + "@babel/core": "npm:^7.11.6" + "@jest/test-sequencer": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + babel-jest: "npm:^29.7.0" + chalk: "npm:^4.0.0" + ci-info: "npm:^3.2.0" + deepmerge: "npm:^4.2.2" + glob: "npm:^7.1.3" + graceful-fs: "npm:^4.2.9" + jest-circus: "npm:^29.7.0" + jest-environment-node: "npm:^29.7.0" + jest-get-type: "npm:^29.6.3" + jest-regex-util: "npm:^29.6.3" + jest-resolve: "npm:^29.7.0" + jest-runner: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + jest-validate: "npm:^29.7.0" + micromatch: "npm:^4.0.4" + parse-json: "npm:^5.2.0" + pretty-format: "npm:^29.7.0" + slash: "npm:^3.0.0" + strip-json-comments: "npm:^3.1.1" + peerDependencies: + "@types/node": "*" + ts-node: ">=9.0.0" + peerDependenciesMeta: + "@types/node": + optional: true + ts-node: + optional: true + checksum: 10c0/bab23c2eda1fff06e0d104b00d6adfb1d1aabb7128441899c9bff2247bd26710b050a5364281ce8d52b46b499153bf7e3ee88b19831a8f3451f1477a0246a0f1 + languageName: node + linkType: hard + +"jest-config@npm:^30.0.2": + version: 30.3.0 + resolution: "jest-config@npm:30.3.0" + dependencies: + "@babel/core": "npm:^7.27.4" + "@jest/get-type": "npm:30.1.0" + "@jest/pattern": "npm:30.0.1" + "@jest/test-sequencer": "npm:30.3.0" + "@jest/types": "npm:30.3.0" + babel-jest: "npm:30.3.0" + chalk: "npm:^4.1.2" + ci-info: "npm:^4.2.0" + deepmerge: "npm:^4.3.1" + glob: "npm:^10.5.0" + graceful-fs: "npm:^4.2.11" + jest-circus: "npm:30.3.0" + jest-docblock: "npm:30.2.0" + jest-environment-node: "npm:30.3.0" + jest-regex-util: "npm:30.0.1" + jest-resolve: "npm:30.3.0" + jest-runner: "npm:30.3.0" + jest-util: "npm:30.3.0" + jest-validate: "npm:30.3.0" + parse-json: "npm:^5.2.0" + pretty-format: "npm:30.3.0" + slash: "npm:^3.0.0" + strip-json-comments: "npm:^3.1.1" + peerDependencies: + "@types/node": "*" + esbuild-register: ">=3.4.0" + ts-node: ">=9.0.0" + peerDependenciesMeta: + "@types/node": + optional: true + esbuild-register: + optional: true + ts-node: + optional: true + checksum: 10c0/157607e5ac5e83924df97d992fbd40a1540af07c5a7be296fae49455b3729687847304f3b4a9112e7da17593b76cec3453cd55c1ecd4334f7318f2489d7d10a1 + languageName: node + linkType: hard + +"jest-diff@npm:30.3.0, jest-diff@npm:>=30.0.0 < 31, jest-diff@npm:^30.0.2": + version: 30.3.0 + resolution: "jest-diff@npm:30.3.0" + dependencies: + "@jest/diff-sequences": "npm:30.3.0" + "@jest/get-type": "npm:30.1.0" + chalk: "npm:^4.1.2" + pretty-format: "npm:30.3.0" + checksum: 10c0/573a2a1a155b95fbde547d8ee33a5375179a8d03d4586025478dac16d695e4614aef075c3afa57e0f3a96cea8f638fa68a55c1e625f6e86b4f5b9e5850311ffb + languageName: node + linkType: hard + +"jest-diff@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-diff@npm:29.7.0" + dependencies: + chalk: "npm:^4.0.0" + diff-sequences: "npm:^29.6.3" + jest-get-type: "npm:^29.6.3" + pretty-format: "npm:^29.7.0" + checksum: 10c0/89a4a7f182590f56f526443dde69acefb1f2f0c9e59253c61d319569856c4931eae66b8a3790c443f529267a0ddba5ba80431c585deed81827032b2b2a1fc999 + languageName: node + linkType: hard + +"jest-docblock@npm:30.2.0": + version: 30.2.0 + resolution: "jest-docblock@npm:30.2.0" + dependencies: + detect-newline: "npm:^3.1.0" + checksum: 10c0/2578366604eef1b36d59ffe1fc52a710995571535d437f83d94ff94756a83f78e699c1ba004c38a34c01859d669fd6c64e865c23c5a7d5bf4837cfca4bef3dda + languageName: node + linkType: hard + +"jest-docblock@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-docblock@npm:29.7.0" + dependencies: + detect-newline: "npm:^3.0.0" + checksum: 10c0/d932a8272345cf6b6142bb70a2bb63e0856cc0093f082821577ea5bdf4643916a98744dfc992189d2b1417c38a11fa42466f6111526bc1fb81366f56410f3be9 + languageName: node + linkType: hard + +"jest-each@npm:30.3.0": + version: 30.3.0 + resolution: "jest-each@npm:30.3.0" + dependencies: + "@jest/get-type": "npm:30.1.0" + "@jest/types": "npm:30.3.0" + chalk: "npm:^4.1.2" + jest-util: "npm:30.3.0" + pretty-format: "npm:30.3.0" + checksum: 10c0/d23d2b43b3ea42beaf99648e2cf1c74b8a13c3e45c7c882979171471c225f7d666cb4a0d5f1ff9031b4504866fa3badc7266ffd885d3d8035420c559a31501e1 + languageName: node + linkType: hard + +"jest-each@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-each@npm:29.7.0" + dependencies: + "@jest/types": "npm:^29.6.3" + chalk: "npm:^4.0.0" + jest-get-type: "npm:^29.6.3" + jest-util: "npm:^29.7.0" + pretty-format: "npm:^29.7.0" + checksum: 10c0/f7f9a90ebee80cc688e825feceb2613627826ac41ea76a366fa58e669c3b2403d364c7c0a74d862d469b103c843154f8456d3b1c02b487509a12afa8b59edbb4 + languageName: node + linkType: hard + +"jest-environment-node@npm:30.3.0": + version: 30.3.0 + resolution: "jest-environment-node@npm:30.3.0" + dependencies: + "@jest/environment": "npm:30.3.0" + "@jest/fake-timers": "npm:30.3.0" + "@jest/types": "npm:30.3.0" + "@types/node": "npm:*" + jest-mock: "npm:30.3.0" + jest-util: "npm:30.3.0" + jest-validate: "npm:30.3.0" + checksum: 10c0/2a4be80861e569fa11456d89ff2aaedd71726ae02ade8f2cc6fbc86ba8749e24c37864676c4718fc08a40f6e6d2b2b51bc48d715b09b1e93e15e42e4a10f7b5b + languageName: node + linkType: hard + +"jest-environment-node@npm:^29, jest-environment-node@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-environment-node@npm:29.7.0" + dependencies: + "@jest/environment": "npm:^29.7.0" + "@jest/fake-timers": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + "@types/node": "npm:*" + jest-mock: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + checksum: 10c0/61f04fec077f8b1b5c1a633e3612fc0c9aa79a0ab7b05600683428f1e01a4d35346c474bde6f439f9fcc1a4aa9a2861ff852d079a43ab64b02105d1004b2592b + languageName: node + linkType: hard + +"jest-get-type@npm:^29.6.3": + version: 29.6.3 + resolution: "jest-get-type@npm:29.6.3" + checksum: 10c0/552e7a97a983d3c2d4e412a44eb7de0430ff773dd99f7500962c268d6dfbfa431d7d08f919c9d960530e5f7f78eb47f267ad9b318265e5092b3ff9ede0db7c2b + languageName: node + linkType: hard + +"jest-haste-map@npm:30.3.0": + version: 30.3.0 + resolution: "jest-haste-map@npm:30.3.0" + dependencies: + "@jest/types": "npm:30.3.0" + "@types/node": "npm:*" + anymatch: "npm:^3.1.3" + fb-watchman: "npm:^2.0.2" + fsevents: "npm:^2.3.3" + graceful-fs: "npm:^4.2.11" + jest-regex-util: "npm:30.0.1" + jest-util: "npm:30.3.0" + jest-worker: "npm:30.3.0" + picomatch: "npm:^4.0.3" + walker: "npm:^1.0.8" + dependenciesMeta: + fsevents: + optional: true + checksum: 10c0/b9ef350082b15d4c119d6188f781024d859d6cfb17ae25d15c90c3a373234e16109afbeffdcf1af4baf6a85eb0cbbab00439c981ad43037c0f05d89ff98bd1af + languageName: node + linkType: hard + +"jest-haste-map@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-haste-map@npm:29.7.0" + dependencies: + "@jest/types": "npm:^29.6.3" + "@types/graceful-fs": "npm:^4.1.3" + "@types/node": "npm:*" + anymatch: "npm:^3.0.3" + fb-watchman: "npm:^2.0.0" + fsevents: "npm:^2.3.2" + graceful-fs: "npm:^4.2.9" + jest-regex-util: "npm:^29.6.3" + jest-util: "npm:^29.7.0" + jest-worker: "npm:^29.7.0" + micromatch: "npm:^4.0.4" + walker: "npm:^1.0.8" + dependenciesMeta: + fsevents: + optional: true + checksum: 10c0/2683a8f29793c75a4728787662972fedd9267704c8f7ef9d84f2beed9a977f1cf5e998c07b6f36ba5603f53cb010c911fe8cd0ac9886e073fe28ca66beefd30c + languageName: node + linkType: hard + +"jest-leak-detector@npm:30.3.0": + version: 30.3.0 + resolution: "jest-leak-detector@npm:30.3.0" + dependencies: + "@jest/get-type": "npm:30.1.0" + pretty-format: "npm:30.3.0" + checksum: 10c0/a648c082b74e6c7d0c2e890002094ba97b108398fa3d0316958fc74321aa7b0824507a685d261a463856f219a724b86a6073bac86d351cf0675ecf962c1ee0ca + languageName: node + linkType: hard + +"jest-leak-detector@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-leak-detector@npm:29.7.0" + dependencies: + jest-get-type: "npm:^29.6.3" + pretty-format: "npm:^29.7.0" + checksum: 10c0/71bb9f77fc489acb842a5c7be030f2b9acb18574dc9fb98b3100fc57d422b1abc55f08040884bd6e6dbf455047a62f7eaff12aa4058f7cbdc11558718ca6a395 + languageName: node + linkType: hard + +"jest-matcher-utils@npm:30.3.0": + version: 30.3.0 + resolution: "jest-matcher-utils@npm:30.3.0" + dependencies: + "@jest/get-type": "npm:30.1.0" + chalk: "npm:^4.1.2" + jest-diff: "npm:30.3.0" + pretty-format: "npm:30.3.0" + checksum: 10c0/4c5f4b6435964110e64c4b5b42e3553fffe303ecdd68021147a7bcc72914aec3a899867c50db22b250c72aded53e3f7a9f64d83c9dca2e65ce27f36d23c6ca78 + languageName: node + linkType: hard + +"jest-matcher-utils@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-matcher-utils@npm:29.7.0" + dependencies: + chalk: "npm:^4.0.0" + jest-diff: "npm:^29.7.0" + jest-get-type: "npm:^29.6.3" + pretty-format: "npm:^29.7.0" + checksum: 10c0/0d0e70b28fa5c7d4dce701dc1f46ae0922102aadc24ed45d594dd9b7ae0a8a6ef8b216718d1ab79e451291217e05d4d49a82666e1a3cc2b428b75cd9c933244e + languageName: node + linkType: hard + +"jest-message-util@npm:30.3.0": + version: 30.3.0 + resolution: "jest-message-util@npm:30.3.0" + dependencies: + "@babel/code-frame": "npm:^7.27.1" + "@jest/types": "npm:30.3.0" + "@types/stack-utils": "npm:^2.0.3" + chalk: "npm:^4.1.2" + graceful-fs: "npm:^4.2.11" + picomatch: "npm:^4.0.3" + pretty-format: "npm:30.3.0" + slash: "npm:^3.0.0" + stack-utils: "npm:^2.0.6" + checksum: 10c0/6ce611caef76394872b23a111286b48e56f42655d14a5fbd0629d9b7437ed892e85ad96b15864bc22185c24ef670afb6665c57b9729458a36d50ffe8310f0926 + languageName: node + linkType: hard + +"jest-message-util@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-message-util@npm:29.7.0" + dependencies: + "@babel/code-frame": "npm:^7.12.13" + "@jest/types": "npm:^29.6.3" + "@types/stack-utils": "npm:^2.0.0" + chalk: "npm:^4.0.0" + graceful-fs: "npm:^4.2.9" + micromatch: "npm:^4.0.4" + pretty-format: "npm:^29.7.0" + slash: "npm:^3.0.0" + stack-utils: "npm:^2.0.3" + checksum: 10c0/850ae35477f59f3e6f27efac5215f706296e2104af39232bb14e5403e067992afb5c015e87a9243ec4d9df38525ef1ca663af9f2f4766aa116f127247008bd22 + languageName: node + linkType: hard + +"jest-mock@npm:30.3.0": + version: 30.3.0 + resolution: "jest-mock@npm:30.3.0" + dependencies: + "@jest/types": "npm:30.3.0" + "@types/node": "npm:*" + jest-util: "npm:30.3.0" + checksum: 10c0/9d95d550c6c998a85887c48ff5ee26de4bca18be91462ea8a8135d6023d591132465756f74981ca39b60f8708dfe38213a55bd4b619798a7b9438ca10d718099 + languageName: node + linkType: hard + +"jest-mock@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-mock@npm:29.7.0" + dependencies: + "@jest/types": "npm:^29.6.3" + "@types/node": "npm:*" + jest-util: "npm:^29.7.0" + checksum: 10c0/7b9f8349ee87695a309fe15c46a74ab04c853369e5c40952d68061d9dc3159a0f0ed73e215f81b07ee97a9faaf10aebe5877a9d6255068a0977eae6a9ff1d5ac + languageName: node + linkType: hard + +"jest-pnp-resolver@npm:^1.2.2, jest-pnp-resolver@npm:^1.2.3": + version: 1.2.3 + resolution: "jest-pnp-resolver@npm:1.2.3" + peerDependencies: + jest-resolve: "*" + peerDependenciesMeta: + jest-resolve: + optional: true + checksum: 10c0/86eec0c78449a2de733a6d3e316d49461af6a858070e113c97f75fb742a48c2396ea94150cbca44159ffd4a959f743a47a8b37a792ef6fdad2cf0a5cba973fac + languageName: node + linkType: hard + +"jest-regex-util@npm:30.0.1": + version: 30.0.1 + resolution: "jest-regex-util@npm:30.0.1" + checksum: 10c0/f30c70524ebde2d1012afe5ffa5691d5d00f7d5ba9e43d588f6460ac6fe96f9e620f2f9b36a02d0d3e7e77bc8efb8b3450ae3b80ac53c8be5099e01bf54f6728 + languageName: node + linkType: hard + +"jest-regex-util@npm:^29.6.3": + version: 29.6.3 + resolution: "jest-regex-util@npm:29.6.3" + checksum: 10c0/4e33fb16c4f42111159cafe26397118dcfc4cf08bc178a67149fb05f45546a91928b820894572679d62559839d0992e21080a1527faad65daaae8743a5705a3b + languageName: node + linkType: hard + +"jest-resolve-dependencies@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-resolve-dependencies@npm:29.7.0" + dependencies: + jest-regex-util: "npm:^29.6.3" + jest-snapshot: "npm:^29.7.0" + checksum: 10c0/b6e9ad8ae5b6049474118ea6441dfddd385b6d1fc471db0136f7c8fbcfe97137a9665e4f837a9f49f15a29a1deb95a14439b7aec812f3f99d08f228464930f0d + languageName: node + linkType: hard + +"jest-resolve@npm:30.3.0, jest-resolve@npm:^30.0.2": + version: 30.3.0 + resolution: "jest-resolve@npm:30.3.0" + dependencies: + chalk: "npm:^4.1.2" + graceful-fs: "npm:^4.2.11" + jest-haste-map: "npm:30.3.0" + jest-pnp-resolver: "npm:^1.2.3" + jest-util: "npm:30.3.0" + jest-validate: "npm:30.3.0" + slash: "npm:^3.0.0" + unrs-resolver: "npm:^1.7.11" + checksum: 10c0/540f59f160c232c1b922b111a93f24ef5202d75e00f2e994de976badf6e88879893b474320ff363a6b97259a7a208b6a4f5eeabede787eea9b7912a12ac64b1b + languageName: node + linkType: hard + +"jest-resolve@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-resolve@npm:29.7.0" + dependencies: + chalk: "npm:^4.0.0" + graceful-fs: "npm:^4.2.9" + jest-haste-map: "npm:^29.7.0" + jest-pnp-resolver: "npm:^1.2.2" + jest-util: "npm:^29.7.0" + jest-validate: "npm:^29.7.0" + resolve: "npm:^1.20.0" + resolve.exports: "npm:^2.0.0" + slash: "npm:^3.0.0" + checksum: 10c0/59da5c9c5b50563e959a45e09e2eace783d7f9ac0b5dcc6375dea4c0db938d2ebda97124c8161310082760e8ebbeff9f6b177c15ca2f57fb424f637a5d2adb47 + languageName: node + linkType: hard + +"jest-runner@npm:30.3.0": + version: 30.3.0 + resolution: "jest-runner@npm:30.3.0" + dependencies: + "@jest/console": "npm:30.3.0" + "@jest/environment": "npm:30.3.0" + "@jest/test-result": "npm:30.3.0" + "@jest/transform": "npm:30.3.0" + "@jest/types": "npm:30.3.0" + "@types/node": "npm:*" + chalk: "npm:^4.1.2" + emittery: "npm:^0.13.1" + exit-x: "npm:^0.2.2" + graceful-fs: "npm:^4.2.11" + jest-docblock: "npm:30.2.0" + jest-environment-node: "npm:30.3.0" + jest-haste-map: "npm:30.3.0" + jest-leak-detector: "npm:30.3.0" + jest-message-util: "npm:30.3.0" + jest-resolve: "npm:30.3.0" + jest-runtime: "npm:30.3.0" + jest-util: "npm:30.3.0" + jest-watcher: "npm:30.3.0" + jest-worker: "npm:30.3.0" + p-limit: "npm:^3.1.0" + source-map-support: "npm:0.5.13" + checksum: 10c0/6fb205f48541658f0b23b6c9a6730f0133f07c994a22ef506ebfcded5bbb444b655ac828074157e6579e664609a46f6a5bf3d366b694c6c8b523b5207a70499c + languageName: node + linkType: hard + +"jest-runner@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-runner@npm:29.7.0" + dependencies: + "@jest/console": "npm:^29.7.0" + "@jest/environment": "npm:^29.7.0" + "@jest/test-result": "npm:^29.7.0" + "@jest/transform": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + "@types/node": "npm:*" + chalk: "npm:^4.0.0" + emittery: "npm:^0.13.1" + graceful-fs: "npm:^4.2.9" + jest-docblock: "npm:^29.7.0" + jest-environment-node: "npm:^29.7.0" + jest-haste-map: "npm:^29.7.0" + jest-leak-detector: "npm:^29.7.0" + jest-message-util: "npm:^29.7.0" + jest-resolve: "npm:^29.7.0" + jest-runtime: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + jest-watcher: "npm:^29.7.0" + jest-worker: "npm:^29.7.0" + p-limit: "npm:^3.1.0" + source-map-support: "npm:0.5.13" + checksum: 10c0/2194b4531068d939f14c8d3274fe5938b77fa73126aedf9c09ec9dec57d13f22c72a3b5af01ac04f5c1cf2e28d0ac0b4a54212a61b05f10b5d6b47f2a1097bb4 + languageName: node + linkType: hard + +"jest-runtime@npm:30.3.0": + version: 30.3.0 + resolution: "jest-runtime@npm:30.3.0" + dependencies: + "@jest/environment": "npm:30.3.0" + "@jest/fake-timers": "npm:30.3.0" + "@jest/globals": "npm:30.3.0" + "@jest/source-map": "npm:30.0.1" + "@jest/test-result": "npm:30.3.0" + "@jest/transform": "npm:30.3.0" + "@jest/types": "npm:30.3.0" + "@types/node": "npm:*" + chalk: "npm:^4.1.2" + cjs-module-lexer: "npm:^2.1.0" + collect-v8-coverage: "npm:^1.0.2" + glob: "npm:^10.5.0" + graceful-fs: "npm:^4.2.11" + jest-haste-map: "npm:30.3.0" + jest-message-util: "npm:30.3.0" + jest-mock: "npm:30.3.0" + jest-regex-util: "npm:30.0.1" + jest-resolve: "npm:30.3.0" + jest-snapshot: "npm:30.3.0" + jest-util: "npm:30.3.0" + slash: "npm:^3.0.0" + strip-bom: "npm:^4.0.0" + checksum: 10c0/79c486157a926d5be5c66356ad26cc3792cca1afb1490e255a550f52784b6c92eea42f1cb3b2c7565650ea777cf17ffc3f8e305d6b97888e7d273f6d7f282686 + languageName: node + linkType: hard + +"jest-runtime@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-runtime@npm:29.7.0" + dependencies: + "@jest/environment": "npm:^29.7.0" + "@jest/fake-timers": "npm:^29.7.0" + "@jest/globals": "npm:^29.7.0" + "@jest/source-map": "npm:^29.6.3" + "@jest/test-result": "npm:^29.7.0" + "@jest/transform": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + "@types/node": "npm:*" + chalk: "npm:^4.0.0" + cjs-module-lexer: "npm:^1.0.0" + collect-v8-coverage: "npm:^1.0.0" + glob: "npm:^7.1.3" + graceful-fs: "npm:^4.2.9" + jest-haste-map: "npm:^29.7.0" + jest-message-util: "npm:^29.7.0" + jest-mock: "npm:^29.7.0" + jest-regex-util: "npm:^29.6.3" + jest-resolve: "npm:^29.7.0" + jest-snapshot: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + slash: "npm:^3.0.0" + strip-bom: "npm:^4.0.0" + checksum: 10c0/7cd89a1deda0bda7d0941835434e44f9d6b7bd50b5c5d9b0fc9a6c990b2d4d2cab59685ab3cb2850ed4cc37059f6de903af5a50565d7f7f1192a77d3fd6dd2a6 + languageName: node + linkType: hard + +"jest-snapshot@npm:30.3.0": + version: 30.3.0 + resolution: "jest-snapshot@npm:30.3.0" + dependencies: + "@babel/core": "npm:^7.27.4" + "@babel/generator": "npm:^7.27.5" + "@babel/plugin-syntax-jsx": "npm:^7.27.1" + "@babel/plugin-syntax-typescript": "npm:^7.27.1" + "@babel/types": "npm:^7.27.3" + "@jest/expect-utils": "npm:30.3.0" + "@jest/get-type": "npm:30.1.0" + "@jest/snapshot-utils": "npm:30.3.0" + "@jest/transform": "npm:30.3.0" + "@jest/types": "npm:30.3.0" + babel-preset-current-node-syntax: "npm:^1.2.0" + chalk: "npm:^4.1.2" + expect: "npm:30.3.0" + graceful-fs: "npm:^4.2.11" + jest-diff: "npm:30.3.0" + jest-matcher-utils: "npm:30.3.0" + jest-message-util: "npm:30.3.0" + jest-util: "npm:30.3.0" + pretty-format: "npm:30.3.0" + semver: "npm:^7.7.2" + synckit: "npm:^0.11.8" + checksum: 10c0/c1dd295d9d4962f2504c965575212fc62a358a849c66ab96b2f6e608ebdf6a6029ca505bb0693664a54a534e581883665d404a59976a5b46b1a1f88b537e96c5 + languageName: node + linkType: hard + +"jest-snapshot@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-snapshot@npm:29.7.0" + dependencies: + "@babel/core": "npm:^7.11.6" + "@babel/generator": "npm:^7.7.2" + "@babel/plugin-syntax-jsx": "npm:^7.7.2" + "@babel/plugin-syntax-typescript": "npm:^7.7.2" + "@babel/types": "npm:^7.3.3" + "@jest/expect-utils": "npm:^29.7.0" + "@jest/transform": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + babel-preset-current-node-syntax: "npm:^1.0.0" + chalk: "npm:^4.0.0" + expect: "npm:^29.7.0" + graceful-fs: "npm:^4.2.9" + jest-diff: "npm:^29.7.0" + jest-get-type: "npm:^29.6.3" + jest-matcher-utils: "npm:^29.7.0" + jest-message-util: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + natural-compare: "npm:^1.4.0" + pretty-format: "npm:^29.7.0" + semver: "npm:^7.5.3" + checksum: 10c0/6e9003c94ec58172b4a62864a91c0146513207bedf4e0a06e1e2ac70a4484088a2683e3a0538d8ea913bcfd53dc54a9b98a98cdfa562e7fe1d1339aeae1da570 + languageName: node + linkType: hard + +"jest-util@npm:30.3.0, jest-util@npm:^30.0.2": + version: 30.3.0 + resolution: "jest-util@npm:30.3.0" + dependencies: + "@jest/types": "npm:30.3.0" + "@types/node": "npm:*" + chalk: "npm:^4.1.2" + ci-info: "npm:^4.2.0" + graceful-fs: "npm:^4.2.11" + picomatch: "npm:^4.0.3" + checksum: 10c0/eea6f39e52a8cb2b1a28bb315a90dc6a8e450fffed73bb5ef4489d02d86f7d91be600d83f1dcba22956b8ac5fefa8f1b250e636c8402d3e8b50a5eec8b5963b2 + languageName: node + linkType: hard + +"jest-util@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-util@npm:29.7.0" + dependencies: + "@jest/types": "npm:^29.6.3" + "@types/node": "npm:*" + chalk: "npm:^4.0.0" + ci-info: "npm:^3.2.0" + graceful-fs: "npm:^4.2.9" + picomatch: "npm:^2.2.3" + checksum: 10c0/bc55a8f49fdbb8f51baf31d2a4f312fb66c9db1483b82f602c9c990e659cdd7ec529c8e916d5a89452ecbcfae4949b21b40a7a59d4ffc0cd813a973ab08c8150 + languageName: node + linkType: hard + +"jest-validate@npm:30.3.0": + version: 30.3.0 + resolution: "jest-validate@npm:30.3.0" + dependencies: + "@jest/get-type": "npm:30.1.0" + "@jest/types": "npm:30.3.0" + camelcase: "npm:^6.3.0" + chalk: "npm:^4.1.2" + leven: "npm:^3.1.0" + pretty-format: "npm:30.3.0" + checksum: 10c0/645629e9ae0926252dee26b0ad71b9f0392daa896328393479c63b1b13d2a70df4dac8b5053227c64e0120e930db1242897898c40706f135f20f73ef77fcf4f5 + languageName: node + linkType: hard + +"jest-validate@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-validate@npm:29.7.0" + dependencies: + "@jest/types": "npm:^29.6.3" + camelcase: "npm:^6.2.0" + chalk: "npm:^4.0.0" + jest-get-type: "npm:^29.6.3" + leven: "npm:^3.1.0" + pretty-format: "npm:^29.7.0" + checksum: 10c0/a20b930480c1ed68778c739f4739dce39423131bc070cd2505ddede762a5570a256212e9c2401b7ae9ba4d7b7c0803f03c5b8f1561c62348213aba18d9dbece2 + languageName: node + linkType: hard + +"jest-watcher@npm:30.3.0": + version: 30.3.0 + resolution: "jest-watcher@npm:30.3.0" + dependencies: + "@jest/test-result": "npm:30.3.0" + "@jest/types": "npm:30.3.0" + "@types/node": "npm:*" + ansi-escapes: "npm:^4.3.2" + chalk: "npm:^4.1.2" + emittery: "npm:^0.13.1" + jest-util: "npm:30.3.0" + string-length: "npm:^4.0.2" + checksum: 10c0/2631be5cc122fbf14cb0bb7566cdea6d6c432b984d8ef3c6385254bb6c378342e0754cbd2dfe094d80762d44bd1c7015de2ec2100eb6f192906619d8b229e1a5 + languageName: node + linkType: hard + +"jest-watcher@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-watcher@npm:29.7.0" + dependencies: + "@jest/test-result": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + "@types/node": "npm:*" + ansi-escapes: "npm:^4.2.1" + chalk: "npm:^4.0.0" + emittery: "npm:^0.13.1" + jest-util: "npm:^29.7.0" + string-length: "npm:^4.0.1" + checksum: 10c0/ec6c75030562fc8f8c727cb8f3b94e75d831fc718785abfc196e1f2a2ebc9a2e38744a15147170039628a853d77a3b695561ce850375ede3a4ee6037a2574567 + languageName: node + linkType: hard + +"jest-worker@npm:30.3.0": + version: 30.3.0 + resolution: "jest-worker@npm:30.3.0" + dependencies: + "@types/node": "npm:*" + "@ungap/structured-clone": "npm:^1.3.0" + jest-util: "npm:30.3.0" + merge-stream: "npm:^2.0.0" + supports-color: "npm:^8.1.1" + checksum: 10c0/25dfb1bc43d389e1daf8baad0ef7964249f001a7da7d92c61e398840424ca13fb1fb6242f6e021f0cbb37952f90371fb8be1ef0183b5d04ef161fdb8f09ee78e + languageName: node + linkType: hard + +"jest-worker@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-worker@npm:29.7.0" + dependencies: + "@types/node": "npm:*" + jest-util: "npm:^29.7.0" + merge-stream: "npm:^2.0.0" + supports-color: "npm:^8.0.0" + checksum: 10c0/5570a3a005b16f46c131968b8a5b56d291f9bbb85ff4217e31c80bd8a02e7de799e59a54b95ca28d5c302f248b54cbffde2d177c2f0f52ffcee7504c6eabf660 + languageName: node + linkType: hard + +"jest@npm:^29": + version: 29.7.0 + resolution: "jest@npm:29.7.0" + dependencies: + "@jest/core": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + import-local: "npm:^3.0.2" + jest-cli: "npm:^29.7.0" + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + bin: + jest: bin/jest.js + checksum: 10c0/f40eb8171cf147c617cc6ada49d062fbb03b4da666cb8d39cdbfb739a7d75eea4c3ca150fb072d0d273dce0c753db4d0467d54906ad0293f59c54f9db4a09d8b + languageName: node + linkType: hard + +"jose@npm:^6.1.3": + version: 6.2.2 + resolution: "jose@npm:6.2.2" + checksum: 10c0/201f4776d77eccd339de99fb3ba940fdf03db15e64be7a99b511e53c232e3f3818e3f21b95223d62f99315a2ab76b4251cedd94e067de56893e45273a8d2151b + languageName: node + linkType: hard + +"js-tiktoken@npm:^1.0.14": + version: 1.0.21 + resolution: "js-tiktoken@npm:1.0.21" + dependencies: + base64-js: "npm:^1.5.1" + checksum: 10c0/49a0b1e8915d271b84b5c2217fcab37de3124cfbba7e9901d3d9afb1acdd931f0ff7025ed94587dd1b59ae5c04cc19949c2869823854ee7f2f3f81678db276f3 + languageName: node + linkType: hard + +"js-tokens@npm:^4.0.0": + version: 4.0.0 + resolution: "js-tokens@npm:4.0.0" + checksum: 10c0/e248708d377aa058eacf2037b07ded847790e6de892bbad3dac0abba2e759cb9f121b00099a65195616badcb6eca8d14d975cb3e89eb1cfda644756402c8aeed + languageName: node + linkType: hard + +"js-yaml@npm:4.1.1, js-yaml@npm:^4.1.0, js-yaml@npm:^4.1.1": + version: 4.1.1 + resolution: "js-yaml@npm:4.1.1" + dependencies: + argparse: "npm:^2.0.1" + bin: + js-yaml: bin/js-yaml.js + checksum: 10c0/561c7d7088c40a9bb53cc75becbfb1df6ae49b34b5e6e5a81744b14ae8667ec564ad2527709d1a6e7d5e5fa6d483aa0f373a50ad98d42fde368ec4a190d4fae7 + languageName: node + linkType: hard + +"js-yaml@npm:^3.10.0, js-yaml@npm:^3.13.1": + version: 3.14.2 + resolution: "js-yaml@npm:3.14.2" + dependencies: + argparse: "npm:^1.0.7" + esprima: "npm:^4.0.0" + bin: + js-yaml: bin/js-yaml.js + checksum: 10c0/3261f25912f5dd76605e5993d0a126c2b6c346311885d3c483706cd722efe34f697ea0331f654ce27c00a42b426e524518ec89d65ed02ea47df8ad26dcc8ce69 + languageName: node + linkType: hard + +"jsesc@npm:^3.0.2, jsesc@npm:~3.1.0": + version: 3.1.0 + resolution: "jsesc@npm:3.1.0" + bin: + jsesc: bin/jsesc + checksum: 10c0/531779df5ec94f47e462da26b4cbf05eb88a83d9f08aac2ba04206508fc598527a153d08bd462bae82fc78b3eaa1a908e1a4a79f886e9238641c4cdefaf118b1 + languageName: node + linkType: hard + +"json-buffer@npm:3.0.1": + version: 3.0.1 + resolution: "json-buffer@npm:3.0.1" + checksum: 10c0/0d1c91569d9588e7eef2b49b59851f297f3ab93c7b35c7c221e288099322be6b562767d11e4821da500f3219542b9afd2e54c5dc573107c1126ed1080f8e96d7 + languageName: node + linkType: hard + +"json-parse-better-errors@npm:^1.0.1": + version: 1.0.2 + resolution: "json-parse-better-errors@npm:1.0.2" + checksum: 10c0/2f1287a7c833e397c9ddd361a78638e828fc523038bb3441fd4fc144cfd2c6cd4963ffb9e207e648cf7b692600f1e1e524e965c32df5152120910e4903a47dcb + languageName: node + linkType: hard + +"json-parse-even-better-errors@npm:^2.3.0": + version: 2.3.1 + resolution: "json-parse-even-better-errors@npm:2.3.1" + checksum: 10c0/140932564c8f0b88455432e0f33c4cb4086b8868e37524e07e723f4eaedb9425bdc2bafd71bd1d9765bd15fd1e2d126972bc83990f55c467168c228c24d665f3 + languageName: node + linkType: hard + +"json-parse-even-better-errors@npm:^4.0.0": + version: 4.0.0 + resolution: "json-parse-even-better-errors@npm:4.0.0" + checksum: 10c0/84cd9304a97e8fb2af3937bf53acb91c026aeb859703c332684e688ea60db27fc2242aa532a84e1883fdcbe1e5c1fb57c2bef38e312021aa1cd300defc63cf16 + languageName: node + linkType: hard + +"json-parse-even-better-errors@npm:^5.0.0": + version: 5.0.0 + resolution: "json-parse-even-better-errors@npm:5.0.0" + checksum: 10c0/9a33d120090a7637a2aa850acec610c011d7c6488c5184d7ffc0460ee0401057f3131a4dff70c6510900cf15a95ab99d3f0f2d959f59edfe6438d227e90bf5ca + languageName: node + linkType: hard + +"json-schema-traverse@npm:^0.4.1": + version: 0.4.1 + resolution: "json-schema-traverse@npm:0.4.1" + checksum: 10c0/108fa90d4cc6f08243aedc6da16c408daf81793bf903e9fd5ab21983cda433d5d2da49e40711da016289465ec2e62e0324dcdfbc06275a607fe3233fde4942ce + languageName: node + linkType: hard + +"json-schema-traverse@npm:^1.0.0": + version: 1.0.0 + resolution: "json-schema-traverse@npm:1.0.0" + checksum: 10c0/71e30015d7f3d6dc1c316d6298047c8ef98a06d31ad064919976583eb61e1018a60a0067338f0f79cabc00d84af3fcc489bd48ce8a46ea165d9541ba17fb30c6 + languageName: node + linkType: hard + +"json-schema-typed@npm:^8.0.2": + version: 8.0.2 + resolution: "json-schema-typed@npm:8.0.2" + checksum: 10c0/89f5e2fb1495483b705c027203c07277ee6bf2665165ad25a9cb55de5af7f72570326d13d32565180781e4083ad5c9688102f222baed7b353c2f39c1e02b0428 + languageName: node + linkType: hard + +"json-stable-stringify-without-jsonify@npm:^1.0.1": + version: 1.0.1 + resolution: "json-stable-stringify-without-jsonify@npm:1.0.1" + checksum: 10c0/cb168b61fd4de83e58d09aaa6425ef71001bae30d260e2c57e7d09a5fd82223e2f22a042dedaab8db23b7d9ae46854b08bb1f91675a8be11c5cffebef5fb66a5 + languageName: node + linkType: hard + +"json-stringify-nice@npm:^1.1.4": + version: 1.1.4 + resolution: "json-stringify-nice@npm:1.1.4" + checksum: 10c0/13673b67ba9e7fde75a103cade0b0d2dd0d21cd3b918de8d8f6cd59d48ad8c78b0e85f6f4a5842073ddfc91ebdde5ef7c81c7f51945b96a33eaddc5d41324b87 + languageName: node + linkType: hard + +"json-stringify-safe@npm:^5.0.1": + version: 5.0.1 + resolution: "json-stringify-safe@npm:5.0.1" + checksum: 10c0/7dbf35cd0411d1d648dceb6d59ce5857ec939e52e4afc37601aa3da611f0987d5cee5b38d58329ceddf3ed48bd7215229c8d52059ab01f2444a338bf24ed0f37 + languageName: node + linkType: hard + +"json5@npm:^2.2.2, json5@npm:^2.2.3": + version: 2.2.3 + resolution: "json5@npm:2.2.3" + bin: + json5: lib/cli.js + checksum: 10c0/5a04eed94810fa55c5ea138b2f7a5c12b97c3750bc63d11e511dcecbfef758003861522a070c2272764ee0f4e3e323862f386945aeb5b85b87ee43f084ba586c + languageName: node + linkType: hard + +"jsonc-parser@npm:3.2.0": + version: 3.2.0 + resolution: "jsonc-parser@npm:3.2.0" + checksum: 10c0/5a12d4d04dad381852476872a29dcee03a57439574e4181d91dca71904fcdcc5e8e4706c0a68a2c61ad9810e1e1c5806b5100d52d3e727b78f5cdc595401045b + languageName: node + linkType: hard + +"jsonfile@npm:^6.0.1": + version: 6.2.0 + resolution: "jsonfile@npm:6.2.0" + dependencies: + graceful-fs: "npm:^4.1.6" + universalify: "npm:^2.0.0" + dependenciesMeta: + graceful-fs: + optional: true + checksum: 10c0/7f4f43b08d1869ded8a6822213d13ae3b99d651151d77efd1557ced0889c466296a7d9684e397bd126acf5eb2cfcb605808c3e681d0fdccd2fe5a04b47e76c0d + languageName: node + linkType: hard + +"jsonparse@npm:^1.2.0, jsonparse@npm:^1.3.1": + version: 1.3.1 + resolution: "jsonparse@npm:1.3.1" + checksum: 10c0/89bc68080cd0a0e276d4b5ab1b79cacd68f562467008d176dc23e16e97d4efec9e21741d92ba5087a8433526a45a7e6a9d5ef25408696c402ca1cfbc01a90bf0 + languageName: node + linkType: hard + +"just-diff-apply@npm:^5.2.0": + version: 5.5.0 + resolution: "just-diff-apply@npm:5.5.0" + checksum: 10c0/d7b85371f2a5a17a108467fda35dddd95264ab438ccec7837b67af5913c57ded7246039d1df2b5bc1ade034ccf815b56d69786c5f1e07383168a066007c796c0 + languageName: node + linkType: hard + +"just-diff@npm:^6.0.0": + version: 6.0.2 + resolution: "just-diff@npm:6.0.2" + checksum: 10c0/1931ca1f0cea4cc480172165c189a84889033ad7a60bee302268ba8ca9f222b43773fd5f272a23ee618d43d85d3048411f06b635571a198159e9a85bb2495f5c + languageName: node + linkType: hard + +"keyv@npm:^4.5.4": + version: 4.5.4 + resolution: "keyv@npm:4.5.4" + dependencies: + json-buffer: "npm:3.0.1" + checksum: 10c0/aa52f3c5e18e16bb6324876bb8b59dd02acf782a4b789c7b2ae21107fab95fab3890ed448d4f8dba80ce05391eeac4bfabb4f02a20221342982f806fa2cf271e + languageName: node + linkType: hard + +"kind-of@npm:^6.0.3": + version: 6.0.3 + resolution: "kind-of@npm:6.0.3" + checksum: 10c0/61cdff9623dabf3568b6445e93e31376bee1cdb93f8ba7033d86022c2a9b1791a1d9510e026e6465ebd701a6dd2f7b0808483ad8838341ac52f003f512e0b4c4 + languageName: node + linkType: hard + +"kleur@npm:^3.0.3": + version: 3.0.3 + resolution: "kleur@npm:3.0.3" + checksum: 10c0/cd3a0b8878e7d6d3799e54340efe3591ca787d9f95f109f28129bdd2915e37807bf8918bb295ab86afb8c82196beec5a1adcaf29042ce3f2bd932b038fe3aa4b + languageName: node + linkType: hard + +"kuler@npm:^2.0.0": + version: 2.0.0 + resolution: "kuler@npm:2.0.0" + checksum: 10c0/0a4e99d92ca373f8f74d1dc37931909c4d0d82aebc94cf2ba265771160fc12c8df34eaaac80805efbda367e2795cb1f1dd4c3d404b6b1cf38aec94035b503d2d + languageName: node + linkType: hard + +"lazystream@npm:^1.0.0": + version: 1.0.1 + resolution: "lazystream@npm:1.0.1" + dependencies: + readable-stream: "npm:^2.0.5" + checksum: 10c0/ea4e509a5226ecfcc303ba6782cc269be8867d372b9bcbd625c88955df1987ea1a20da4643bf9270336415a398d33531ebf0d5f0d393b9283dc7c98bfcbd7b69 + languageName: node + linkType: hard + +"lerna@npm:^9.0.7": + version: 9.0.7 + resolution: "lerna@npm:9.0.7" + dependencies: + "@npmcli/arborist": "npm:9.1.6" + "@npmcli/package-json": "npm:7.0.2" + "@npmcli/run-script": "npm:10.0.3" + "@nx/devkit": "npm:>=21.5.2 < 23.0.0" + "@octokit/plugin-enterprise-rest": "npm:6.0.1" + "@octokit/rest": "npm:20.1.2" + aproba: "npm:2.0.0" + byte-size: "npm:8.1.1" + chalk: "npm:4.1.0" + ci-info: "npm:4.3.1" + cmd-shim: "npm:6.0.3" + color-support: "npm:1.1.3" + columnify: "npm:1.6.0" + console-control-strings: "npm:^1.1.0" + conventional-changelog-angular: "npm:7.0.0" + conventional-changelog-core: "npm:5.0.1" + conventional-recommended-bump: "npm:7.0.1" + cosmiconfig: "npm:9.0.0" + dedent: "npm:1.5.3" + envinfo: "npm:7.13.0" + execa: "npm:5.0.0" + fs-extra: "npm:^11.2.0" + get-stream: "npm:6.0.0" + git-url-parse: "npm:14.0.0" + glob-parent: "npm:6.0.2" + has-unicode: "npm:2.0.1" + import-local: "npm:3.1.0" + ini: "npm:^1.3.8" + init-package-json: "npm:8.2.2" + inquirer: "npm:12.9.6" + is-ci: "npm:3.0.1" + jest-diff: "npm:>=30.0.0 < 31" + js-yaml: "npm:4.1.1" + libnpmaccess: "npm:10.0.3" + libnpmpublish: "npm:11.1.2" + load-json-file: "npm:6.2.0" + make-fetch-happen: "npm:15.0.2" + minimatch: "npm:3.1.4" + npm-package-arg: "npm:13.0.1" + npm-packlist: "npm:10.0.3" + npm-registry-fetch: "npm:19.1.0" + nx: "npm:>=21.5.3 < 23.0.0" + p-map: "npm:4.0.0" + p-map-series: "npm:2.1.0" + p-pipe: "npm:3.1.0" + p-queue: "npm:6.6.2" + p-reduce: "npm:2.1.0" + p-waterfall: "npm:2.1.1" + pacote: "npm:21.0.1" + read-cmd-shim: "npm:4.0.0" + semver: "npm:7.7.2" + signal-exit: "npm:3.0.7" + slash: "npm:3.0.0" + ssri: "npm:12.0.0" + string-width: "npm:^4.2.3" + tar: "npm:7.5.11" + through: "npm:2.3.8" + tinyglobby: "npm:0.2.12" + typescript: "npm:>=3 < 6" + upath: "npm:2.0.1" + validate-npm-package-license: "npm:3.0.4" + validate-npm-package-name: "npm:6.0.2" + wide-align: "npm:1.1.5" + write-file-atomic: "npm:5.0.1" + yargs: "npm:17.7.2" + yargs-parser: "npm:21.1.1" + bin: + lerna: dist/cli.js + checksum: 10c0/60e50239790ef3230ee3bfbd084553d6ec164991df5a37443cc9be680a358ed1e61e3334ec403d7a3fc4a5b6d6913e850e52df27d9b04d34cf1501b7eeedcb8a + languageName: node + linkType: hard + +"leven@npm:^3.1.0": + version: 3.1.0 + resolution: "leven@npm:3.1.0" + checksum: 10c0/cd778ba3fbab0f4d0500b7e87d1f6e1f041507c56fdcd47e8256a3012c98aaee371d4c15e0a76e0386107af2d42e2b7466160a2d80688aaa03e66e49949f42df + languageName: node + linkType: hard + +"levn@npm:^0.4.1": + version: 0.4.1 + resolution: "levn@npm:0.4.1" + dependencies: + prelude-ls: "npm:^1.2.1" + type-check: "npm:~0.4.0" + checksum: 10c0/effb03cad7c89dfa5bd4f6989364bfc79994c2042ec5966cb9b95990e2edee5cd8969ddf42616a0373ac49fac1403437deaf6e9050fbbaa3546093a59b9ac94e + languageName: node + linkType: hard + +"libnpmaccess@npm:10.0.3": + version: 10.0.3 + resolution: "libnpmaccess@npm:10.0.3" + dependencies: + npm-package-arg: "npm:^13.0.0" + npm-registry-fetch: "npm:^19.0.0" + checksum: 10c0/4582f7a1b5e5a0103ed4e76776df3b82f5b296fc5d3ab92391d61ef526899783cdfa7983cb4cbc0d354ca4cdfd9e183523f8e45cb8be80a6804af05a7291127d + languageName: node + linkType: hard + +"libnpmpublish@npm:11.1.2": + version: 11.1.2 + resolution: "libnpmpublish@npm:11.1.2" + dependencies: + "@npmcli/package-json": "npm:^7.0.0" + ci-info: "npm:^4.0.0" + npm-package-arg: "npm:^13.0.0" + npm-registry-fetch: "npm:^19.0.0" + proc-log: "npm:^5.0.0" + semver: "npm:^7.3.7" + sigstore: "npm:^4.0.0" + ssri: "npm:^12.0.0" + checksum: 10c0/213cd2aeb65822892c3723a81d191a385e97f126ec63800f7051609e24c38c3fa36ea529b26739dc56dfba21f7f456347889f3aa1e6024c8c6a40bfa4cd9d184 + languageName: node + linkType: hard + +"libphonenumber-js@npm:^1.11.1": + version: 1.12.41 + resolution: "libphonenumber-js@npm:1.12.41" + checksum: 10c0/dda2a3ada1d4271a93f6eb9cc9b061e294ab05e7efb71c5e2e2bea02f8f478d7b4359fcd3a67b8a377e53ca671d0303ffa78e3df4857901d5aa03ecfb19becf0 + languageName: node + linkType: hard + +"lines-and-columns@npm:2.0.3": + version: 2.0.3 + resolution: "lines-and-columns@npm:2.0.3" + checksum: 10c0/09525c10010a925b7efe858f1dd3184eeac34f0a9bc34993075ec490efad71e948147746b18e9540279cc87cd44085b038f986903db3de65ffe96d38a7b91c4c + languageName: node + linkType: hard + +"lines-and-columns@npm:^1.1.6": + version: 1.2.4 + resolution: "lines-and-columns@npm:1.2.4" + checksum: 10c0/3da6ee62d4cd9f03f5dc90b4df2540fb85b352081bee77fe4bbcd12c9000ead7f35e0a38b8d09a9bb99b13223446dd8689ff3c4959807620726d788701a83d2d + languageName: node + linkType: hard + +"load-json-file@npm:6.2.0": + version: 6.2.0 + resolution: "load-json-file@npm:6.2.0" + dependencies: + graceful-fs: "npm:^4.1.15" + parse-json: "npm:^5.0.0" + strip-bom: "npm:^4.0.0" + type-fest: "npm:^0.6.0" + checksum: 10c0/fcb46ef75bab917f37170ba76781a1690bf67144bb53931cb0ed8e4aa20ca439e9c354fcf3594aed531f47dbeb4a49800acab7fdffd553c402ac40c987706d7b + languageName: node + linkType: hard + +"load-json-file@npm:^4.0.0": + version: 4.0.0 + resolution: "load-json-file@npm:4.0.0" + dependencies: + graceful-fs: "npm:^4.1.2" + parse-json: "npm:^4.0.0" + pify: "npm:^3.0.0" + strip-bom: "npm:^3.0.0" + checksum: 10c0/6b48f6a0256bdfcc8970be2c57f68f10acb2ee7e63709b386b2febb6ad3c86198f840889cdbe71d28f741cbaa2f23a7771206b138cd1bdd159564511ca37c1d5 + languageName: node + linkType: hard + +"locate-path@npm:^2.0.0": + version: 2.0.0 + resolution: "locate-path@npm:2.0.0" + dependencies: + p-locate: "npm:^2.0.0" + path-exists: "npm:^3.0.0" + checksum: 10c0/24efa0e589be6aa3c469b502f795126b26ab97afa378846cb508174211515633b770aa0ba610cab113caedab8d2a4902b061a08aaed5297c12ab6f5be4df0133 + languageName: node + linkType: hard + +"locate-path@npm:^5.0.0": + version: 5.0.0 + resolution: "locate-path@npm:5.0.0" + dependencies: + p-locate: "npm:^4.1.0" + checksum: 10c0/33a1c5247e87e022f9713e6213a744557a3e9ec32c5d0b5efb10aa3a38177615bf90221a5592674857039c1a0fd2063b82f285702d37b792d973e9e72ace6c59 + languageName: node + linkType: hard + +"locate-path@npm:^6.0.0": + version: 6.0.0 + resolution: "locate-path@npm:6.0.0" + dependencies: + p-locate: "npm:^5.0.0" + checksum: 10c0/d3972ab70dfe58ce620e64265f90162d247e87159b6126b01314dd67be43d50e96a50b517bce2d9452a79409c7614054c277b5232377de50416564a77ac7aad3 + languageName: node + linkType: hard + +"lodash.camelcase@npm:^4.3.0": + version: 4.3.0 + resolution: "lodash.camelcase@npm:4.3.0" + checksum: 10c0/fcba15d21a458076dd309fce6b1b4bf611d84a0ec252cb92447c948c533ac250b95d2e00955801ebc367e5af5ed288b996d75d37d2035260a937008e14eaf432 + languageName: node + linkType: hard + +"lodash.debounce@npm:^4.0.8": + version: 4.0.8 + resolution: "lodash.debounce@npm:4.0.8" + checksum: 10c0/762998a63e095412b6099b8290903e0a8ddcb353ac6e2e0f2d7e7d03abd4275fe3c689d88960eb90b0dde4f177554d51a690f22a343932ecbc50a5d111849987 + languageName: node + linkType: hard + +"lodash.defaults@npm:^4.2.0": + version: 4.2.0 + resolution: "lodash.defaults@npm:4.2.0" + checksum: 10c0/d5b77aeb702caa69b17be1358faece33a84497bcca814897383c58b28a2f8dfc381b1d9edbec239f8b425126a3bbe4916223da2a576bb0411c2cefd67df80707 + languageName: node + linkType: hard + +"lodash.isarguments@npm:^3.1.0": + version: 3.1.0 + resolution: "lodash.isarguments@npm:3.1.0" + checksum: 10c0/5e8f95ba10975900a3920fb039a3f89a5a79359a1b5565e4e5b4310ed6ebe64011e31d402e34f577eca983a1fc01ff86c926e3cbe602e1ddfc858fdd353e62d8 + languageName: node + linkType: hard + +"lodash.ismatch@npm:^4.4.0": + version: 4.4.0 + resolution: "lodash.ismatch@npm:4.4.0" + checksum: 10c0/8f96a5dc4b8d3fc5a033dcb259d0c3148a1044fa4d02b4a0e8dce0fa1f2ef3ec4ac131e20b5cb2c985a4e9bcb1c37c0aa5af2cef70094959389617347b8fc645 + languageName: node + linkType: hard + +"lodash.memoize@npm:^4.1.2": + version: 4.1.2 + resolution: "lodash.memoize@npm:4.1.2" + checksum: 10c0/c8713e51eccc650422716a14cece1809cfe34bc5ab5e242b7f8b4e2241c2483697b971a604252807689b9dd69bfe3a98852e19a5b89d506b000b4187a1285df8 + languageName: node + linkType: hard + +"lodash.merge@npm:^4.6.2": + version: 4.6.2 + resolution: "lodash.merge@npm:4.6.2" + checksum: 10c0/402fa16a1edd7538de5b5903a90228aa48eb5533986ba7fa26606a49db2572bf414ff73a2c9f5d5fd36b31c46a5d5c7e1527749c07cbcf965ccff5fbdf32c506 + languageName: node + linkType: hard + +"lodash@npm:^4.17.15, lodash@npm:^4.17.21": + version: 4.18.1 + resolution: "lodash@npm:4.18.1" + checksum: 10c0/757228fc68805c59789e82185135cf85f05d0b2d3d54631d680ca79ec21944ec8314d4533639a14b8bcfbd97a517e78960933041a5af17ecb693ec6eecb99a27 + languageName: node + linkType: hard + +"log-symbols@npm:^4.0.0": + version: 4.1.0 + resolution: "log-symbols@npm:4.1.0" + dependencies: + chalk: "npm:^4.1.0" + is-unicode-supported: "npm:^0.1.0" + checksum: 10c0/67f445a9ffa76db1989d0fa98586e5bc2fd5247260dafb8ad93d9f0ccd5896d53fb830b0e54dade5ad838b9de2006c826831a3c528913093af20dff8bd24aca6 + languageName: node + linkType: hard + +"logform@npm:^2.7.0": + version: 2.7.0 + resolution: "logform@npm:2.7.0" + dependencies: + "@colors/colors": "npm:1.6.0" + "@types/triple-beam": "npm:^1.3.2" + fecha: "npm:^4.2.0" + ms: "npm:^2.1.1" + safe-stable-stringify: "npm:^2.3.1" + triple-beam: "npm:^1.3.0" + checksum: 10c0/4789b4b37413c731d1835734cb799240d31b865afde6b7b3e06051d6a4127bfda9e88c99cfbf296d084a315ccbed2647796e6a56b66e725bcb268c586f57558f + languageName: node + linkType: hard + +"long@npm:^5.0.0": + version: 5.3.2 + resolution: "long@npm:5.3.2" + checksum: 10c0/7130fe1cbce2dca06734b35b70d380ca3f70271c7f8852c922a7c62c86c4e35f0c39290565eca7133c625908d40e126ac57c02b1b1a4636b9457d77e1e60b981 + languageName: node + linkType: hard + +"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": + version: 10.4.3 + resolution: "lru-cache@npm:10.4.3" + checksum: 10c0/ebd04fbca961e6c1d6c0af3799adcc966a1babe798f685bb84e6599266599cd95d94630b10262f5424539bc4640107e8a33aa28585374abf561d30d16f4b39fb + languageName: node + linkType: hard + +"lru-cache@npm:^11.0.0, lru-cache@npm:^11.1.0, lru-cache@npm:^11.2.1": + version: 11.2.7 + resolution: "lru-cache@npm:11.2.7" + checksum: 10c0/549cdb59488baa617135fc12159cafb1a97f91079f35093bb3bcad72e849fc64ace636d244212c181dfdf1a99bbfa90757ff303f98561958ee4d0f885d9bd5f7 + languageName: node + linkType: hard + +"lru-cache@npm:^5.1.1": + version: 5.1.1 + resolution: "lru-cache@npm:5.1.1" + dependencies: + yallist: "npm:^3.0.2" + checksum: 10c0/89b2ef2ef45f543011e38737b8a8622a2f8998cddf0e5437174ef8f1f70a8b9d14a918ab3e232cb3ba343b7abddffa667f0b59075b2b80e6b4d63c3de6127482 + languageName: node + linkType: hard + +"lru-cache@npm:^6.0.0": + version: 6.0.0 + resolution: "lru-cache@npm:6.0.0" + dependencies: + yallist: "npm:^4.0.0" + checksum: 10c0/cb53e582785c48187d7a188d3379c181b5ca2a9c78d2bce3e7dee36f32761d1c42983da3fe12b55cb74e1779fa94cdc2e5367c028a9b35317184ede0c07a30a9 + languageName: node + linkType: hard + +"luxon@npm:^3.2.1, luxon@npm:^3.6.0": + version: 3.7.2 + resolution: "luxon@npm:3.7.2" + checksum: 10c0/ed8f0f637826c08c343a29dd478b00628be93bba6f068417b1d8896b61cb61c6deacbe1df1e057dbd9298334044afa150f9aaabbeb3181418ac8520acfdc2ae2 + languageName: node + linkType: hard + +"make-dir@npm:^4.0.0": + version: 4.0.0 + resolution: "make-dir@npm:4.0.0" + dependencies: + semver: "npm:^7.5.3" + checksum: 10c0/69b98a6c0b8e5c4fe9acb61608a9fbcfca1756d910f51e5dbe7a9e5cfb74fca9b8a0c8a0ffdf1294a740826c1ab4871d5bf3f62f72a3049e5eac6541ddffed68 + languageName: node + linkType: hard + +"make-error@npm:^1.1.1, make-error@npm:^1.3.6": + version: 1.3.6 + resolution: "make-error@npm:1.3.6" + checksum: 10c0/171e458d86854c6b3fc46610cfacf0b45149ba043782558c6875d9f42f222124384ad0b468c92e996d815a8a2003817a710c0a160e49c1c394626f76fa45396f + languageName: node + linkType: hard + +"make-fetch-happen@npm:15.0.2": + version: 15.0.2 + resolution: "make-fetch-happen@npm:15.0.2" + dependencies: + "@npmcli/agent": "npm:^4.0.0" + cacache: "npm:^20.0.1" + http-cache-semantics: "npm:^4.1.1" + minipass: "npm:^7.0.2" + minipass-fetch: "npm:^4.0.0" + minipass-flush: "npm:^1.0.5" + minipass-pipeline: "npm:^1.2.4" + negotiator: "npm:^1.0.0" + proc-log: "npm:^5.0.0" + promise-retry: "npm:^2.0.1" + ssri: "npm:^12.0.0" + checksum: 10c0/3cc9b4e71bba88bcec53f5307f9c3096c6193a2357e825bf3a3a03c99896d2fa14abba8363a84199829dade639e85dc0eb07de77d247aa249d13ff80511adf2c + languageName: node + linkType: hard + +"make-fetch-happen@npm:^15.0.0, make-fetch-happen@npm:^15.0.1, make-fetch-happen@npm:^15.0.4": + version: 15.0.5 + resolution: "make-fetch-happen@npm:15.0.5" + dependencies: + "@gar/promise-retry": "npm:^1.0.0" + "@npmcli/agent": "npm:^4.0.0" + "@npmcli/redact": "npm:^4.0.0" + cacache: "npm:^20.0.1" + http-cache-semantics: "npm:^4.1.1" + minipass: "npm:^7.0.2" + minipass-fetch: "npm:^5.0.0" + minipass-flush: "npm:^1.0.5" + minipass-pipeline: "npm:^1.2.4" + negotiator: "npm:^1.0.0" + proc-log: "npm:^6.0.0" + ssri: "npm:^13.0.0" + checksum: 10c0/527580eb5e5476e6ad07a4e3bd017d13e935f4be815674b442081ae5a721c13d3af5715006619e6be79a85723067e047f83a0c9e699f41d8cec43609a8de4f7b + languageName: node + linkType: hard + +"makeerror@npm:1.0.12": + version: 1.0.12 + resolution: "makeerror@npm:1.0.12" + dependencies: + tmpl: "npm:1.0.5" + checksum: 10c0/b0e6e599780ce6bab49cc413eba822f7d1f0dfebd1c103eaa3785c59e43e22c59018323cf9e1708f0ef5329e94a745d163fcbb6bff8e4c6742f9be9e86f3500c + languageName: node + linkType: hard + +"map-obj@npm:^1.0.0": + version: 1.0.1 + resolution: "map-obj@npm:1.0.1" + checksum: 10c0/ccca88395e7d38671ed9f5652ecf471ecd546924be2fb900836b9da35e068a96687d96a5f93dcdfa94d9a27d649d2f10a84595590f89a347fb4dda47629dcc52 + languageName: node + linkType: hard + +"map-obj@npm:^4.0.0": + version: 4.3.0 + resolution: "map-obj@npm:4.3.0" + checksum: 10c0/1c19e1c88513c8abdab25c316367154c6a0a6a0f77e3e8c391bb7c0e093aefed293f539d026dc013d86219e5e4c25f23b0003ea588be2101ccd757bacc12d43b + languageName: node + linkType: hard + +"math-intrinsics@npm:^1.1.0": + version: 1.1.0 + resolution: "math-intrinsics@npm:1.1.0" + checksum: 10c0/7579ff94e899e2f76ab64491d76cf606274c874d8f2af4a442c016bd85688927fcfca157ba6bf74b08e9439dc010b248ce05b96cc7c126a354c3bae7fcb48b7f + languageName: node + linkType: hard + +"media-typer@npm:0.3.0": + version: 0.3.0 + resolution: "media-typer@npm:0.3.0" + checksum: 10c0/d160f31246907e79fed398470285f21bafb45a62869dc469b1c8877f3f064f5eabc4bcc122f9479b8b605bc5c76187d7871cf84c4ee3ecd3e487da1993279928 + languageName: node + linkType: hard + +"media-typer@npm:^1.1.0": + version: 1.1.0 + resolution: "media-typer@npm:1.1.0" + checksum: 10c0/7b4baa40b25964bb90e2121ee489ec38642127e48d0cc2b6baa442688d3fde6262bfdca86d6bbf6ba708784afcac168c06840c71facac70e390f5f759ac121b9 + languageName: node + linkType: hard + +"meow@npm:^8.1.2": + version: 8.1.2 + resolution: "meow@npm:8.1.2" + dependencies: + "@types/minimist": "npm:^1.2.0" + camelcase-keys: "npm:^6.2.2" + decamelize-keys: "npm:^1.1.0" + hard-rejection: "npm:^2.1.0" + minimist-options: "npm:4.1.0" + normalize-package-data: "npm:^3.0.0" + read-pkg-up: "npm:^7.0.1" + redent: "npm:^3.0.0" + trim-newlines: "npm:^3.0.0" + type-fest: "npm:^0.18.0" + yargs-parser: "npm:^20.2.3" + checksum: 10c0/9a8d90e616f783650728a90f4ea1e5f763c1c5260369e6596b52430f877f4af8ecbaa8c9d952c93bbefd6d5bda4caed6a96a20ba7d27b511d2971909b01922a2 + languageName: node + linkType: hard + +"merge-descriptors@npm:1.0.3": + version: 1.0.3 + resolution: "merge-descriptors@npm:1.0.3" + checksum: 10c0/866b7094afd9293b5ea5dcd82d71f80e51514bed33b4c4e9f516795dc366612a4cbb4dc94356e943a8a6914889a914530badff27f397191b9b75cda20b6bae93 + languageName: node + linkType: hard + +"merge-descriptors@npm:^2.0.0": + version: 2.0.0 + resolution: "merge-descriptors@npm:2.0.0" + checksum: 10c0/95389b7ced3f9b36fbdcf32eb946dc3dd1774c2fdf164609e55b18d03aa499b12bd3aae3a76c1c7185b96279e9803525550d3eb292b5224866060a288f335cb3 + languageName: node + linkType: hard + +"merge-stream@npm:^2.0.0": + version: 2.0.0 + resolution: "merge-stream@npm:2.0.0" + checksum: 10c0/867fdbb30a6d58b011449b8885601ec1690c3e41c759ecd5a9d609094f7aed0096c37823ff4a7190ef0b8f22cc86beb7049196ff68c016e3b3c671d0dac91ce5 + languageName: node + linkType: hard + +"methods@npm:~1.1.2": + version: 1.1.2 + resolution: "methods@npm:1.1.2" + checksum: 10c0/bdf7cc72ff0a33e3eede03708c08983c4d7a173f91348b4b1e4f47d4cdbf734433ad971e7d1e8c77247d9e5cd8adb81ea4c67b0a2db526b758b2233d7814b8b2 + languageName: node + linkType: hard + +"micromatch@npm:^4.0.4": + version: 4.0.8 + resolution: "micromatch@npm:4.0.8" + dependencies: + braces: "npm:^3.0.3" + picomatch: "npm:^2.3.1" + checksum: 10c0/166fa6eb926b9553f32ef81f5f531d27b4ce7da60e5baf8c021d043b27a388fb95e46a8038d5045877881e673f8134122b59624d5cecbd16eb50a42e7a6b5ca8 + languageName: node + linkType: hard + +"mime-db@npm:1.52.0": + version: 1.52.0 + resolution: "mime-db@npm:1.52.0" + checksum: 10c0/0557a01deebf45ac5f5777fe7740b2a5c309c6d62d40ceab4e23da9f821899ce7a900b7ac8157d4548ddbb7beffe9abc621250e6d182b0397ec7f10c7b91a5aa + languageName: node + linkType: hard + +"mime-db@npm:^1.54.0": + version: 1.54.0 + resolution: "mime-db@npm:1.54.0" + checksum: 10c0/8d907917bc2a90fa2df842cdf5dfeaf509adc15fe0531e07bb2f6ab15992416479015828d6a74200041c492e42cce3ebf78e5ce714388a0a538ea9c53eece284 + languageName: node + linkType: hard + +"mime-types@npm:^2.1.12, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": + version: 2.1.35 + resolution: "mime-types@npm:2.1.35" + dependencies: + mime-db: "npm:1.52.0" + checksum: 10c0/82fb07ec56d8ff1fc999a84f2f217aa46cb6ed1033fefaabd5785b9a974ed225c90dc72fff460259e66b95b73648596dbcc50d51ed69cdf464af2d237d3149b2 + languageName: node + linkType: hard + +"mime-types@npm:^3.0.0, mime-types@npm:^3.0.2": + version: 3.0.2 + resolution: "mime-types@npm:3.0.2" + dependencies: + mime-db: "npm:^1.54.0" + checksum: 10c0/35a0dd1035d14d185664f346efcdb72e93ef7a9b6e9ae808bd1f6358227010267fab52657b37562c80fc888ff76becb2b2938deb5e730818b7983bf8bd359767 + languageName: node + linkType: hard + +"mime@npm:1.6.0": + version: 1.6.0 + resolution: "mime@npm:1.6.0" + bin: + mime: cli.js + checksum: 10c0/b92cd0adc44888c7135a185bfd0dddc42c32606401c72896a842ae15da71eb88858f17669af41e498b463cd7eb998f7b48939a25b08374c7924a9c8a6f8a81b0 + languageName: node + linkType: hard + +"mimic-fn@npm:^2.1.0": + version: 2.1.0 + resolution: "mimic-fn@npm:2.1.0" + checksum: 10c0/b26f5479d7ec6cc2bce275a08f146cf78f5e7b661b18114e2506dd91ec7ec47e7a25bf4360e5438094db0560bcc868079fb3b1fb3892b833c1ecbf63f80c95a4 + languageName: node + linkType: hard + +"min-indent@npm:^1.0.0": + version: 1.0.1 + resolution: "min-indent@npm:1.0.1" + checksum: 10c0/7e207bd5c20401b292de291f02913230cb1163abca162044f7db1d951fa245b174dc00869d40dd9a9f32a885ad6a5f3e767ee104cf278f399cb4e92d3f582d5c + languageName: node + linkType: hard + +"minimatch@npm:10.2.4": + version: 10.2.4 + resolution: "minimatch@npm:10.2.4" + dependencies: + brace-expansion: "npm:^5.0.2" + checksum: 10c0/35f3dfb7b99b51efd46afd378486889f590e7efb10e0f6a10ba6800428cf65c9a8dedb74427d0570b318d749b543dc4e85f06d46d2858bc8cac7e1eb49a95945 + languageName: node + linkType: hard + +"minimatch@npm:3.1.4": + version: 3.1.4 + resolution: "minimatch@npm:3.1.4" + dependencies: + brace-expansion: "npm:^1.1.7" + checksum: 10c0/868aab7e5f52570107eb283f021383be111cfeee0817a615f2a9ffe61fdc8fb86d535b9bf169fb8882261e7cb9da22b4d7b6f8b3402037f63558bab173f82212 + languageName: node + linkType: hard + +"minimatch@npm:^10.0.3, minimatch@npm:^10.1.1, minimatch@npm:^10.2.2": + version: 10.2.5 + resolution: "minimatch@npm:10.2.5" + dependencies: + brace-expansion: "npm:^5.0.5" + checksum: 10c0/6bb058bd6324104b9ec2f763476a35386d05079c1f5fe4fbf1f324a25237cd4534d6813ecd71f48208f4e635c1221899bef94c3c89f7df55698fe373aaae20fd + languageName: node + linkType: hard + +"minimatch@npm:^3.0.4, minimatch@npm:^3.1.1, minimatch@npm:^3.1.5": + version: 3.1.5 + resolution: "minimatch@npm:3.1.5" + dependencies: + brace-expansion: "npm:^1.1.7" + checksum: 10c0/2ecbdc0d33f07bddb0315a8b5afbcb761307a8778b48f0b312418ccbced99f104a2d17d8aca7573433c70e8ccd1c56823a441897a45e384ea76ef401a26ace70 + languageName: node + linkType: hard + +"minimatch@npm:^5.0.1, minimatch@npm:^5.1.0": + version: 5.1.9 + resolution: "minimatch@npm:5.1.9" + dependencies: + brace-expansion: "npm:^2.0.1" + checksum: 10c0/4202718683815a7288b13e470160a4f9560cf392adef4f453927505817e01ef6b3476ecde13cfcaed17e7326dd3b69ad44eb2daeb19a217c5500f9277893f1d6 + languageName: node + linkType: hard + +"minimatch@npm:^9.0.4": + version: 9.0.9 + resolution: "minimatch@npm:9.0.9" + dependencies: + brace-expansion: "npm:^2.0.2" + checksum: 10c0/0b6a58530dbb00361745aa6c8cffaba4c90f551afe7c734830bd95fd88ebf469dd7355a027824ea1d09e37181cfeb0a797fb17df60c15ac174303ac110eb7e86 + languageName: node + linkType: hard + +"minimist-options@npm:4.1.0": + version: 4.1.0 + resolution: "minimist-options@npm:4.1.0" + dependencies: + arrify: "npm:^1.0.1" + is-plain-obj: "npm:^1.1.0" + kind-of: "npm:^6.0.3" + checksum: 10c0/7871f9cdd15d1e7374e5b013e2ceda3d327a06a8c7b38ae16d9ef941e07d985e952c589e57213f7aa90a8744c60aed9524c0d85e501f5478382d9181f2763f54 + languageName: node + linkType: hard + +"minimist@npm:^1.2.5, minimist@npm:^1.2.6": + version: 1.2.8 + resolution: "minimist@npm:1.2.8" + checksum: 10c0/19d3fcdca050087b84c2029841a093691a91259a47def2f18222f41e7645a0b7c44ef4b40e88a1e58a40c84d2ef0ee6047c55594d298146d0eb3f6b737c20ce6 + languageName: node + linkType: hard + +"minipass-collect@npm:^2.0.1": + version: 2.0.1 + resolution: "minipass-collect@npm:2.0.1" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10c0/5167e73f62bb74cc5019594709c77e6a742051a647fe9499abf03c71dca75515b7959d67a764bdc4f8b361cf897fbf25e2d9869ee039203ed45240f48b9aa06e + languageName: node + linkType: hard + +"minipass-fetch@npm:^4.0.0": + version: 4.0.1 + resolution: "minipass-fetch@npm:4.0.1" + dependencies: + encoding: "npm:^0.1.13" + minipass: "npm:^7.0.3" + minipass-sized: "npm:^1.0.3" + minizlib: "npm:^3.0.1" + dependenciesMeta: + encoding: + optional: true + checksum: 10c0/a3147b2efe8e078c9bf9d024a0059339c5a09c5b1dded6900a219c218cc8b1b78510b62dae556b507304af226b18c3f1aeb1d48660283602d5b6586c399eed5c + languageName: node + linkType: hard + +"minipass-fetch@npm:^5.0.0": + version: 5.0.2 + resolution: "minipass-fetch@npm:5.0.2" + dependencies: + iconv-lite: "npm:^0.7.2" + minipass: "npm:^7.0.3" + minipass-sized: "npm:^2.0.0" + minizlib: "npm:^3.0.1" + dependenciesMeta: + iconv-lite: + optional: true + checksum: 10c0/ce4ab9f21cfabaead2097d95dd33f485af8072fbc6b19611bce694965393453a1639d641c2bcf1c48f2ea7d41ea7fab8278373f1d0bee4e63b0a5b2cdd0ef649 + languageName: node + linkType: hard + +"minipass-flush@npm:^1.0.5": + version: 1.0.7 + resolution: "minipass-flush@npm:1.0.7" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/960915c02aa0991662c37c404517dd93708d17f96533b2ca8c1e776d158715d8107c5ced425ffc61674c167d93607f07f48a83c139ce1057f8781e5dfb4b90c2 + languageName: node + linkType: hard + +"minipass-pipeline@npm:^1.2.4": + version: 1.2.4 + resolution: "minipass-pipeline@npm:1.2.4" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/cbda57cea20b140b797505dc2cac71581a70b3247b84480c1fed5ca5ba46c25ecc25f68bfc9e6dcb1a6e9017dab5c7ada5eab73ad4f0a49d84e35093e0c643f2 + languageName: node + linkType: hard + +"minipass-sized@npm:^1.0.3": + version: 1.0.3 + resolution: "minipass-sized@npm:1.0.3" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/298f124753efdc745cfe0f2bdfdd81ba25b9f4e753ca4a2066eb17c821f25d48acea607dfc997633ee5bf7b6dfffb4eee4f2051eb168663f0b99fad2fa4829cb + languageName: node + linkType: hard + +"minipass-sized@npm:^2.0.0": + version: 2.0.0 + resolution: "minipass-sized@npm:2.0.0" + dependencies: + minipass: "npm:^7.1.2" + checksum: 10c0/f9201696a6f6d68610d04c9c83e3d2e5cb9c026aae1c8cbf7e17f386105cb79c1bb088dbc21bf0b1eb4f3fb5df384fd1e7aa3bf1f33868c416ae8c8a92679db8 + languageName: node + linkType: hard + +"minipass@npm:^3.0.0": + version: 3.3.6 + resolution: "minipass@npm:3.3.6" + dependencies: + yallist: "npm:^4.0.0" + checksum: 10c0/a114746943afa1dbbca8249e706d1d38b85ed1298b530f5808ce51f8e9e941962e2a5ad2e00eae7dd21d8a4aae6586a66d4216d1a259385e9d0358f0c1eba16c + languageName: node + linkType: hard + +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2, minipass@npm:^7.1.3": + version: 7.1.3 + resolution: "minipass@npm:7.1.3" + checksum: 10c0/539da88daca16533211ea5a9ee98dc62ff5742f531f54640dd34429e621955e91cc280a91a776026264b7f9f6735947629f920944e9c1558369e8bf22eb33fbb + languageName: node + linkType: hard + +"minizlib@npm:^3.0.1, minizlib@npm:^3.1.0": + version: 3.1.0 + resolution: "minizlib@npm:3.1.0" + dependencies: + minipass: "npm:^7.1.2" + checksum: 10c0/5aad75ab0090b8266069c9aabe582c021ae53eb33c6c691054a13a45db3b4f91a7fb1bd79151e6b4e9e9a86727b522527c0a06ec7d45206b745d54cd3097bcec + languageName: node + linkType: hard + +"mkdirp-classic@npm:^0.5.2": + version: 0.5.3 + resolution: "mkdirp-classic@npm:0.5.3" + checksum: 10c0/95371d831d196960ddc3833cc6907e6b8f67ac5501a6582f47dfae5eb0f092e9f8ce88e0d83afcae95d6e2b61a01741ba03714eeafb6f7a6e9dcc158ac85b168 + languageName: node + linkType: hard + +"mkdirp@npm:^0.5.6": + version: 0.5.6 + resolution: "mkdirp@npm:0.5.6" + dependencies: + minimist: "npm:^1.2.6" + bin: + mkdirp: bin/cmd.js + checksum: 10c0/e2e2be789218807b58abced04e7b49851d9e46e88a2f9539242cc8a92c9b5c3a0b9bab360bd3014e02a140fc4fbc58e31176c408b493f8a2a6f4986bd7527b01 + languageName: node + linkType: hard + +"mkdirp@npm:^1.0.4": + version: 1.0.4 + resolution: "mkdirp@npm:1.0.4" + bin: + mkdirp: bin/cmd.js + checksum: 10c0/46ea0f3ffa8bc6a5bc0c7081ffc3907777f0ed6516888d40a518c5111f8366d97d2678911ad1a6882bf592fa9de6c784fea32e1687bb94e1f4944170af48a5cf + languageName: node + linkType: hard + +"mkdirp@npm:^3.0.1": + version: 3.0.1 + resolution: "mkdirp@npm:3.0.1" + bin: + mkdirp: dist/cjs/src/bin.js + checksum: 10c0/9f2b975e9246351f5e3a40dcfac99fcd0baa31fbfab615fe059fb11e51f10e4803c63de1f384c54d656e4db31d000e4767e9ef076a22e12a641357602e31d57d + languageName: node + linkType: hard + +"modify-values@npm:^1.0.1": + version: 1.0.1 + resolution: "modify-values@npm:1.0.1" + checksum: 10c0/6acb1b82aaf7a02f9f7b554b20cbfc159f223a79c66b0a257511c5933d50b85e12ea1220b0a90a2af6f80bc29ff784f929a52a51881867a93ae6a12ce87a729a + languageName: node + linkType: hard + +"moment-timezone@npm:^0.5.43": + version: 0.5.48 + resolution: "moment-timezone@npm:0.5.48" + dependencies: + moment: "npm:^2.29.4" + checksum: 10c0/ab14ec9d94bc33f29ac18e5417b7f8aca0b17130b952c5cc9697b8fea839e5ece9313af5fd3c9703a05db472b1560ddbfc7ad2aa24aac9afd047d6da6c3c6033 + languageName: node + linkType: hard + +"moment@npm:^2.29.4": + version: 2.30.1 + resolution: "moment@npm:2.30.1" + checksum: 10c0/865e4279418c6de666fca7786607705fd0189d8a7b7624e2e56be99290ac846f90878a6f602e34b4e0455c549b85385b1baf9966845962b313699e7cb847543a + languageName: node + linkType: hard + +"ms@npm:2.0.0": + version: 2.0.0 + resolution: "ms@npm:2.0.0" + checksum: 10c0/f8fda810b39fd7255bbdc451c46286e549794fcc700dc9cd1d25658bbc4dc2563a5de6fe7c60f798a16a60c6ceb53f033cb353f493f0cf63e5199b702943159d + languageName: node + linkType: hard + +"ms@npm:2.1.3, ms@npm:^2.0.0, ms@npm:^2.1.1, ms@npm:^2.1.3": + version: 2.1.3 + resolution: "ms@npm:2.1.3" + checksum: 10c0/d924b57e7312b3b63ad21fc5b3dc0af5e78d61a1fc7cfb5457edaf26326bf62be5307cc87ffb6862ef1c2b33b0233cdb5d4f01c4c958cc0d660948b65a287a48 + languageName: node + linkType: hard + +"msgpackr-extract@npm:^3.0.2": + version: 3.0.3 + resolution: "msgpackr-extract@npm:3.0.3" + dependencies: + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "npm:3.0.3" + "@msgpackr-extract/msgpackr-extract-darwin-x64": "npm:3.0.3" + "@msgpackr-extract/msgpackr-extract-linux-arm": "npm:3.0.3" + "@msgpackr-extract/msgpackr-extract-linux-arm64": "npm:3.0.3" + "@msgpackr-extract/msgpackr-extract-linux-x64": "npm:3.0.3" + "@msgpackr-extract/msgpackr-extract-win32-x64": "npm:3.0.3" + node-gyp: "npm:latest" + node-gyp-build-optional-packages: "npm:5.2.2" + dependenciesMeta: + "@msgpackr-extract/msgpackr-extract-darwin-arm64": + optional: true + "@msgpackr-extract/msgpackr-extract-darwin-x64": + optional: true + "@msgpackr-extract/msgpackr-extract-linux-arm": + optional: true + "@msgpackr-extract/msgpackr-extract-linux-arm64": + optional: true + "@msgpackr-extract/msgpackr-extract-linux-x64": + optional: true + "@msgpackr-extract/msgpackr-extract-win32-x64": + optional: true + bin: + download-msgpackr-prebuilds: bin/download-prebuilds.js + checksum: 10c0/e504fd8bf86a29d7527c83776530ee6dc92dcb0273bb3679fd4a85173efead7f0ee32fb82c8410a13c33ef32828c45f81118ffc0fbed5d6842e72299894623b4 + languageName: node + linkType: hard + +"msgpackr@npm:1.11.5": + version: 1.11.5 + resolution: "msgpackr@npm:1.11.5" + dependencies: + msgpackr-extract: "npm:^3.0.2" + dependenciesMeta: + msgpackr-extract: + optional: true + checksum: 10c0/f35ffd218661e8afc52490cde3dbf2656304e7940563c5313aa2f45e31ac5bdce3b58f27e55b785c700085ee76f26fc7afbae25ae5abe05068a8f000fd0ac6cd + languageName: node + linkType: hard + +"multer@npm:2.0.2": + version: 2.0.2 + resolution: "multer@npm:2.0.2" + dependencies: + append-field: "npm:^1.0.0" + busboy: "npm:^1.6.0" + concat-stream: "npm:^2.0.0" + mkdirp: "npm:^0.5.6" + object-assign: "npm:^4.1.1" + type-is: "npm:^1.6.18" + xtend: "npm:^4.0.2" + checksum: 10c0/d3b99dd0512169bbabf15440e1bbb3ecdc000b761e5a3e4aaca40b5e5e213c6cdcc9b7dffebaa601b7691a84f6876aa87e0173ffcc47139253793cf5657819eb + languageName: node + linkType: hard + +"mute-stream@npm:^2.0.0": + version: 2.0.0 + resolution: "mute-stream@npm:2.0.0" + checksum: 10c0/2cf48a2087175c60c8dcdbc619908b49c07f7adcfc37d29236b0c5c612d6204f789104c98cc44d38acab7b3c96f4a3ec2cfdc4934d0738d876dbefa2a12c69f4 + languageName: node + linkType: hard + +"nan@npm:^2.19.0, nan@npm:^2.23.0": + version: 2.26.2 + resolution: "nan@npm:2.26.2" + dependencies: + node-gyp: "npm:latest" + checksum: 10c0/ff204c964729279cf3abb8b170c77753ed36092e2235f11bfb0204dfd3e8cc2d5a3bcfdfd3b677f06a0743d7f835d873dce59f23a2dbf6fb671d9351cc655d73 + languageName: node + linkType: hard + +"napi-postinstall@npm:^0.3.0": + version: 0.3.4 + resolution: "napi-postinstall@npm:0.3.4" + bin: + napi-postinstall: lib/cli.js + checksum: 10c0/b33d64150828bdade3a5d07368a8b30da22ee393f8dd8432f1b9e5486867be21c84ec443dd875dd3ef3c7401a079a7ab7e2aa9d3538a889abbcd96495d5104fe + languageName: node + linkType: hard + +"natural-compare@npm:^1.4.0": + version: 1.4.0 + resolution: "natural-compare@npm:1.4.0" + checksum: 10c0/f5f9a7974bfb28a91afafa254b197f0f22c684d4a1731763dda960d2c8e375b36c7d690e0d9dc8fba774c537af14a7e979129bca23d88d052fbeb9466955e447 + languageName: node + linkType: hard + +"negotiator@npm:0.6.3": + version: 0.6.3 + resolution: "negotiator@npm:0.6.3" + checksum: 10c0/3ec9fd413e7bf071c937ae60d572bc67155262068ed522cf4b3be5edbe6ddf67d095ec03a3a14ebf8fc8e95f8e1d61be4869db0dbb0de696f6b837358bd43fc2 + languageName: node + linkType: hard + +"negotiator@npm:^1.0.0": + version: 1.0.0 + resolution: "negotiator@npm:1.0.0" + checksum: 10c0/4c559dd52669ea48e1914f9d634227c561221dd54734070791f999c52ed0ff36e437b2e07d5c1f6e32909fc625fe46491c16e4a8f0572567d4dd15c3a4fda04b + languageName: node + linkType: hard + +"neo-async@npm:^2.6.2": + version: 2.6.2 + resolution: "neo-async@npm:2.6.2" + checksum: 10c0/c2f5a604a54a8ec5438a342e1f356dff4bc33ccccdb6dc668d94fe8e5eccfc9d2c2eea6064b0967a767ba63b33763f51ccf2cd2441b461a7322656c1f06b3f5d + languageName: node + linkType: hard + +"nice-grpc-common@npm:^2.0.2": + version: 2.0.2 + resolution: "nice-grpc-common@npm:2.0.2" + dependencies: + ts-error: "npm:^1.0.6" + checksum: 10c0/9eb8a44e1a5c7051cf0e4a06dc7fda2c7abb6cfbcbb746806418c2c58f3f0075212c61bbce54239a204e6a552065f0fa92dfedcf3402dc16220b2ffaee4ab857 + languageName: node + linkType: hard + +"nice-grpc@npm:^2.1.0": + version: 2.1.14 + resolution: "nice-grpc@npm:2.1.14" + dependencies: + "@grpc/grpc-js": "npm:^1.14.0" + abort-controller-x: "npm:^0.4.0" + nice-grpc-common: "npm:^2.0.2" + checksum: 10c0/e9d0978d6167090b3fe7bb2ecb3b6cfbfcdb0da08a2ab20ca570d2ef38eee6e66da47860b431c47c228e2bf74fe6c0de2e382425ccdcaba95e4fffaad139ea9c + languageName: node + linkType: hard + +"node-abort-controller@npm:3.1.1": + version: 3.1.1 + resolution: "node-abort-controller@npm:3.1.1" + checksum: 10c0/f7ad0e7a8e33809d4f3a0d1d65036a711c39e9d23e0319d80ebe076b9a3b4432b4d6b86a7fab65521de3f6872ffed36fc35d1327487c48eb88c517803403eda3 + languageName: node + linkType: hard + +"node-addon-api@npm:^8.3.0": + version: 8.7.0 + resolution: "node-addon-api@npm:8.7.0" + dependencies: + node-gyp: "npm:latest" + checksum: 10c0/31a03b00f6b0753ab08360952fdf80a1abb619dcf8125fa1ab07e3a414da050963440c3a86c77a0334c0be7a71acb5e242dc468b79201ee6151c7b943afe946d + languageName: node + linkType: hard + +"node-domexception@npm:1.0.0": + version: 1.0.0 + resolution: "node-domexception@npm:1.0.0" + checksum: 10c0/5e5d63cda29856402df9472335af4bb13875e1927ad3be861dc5ebde38917aecbf9ae337923777af52a48c426b70148815e890a5d72760f1b4d758cc671b1a2b + languageName: node + linkType: hard + +"node-fetch@npm:^2.6.1, node-fetch@npm:^2.6.7": + version: 2.7.0 + resolution: "node-fetch@npm:2.7.0" + dependencies: + whatwg-url: "npm:^5.0.0" + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + checksum: 10c0/b55786b6028208e6fbe594ccccc213cab67a72899c9234eb59dba51062a299ea853210fcf526998eaa2867b0963ad72338824450905679ff0fa304b8c5093ae8 + languageName: node + linkType: hard + +"node-gyp-build-optional-packages@npm:5.2.2": + version: 5.2.2 + resolution: "node-gyp-build-optional-packages@npm:5.2.2" + dependencies: + detect-libc: "npm:^2.0.1" + bin: + node-gyp-build-optional-packages: bin.js + node-gyp-build-optional-packages-optional: optional.js + node-gyp-build-optional-packages-test: build-test.js + checksum: 10c0/c81128c6f91873381be178c5eddcbdf66a148a6a89a427ce2bcd457593ce69baf2a8662b6d22cac092d24aa9c43c230dec4e69b3a0da604503f4777cd77e282b + languageName: node + linkType: hard + +"node-gyp-build@npm:^4.8.4": + version: 4.8.4 + resolution: "node-gyp-build@npm:4.8.4" + bin: + node-gyp-build: bin.js + node-gyp-build-optional: optional.js + node-gyp-build-test: build-test.js + checksum: 10c0/444e189907ece2081fe60e75368784f7782cfddb554b60123743dfb89509df89f1f29c03bbfa16b3a3e0be3f48799a4783f487da6203245fa5bed239ba7407e1 + languageName: node + linkType: hard + +"node-gyp@npm:^12.1.0, node-gyp@npm:latest": + version: 12.2.0 + resolution: "node-gyp@npm:12.2.0" + dependencies: + env-paths: "npm:^2.2.0" + exponential-backoff: "npm:^3.1.1" + graceful-fs: "npm:^4.2.6" + make-fetch-happen: "npm:^15.0.0" + nopt: "npm:^9.0.0" + proc-log: "npm:^6.0.0" + semver: "npm:^7.3.5" + tar: "npm:^7.5.4" + tinyglobby: "npm:^0.2.12" + which: "npm:^6.0.0" + bin: + node-gyp: bin/node-gyp.js + checksum: 10c0/3ed046746a5a7d90950cd8b0547332b06598443f31fe213ef4332a7174c7b7d259e1704835feda79b87d3f02e59d7791842aac60642ede4396ab25fdf0f8f759 + languageName: node + linkType: hard + +"node-int64@npm:^0.4.0": + version: 0.4.0 + resolution: "node-int64@npm:0.4.0" + checksum: 10c0/a6a4d8369e2f2720e9c645255ffde909c0fbd41c92ea92a5607fc17055955daac99c1ff589d421eee12a0d24e99f7bfc2aabfeb1a4c14742f6c099a51863f31a + languageName: node + linkType: hard + +"node-releases@npm:^2.0.36": + version: 2.0.37 + resolution: "node-releases@npm:2.0.37" + checksum: 10c0/306df89190b3225d0cb001260de52f0befd225a782ec85311ce97b0aa3b2e22f5e4e4c00395c6dc9bc9ef440c64723f6205fe1e27d32b8dd1d140891fbadf901 + languageName: node + linkType: hard + +"nopt@npm:^8.0.0": + version: 8.1.0 + resolution: "nopt@npm:8.1.0" + dependencies: + abbrev: "npm:^3.0.0" + bin: + nopt: bin/nopt.js + checksum: 10c0/62e9ea70c7a3eb91d162d2c706b6606c041e4e7b547cbbb48f8b3695af457dd6479904d7ace600856bf923dd8d1ed0696f06195c8c20f02ac87c1da0e1d315ef + languageName: node + linkType: hard + +"nopt@npm:^9.0.0": + version: 9.0.0 + resolution: "nopt@npm:9.0.0" + dependencies: + abbrev: "npm:^4.0.0" + bin: + nopt: bin/nopt.js + checksum: 10c0/1822eb6f9b020ef6f7a7516d7b64a8036e09666ea55ac40416c36e4b2b343122c3cff0e2f085675f53de1d2db99a2a89a60ccea1d120bcd6a5347bf6ceb4a7fd + languageName: node + linkType: hard + +"normalize-package-data@npm:^2.3.2, normalize-package-data@npm:^2.5.0": + version: 2.5.0 + resolution: "normalize-package-data@npm:2.5.0" + dependencies: + hosted-git-info: "npm:^2.1.4" + resolve: "npm:^1.10.0" + semver: "npm:2 || 3 || 4 || 5" + validate-npm-package-license: "npm:^3.0.1" + checksum: 10c0/357cb1646deb42f8eb4c7d42c4edf0eec312f3628c2ef98501963cc4bbe7277021b2b1d977f982b2edce78f5a1014613ce9cf38085c3df2d76730481357ca504 + languageName: node + linkType: hard + +"normalize-package-data@npm:^3.0.0, normalize-package-data@npm:^3.0.3": + version: 3.0.3 + resolution: "normalize-package-data@npm:3.0.3" + dependencies: + hosted-git-info: "npm:^4.0.1" + is-core-module: "npm:^2.5.0" + semver: "npm:^7.3.4" + validate-npm-package-license: "npm:^3.0.1" + checksum: 10c0/e5d0f739ba2c465d41f77c9d950e291ea4af78f8816ddb91c5da62257c40b76d8c83278b0d08ffbcd0f187636ebddad20e181e924873916d03e6e5ea2ef026be + languageName: node + linkType: hard + +"normalize-path@npm:^3.0.0": + version: 3.0.0 + resolution: "normalize-path@npm:3.0.0" + checksum: 10c0/e008c8142bcc335b5e38cf0d63cfd39d6cf2d97480af9abdbe9a439221fd4d749763bab492a8ee708ce7a194bb00c9da6d0a115018672310850489137b3da046 + languageName: node + linkType: hard + +"npm-bundled@npm:^4.0.0": + version: 4.0.0 + resolution: "npm-bundled@npm:4.0.0" + dependencies: + npm-normalize-package-bin: "npm:^4.0.0" + checksum: 10c0/e6e20caefbc6a41138d3767ec998f6a2cf55f33371c119417a556ff6052390a2ffeb3b465a74aea127fb211ddfcb7db776620faf12b64e48e60e332b25b5b8a0 + languageName: node + linkType: hard + +"npm-bundled@npm:^5.0.0": + version: 5.0.0 + resolution: "npm-bundled@npm:5.0.0" + dependencies: + npm-normalize-package-bin: "npm:^5.0.0" + checksum: 10c0/6408b38343b51d5e329a0a4af4cf19d7872bc9099f6f7553fbadb5d56e69092d5af76fe501fa0817fcb8af29cf3cc8f8806a88031580f54068e5e80abf1ca870 + languageName: node + linkType: hard + +"npm-install-checks@npm:^7.1.0": + version: 7.1.2 + resolution: "npm-install-checks@npm:7.1.2" + dependencies: + semver: "npm:^7.1.1" + checksum: 10c0/eb490ac637869f6de65af0886f3a96f4d942609f1b3cfe0caf08b73bd76aff35ca4613fd3cbc36f3219727bc3183322051d1468b065911a59dbf87ecdb603bce + languageName: node + linkType: hard + +"npm-install-checks@npm:^8.0.0": + version: 8.0.0 + resolution: "npm-install-checks@npm:8.0.0" + dependencies: + semver: "npm:^7.1.1" + checksum: 10c0/a979cbc8fceacedf91bf59c2883f46f3c56bd421869f6664cce66aa605af14f875041730e66f3d1c543d49bdb032cbb147cdb481a17c541780d016bc2df89141 + languageName: node + linkType: hard + +"npm-normalize-package-bin@npm:^4.0.0": + version: 4.0.0 + resolution: "npm-normalize-package-bin@npm:4.0.0" + checksum: 10c0/1fa546fcae8eaab61ef9b9ec237b6c795008da50e1883eae030e9e38bb04ffa32c5aabcef9a0400eae3dc1f91809bcfa85e437ce80d677c69b419d1d9cacf0ab + languageName: node + linkType: hard + +"npm-normalize-package-bin@npm:^5.0.0": + version: 5.0.0 + resolution: "npm-normalize-package-bin@npm:5.0.0" + checksum: 10c0/9cd875669354ce451779495a111dc1622bedf702f7ad8b36b05b4037a2c961356361cff49c1e2e77d90b80194dffd18fdb52f16bf64e00ccffe6129003a55248 + languageName: node + linkType: hard + +"npm-package-arg@npm:13.0.1": + version: 13.0.1 + resolution: "npm-package-arg@npm:13.0.1" + dependencies: + hosted-git-info: "npm:^9.0.0" + proc-log: "npm:^5.0.0" + semver: "npm:^7.3.5" + validate-npm-package-name: "npm:^6.0.0" + checksum: 10c0/14ff9f491e2a1c68b5a0b0faede011179663e2ae59b96bf9fa3e4ea95ee1927fc3a20c0967e9dc20e0ee0ebddb7ea2172bd83abd4e7a5689ed837d156ad0f79f + languageName: node + linkType: hard + +"npm-package-arg@npm:^12.0.0": + version: 12.0.2 + resolution: "npm-package-arg@npm:12.0.2" + dependencies: + hosted-git-info: "npm:^8.0.0" + proc-log: "npm:^5.0.0" + semver: "npm:^7.3.5" + validate-npm-package-name: "npm:^6.0.0" + checksum: 10c0/a507046ca0999862d6f1a4878d2e22d47a728062b49d670ea7a965b0b555fc84ba4473daf34eb72c711b68aeb02e4f567fdb410d54385535cb7e4d85aaf49544 + languageName: node + linkType: hard + +"npm-package-arg@npm:^13.0.0": + version: 13.0.2 + resolution: "npm-package-arg@npm:13.0.2" + dependencies: + hosted-git-info: "npm:^9.0.0" + proc-log: "npm:^6.0.0" + semver: "npm:^7.3.5" + validate-npm-package-name: "npm:^7.0.0" + checksum: 10c0/bf4ecdbfac876250f17710c6d0fac014bb345555acc80ce3b9e685d828107f3682378a9c413278c2fe4e958f4aad261677769be9a2b7c3965ab219b5bb852197 + languageName: node + linkType: hard + +"npm-packlist@npm:10.0.3": + version: 10.0.3 + resolution: "npm-packlist@npm:10.0.3" + dependencies: + ignore-walk: "npm:^8.0.0" + proc-log: "npm:^6.0.0" + checksum: 10c0/f4fa58890e7d9e80299c284cdf65fafac6eae0c23b830bbae9953255571364897a6f22a02b5da63f0c43e45019d7446feec6ed79124edc6a44c8d6c9a19d25cf + languageName: node + linkType: hard + +"npm-packlist@npm:^10.0.1": + version: 10.0.4 + resolution: "npm-packlist@npm:10.0.4" + dependencies: + ignore-walk: "npm:^8.0.0" + proc-log: "npm:^6.0.0" + checksum: 10c0/500ec00ed5edc3f7136255a8c17dfd36fb718182af61a86a68768aa3b325f69739953fe8888fa8e4765db00e7892a9d0a30093b145d091b23e96b7d1bbf1187e + languageName: node + linkType: hard + +"npm-pick-manifest@npm:^10.0.0": + version: 10.0.0 + resolution: "npm-pick-manifest@npm:10.0.0" + dependencies: + npm-install-checks: "npm:^7.1.0" + npm-normalize-package-bin: "npm:^4.0.0" + npm-package-arg: "npm:^12.0.0" + semver: "npm:^7.3.5" + checksum: 10c0/946e791f6164a04dbc3340749cd7521d4d1f60accb2d0ca901375314b8425c8a12b34b4b70e2850462cc898fba5fa8d1f283221bf788a1d37276f06a85c4562a + languageName: node + linkType: hard + +"npm-pick-manifest@npm:^11.0.1": + version: 11.0.3 + resolution: "npm-pick-manifest@npm:11.0.3" + dependencies: + npm-install-checks: "npm:^8.0.0" + npm-normalize-package-bin: "npm:^5.0.0" + npm-package-arg: "npm:^13.0.0" + semver: "npm:^7.3.5" + checksum: 10c0/214a9966de69bbb1e3c4ade8f33e99fefa1bdc7cbef480e4d2dc3fa63104e05f94bd84b56814c13b20bf838398bfc72f39691cb5d06d7c17333fe0ee33fe3e71 + languageName: node + linkType: hard + +"npm-registry-fetch@npm:19.1.0": + version: 19.1.0 + resolution: "npm-registry-fetch@npm:19.1.0" + dependencies: + "@npmcli/redact": "npm:^3.0.0" + jsonparse: "npm:^1.3.1" + make-fetch-happen: "npm:^15.0.0" + minipass: "npm:^7.0.2" + minipass-fetch: "npm:^4.0.0" + minizlib: "npm:^3.0.1" + npm-package-arg: "npm:^13.0.0" + proc-log: "npm:^5.0.0" + checksum: 10c0/f326a0ba808b159da0ef8aec28411eec49972477584485211f48a47915d90750c9c589c187521dadb4053b5959bde911c4a6151596cb4ff19bd42aada315c609 + languageName: node + linkType: hard + +"npm-registry-fetch@npm:^19.0.0": + version: 19.1.1 + resolution: "npm-registry-fetch@npm:19.1.1" + dependencies: + "@npmcli/redact": "npm:^4.0.0" + jsonparse: "npm:^1.3.1" + make-fetch-happen: "npm:^15.0.0" + minipass: "npm:^7.0.2" + minipass-fetch: "npm:^5.0.0" + minizlib: "npm:^3.0.1" + npm-package-arg: "npm:^13.0.0" + proc-log: "npm:^6.0.0" + checksum: 10c0/19903dc5cfd6cfc0d6922e4eeac042e95461f4cc58d280e6d6585e187a839a1d039c6a25b909157d7d655016aec8a8a5f3fa75f62cffa87ac133f95842e12b2c + languageName: node + linkType: hard + +"npm-run-path@npm:^4.0.1": + version: 4.0.1 + resolution: "npm-run-path@npm:4.0.1" + dependencies: + path-key: "npm:^3.0.0" + checksum: 10c0/6f9353a95288f8455cf64cbeb707b28826a7f29690244c1e4bb61ec573256e021b6ad6651b394eb1ccfd00d6ec50147253aba2c5fe58a57ceb111fad62c519ac + languageName: node + linkType: hard + +"nx@npm:22.6.4, nx@npm:>=21.5.3 < 23.0.0, nx@npm:^22.6.4": + version: 22.6.4 + resolution: "nx@npm:22.6.4" + dependencies: + "@ltd/j-toml": "npm:^1.38.0" + "@napi-rs/wasm-runtime": "npm:0.2.4" + "@nx/nx-darwin-arm64": "npm:22.6.4" + "@nx/nx-darwin-x64": "npm:22.6.4" + "@nx/nx-freebsd-x64": "npm:22.6.4" + "@nx/nx-linux-arm-gnueabihf": "npm:22.6.4" + "@nx/nx-linux-arm64-gnu": "npm:22.6.4" + "@nx/nx-linux-arm64-musl": "npm:22.6.4" + "@nx/nx-linux-x64-gnu": "npm:22.6.4" + "@nx/nx-linux-x64-musl": "npm:22.6.4" + "@nx/nx-win32-arm64-msvc": "npm:22.6.4" + "@nx/nx-win32-x64-msvc": "npm:22.6.4" + "@yarnpkg/lockfile": "npm:^1.1.0" + "@yarnpkg/parsers": "npm:3.0.2" + "@zkochan/js-yaml": "npm:0.0.7" + axios: "npm:1.12.0" + cli-cursor: "npm:3.1.0" + cli-spinners: "npm:2.6.1" + cliui: "npm:^8.0.1" + dotenv: "npm:~16.4.5" + dotenv-expand: "npm:~11.0.6" + ejs: "npm:^3.1.7" + enquirer: "npm:~2.3.6" + figures: "npm:3.2.0" + flat: "npm:^5.0.2" + front-matter: "npm:^4.0.2" + ignore: "npm:^7.0.5" + jest-diff: "npm:^30.0.2" + jsonc-parser: "npm:3.2.0" + lines-and-columns: "npm:2.0.3" + minimatch: "npm:10.2.4" + npm-run-path: "npm:^4.0.1" + open: "npm:^8.4.0" + ora: "npm:5.3.0" + picocolors: "npm:^1.1.0" + resolve.exports: "npm:2.0.3" + semver: "npm:^7.6.3" + string-width: "npm:^4.2.3" + tar-stream: "npm:~2.2.0" + tmp: "npm:~0.2.1" + tree-kill: "npm:^1.2.2" + tsconfig-paths: "npm:^4.1.2" + tslib: "npm:^2.3.0" + yaml: "npm:^2.6.0" + yargs: "npm:^17.6.2" + yargs-parser: "npm:21.1.1" + peerDependencies: + "@swc-node/register": ^1.11.1 + "@swc/core": ^1.15.8 + dependenciesMeta: + "@nx/nx-darwin-arm64": + optional: true + "@nx/nx-darwin-x64": + optional: true + "@nx/nx-freebsd-x64": + optional: true + "@nx/nx-linux-arm-gnueabihf": + optional: true + "@nx/nx-linux-arm64-gnu": + optional: true + "@nx/nx-linux-arm64-musl": + optional: true + "@nx/nx-linux-x64-gnu": + optional: true + "@nx/nx-linux-x64-musl": + optional: true + "@nx/nx-win32-arm64-msvc": + optional: true + "@nx/nx-win32-x64-msvc": + optional: true + peerDependenciesMeta: + "@swc-node/register": + optional: true + "@swc/core": + optional: true + bin: + nx: bin/nx.js + nx-cloud: bin/nx-cloud.js + checksum: 10c0/96ceb9691abb7bec654377394344491cce5fa8b4c888c18a9954850fa2c3d1268c62690653b3eaeec52704aa70cc429cfd8866ae8e5931db3d53719302193680 + languageName: node + linkType: hard + +"object-assign@npm:^4, object-assign@npm:^4.1.1": + version: 4.1.1 + resolution: "object-assign@npm:4.1.1" + checksum: 10c0/1f4df9945120325d041ccf7b86f31e8bcc14e73d29171e37a7903050e96b81323784ec59f93f102ec635bcf6fa8034ba3ea0a8c7e69fa202b87ae3b6cec5a414 + languageName: node + linkType: hard + +"object-inspect@npm:^1.13.3": + version: 1.13.4 + resolution: "object-inspect@npm:1.13.4" + checksum: 10c0/d7f8711e803b96ea3191c745d6f8056ce1f2496e530e6a19a0e92d89b0fa3c76d910c31f0aa270432db6bd3b2f85500a376a83aaba849a8d518c8845b3211692 + languageName: node + linkType: hard + +"on-finished@npm:^2.4.1, on-finished@npm:~2.4.1": + version: 2.4.1 + resolution: "on-finished@npm:2.4.1" + dependencies: + ee-first: "npm:1.1.1" + checksum: 10c0/46fb11b9063782f2d9968863d9cbba33d77aa13c17f895f56129c274318b86500b22af3a160fe9995aa41317efcd22941b6eba747f718ced08d9a73afdb087b4 + languageName: node + linkType: hard + +"once@npm:^1.3.0, once@npm:^1.3.1, once@npm:^1.4.0": + version: 1.4.0 + resolution: "once@npm:1.4.0" + dependencies: + wrappy: "npm:1" + checksum: 10c0/5d48aca287dfefabd756621c5dfce5c91a549a93e9fdb7b8246bc4c4790aa2ec17b34a260530474635147aeb631a2dcc8b32c613df0675f96041cbb8244517d0 + languageName: node + linkType: hard + +"one-time@npm:^1.0.0": + version: 1.0.0 + resolution: "one-time@npm:1.0.0" + dependencies: + fn.name: "npm:1.x.x" + checksum: 10c0/6e4887b331edbb954f4e915831cbec0a7b9956c36f4feb5f6de98c448ac02ff881fd8d9b55a6b1b55030af184c6b648f340a76eb211812f4ad8c9b4b8692fdaa + languageName: node + linkType: hard + +"onetime@npm:^5.1.0, onetime@npm:^5.1.2": + version: 5.1.2 + resolution: "onetime@npm:5.1.2" + dependencies: + mimic-fn: "npm:^2.1.0" + checksum: 10c0/ffcef6fbb2692c3c40749f31ea2e22677a876daea92959b8a80b521d95cca7a668c884d8b2045d1d8ee7d56796aa405c405462af112a1477594cc63531baeb8f + languageName: node + linkType: hard + +"open@npm:^8.4.0": + version: 8.4.2 + resolution: "open@npm:8.4.2" + dependencies: + define-lazy-prop: "npm:^2.0.0" + is-docker: "npm:^2.1.1" + is-wsl: "npm:^2.2.0" + checksum: 10c0/bb6b3a58401dacdb0aad14360626faf3fb7fba4b77816b373495988b724fb48941cad80c1b65d62bb31a17609b2cd91c41a181602caea597ca80dfbcc27e84c9 + languageName: node + linkType: hard + +"openai@npm:^4.77.0": + version: 4.104.0 + resolution: "openai@npm:4.104.0" + dependencies: + "@types/node": "npm:^18.11.18" + "@types/node-fetch": "npm:^2.6.4" + abort-controller: "npm:^3.0.0" + agentkeepalive: "npm:^4.2.1" + form-data-encoder: "npm:1.7.2" + formdata-node: "npm:^4.3.2" + node-fetch: "npm:^2.6.7" + peerDependencies: + ws: ^8.18.0 + zod: ^3.23.8 + peerDependenciesMeta: + ws: + optional: true + zod: + optional: true + bin: + openai: bin/cli + checksum: 10c0/c4f2e837684ed96b8cec58c65a584646d667c69918f29052775e2e8c05ff5c860d8b58214a7770bc6895ca8602480420c1db6a5392dd250179eb0b91c2b19a2f + languageName: node + linkType: hard + +"openai@npm:^6": + version: 6.33.0 + resolution: "openai@npm:6.33.0" + peerDependencies: + ws: ^8.18.0 + zod: ^3.25 || ^4.0 + peerDependenciesMeta: + ws: + optional: true + zod: + optional: true + bin: + openai: bin/cli + checksum: 10c0/158b6466469d269e944ea64453e32f116193523f0fbe93e73193ebfd84e1be40d5bc2d6dbfada327d8b7c70ede4c6530c5e023e1dfb62a11b8706c46c6dc1889 + languageName: node + linkType: hard + +"optionator@npm:^0.9.3": + version: 0.9.4 + resolution: "optionator@npm:0.9.4" + dependencies: + deep-is: "npm:^0.1.3" + fast-levenshtein: "npm:^2.0.6" + levn: "npm:^0.4.1" + prelude-ls: "npm:^1.2.1" + type-check: "npm:^0.4.0" + word-wrap: "npm:^1.2.5" + checksum: 10c0/4afb687a059ee65b61df74dfe87d8d6815cd6883cb8b3d5883a910df72d0f5d029821f37025e4bccf4048873dbdb09acc6d303d27b8f76b1a80dd5a7d5334675 + languageName: node + linkType: hard + +"ora@npm:5.3.0": + version: 5.3.0 + resolution: "ora@npm:5.3.0" + dependencies: + bl: "npm:^4.0.3" + chalk: "npm:^4.1.0" + cli-cursor: "npm:^3.1.0" + cli-spinners: "npm:^2.5.0" + is-interactive: "npm:^1.0.0" + log-symbols: "npm:^4.0.0" + strip-ansi: "npm:^6.0.0" + wcwidth: "npm:^1.0.1" + checksum: 10c0/30d5f3218eb75b0a2028c5fb9aa88e83e38a2f1745ab56839abb06c3ba31bae35f768f4e72c4f9e04e2a66be6a898e9312e8cf85c9333e1e3613eabb8c7cdf57 + languageName: node + linkType: hard + +"p-finally@npm:^1.0.0": + version: 1.0.0 + resolution: "p-finally@npm:1.0.0" + checksum: 10c0/6b8552339a71fe7bd424d01d8451eea92d379a711fc62f6b2fe64cad8a472c7259a236c9a22b4733abca0b5666ad503cb497792a0478c5af31ded793d00937e7 + languageName: node + linkType: hard + +"p-limit@npm:^1.1.0": + version: 1.3.0 + resolution: "p-limit@npm:1.3.0" + dependencies: + p-try: "npm:^1.0.0" + checksum: 10c0/5c1b1d53d180b2c7501efb04b7c817448e10efe1ba46f4783f8951994d5027e4cd88f36ad79af50546682594c4ebd11702ac4b9364c47f8074890e2acad0edee + languageName: node + linkType: hard + +"p-limit@npm:^2.2.0": + version: 2.3.0 + resolution: "p-limit@npm:2.3.0" + dependencies: + p-try: "npm:^2.0.0" + checksum: 10c0/8da01ac53efe6a627080fafc127c873da40c18d87b3f5d5492d465bb85ec7207e153948df6b9cbaeb130be70152f874229b8242ee2be84c0794082510af97f12 + languageName: node + linkType: hard + +"p-limit@npm:^3.0.2, p-limit@npm:^3.1.0": + version: 3.1.0 + resolution: "p-limit@npm:3.1.0" + dependencies: + yocto-queue: "npm:^0.1.0" + checksum: 10c0/9db675949dbdc9c3763c89e748d0ef8bdad0afbb24d49ceaf4c46c02c77d30db4e0652ed36d0a0a7a95154335fab810d95c86153105bb73b3a90448e2bb14e1a + languageName: node + linkType: hard + +"p-locate@npm:^2.0.0": + version: 2.0.0 + resolution: "p-locate@npm:2.0.0" + dependencies: + p-limit: "npm:^1.1.0" + checksum: 10c0/82da4be88fb02fd29175e66021610c881938d3cc97c813c71c1a605fac05617d57fd5d3b337494a6106c0edb2a37c860241430851411f1b265108cead34aee67 + languageName: node + linkType: hard + +"p-locate@npm:^4.1.0": + version: 4.1.0 + resolution: "p-locate@npm:4.1.0" + dependencies: + p-limit: "npm:^2.2.0" + checksum: 10c0/1b476ad69ad7f6059744f343b26d51ce091508935c1dbb80c4e0a2f397ffce0ca3a1f9f5cd3c7ce19d7929a09719d5c65fe70d8ee289c3f267cd36f2881813e9 + languageName: node + linkType: hard + +"p-locate@npm:^5.0.0": + version: 5.0.0 + resolution: "p-locate@npm:5.0.0" + dependencies: + p-limit: "npm:^3.0.2" + checksum: 10c0/2290d627ab7903b8b70d11d384fee714b797f6040d9278932754a6860845c4d3190603a0772a663c8cb5a7b21d1b16acb3a6487ebcafa9773094edc3dfe6009a + languageName: node + linkType: hard + +"p-map-series@npm:2.1.0": + version: 2.1.0 + resolution: "p-map-series@npm:2.1.0" + checksum: 10c0/302ca686a61c498b227fc45d4e2b2e5bfd20a03f4156a976d94c4ff7decf9cd5a815fa6846b43b37d587ffa8d4671ff2bd596fa83fe8b9113b5102da94940e2a + languageName: node + linkType: hard + +"p-map@npm:4.0.0": + version: 4.0.0 + resolution: "p-map@npm:4.0.0" + dependencies: + aggregate-error: "npm:^3.0.0" + checksum: 10c0/592c05bd6262c466ce269ff172bb8de7c6975afca9b50c975135b974e9bdaafbfe80e61aaaf5be6d1200ba08b30ead04b88cfa7e25ff1e3b93ab28c9f62a2c75 + languageName: node + linkType: hard + +"p-map@npm:^7.0.2": + version: 7.0.4 + resolution: "p-map@npm:7.0.4" + checksum: 10c0/a5030935d3cb2919d7e89454d1ce82141e6f9955413658b8c9403cfe379283770ed3048146b44cde168aa9e8c716505f196d5689db0ae3ce9a71521a2fef3abd + languageName: node + linkType: hard + +"p-pipe@npm:3.1.0": + version: 3.1.0 + resolution: "p-pipe@npm:3.1.0" + checksum: 10c0/9b3076828ea7e9469c0f92c78fa44096726208d547efdb2d6148cbe135d1a70bd449de5be13e234dd669d9515343bd68527b316bf9d5639cee639e2fdde20aaf + languageName: node + linkType: hard + +"p-queue@npm:6.6.2": + version: 6.6.2 + resolution: "p-queue@npm:6.6.2" + dependencies: + eventemitter3: "npm:^4.0.4" + p-timeout: "npm:^3.2.0" + checksum: 10c0/5739ecf5806bbeadf8e463793d5e3004d08bb3f6177bd1a44a005da8fd81bb90f80e4633e1fb6f1dfd35ee663a5c0229abe26aebb36f547ad5a858347c7b0d3e + languageName: node + linkType: hard + +"p-reduce@npm:2.1.0, p-reduce@npm:^2.0.0": + version: 2.1.0 + resolution: "p-reduce@npm:2.1.0" + checksum: 10c0/27b8ff0fb044995507a06cd6357dffba0f2b98862864745972562a21885d7906ce5c794036d2aaa63ef6303158e41e19aed9f19651dfdafb38548ecec7d0de15 + languageName: node + linkType: hard + +"p-timeout@npm:^3.2.0": + version: 3.2.0 + resolution: "p-timeout@npm:3.2.0" + dependencies: + p-finally: "npm:^1.0.0" + checksum: 10c0/524b393711a6ba8e1d48137c5924749f29c93d70b671e6db761afa784726572ca06149c715632da8f70c090073afb2af1c05730303f915604fd38ee207b70a61 + languageName: node + linkType: hard + +"p-try@npm:^1.0.0": + version: 1.0.0 + resolution: "p-try@npm:1.0.0" + checksum: 10c0/757ba31de5819502b80c447826fac8be5f16d3cb4fbf9bc8bc4971dba0682e84ac33e4b24176ca7058c69e29f64f34d8d9e9b08e873b7b7bb0aa89d620fa224a + languageName: node + linkType: hard + +"p-try@npm:^2.0.0": + version: 2.2.0 + resolution: "p-try@npm:2.2.0" + checksum: 10c0/c36c19907734c904b16994e6535b02c36c2224d433e01a2f1ab777237f4d86e6289fd5fd464850491e940379d4606ed850c03e0f9ab600b0ebddb511312e177f + languageName: node + linkType: hard + +"p-waterfall@npm:2.1.1": + version: 2.1.1 + resolution: "p-waterfall@npm:2.1.1" + dependencies: + p-reduce: "npm:^2.0.0" + checksum: 10c0/ccae582b75a3597018a375f8eac32b93e8bfb9fc22a8e5037787ef4ebf5958d7465c2d3cbe26443971fbbfda2bcb7b645f694b91f928fc9a71fa5031e6e33f85 + languageName: node + linkType: hard + +"package-json-from-dist@npm:^1.0.0": + version: 1.0.1 + resolution: "package-json-from-dist@npm:1.0.1" + checksum: 10c0/62ba2785eb655fec084a257af34dbe24292ab74516d6aecef97ef72d4897310bc6898f6c85b5cd22770eaa1ce60d55a0230e150fb6a966e3ecd6c511e23d164b + languageName: node + linkType: hard + +"pacote@npm:21.0.1": + version: 21.0.1 + resolution: "pacote@npm:21.0.1" + dependencies: + "@npmcli/git": "npm:^6.0.0" + "@npmcli/installed-package-contents": "npm:^3.0.0" + "@npmcli/package-json": "npm:^7.0.0" + "@npmcli/promise-spawn": "npm:^8.0.0" + "@npmcli/run-script": "npm:^10.0.0" + cacache: "npm:^20.0.0" + fs-minipass: "npm:^3.0.0" + minipass: "npm:^7.0.2" + npm-package-arg: "npm:^13.0.0" + npm-packlist: "npm:^10.0.1" + npm-pick-manifest: "npm:^10.0.0" + npm-registry-fetch: "npm:^19.0.0" + proc-log: "npm:^5.0.0" + promise-retry: "npm:^2.0.1" + sigstore: "npm:^4.0.0" + ssri: "npm:^12.0.0" + tar: "npm:^7.4.3" + bin: + pacote: bin/index.js + checksum: 10c0/df4755db6a11982371e5c37763364dbb6cb281de911221a079d896bbb4dbef3411b01c3a13f4489eac1b992984850f7888bbc4bcdd8c01bdd610918b8a4781fc + languageName: node + linkType: hard + +"pacote@npm:^21.0.0, pacote@npm:^21.0.2": + version: 21.5.0 + resolution: "pacote@npm:21.5.0" + dependencies: + "@gar/promise-retry": "npm:^1.0.0" + "@npmcli/git": "npm:^7.0.0" + "@npmcli/installed-package-contents": "npm:^4.0.0" + "@npmcli/package-json": "npm:^7.0.0" + "@npmcli/promise-spawn": "npm:^9.0.0" + "@npmcli/run-script": "npm:^10.0.0" + cacache: "npm:^20.0.0" + fs-minipass: "npm:^3.0.0" + minipass: "npm:^7.0.2" + npm-package-arg: "npm:^13.0.0" + npm-packlist: "npm:^10.0.1" + npm-pick-manifest: "npm:^11.0.1" + npm-registry-fetch: "npm:^19.0.0" + proc-log: "npm:^6.0.0" + sigstore: "npm:^4.0.0" + ssri: "npm:^13.0.0" + tar: "npm:^7.4.3" + bin: + pacote: bin/index.js + checksum: 10c0/f91ee9c3645300b52eebdce461d4e1d8a9311e9ddf7f55f87532cd3df0282379613b0a9703f97d81c9efaae382f08fcf29e359d7f47f0e9c9670cfb7fc472954 + languageName: node + linkType: hard + +"parent-module@npm:^1.0.0": + version: 1.0.1 + resolution: "parent-module@npm:1.0.1" + dependencies: + callsites: "npm:^3.0.0" + checksum: 10c0/c63d6e80000d4babd11978e0d3fee386ca7752a02b035fd2435960ffaa7219dc42146f07069fb65e6e8bf1caef89daf9af7535a39bddf354d78bf50d8294f556 + languageName: node + linkType: hard + +"parse-conflict-json@npm:^4.0.0": + version: 4.0.0 + resolution: "parse-conflict-json@npm:4.0.0" + dependencies: + json-parse-even-better-errors: "npm:^4.0.0" + just-diff: "npm:^6.0.0" + just-diff-apply: "npm:^5.2.0" + checksum: 10c0/5e027cdb6c93a283e32e406e829c1d5b30bfb344ab93dd5a0b8fe983f26dab05dd4d8cba3b3106259f32cbea722f383eda2c8132da3a4a9846803d2bdb004feb + languageName: node + linkType: hard + +"parse-json@npm:^4.0.0": + version: 4.0.0 + resolution: "parse-json@npm:4.0.0" + dependencies: + error-ex: "npm:^1.3.1" + json-parse-better-errors: "npm:^1.0.1" + checksum: 10c0/8d80790b772ccb1bcea4e09e2697555e519d83d04a77c2b4237389b813f82898943a93ffff7d0d2406203bdd0c30dcf95b1661e3a53f83d0e417f053957bef32 + languageName: node + linkType: hard + +"parse-json@npm:^5.0.0, parse-json@npm:^5.2.0": + version: 5.2.0 + resolution: "parse-json@npm:5.2.0" + dependencies: + "@babel/code-frame": "npm:^7.0.0" + error-ex: "npm:^1.3.1" + json-parse-even-better-errors: "npm:^2.3.0" + lines-and-columns: "npm:^1.1.6" + checksum: 10c0/77947f2253005be7a12d858aedbafa09c9ae39eb4863adf330f7b416ca4f4a08132e453e08de2db46459256fb66afaac5ee758b44fe6541b7cdaf9d252e59585 + languageName: node + linkType: hard + +"parse-path@npm:^7.0.0": + version: 7.1.0 + resolution: "parse-path@npm:7.1.0" + dependencies: + protocols: "npm:^2.0.0" + checksum: 10c0/8c8c8b3019323d686e7b1cd6fd9653bc233404403ad68827836fbfe59dfe26aaef64ed4e0396d0e20c4a7e1469312ec969a679618960e79d5e7c652dc0da5a0f + languageName: node + linkType: hard + +"parse-url@npm:^8.1.0": + version: 8.1.0 + resolution: "parse-url@npm:8.1.0" + dependencies: + parse-path: "npm:^7.0.0" + checksum: 10c0/68b95afdf4bbf72e57c7ab66f8757c935fff888f7e2b0f1e06098b4faa19e06b6b743bddaed5bc8df4f0c2de6fc475355d787373b2fdd40092be9e4e4b996648 + languageName: node + linkType: hard + +"parseurl@npm:^1.3.3, parseurl@npm:~1.3.3": + version: 1.3.3 + resolution: "parseurl@npm:1.3.3" + checksum: 10c0/90dd4760d6f6174adb9f20cf0965ae12e23879b5f5464f38e92fce8073354341e4b3b76fa3d878351efe7d01e617121955284cfd002ab087fba1a0726ec0b4f5 + languageName: node + linkType: hard + +"path-exists@npm:^3.0.0": + version: 3.0.0 + resolution: "path-exists@npm:3.0.0" + checksum: 10c0/17d6a5664bc0a11d48e2b2127d28a0e58822c6740bde30403f08013da599182289c56518bec89407e3f31d3c2b6b296a4220bc3f867f0911fee6952208b04167 + languageName: node + linkType: hard + +"path-exists@npm:^4.0.0": + version: 4.0.0 + resolution: "path-exists@npm:4.0.0" + checksum: 10c0/8c0bd3f5238188197dc78dced15207a4716c51cc4e3624c44fc97acf69558f5ebb9a2afff486fe1b4ee148e0c133e96c5e11a9aa5c48a3006e3467da070e5e1b + languageName: node + linkType: hard + +"path-is-absolute@npm:^1.0.0": + version: 1.0.1 + resolution: "path-is-absolute@npm:1.0.1" + checksum: 10c0/127da03c82172a2a50099cddbf02510c1791fc2cc5f7713ddb613a56838db1e8168b121a920079d052e0936c23005562059756d653b7c544c53185efe53be078 + languageName: node + linkType: hard + +"path-key@npm:^3.0.0, path-key@npm:^3.1.0": + version: 3.1.1 + resolution: "path-key@npm:3.1.1" + checksum: 10c0/748c43efd5a569c039d7a00a03b58eecd1d75f3999f5a28303d75f521288df4823bc057d8784eb72358b2895a05f29a070bc9f1f17d28226cc4e62494cc58c4c + languageName: node + linkType: hard + +"path-parse@npm:^1.0.7": + version: 1.0.7 + resolution: "path-parse@npm:1.0.7" + checksum: 10c0/11ce261f9d294cc7a58d6a574b7f1b935842355ec66fba3c3fd79e0f036462eaf07d0aa95bb74ff432f9afef97ce1926c720988c6a7451d8a584930ae7de86e1 + languageName: node + linkType: hard + +"path-scurry@npm:^1.11.1": + version: 1.11.1 + resolution: "path-scurry@npm:1.11.1" + dependencies: + lru-cache: "npm:^10.2.0" + minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" + checksum: 10c0/32a13711a2a505616ae1cc1b5076801e453e7aae6ac40ab55b388bb91b9d0547a52f5aaceff710ea400205f18691120d4431e520afbe4266b836fadede15872d + languageName: node + linkType: hard + +"path-scurry@npm:^2.0.0, path-scurry@npm:^2.0.2": + version: 2.0.2 + resolution: "path-scurry@npm:2.0.2" + dependencies: + lru-cache: "npm:^11.0.0" + minipass: "npm:^7.1.2" + checksum: 10c0/b35ad37cf6557a87fd057121ce2be7695380c9138d93e87ae928609da259ea0a170fac6f3ef1eb3ece8a068e8b7f2f3adf5bb2374cf4d4a57fe484954fcc9482 + languageName: node + linkType: hard + +"path-to-regexp@npm:3.3.0": + version: 3.3.0 + resolution: "path-to-regexp@npm:3.3.0" + checksum: 10c0/ffa0ebe7088d38d435a8d08b0fe6e8c93ceb2a81a65d4dd1d9a538f52e09d5e3474ed5f553cb3b180d894b0caa10698a68737ab599fd1e56b4663d1a64c9f77b + languageName: node + linkType: hard + +"path-to-regexp@npm:^8.0.0": + version: 8.4.2 + resolution: "path-to-regexp@npm:8.4.2" + checksum: 10c0/05b115c49b47ad252ce05faa32930f643f23769c68b8bcfe78ad833545140c48bbffb3266986d6c8d5db13a64cf12e07e0d72d9882cab830efeefa553533ebaf + languageName: node + linkType: hard + +"path-to-regexp@npm:~0.1.12": + version: 0.1.13 + resolution: "path-to-regexp@npm:0.1.13" + checksum: 10c0/1cae3921739c154a8926e136185a10c916f79a249b9072a5001b266d96e193860ca03867e8e8cc808b786862d750f427ed93686bc259355442c3407a62deab1a + languageName: node + linkType: hard + +"path-type@npm:^3.0.0": + version: 3.0.0 + resolution: "path-type@npm:3.0.0" + dependencies: + pify: "npm:^3.0.0" + checksum: 10c0/1332c632f1cac15790ebab8dd729b67ba04fc96f81647496feb1c2975d862d046f41e4b975dbd893048999b2cc90721f72924ad820acc58c78507ba7141a8e56 + languageName: node + linkType: hard + +"path-type@npm:^4.0.0": + version: 4.0.0 + resolution: "path-type@npm:4.0.0" + checksum: 10c0/666f6973f332f27581371efaf303fd6c272cc43c2057b37aa99e3643158c7e4b2626549555d88626e99ea9e046f82f32e41bbde5f1508547e9a11b149b52387c + languageName: node + linkType: hard + +"pg-cloudflare@npm:^1.3.0": + version: 1.3.0 + resolution: "pg-cloudflare@npm:1.3.0" + checksum: 10c0/b0866c88af8e54c7b3ed510719d92df37714b3af5e3a3a10d9f761fcec99483e222f5b78a1f2de590368127648087c45c01aaf66fadbe46edb25673eedc4f8fc + languageName: node + linkType: hard + +"pg-connection-string@npm:^2.12.0, pg-connection-string@npm:^2.6.1": + version: 2.12.0 + resolution: "pg-connection-string@npm:2.12.0" + checksum: 10c0/3a26c62884a9f0464718f652bd5d6bce276ebda830c0fef4de4f88ae73c2507d70cae1d45c2f5b49bebd76187fb4c94f889d07c53fca6acd06b2eecbebcdc336 + languageName: node + linkType: hard + +"pg-int8@npm:1.0.1": + version: 1.0.1 + resolution: "pg-int8@npm:1.0.1" + checksum: 10c0/be6a02d851fc2a4ae3e9de81710d861de3ba35ac927268973eb3cb618873a05b9424656df464dd43bd7dc3fc5295c3f5b3c8349494f87c7af50ec59ef14e0b98 + languageName: node + linkType: hard + +"pg-pool@npm:^3.13.0": + version: 3.13.0 + resolution: "pg-pool@npm:3.13.0" + peerDependencies: + pg: ">=8.0" + checksum: 10c0/2756f79cda14e3834356f2ca035deab806bca2172a38a488b62ada54bd3e65d33f583661bbe96da0c0e75e6bc59807ada733c37efca6e24ae2893429936a1549 + languageName: node + linkType: hard + +"pg-protocol@npm:^1.13.0": + version: 1.13.0 + resolution: "pg-protocol@npm:1.13.0" + checksum: 10c0/a4e851e6bb8ff404ca19d561cf49b6b0caf45163bd3f289889edaf6c4e9fb25b08fb57f50d37a8cc86007efcf2cbb3dd2372c97a353a546f45eb49ddebc84fa9 + languageName: node + linkType: hard + +"pg-types@npm:2.2.0": + version: 2.2.0 + resolution: "pg-types@npm:2.2.0" + dependencies: + pg-int8: "npm:1.0.1" + postgres-array: "npm:~2.0.0" + postgres-bytea: "npm:~1.0.0" + postgres-date: "npm:~1.0.4" + postgres-interval: "npm:^1.1.0" + checksum: 10c0/ab3f8069a323f601cd2d2279ca8c425447dab3f9b61d933b0601d7ffc00d6200df25e26a4290b2b0783b59278198f7dd2ed03e94c4875797919605116a577c65 + languageName: node + linkType: hard + +"pg@npm:^8.20.0": + version: 8.20.0 + resolution: "pg@npm:8.20.0" + dependencies: + pg-cloudflare: "npm:^1.3.0" + pg-connection-string: "npm:^2.12.0" + pg-pool: "npm:^3.13.0" + pg-protocol: "npm:^1.13.0" + pg-types: "npm:2.2.0" + pgpass: "npm:1.0.5" + peerDependencies: + pg-native: ">=3.0.1" + dependenciesMeta: + pg-cloudflare: + optional: true + peerDependenciesMeta: + pg-native: + optional: true + checksum: 10c0/e21d44b9fb3ec188e67778d7abd32d945a546f2da5128b6c8c16da8ae1e42fdc953c0d6f0a2ee65d11f31808c1dffaf908cb9c880cd2e8f0ae05525e4b8bc832 + languageName: node + linkType: hard + +"pgpass@npm:1.0.5": + version: 1.0.5 + resolution: "pgpass@npm:1.0.5" + dependencies: + split2: "npm:^4.1.0" + checksum: 10c0/5ea6c9b2de04c33abb08d33a2dded303c4a3c7162a9264519cbe85c0a9857d712463140ba42fad0c7cd4b21f644dd870b45bb2e02fcbe505b4de0744fd802c1d + languageName: node + linkType: hard + +"picocolors@npm:^1.1.0, picocolors@npm:^1.1.1": + version: 1.1.1 + resolution: "picocolors@npm:1.1.1" + checksum: 10c0/e2e3e8170ab9d7c7421969adaa7e1b31434f789afb9b3f115f6b96d91945041ac3ceb02e9ec6fe6510ff036bcc0bf91e69a1772edc0b707e12b19c0f2d6bcf58 + languageName: node + linkType: hard + +"picomatch@npm:4.0.4, picomatch@npm:^4.0.2, picomatch@npm:^4.0.3": + version: 4.0.4 + resolution: "picomatch@npm:4.0.4" + checksum: 10c0/e2c6023372cc7b5764719a5ffb9da0f8e781212fa7ca4bd0562db929df8e117460f00dff3cb7509dacfc06b86de924b247f504d0ce1806a37fac4633081466b0 + languageName: node + linkType: hard + +"picomatch@npm:^2.0.4, picomatch@npm:^2.2.3, picomatch@npm:^2.3.1": + version: 2.3.2 + resolution: "picomatch@npm:2.3.2" + checksum: 10c0/a554d1709e59be97d1acb9eaedbbc700a5c03dbd4579807baed95100b00420bc729335440ef15004ae2378984e2487a7c1cebd743cfdb72b6fa9ab69223c0d61 + languageName: node + linkType: hard + +"pify@npm:^2.3.0": + version: 2.3.0 + resolution: "pify@npm:2.3.0" + checksum: 10c0/551ff8ab830b1052633f59cb8adc9ae8407a436e06b4a9718bcb27dc5844b83d535c3a8512b388b6062af65a98c49bdc0dd523d8b2617b188f7c8fee457158dc + languageName: node + linkType: hard + +"pify@npm:^3.0.0": + version: 3.0.0 + resolution: "pify@npm:3.0.0" + checksum: 10c0/fead19ed9d801f1b1fcd0638a1ac53eabbb0945bf615f2f8806a8b646565a04a1b0e7ef115c951d225f042cca388fdc1cd3add46d10d1ed6951c20bd2998af10 + languageName: node + linkType: hard + +"pirates@npm:^4.0.4, pirates@npm:^4.0.7": + version: 4.0.7 + resolution: "pirates@npm:4.0.7" + checksum: 10c0/a51f108dd811beb779d58a76864bbd49e239fa40c7984cd11596c75a121a8cc789f1c8971d8bb15f0dbf9d48b76c05bb62fcbce840f89b688c0fa64b37e8478a + languageName: node + linkType: hard + +"pkce-challenge@npm:^5.0.0": + version: 5.0.1 + resolution: "pkce-challenge@npm:5.0.1" + checksum: 10c0/207f4cb976682f27e8324eb49cf71937c98fbb8341a0b8f6142bc6f664825b30e049a54a21b5c034e823ee3c3d412f10d74bd21de78e17452a6a496c2991f57c + languageName: node + linkType: hard + +"pkg-dir@npm:^4.2.0": + version: 4.2.0 + resolution: "pkg-dir@npm:4.2.0" + dependencies: + find-up: "npm:^4.0.0" + checksum: 10c0/c56bda7769e04907a88423feb320babaed0711af8c436ce3e56763ab1021ba107c7b0cafb11cde7529f669cfc22bffcaebffb573645cbd63842ea9fb17cd7728 + languageName: node + linkType: hard + +"postcss-selector-parser@npm:^7.0.0": + version: 7.1.1 + resolution: "postcss-selector-parser@npm:7.1.1" + dependencies: + cssesc: "npm:^3.0.0" + util-deprecate: "npm:^1.0.2" + checksum: 10c0/02d3b1589ddcddceed4b583b098b95a7266dacd5135f041e5d913ebb48e874fd333a36e564cc9a2ec426a464cb18db11cb192ac76247aced5eba8c951bf59507 + languageName: node + linkType: hard + +"postgres-array@npm:~2.0.0": + version: 2.0.0 + resolution: "postgres-array@npm:2.0.0" + checksum: 10c0/cbd56207e4141d7fbf08c86f2aebf21fa7064943d3f808ec85f442ff94b48d891e7a144cc02665fb2de5dbcb9b8e3183a2ac749959e794b4a4cfd379d7a21d08 + languageName: node + linkType: hard + +"postgres-bytea@npm:~1.0.0": + version: 1.0.1 + resolution: "postgres-bytea@npm:1.0.1" + checksum: 10c0/10b28a27c9d703d5befd97c443e62b551096d1014bc59ab574c65bf0688de7f3f068003b2aea8dcff83cf0f6f9a35f9f74457c38856cf8eb81b00cf3fb44f164 + languageName: node + linkType: hard + +"postgres-date@npm:~1.0.4": + version: 1.0.7 + resolution: "postgres-date@npm:1.0.7" + checksum: 10c0/0ff91fccc64003e10b767fcfeefb5eaffbc522c93aa65d5051c49b3c4ce6cb93ab091a7d22877a90ad60b8874202c6f1d0f935f38a7235ed3b258efd54b97ca9 + languageName: node + linkType: hard + +"postgres-interval@npm:^1.1.0": + version: 1.2.0 + resolution: "postgres-interval@npm:1.2.0" + dependencies: + xtend: "npm:^4.0.0" + checksum: 10c0/c1734c3cb79e7f22579af0b268a463b1fa1d084e742a02a7a290c4f041e349456f3bee3b4ee0bb3f226828597f7b76deb615c1b857db9a742c45520100456272 + languageName: node + linkType: hard + +"prelude-ls@npm:^1.2.1": + version: 1.2.1 + resolution: "prelude-ls@npm:1.2.1" + checksum: 10c0/b00d617431e7886c520a6f498a2e14c75ec58f6d93ba48c3b639cf241b54232d90daa05d83a9e9b9fef6baa63cb7e1e4602c2372fea5bc169668401eb127d0cd + languageName: node + linkType: hard + +"prettier-linter-helpers@npm:^1.0.1": + version: 1.0.1 + resolution: "prettier-linter-helpers@npm:1.0.1" + dependencies: + fast-diff: "npm:^1.1.2" + checksum: 10c0/91cea965681bc5f62c9d26bd3ca6358b81557261d4802e96ec1cf0acbd99d4b61632d53320cd2c3ec7d7f7805a81345644108a41ef46ddc9688e783a9ac792d1 + languageName: node + linkType: hard + +"prettier@npm:^3.8.1": + version: 3.8.1 + resolution: "prettier@npm:3.8.1" + bin: + prettier: bin/prettier.cjs + checksum: 10c0/33169b594009e48f570471271be7eac7cdcf88a209eed39ac3b8d6d78984039bfa9132f82b7e6ba3b06711f3bfe0222a62a1bfb87c43f50c25a83df1b78a2c42 + languageName: node + linkType: hard + +"pretty-format@npm:30.3.0": + version: 30.3.0 + resolution: "pretty-format@npm:30.3.0" + dependencies: + "@jest/schemas": "npm:30.0.5" + ansi-styles: "npm:^5.2.0" + react-is: "npm:^18.3.1" + checksum: 10c0/719b27d70cd8b01013485054c5d094e1fe85e093b09ee73553e3b19302da3cf54fbd6a7ea9577d6471aeff8d372200e56979ffc4c831e2133520bd18060895fb + languageName: node + linkType: hard + +"pretty-format@npm:^29.0.0, pretty-format@npm:^29.7.0": + version: 29.7.0 + resolution: "pretty-format@npm:29.7.0" + dependencies: + "@jest/schemas": "npm:^29.6.3" + ansi-styles: "npm:^5.0.0" + react-is: "npm:^18.0.0" + checksum: 10c0/edc5ff89f51916f036c62ed433506b55446ff739358de77207e63e88a28ca2894caac6e73dcb68166a606e51c8087d32d400473e6a9fdd2dbe743f46c9c0276f + languageName: node + linkType: hard + +"proc-log@npm:^5.0.0": + version: 5.0.0 + resolution: "proc-log@npm:5.0.0" + checksum: 10c0/bbe5edb944b0ad63387a1d5b1911ae93e05ce8d0f60de1035b218cdcceedfe39dbd2c697853355b70f1a090f8f58fe90da487c85216bf9671f9499d1a897e9e3 + languageName: node + linkType: hard + +"proc-log@npm:^6.0.0, proc-log@npm:^6.1.0": + version: 6.1.0 + resolution: "proc-log@npm:6.1.0" + checksum: 10c0/4f178d4062733ead9d71a9b1ab24ebcecdfe2250916a5b1555f04fe2eda972a0ec76fbaa8df1ad9c02707add6749219d118a4fc46dc56bdfe4dde4b47d80bb82 + languageName: node + linkType: hard + +"process-nextick-args@npm:~2.0.0": + version: 2.0.1 + resolution: "process-nextick-args@npm:2.0.1" + checksum: 10c0/bec089239487833d46b59d80327a1605e1c5287eaad770a291add7f45fda1bb5e28b38e0e061add0a1d0ee0984788ce74fa394d345eed1c420cacf392c554367 + languageName: node + linkType: hard + +"process@npm:^0.11.10": + version: 0.11.10 + resolution: "process@npm:0.11.10" + checksum: 10c0/40c3ce4b7e6d4b8c3355479df77aeed46f81b279818ccdc500124e6a5ab882c0cc81ff7ea16384873a95a74c4570b01b120f287abbdd4c877931460eca6084b3 + languageName: node + linkType: hard + +"proggy@npm:^3.0.0": + version: 3.0.0 + resolution: "proggy@npm:3.0.0" + checksum: 10c0/b4265664405e780edf7a164b2424bb59fc7bd3ab917365c88c6540e5f3bedcbbfb1a534da9c6a4a5570f374a41ef6942e9a4e862dc3ea744798b6c7be63e4351 + languageName: node + linkType: hard + +"promise-all-reject-late@npm:^1.0.0": + version: 1.0.1 + resolution: "promise-all-reject-late@npm:1.0.1" + checksum: 10c0/f1af0c7b0067e84d64751148ee5bb6c3e84f4a4d1316d6fe56261e1d2637cf71b49894bcbd2c6daf7d45afb1bc99efc3749be277c3e0518b70d0c5a29d037011 + languageName: node + linkType: hard + +"promise-call-limit@npm:^3.0.1": + version: 3.0.2 + resolution: "promise-call-limit@npm:3.0.2" + checksum: 10c0/1f984c16025925594d738833f5da7525b755f825a198d5a0cac1c0280b4f38ecc3c32c1f4e5ef614ddcfd6718c1a8c3f98a3290ae6f421342281c9a88c488bf7 + languageName: node + linkType: hard + +"promise-retry@npm:^2.0.1": + version: 2.0.1 + resolution: "promise-retry@npm:2.0.1" + dependencies: + err-code: "npm:^2.0.2" + retry: "npm:^0.12.0" + checksum: 10c0/9c7045a1a2928094b5b9b15336dcd2a7b1c052f674550df63cc3f36cd44028e5080448175b6f6ca32b642de81150f5e7b1a98b728f15cb069f2dd60ac2616b96 + languageName: node + linkType: hard + +"prompts@npm:^2.0.1": + version: 2.4.2 + resolution: "prompts@npm:2.4.2" + dependencies: + kleur: "npm:^3.0.3" + sisteransi: "npm:^1.0.5" + checksum: 10c0/16f1ac2977b19fe2cf53f8411cc98db7a3c8b115c479b2ca5c82b5527cd937aa405fa04f9a5960abeb9daef53191b53b4d13e35c1f5d50e8718c76917c5f1ea4 + languageName: node + linkType: hard + +"promzard@npm:^2.0.0": + version: 2.0.0 + resolution: "promzard@npm:2.0.0" + dependencies: + read: "npm:^4.0.0" + checksum: 10c0/09d8c8c5d49ebed99686b7bed386f02ef32fc90cef4b2626c46e39d74903735a1ca88788613076561fc5548a76fe5f91897f2afd8025ce77dfa1f603eaaee1cd + languageName: node + linkType: hard + +"proper-lockfile@npm:^4.1.2": + version: 4.1.2 + resolution: "proper-lockfile@npm:4.1.2" + dependencies: + graceful-fs: "npm:^4.2.4" + retry: "npm:^0.12.0" + signal-exit: "npm:^3.0.2" + checksum: 10c0/2f265dbad15897a43110a02dae55105c04d356ec4ed560723dcb9f0d34bc4fb2f13f79bb930e7561be10278e2314db5aca2527d5d3dcbbdee5e6b331d1571f6d + languageName: node + linkType: hard + +"properties-reader@npm:^2.3.0": + version: 2.3.0 + resolution: "properties-reader@npm:2.3.0" + dependencies: + mkdirp: "npm:^1.0.4" + checksum: 10c0/f665057e3a9076c643ba1198afcc71703eda227a59913252f7ff9467ece8d29c0cf8bf14bf1abcaef71570840c32a4e257e6c39b7550451bbff1a777efcf5667 + languageName: node + linkType: hard + +"properties-reader@npm:^3.0.1": + version: 3.0.1 + resolution: "properties-reader@npm:3.0.1" + dependencies: + "@kwsites/file-exists": "npm:^1.1.1" + mkdirp: "npm:^3.0.1" + checksum: 10c0/271fae77b717e25aa5773ab1e769f416ccfdc3606a62f25cd76b2cceeb04278f2ee0e4d671ff2c06391a5e093b4b1097f9ce3916fddd4de34077a4a6e92ccb48 + languageName: node + linkType: hard + +"protobufjs@npm:^7.2.5, protobufjs@npm:^7.3.2, protobufjs@npm:^7.5.3": + version: 7.5.4 + resolution: "protobufjs@npm:7.5.4" + dependencies: + "@protobufjs/aspromise": "npm:^1.1.2" + "@protobufjs/base64": "npm:^1.1.2" + "@protobufjs/codegen": "npm:^2.0.4" + "@protobufjs/eventemitter": "npm:^1.1.0" + "@protobufjs/fetch": "npm:^1.1.0" + "@protobufjs/float": "npm:^1.0.2" + "@protobufjs/inquire": "npm:^1.1.0" + "@protobufjs/path": "npm:^1.1.2" + "@protobufjs/pool": "npm:^1.1.0" + "@protobufjs/utf8": "npm:^1.1.0" + "@types/node": "npm:>=13.7.0" + long: "npm:^5.0.0" + checksum: 10c0/913b676109ffb3c05d3d31e03a684e569be91f3bba8613da4a683d69d9dba948daa2afd7d2e7944d1aa6c417890c35d9d9a8883c1160affafb0f9670d59ef722 + languageName: node + linkType: hard + +"protocols@npm:^2.0.0, protocols@npm:^2.0.1": + version: 2.0.2 + resolution: "protocols@npm:2.0.2" + checksum: 10c0/b87d78c1fcf038d33691da28447ce94011d5c7f0c7fd25bcb5fb4d975991c99117873200c84f4b6a9d7f8b9092713a064356236960d1473a7d6fcd4228897b60 + languageName: node + linkType: hard + +"proxy-addr@npm:^2.0.7, proxy-addr@npm:~2.0.7": + version: 2.0.7 + resolution: "proxy-addr@npm:2.0.7" + dependencies: + forwarded: "npm:0.2.0" + ipaddr.js: "npm:1.9.1" + checksum: 10c0/c3eed999781a35f7fd935f398b6d8920b6fb00bbc14287bc6de78128ccc1a02c89b95b56742bf7cf0362cc333c61d138532049c7dedc7a328ef13343eff81210 + languageName: node + linkType: hard + +"proxy-from-env@npm:^1.1.0": + version: 1.1.0 + resolution: "proxy-from-env@npm:1.1.0" + checksum: 10c0/fe7dd8b1bdbbbea18d1459107729c3e4a2243ca870d26d34c2c1bcd3e4425b7bcc5112362df2d93cc7fb9746f6142b5e272fd1cc5c86ddf8580175186f6ad42b + languageName: node + linkType: hard + +"proxy-from-env@npm:^2.1.0": + version: 2.1.0 + resolution: "proxy-from-env@npm:2.1.0" + checksum: 10c0/ed01729fd4d094eab619cd7e17ce3698b3413b31eb102c4904f9875e677cd207392795d5b4adee9cec359dfd31c44d5ad7595a3a3ad51c40250e141512281c58 + languageName: node + linkType: hard + +"pump@npm:^3.0.0": + version: 3.0.4 + resolution: "pump@npm:3.0.4" + dependencies: + end-of-stream: "npm:^1.1.0" + once: "npm:^1.3.1" + checksum: 10c0/2780e66b5471c19e3e3e1063b84f3f6a3a08367f24c5ed552f98cd5901e6ada27c7ad6495d4244f553fd03b01884a4561933064f053f47c8994d84fd352768ea + languageName: node + linkType: hard + +"punycode@npm:^2.1.0": + version: 2.3.1 + resolution: "punycode@npm:2.3.1" + checksum: 10c0/14f76a8206bc3464f794fb2e3d3cc665ae416c01893ad7a02b23766eb07159144ee612ad67af5e84fa4479ccfe67678c4feb126b0485651b302babf66f04f9e9 + languageName: node + linkType: hard + +"pure-rand@npm:^6.0.0": + version: 6.1.0 + resolution: "pure-rand@npm:6.1.0" + checksum: 10c0/1abe217897bf74dcb3a0c9aba3555fe975023147b48db540aa2faf507aee91c03bf54f6aef0eb2bf59cc259a16d06b28eca37f0dc426d94f4692aeff02fb0e65 + languageName: node + linkType: hard + +"pure-rand@npm:^7.0.0": + version: 7.0.1 + resolution: "pure-rand@npm:7.0.1" + checksum: 10c0/9cade41030f5ec95f5d55a11a71404cd6f46b69becaad892097cd7f58e2c6248cd0a933349ca7d21336ab629f1da42ffe899699b671bc4651600eaf6e57f837e + languageName: node + linkType: hard + +"qs@npm:^6.14.0, qs@npm:^6.14.1": + version: 6.15.0 + resolution: "qs@npm:6.15.0" + dependencies: + side-channel: "npm:^1.1.0" + checksum: 10c0/ff341078a78a991d8a48b4524d52949211447b4b1ad907f489cac0770cbc346a28e47304455c0320e5fb000f8762d64b03331e3b71865f663bf351bcba8cdb4b + languageName: node + linkType: hard + +"qs@npm:~6.14.0": + version: 6.14.2 + resolution: "qs@npm:6.14.2" + dependencies: + side-channel: "npm:^1.1.0" + checksum: 10c0/646110124476fc9acf3c80994c8c3a0600cbad06a4ede1c9e93341006e8426d64e85e048baf8f0c4995f0f1bf0f37d1f3acc5ec1455850b81978792969a60ef6 + languageName: node + linkType: hard + +"quick-lru@npm:^4.0.1": + version: 4.0.1 + resolution: "quick-lru@npm:4.0.1" + checksum: 10c0/f9b1596fa7595a35c2f9d913ac312fede13d37dc8a747a51557ab36e11ce113bbe88ef4c0154968845559a7709cb6a7e7cbe75f7972182451cd45e7f057a334d + languageName: node + linkType: hard + +"randombytes@npm:2.1.0": + version: 2.1.0 + resolution: "randombytes@npm:2.1.0" + dependencies: + safe-buffer: "npm:^5.1.0" + checksum: 10c0/50395efda7a8c94f5dffab564f9ff89736064d32addf0cc7e8bf5e4166f09f8ded7a0849ca6c2d2a59478f7d90f78f20d8048bca3cdf8be09d8e8a10790388f3 + languageName: node + linkType: hard + +"randomstring@npm:^1.3.0": + version: 1.3.1 + resolution: "randomstring@npm:1.3.1" + dependencies: + randombytes: "npm:2.1.0" + bin: + randomstring: bin/randomstring + checksum: 10c0/1509b0dbda91b5270986c2e28389aba68dfda6edbc2357cd3938b16616a3596e9b8e04006be414960266ff73a7686f5cce784cf7b6a05a3e918d0f7e45333c33 + languageName: node + linkType: hard + +"range-parser@npm:^1.2.1, range-parser@npm:~1.2.1": + version: 1.2.1 + resolution: "range-parser@npm:1.2.1" + checksum: 10c0/96c032ac2475c8027b7a4e9fe22dc0dfe0f6d90b85e496e0f016fbdb99d6d066de0112e680805075bd989905e2123b3b3d002765149294dce0c1f7f01fcc2ea0 + languageName: node + linkType: hard + +"raw-body@npm:^3.0.0, raw-body@npm:^3.0.1": + version: 3.0.2 + resolution: "raw-body@npm:3.0.2" + dependencies: + bytes: "npm:~3.1.2" + http-errors: "npm:~2.0.1" + iconv-lite: "npm:~0.7.0" + unpipe: "npm:~1.0.0" + checksum: 10c0/d266678d08e1e7abea62c0ce5864344e980fa81c64f6b481e9842c5beaed2cdcf975f658a3ccd67ad35fc919c1f6664ccc106067801850286a6cbe101de89f29 + languageName: node + linkType: hard + +"raw-body@npm:~2.5.3": + version: 2.5.3 + resolution: "raw-body@npm:2.5.3" + dependencies: + bytes: "npm:~3.1.2" + http-errors: "npm:~2.0.1" + iconv-lite: "npm:~0.4.24" + unpipe: "npm:~1.0.0" + checksum: 10c0/449844344fc90547fb994383a494b83300e4f22199f146a79f68d78a199a8f2a923ea9fd29c3be979bfd50291a3884733619ffc15ba02a32e703b612f8d3f74a + languageName: node + linkType: hard + +"react-is@npm:^18.0.0, react-is@npm:^18.3.1": + version: 18.3.1 + resolution: "react-is@npm:18.3.1" + checksum: 10c0/f2f1e60010c683479e74c63f96b09fb41603527cd131a9959e2aee1e5a8b0caf270b365e5ca77d4a6b18aae659b60a86150bb3979073528877029b35aecd2072 + languageName: node + linkType: hard + +"read-cmd-shim@npm:4.0.0": + version: 4.0.0 + resolution: "read-cmd-shim@npm:4.0.0" + checksum: 10c0/e62db17ec9708f1e7c6a31f0a46d43df2069d85cf0df3b9d1d99e5ed36e29b1e8b2f8a427fd8bbb9bc40829788df1471794f9b01057e4b95ed062806e4df5ba9 + languageName: node + linkType: hard + +"read-cmd-shim@npm:^5.0.0": + version: 5.0.0 + resolution: "read-cmd-shim@npm:5.0.0" + checksum: 10c0/5688aea2742d928575a1dd87ee0ce691f57b344935fe87d6460067951e7a3bb3677501513316785e1e9ea43b0bb1635eacba3b00b81ad158f9b23512f1de26d2 + languageName: node + linkType: hard + +"read-pkg-up@npm:^3.0.0": + version: 3.0.0 + resolution: "read-pkg-up@npm:3.0.0" + dependencies: + find-up: "npm:^2.0.0" + read-pkg: "npm:^3.0.0" + checksum: 10c0/2cd0a180260b0d235990e6e9c8c2330a03882d36bc2eba8930e437ef23ee52a68a894e7e1ccb1c33f03bcceb270a861ee5f7eac686f238857755e2cddfb48ffd + languageName: node + linkType: hard + +"read-pkg-up@npm:^7.0.1": + version: 7.0.1 + resolution: "read-pkg-up@npm:7.0.1" + dependencies: + find-up: "npm:^4.1.0" + read-pkg: "npm:^5.2.0" + type-fest: "npm:^0.8.1" + checksum: 10c0/82b3ac9fd7c6ca1bdc1d7253eb1091a98ff3d195ee0a45386582ce3e69f90266163c34121e6a0a02f1630073a6c0585f7880b3865efcae9c452fa667f02ca385 + languageName: node + linkType: hard + +"read-pkg@npm:^3.0.0": + version: 3.0.0 + resolution: "read-pkg@npm:3.0.0" + dependencies: + load-json-file: "npm:^4.0.0" + normalize-package-data: "npm:^2.3.2" + path-type: "npm:^3.0.0" + checksum: 10c0/65acf2df89fbcd506b48b7ced56a255ba00adf7ecaa2db759c86cc58212f6fd80f1f0b7a85c848551a5d0685232e9b64f45c1fd5b48d85df2761a160767eeb93 + languageName: node + linkType: hard + +"read-pkg@npm:^5.2.0": + version: 5.2.0 + resolution: "read-pkg@npm:5.2.0" + dependencies: + "@types/normalize-package-data": "npm:^2.4.0" + normalize-package-data: "npm:^2.5.0" + parse-json: "npm:^5.0.0" + type-fest: "npm:^0.6.0" + checksum: 10c0/b51a17d4b51418e777029e3a7694c9bd6c578a5ab99db544764a0b0f2c7c0f58f8a6bc101f86a6fceb8ba6d237d67c89acf6170f6b98695d0420ddc86cf109fb + languageName: node + linkType: hard + +"read@npm:^4.0.0": + version: 4.1.0 + resolution: "read@npm:4.1.0" + dependencies: + mute-stream: "npm:^2.0.0" + checksum: 10c0/5ad25883d6ffd0e63afe538166e22f1b67108d11fc9f9df65dedf0224b28871b0576f4f941c6f28febe53ca91a0338073c732be3fbd1a2bdad37bd25a9ff5ccf + languageName: node + linkType: hard + +"readable-stream@npm:^2.0.5, readable-stream@npm:~2.3.6": + version: 2.3.8 + resolution: "readable-stream@npm:2.3.8" + dependencies: + core-util-is: "npm:~1.0.0" + inherits: "npm:~2.0.3" + isarray: "npm:~1.0.0" + process-nextick-args: "npm:~2.0.0" + safe-buffer: "npm:~5.1.1" + string_decoder: "npm:~1.1.1" + util-deprecate: "npm:~1.0.1" + checksum: 10c0/7efdb01f3853bc35ac62ea25493567bf588773213f5f4a79f9c365e1ad13bab845ac0dae7bc946270dc40c3929483228415e92a3fc600cc7e4548992f41ee3fa + languageName: node + linkType: hard + +"readable-stream@npm:^3.0.0, readable-stream@npm:^3.0.2, readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0, readable-stream@npm:^3.5.0, readable-stream@npm:^3.6.2": + version: 3.6.2 + resolution: "readable-stream@npm:3.6.2" + dependencies: + inherits: "npm:^2.0.3" + string_decoder: "npm:^1.1.1" + util-deprecate: "npm:^1.0.1" + checksum: 10c0/e37be5c79c376fdd088a45fa31ea2e423e5d48854be7a22a58869b4e84d25047b193f6acb54f1012331e1bcd667ffb569c01b99d36b0bd59658fb33f513511b7 + languageName: node + linkType: hard + +"readable-stream@npm:^4.0.0": + version: 4.7.0 + resolution: "readable-stream@npm:4.7.0" + dependencies: + abort-controller: "npm:^3.0.0" + buffer: "npm:^6.0.3" + events: "npm:^3.3.0" + process: "npm:^0.11.10" + string_decoder: "npm:^1.3.0" + checksum: 10c0/fd86d068da21cfdb10f7a4479f2e47d9c0a9b0c862fc0c840a7e5360201580a55ac399c764b12a4f6fa291f8cee74d9c4b7562e0d53b3c4b2769f2c98155d957 + languageName: node + linkType: hard + +"readdir-glob@npm:^1.1.2": + version: 1.1.3 + resolution: "readdir-glob@npm:1.1.3" + dependencies: + minimatch: "npm:^5.1.0" + checksum: 10c0/a37e0716726650845d761f1041387acd93aa91b28dd5381950733f994b6c349ddc1e21e266ec7cc1f9b92e205a7a972232f9b89d5424d07361c2c3753d5dbace + languageName: node + linkType: hard + +"redent@npm:^3.0.0": + version: 3.0.0 + resolution: "redent@npm:3.0.0" + dependencies: + indent-string: "npm:^4.0.0" + strip-indent: "npm:^3.0.0" + checksum: 10c0/d64a6b5c0b50eb3ddce3ab770f866658a2b9998c678f797919ceb1b586bab9259b311407280bd80b804e2a7c7539b19238ae6a2a20c843f1a7fcff21d48c2eae + languageName: node + linkType: hard + +"redis-errors@npm:^1.0.0, redis-errors@npm:^1.2.0": + version: 1.2.0 + resolution: "redis-errors@npm:1.2.0" + checksum: 10c0/5b316736e9f532d91a35bff631335137a4f974927bb2fb42bf8c2f18879173a211787db8ac4c3fde8f75ed6233eb0888e55d52510b5620e30d69d7d719c8b8a7 + languageName: node + linkType: hard + +"redis-parser@npm:^3.0.0": + version: 3.0.0 + resolution: "redis-parser@npm:3.0.0" + dependencies: + redis-errors: "npm:^1.0.0" + checksum: 10c0/ee16ac4c7b2a60b1f42a2cdaee22b005bd4453eb2d0588b8a4939718997ae269da717434da5d570fe0b05030466eeb3f902a58cf2e8e1ca058bf6c9c596f632f + languageName: node + linkType: hard + +"redis@npm:^4.7.0": + version: 4.7.1 + resolution: "redis@npm:4.7.1" + dependencies: + "@redis/bloom": "npm:1.2.0" + "@redis/client": "npm:1.6.1" + "@redis/graph": "npm:1.1.1" + "@redis/json": "npm:1.0.7" + "@redis/search": "npm:1.2.0" + "@redis/time-series": "npm:1.1.0" + checksum: 10c0/36fc11b7b305e73cafd0a32c5e7070aef72d3a33f2b34f609a1c295afb7d1a022d74eeda96e8d887ef596bbe8ce10811450d02b63175a338d2ff258ff34bd237 + languageName: node + linkType: hard + +"reflect-metadata@npm:^0.2.0": + version: 0.2.2 + resolution: "reflect-metadata@npm:0.2.2" + checksum: 10c0/1cd93a15ea291e420204955544637c264c216e7aac527470e393d54b4bb075f10a17e60d8168ec96600c7e0b9fcc0cb0bb6e91c3fbf5b0d8c9056f04e6ac1ec2 + languageName: node + linkType: hard + +"regenerate-unicode-properties@npm:^10.2.2": + version: 10.2.2 + resolution: "regenerate-unicode-properties@npm:10.2.2" + dependencies: + regenerate: "npm:^1.4.2" + checksum: 10c0/66a1d6a1dbacdfc49afd88f20b2319a4c33cee56d245163e4d8f5f283e0f45d1085a78f7f7406dd19ea3a5dd7a7799cd020cd817c97464a7507f9d10fbdce87c + languageName: node + linkType: hard + +"regenerate@npm:^1.4.2": + version: 1.4.2 + resolution: "regenerate@npm:1.4.2" + checksum: 10c0/f73c9eba5d398c818edc71d1c6979eaa05af7a808682749dd079f8df2a6d91a9b913db216c2c9b03e0a8ba2bba8701244a93f45211afbff691c32c7b275db1b8 + languageName: node + linkType: hard + +"regexpu-core@npm:^6.3.1": + version: 6.4.0 + resolution: "regexpu-core@npm:6.4.0" + dependencies: + regenerate: "npm:^1.4.2" + regenerate-unicode-properties: "npm:^10.2.2" + regjsgen: "npm:^0.8.0" + regjsparser: "npm:^0.13.0" + unicode-match-property-ecmascript: "npm:^2.0.0" + unicode-match-property-value-ecmascript: "npm:^2.2.1" + checksum: 10c0/1eed9783c023dd06fb1f3ce4b6e3fdf0bc1e30cb036f30aeb2019b351e5e0b74355b40462282ea5db092c79a79331c374c7e9897e44a5ca4509e9f0b570263de + languageName: node + linkType: hard + +"regjsgen@npm:^0.8.0": + version: 0.8.0 + resolution: "regjsgen@npm:0.8.0" + checksum: 10c0/44f526c4fdbf0b29286101a282189e4dbb303f4013cf3fea058668d96d113b9180d3d03d1e13f6d4cbde38b7728bf951aecd9dc199938c080093a9a6f0d7a6bd + languageName: node + linkType: hard + +"regjsparser@npm:^0.13.0": + version: 0.13.1 + resolution: "regjsparser@npm:0.13.1" + dependencies: + jsesc: "npm:~3.1.0" + bin: + regjsparser: bin/parser + checksum: 10c0/1276c983f00de49e37ef76b181df4390699b46e3666fbe6b8b5512bd75919112574cf023f28ac720d427be158af60dba6a77cce9a8aaff14967263636e667356 + languageName: node + linkType: hard + +"require-directory@npm:^2.1.1": + version: 2.1.1 + resolution: "require-directory@npm:2.1.1" + checksum: 10c0/83aa76a7bc1531f68d92c75a2ca2f54f1b01463cb566cf3fbc787d0de8be30c9dbc211d1d46be3497dac5785fe296f2dd11d531945ac29730643357978966e99 + languageName: node + linkType: hard + +"require-from-string@npm:^2.0.2": + version: 2.0.2 + resolution: "require-from-string@npm:2.0.2" + checksum: 10c0/aaa267e0c5b022fc5fd4eef49d8285086b15f2a1c54b28240fdf03599cbd9c26049fee3eab894f2e1f6ca65e513b030a7c264201e3f005601e80c49fb2937ce2 + languageName: node + linkType: hard + +"resolve-cwd@npm:^3.0.0": + version: 3.0.0 + resolution: "resolve-cwd@npm:3.0.0" + dependencies: + resolve-from: "npm:^5.0.0" + checksum: 10c0/e608a3ebd15356264653c32d7ecbc8fd702f94c6703ea4ac2fb81d9c359180cba0ae2e6b71faa446631ed6145454d5a56b227efc33a2d40638ac13f8beb20ee4 + languageName: node + linkType: hard + +"resolve-from@npm:^4.0.0": + version: 4.0.0 + resolution: "resolve-from@npm:4.0.0" + checksum: 10c0/8408eec31a3112ef96e3746c37be7d64020cda07c03a920f5024e77290a218ea758b26ca9529fd7b1ad283947f34b2291c1c0f6aa0ed34acfdda9c6014c8d190 + languageName: node + linkType: hard + +"resolve-from@npm:^5.0.0": + version: 5.0.0 + resolution: "resolve-from@npm:5.0.0" + checksum: 10c0/b21cb7f1fb746de8107b9febab60095187781137fd803e6a59a76d421444b1531b641bba5857f5dc011974d8a5c635d61cec49e6bd3b7fc20e01f0fafc4efbf2 + languageName: node + linkType: hard + +"resolve.exports@npm:2.0.3, resolve.exports@npm:^2.0.0": + version: 2.0.3 + resolution: "resolve.exports@npm:2.0.3" + checksum: 10c0/1ade1493f4642a6267d0a5e68faeac20b3d220f18c28b140343feb83694d8fed7a286852aef43689d16042c61e2ddb270be6578ad4a13990769e12065191200d + languageName: node + linkType: hard + +"resolve@npm:^1.10.0, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.22.11": + version: 1.22.11 + resolution: "resolve@npm:1.22.11" + dependencies: + is-core-module: "npm:^2.16.1" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10c0/f657191507530f2cbecb5815b1ee99b20741ea6ee02a59c57028e9ec4c2c8d7681afcc35febbd554ac0ded459db6f2d8153382c53a2f266cee2575e512674409 + languageName: node + linkType: hard + +"resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.19.0#optional!builtin, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.11#optional!builtin": + version: 1.22.11 + resolution: "resolve@patch:resolve@npm%3A1.22.11#optional!builtin::version=1.22.11&hash=c3c19d" + dependencies: + is-core-module: "npm:^2.16.1" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10c0/ee5b182f2e37cb1165465e58c6abc797fec0a80b5ba3231607beb4677db0c9291ac010c47cf092b6daa2b7f518d69a0e21888e7e2b633f68d501a874212a8c63 + languageName: node + linkType: hard + +"restore-cursor@npm:^3.1.0": + version: 3.1.0 + resolution: "restore-cursor@npm:3.1.0" + dependencies: + onetime: "npm:^5.1.0" + signal-exit: "npm:^3.0.2" + checksum: 10c0/8051a371d6aa67ff21625fa94e2357bd81ffdc96267f3fb0fc4aaf4534028343836548ef34c240ffa8c25b280ca35eb36be00b3cb2133fa4f51896d7e73c6b4f + languageName: node + linkType: hard + +"retry-as-promised@npm:^7.0.4": + version: 7.1.1 + resolution: "retry-as-promised@npm:7.1.1" + checksum: 10c0/d0f8477d0e5e3c979947824ea415ea622c4a9f423d6f2d2c421182243085c8aaf4686efcaccb4573a7f6bf4b094d9ee39d239f20b9e31ed601dd489ea3713198 + languageName: node + linkType: hard + +"retry@npm:^0.12.0": + version: 0.12.0 + resolution: "retry@npm:0.12.0" + checksum: 10c0/59933e8501727ba13ad73ef4a04d5280b3717fd650408460c987392efe9d7be2040778ed8ebe933c5cbd63da3dcc37919c141ef8af0a54a6e4fca5a2af177bfe + languageName: node + linkType: hard + +"router@npm:^2.2.0": + version: 2.2.0 + resolution: "router@npm:2.2.0" + dependencies: + debug: "npm:^4.4.0" + depd: "npm:^2.0.0" + is-promise: "npm:^4.0.0" + parseurl: "npm:^1.3.3" + path-to-regexp: "npm:^8.0.0" + checksum: 10c0/3279de7450c8eae2f6e095e9edacbdeec0abb5cb7249c6e719faa0db2dba43574b4fff5892d9220631c9abaff52dd3cad648cfea2aaace845e1a071915ac8867 + languageName: node + linkType: hard + +"run-async@npm:^4.0.5": + version: 4.0.6 + resolution: "run-async@npm:4.0.6" + checksum: 10c0/3e512c689d356238a06a59839deddeb09aec23bc66f780fe970fcf12b64bfc00c6880e9530ea22b8cf88a927145561f5a43343d8be87166e849ec0daaa3d4cf4 + languageName: node + linkType: hard + +"rxjs@npm:^7.8.2": + version: 7.8.2 + resolution: "rxjs@npm:7.8.2" + dependencies: + tslib: "npm:^2.1.0" + checksum: 10c0/1fcd33d2066ada98ba8f21fcbbcaee9f0b271de1d38dc7f4e256bfbc6ffcdde68c8bfb69093de7eeb46f24b1fb820620bf0223706cff26b4ab99a7ff7b2e2c45 + languageName: node + linkType: hard + +"safe-buffer@npm:5.2.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:~5.2.0": + version: 5.2.1 + resolution: "safe-buffer@npm:5.2.1" + checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3 + languageName: node + linkType: hard + +"safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1": + version: 5.1.2 + resolution: "safe-buffer@npm:5.1.2" + checksum: 10c0/780ba6b5d99cc9a40f7b951d47152297d0e260f0df01472a1b99d4889679a4b94a13d644f7dbc4f022572f09ae9005fa2fbb93bbbd83643316f365a3e9a45b21 + languageName: node + linkType: hard + +"safe-stable-stringify@npm:^2.3.1": + version: 2.5.0 + resolution: "safe-stable-stringify@npm:2.5.0" + checksum: 10c0/baea14971858cadd65df23894a40588ed791769db21bafb7fd7608397dbdce9c5aac60748abae9995e0fc37e15f2061980501e012cd48859740796bea2987f49 + languageName: node + linkType: hard + +"safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0, safer-buffer@npm:~2.1.0": + version: 2.1.2 + resolution: "safer-buffer@npm:2.1.2" + checksum: 10c0/7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4 + languageName: node + linkType: hard + +"semver@npm:2 || 3 || 4 || 5": + version: 5.7.2 + resolution: "semver@npm:5.7.2" + bin: + semver: bin/semver + checksum: 10c0/e4cf10f86f168db772ae95d86ba65b3fd6c5967c94d97c708ccb463b778c2ee53b914cd7167620950fc07faf5a564e6efe903836639e512a1aa15fbc9667fa25 + languageName: node + linkType: hard + +"semver@npm:7.7.2": + version: 7.7.2 + resolution: "semver@npm:7.7.2" + bin: + semver: bin/semver.js + checksum: 10c0/aca305edfbf2383c22571cb7714f48cadc7ac95371b4b52362fb8eeffdfbc0de0669368b82b2b15978f8848f01d7114da65697e56cd8c37b0dab8c58e543f9ea + languageName: node + linkType: hard + +"semver@npm:7.7.4, semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.3, semver@npm:^7.7.2, semver@npm:^7.7.3, semver@npm:^7.7.4": + version: 7.7.4 + resolution: "semver@npm:7.7.4" + bin: + semver: bin/semver.js + checksum: 10c0/5215ad0234e2845d4ea5bb9d836d42b03499546ddafb12075566899fc617f68794bb6f146076b6881d755de17d6c6cc73372555879ec7dce2c2feee947866ad2 + languageName: node + linkType: hard + +"semver@npm:^6.3.0, semver@npm:^6.3.1": + version: 6.3.1 + resolution: "semver@npm:6.3.1" + bin: + semver: bin/semver.js + checksum: 10c0/e3d79b609071caa78bcb6ce2ad81c7966a46a7431d9d58b8800cfa9cb6a63699b3899a0e4bcce36167a284578212d9ae6942b6929ba4aa5015c079a67751d42d + languageName: node + linkType: hard + +"send@npm:^1.1.0, send@npm:^1.2.0": + version: 1.2.1 + resolution: "send@npm:1.2.1" + dependencies: + debug: "npm:^4.4.3" + encodeurl: "npm:^2.0.0" + escape-html: "npm:^1.0.3" + etag: "npm:^1.8.1" + fresh: "npm:^2.0.0" + http-errors: "npm:^2.0.1" + mime-types: "npm:^3.0.2" + ms: "npm:^2.1.3" + on-finished: "npm:^2.4.1" + range-parser: "npm:^1.2.1" + statuses: "npm:^2.0.2" + checksum: 10c0/fbbbbdc902a913d65605274be23f3d604065cfc3ee3d78bf9fc8af1dc9fc82667c50d3d657f5e601ac657bac9b396b50ee97bd29cd55436320cf1cddebdcec72 + languageName: node + linkType: hard + +"send@npm:~0.19.0, send@npm:~0.19.1": + version: 0.19.2 + resolution: "send@npm:0.19.2" + dependencies: + debug: "npm:2.6.9" + depd: "npm:2.0.0" + destroy: "npm:1.2.0" + encodeurl: "npm:~2.0.0" + escape-html: "npm:~1.0.3" + etag: "npm:~1.8.1" + fresh: "npm:~0.5.2" + http-errors: "npm:~2.0.1" + mime: "npm:1.6.0" + ms: "npm:2.1.3" + on-finished: "npm:~2.4.1" + range-parser: "npm:~1.2.1" + statuses: "npm:~2.0.2" + checksum: 10c0/20c2389fe0fdf3fc499938cac598bc32272287e993c4960717381a10de8550028feadfb9076f959a3a3ebdea42e1f690e116f0d16468fa56b9fd41866d3dc267 + languageName: node + linkType: hard + +"sequelize-pool@npm:^7.1.0": + version: 7.1.0 + resolution: "sequelize-pool@npm:7.1.0" + checksum: 10c0/798f9856ce39ec1fabfbb4f966343be5ebb182e1a6b902bf131a7054df52a8dd183b18787c4952b0e3fa5aa7d1d72b5640682386c088538bfc127b6a6187a560 + languageName: node + linkType: hard + +"sequelize@npm:^6.37.0": + version: 6.37.8 + resolution: "sequelize@npm:6.37.8" + dependencies: + "@types/debug": "npm:^4.1.8" + "@types/validator": "npm:^13.7.17" + debug: "npm:^4.3.4" + dottie: "npm:^2.0.6" + inflection: "npm:^1.13.4" + lodash: "npm:^4.17.21" + moment: "npm:^2.29.4" + moment-timezone: "npm:^0.5.43" + pg-connection-string: "npm:^2.6.1" + retry-as-promised: "npm:^7.0.4" + semver: "npm:^7.5.4" + sequelize-pool: "npm:^7.1.0" + toposort-class: "npm:^1.0.1" + uuid: "npm:^8.3.2" + validator: "npm:^13.9.0" + wkx: "npm:^0.5.0" + peerDependenciesMeta: + ibm_db: + optional: true + mariadb: + optional: true + mysql2: + optional: true + oracledb: + optional: true + pg: + optional: true + pg-hstore: + optional: true + snowflake-sdk: + optional: true + sqlite3: + optional: true + tedious: + optional: true + checksum: 10c0/af1c5177e99dd2b65ee21b277e4f5744f28f51c2c3726efca3cae8fc58508cd0c8f377d423f0f4ad2c395f4c8ac41210ea68341eb52c591b93c12246f46a9efb + languageName: node + linkType: hard + +"serve-static@npm:^2.2.0": + version: 2.2.1 + resolution: "serve-static@npm:2.2.1" + dependencies: + encodeurl: "npm:^2.0.0" + escape-html: "npm:^1.0.3" + parseurl: "npm:^1.3.3" + send: "npm:^1.2.0" + checksum: 10c0/37986096e8572e2dfaad35a3925fa8da0c0969f8814fd7788e84d4d388bc068cf0c06d1658509788e55bed942a6b6d040a8a267fa92bb9ffb1179f8bacde5fd7 + languageName: node + linkType: hard + +"serve-static@npm:~1.16.2": + version: 1.16.3 + resolution: "serve-static@npm:1.16.3" + dependencies: + encodeurl: "npm:~2.0.0" + escape-html: "npm:~1.0.3" + parseurl: "npm:~1.3.3" + send: "npm:~0.19.1" + checksum: 10c0/36320397a073c71bedf58af48a4a100fe6d93f07459af4d6f08b9a7217c04ce2a4939e0effd842dc7bece93ffcd59eb52f58c4fff2a8e002dc29ae6b219cd42b + languageName: node + linkType: hard + +"setprototypeof@npm:1.2.0, setprototypeof@npm:~1.2.0": + version: 1.2.0 + resolution: "setprototypeof@npm:1.2.0" + checksum: 10c0/68733173026766fa0d9ecaeb07f0483f4c2dc70ca376b3b7c40b7cda909f94b0918f6c5ad5ce27a9160bdfb475efaa9d5e705a11d8eaae18f9835d20976028bc + languageName: node + linkType: hard + +"shebang-command@npm:^2.0.0": + version: 2.0.0 + resolution: "shebang-command@npm:2.0.0" + dependencies: + shebang-regex: "npm:^3.0.0" + checksum: 10c0/a41692e7d89a553ef21d324a5cceb5f686d1f3c040759c50aab69688634688c5c327f26f3ecf7001ebfd78c01f3c7c0a11a7c8bfd0a8bc9f6240d4f40b224e4e + languageName: node + linkType: hard + +"shebang-regex@npm:^3.0.0": + version: 3.0.0 + resolution: "shebang-regex@npm:3.0.0" + checksum: 10c0/1dbed0726dd0e1152a92696c76c7f06084eb32a90f0528d11acd764043aacf76994b2fb30aa1291a21bd019d6699164d048286309a278855ee7bec06cf6fb690 + languageName: node + linkType: hard + +"side-channel-list@npm:^1.0.0": + version: 1.0.0 + resolution: "side-channel-list@npm:1.0.0" + dependencies: + es-errors: "npm:^1.3.0" + object-inspect: "npm:^1.13.3" + checksum: 10c0/644f4ac893456c9490ff388bf78aea9d333d5e5bfc64cfb84be8f04bf31ddc111a8d4b83b85d7e7e8a7b845bc185a9ad02c052d20e086983cf59f0be517d9b3d + languageName: node + linkType: hard + +"side-channel-map@npm:^1.0.1": + version: 1.0.1 + resolution: "side-channel-map@npm:1.0.1" + dependencies: + call-bound: "npm:^1.0.2" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.5" + object-inspect: "npm:^1.13.3" + checksum: 10c0/010584e6444dd8a20b85bc926d934424bd809e1a3af941cace229f7fdcb751aada0fb7164f60c2e22292b7fa3c0ff0bce237081fd4cdbc80de1dc68e95430672 + languageName: node + linkType: hard + +"side-channel-weakmap@npm:^1.0.2": + version: 1.0.2 + resolution: "side-channel-weakmap@npm:1.0.2" + dependencies: + call-bound: "npm:^1.0.2" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.5" + object-inspect: "npm:^1.13.3" + side-channel-map: "npm:^1.0.1" + checksum: 10c0/71362709ac233e08807ccd980101c3e2d7efe849edc51455030327b059f6c4d292c237f94dc0685031dd11c07dd17a68afde235d6cf2102d949567f98ab58185 + languageName: node + linkType: hard + +"side-channel@npm:^1.1.0": + version: 1.1.0 + resolution: "side-channel@npm:1.1.0" + dependencies: + es-errors: "npm:^1.3.0" + object-inspect: "npm:^1.13.3" + side-channel-list: "npm:^1.0.0" + side-channel-map: "npm:^1.0.1" + side-channel-weakmap: "npm:^1.0.2" + checksum: 10c0/cb20dad41eb032e6c24c0982e1e5a24963a28aa6122b4f05b3f3d6bf8ae7fd5474ef382c8f54a6a3ab86e0cac4d41a23bd64ede3970e5bfb50326ba02a7996e6 + languageName: node + linkType: hard + +"signal-exit@npm:3.0.7, signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": + version: 3.0.7 + resolution: "signal-exit@npm:3.0.7" + checksum: 10c0/25d272fa73e146048565e08f3309d5b942c1979a6f4a58a8c59d5fa299728e9c2fcd1a759ec870863b1fd38653670240cd420dad2ad9330c71f36608a6a1c912 + languageName: node + linkType: hard + +"signal-exit@npm:^4.0.1, signal-exit@npm:^4.1.0": + version: 4.1.0 + resolution: "signal-exit@npm:4.1.0" + checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 + languageName: node + linkType: hard + +"sigstore@npm:^4.0.0": + version: 4.1.0 + resolution: "sigstore@npm:4.1.0" + dependencies: + "@sigstore/bundle": "npm:^4.0.0" + "@sigstore/core": "npm:^3.1.0" + "@sigstore/protobuf-specs": "npm:^0.5.0" + "@sigstore/sign": "npm:^4.1.0" + "@sigstore/tuf": "npm:^4.0.1" + "@sigstore/verify": "npm:^3.1.0" + checksum: 10c0/6a62601b75c5b0336c15b62d41be6d07e750a2ebd93a49856401cff201aaab4af8304f3edeaffb4777409385c828c11c09b94b721be5932c1335de2292cceadd + languageName: node + linkType: hard + +"sisteransi@npm:^1.0.5": + version: 1.0.5 + resolution: "sisteransi@npm:1.0.5" + checksum: 10c0/230ac975cca485b7f6fe2b96a711aa62a6a26ead3e6fb8ba17c5a00d61b8bed0d7adc21f5626b70d7c33c62ff4e63933017a6462942c719d1980bb0b1207ad46 + languageName: node + linkType: hard + +"slash@npm:3.0.0, slash@npm:^3.0.0": + version: 3.0.0 + resolution: "slash@npm:3.0.0" + checksum: 10c0/e18488c6a42bdfd4ac5be85b2ced3ccd0224773baae6ad42cfbb9ec74fc07f9fa8396bd35ee638084ead7a2a0818eb5e7151111544d4731ce843019dab4be47b + languageName: node + linkType: hard + +"smart-buffer@npm:^4.2.0": + version: 4.2.0 + resolution: "smart-buffer@npm:4.2.0" + checksum: 10c0/a16775323e1404dd43fabafe7460be13a471e021637bc7889468eb45ce6a6b207261f454e4e530a19500cc962c4cc5348583520843b363f4193cee5c00e1e539 + languageName: node + linkType: hard + +"socks-proxy-agent@npm:^8.0.3": + version: 8.0.5 + resolution: "socks-proxy-agent@npm:8.0.5" + dependencies: + agent-base: "npm:^7.1.2" + debug: "npm:^4.3.4" + socks: "npm:^2.8.3" + checksum: 10c0/5d2c6cecba6821389aabf18728325730504bf9bb1d9e342e7987a5d13badd7a98838cc9a55b8ed3cb866ad37cc23e1086f09c4d72d93105ce9dfe76330e9d2a6 + languageName: node + linkType: hard + +"socks@npm:^2.8.3": + version: 2.8.7 + resolution: "socks@npm:2.8.7" + dependencies: + ip-address: "npm:^10.0.1" + smart-buffer: "npm:^4.2.0" + checksum: 10c0/2805a43a1c4bcf9ebf6e018268d87b32b32b06fbbc1f9282573583acc155860dc361500f89c73bfbb157caa1b4ac78059eac0ef15d1811eb0ca75e0bdadbc9d2 + languageName: node + linkType: hard + +"source-map-support@npm:0.5.13": + version: 0.5.13 + resolution: "source-map-support@npm:0.5.13" + dependencies: + buffer-from: "npm:^1.0.0" + source-map: "npm:^0.6.0" + checksum: 10c0/137539f8c453fa0f496ea42049ab5da4569f96781f6ac8e5bfda26937be9494f4e8891f523c5f98f0e85f71b35d74127a00c46f83f6a4f54672b58d53202565e + languageName: node + linkType: hard + +"source-map-support@npm:0.5.19": + version: 0.5.19 + resolution: "source-map-support@npm:0.5.19" + dependencies: + buffer-from: "npm:^1.0.0" + source-map: "npm:^0.6.0" + checksum: 10c0/a232cb02dc5c2c048460dff3ca1a4c2aa44488822028932daff99b8707c8e4f87d2535dae319d65691c905096f2c06a2517793472634efb01f8a095661b9aa93 + languageName: node + linkType: hard + +"source-map@npm:^0.6.0, source-map@npm:^0.6.1": + version: 0.6.1 + resolution: "source-map@npm:0.6.1" + checksum: 10c0/ab55398007c5e5532957cb0beee2368529618ac0ab372d789806f5718123cc4367d57de3904b4e6a4170eb5a0b0f41373066d02ca0735a0c4d75c7d328d3e011 + languageName: node + linkType: hard + +"spdx-correct@npm:^3.0.0": + version: 3.2.0 + resolution: "spdx-correct@npm:3.2.0" + dependencies: + spdx-expression-parse: "npm:^3.0.0" + spdx-license-ids: "npm:^3.0.0" + checksum: 10c0/49208f008618b9119208b0dadc9208a3a55053f4fd6a0ae8116861bd22696fc50f4142a35ebfdb389e05ccf2de8ad142573fefc9e26f670522d899f7b2fe7386 + languageName: node + linkType: hard + +"spdx-exceptions@npm:^2.1.0": + version: 2.5.0 + resolution: "spdx-exceptions@npm:2.5.0" + checksum: 10c0/37217b7762ee0ea0d8b7d0c29fd48b7e4dfb94096b109d6255b589c561f57da93bf4e328c0290046115961b9209a8051ad9f525e48d433082fc79f496a4ea940 + languageName: node + linkType: hard + +"spdx-expression-parse@npm:^3.0.0": + version: 3.0.1 + resolution: "spdx-expression-parse@npm:3.0.1" + dependencies: + spdx-exceptions: "npm:^2.1.0" + spdx-license-ids: "npm:^3.0.0" + checksum: 10c0/6f8a41c87759fa184a58713b86c6a8b028250f158159f1d03ed9d1b6ee4d9eefdc74181c8ddc581a341aa971c3e7b79e30b59c23b05d2436d5de1c30bdef7171 + languageName: node + linkType: hard + +"spdx-expression-parse@npm:^4.0.0": + version: 4.0.0 + resolution: "spdx-expression-parse@npm:4.0.0" + dependencies: + spdx-exceptions: "npm:^2.1.0" + spdx-license-ids: "npm:^3.0.0" + checksum: 10c0/965c487e77f4fb173f1c471f3eef4eb44b9f0321adc7f93d95e7620da31faa67d29356eb02523cd7df8a7fc1ec8238773cdbf9e45bd050329d2b26492771b736 + languageName: node + linkType: hard + +"spdx-license-ids@npm:^3.0.0": + version: 3.0.23 + resolution: "spdx-license-ids@npm:3.0.23" + checksum: 10c0/8495620f6f2a237749cce922ea2d593a66f7885c301b1a0f5542183e7041182f27f616a8f13345cefdea0c9b3e0899328e0aa8cec100cf4f3fac4bb3bd975515 + languageName: node + linkType: hard + +"split-ca@npm:^1.0.1": + version: 1.0.1 + resolution: "split-ca@npm:1.0.1" + checksum: 10c0/f339170b84c6b4706fcf4c60cc84acb36574c0447566bd713301a8d9b4feff7f4627efc8c334bec24944a3e2f35bc596bd58c673c9980d6bfe3137aae1116ba7 + languageName: node + linkType: hard + +"split2@npm:^3.2.2": + version: 3.2.2 + resolution: "split2@npm:3.2.2" + dependencies: + readable-stream: "npm:^3.0.0" + checksum: 10c0/2dad5603c52b353939befa3e2f108f6e3aff42b204ad0f5f16dd12fd7c2beab48d117184ce6f7c8854f9ee5ffec6faae70d243711dd7d143a9f635b4a285de4e + languageName: node + linkType: hard + +"split2@npm:^4.1.0": + version: 4.2.0 + resolution: "split2@npm:4.2.0" + checksum: 10c0/b292beb8ce9215f8c642bb68be6249c5a4c7f332fc8ecadae7be5cbdf1ea95addc95f0459ef2e7ad9d45fd1064698a097e4eb211c83e772b49bc0ee423e91534 + languageName: node + linkType: hard + +"split@npm:^1.0.1": + version: 1.0.1 + resolution: "split@npm:1.0.1" + dependencies: + through: "npm:2" + checksum: 10c0/7f489e7ed5ff8a2e43295f30a5197ffcb2d6202c9cf99357f9690d645b19c812bccf0be3ff336fea5054cda17ac96b91d67147d95dbfc31fbb5804c61962af85 + languageName: node + linkType: hard + +"sprintf-js@npm:~1.0.2": + version: 1.0.3 + resolution: "sprintf-js@npm:1.0.3" + checksum: 10c0/ecadcfe4c771890140da5023d43e190b7566d9cf8b2d238600f31bec0fc653f328da4450eb04bd59a431771a8e9cc0e118f0aa3974b683a4981b4e07abc2a5bb + languageName: node + linkType: hard + +"ssh-remote-port-forward@npm:^1.0.4": + version: 1.0.4 + resolution: "ssh-remote-port-forward@npm:1.0.4" + dependencies: + "@types/ssh2": "npm:^0.5.48" + ssh2: "npm:^1.4.0" + checksum: 10c0/33a441af12817577ea30d089b03c19f980d2fb2370933123a35026dc6be40f2dfce067e4dfc173e23d745464537ff647aa1bb7469be5571cc21f7cdb25181c09 + languageName: node + linkType: hard + +"ssh2@npm:^1.15.0, ssh2@npm:^1.4.0": + version: 1.17.0 + resolution: "ssh2@npm:1.17.0" + dependencies: + asn1: "npm:^0.2.6" + bcrypt-pbkdf: "npm:^1.0.2" + cpu-features: "npm:~0.0.10" + nan: "npm:^2.23.0" + dependenciesMeta: + cpu-features: + optional: true + nan: + optional: true + checksum: 10c0/637c1b7e8070fc8a3027f8abf771cd98419f56eaf3817171180e768004d4dea26c65fb3763294ed2f784429857f196c83c4f6889d2c31cc0e2648ea5ad730665 + languageName: node + linkType: hard + +"ssri@npm:12.0.0, ssri@npm:^12.0.0": + version: 12.0.0 + resolution: "ssri@npm:12.0.0" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10c0/caddd5f544b2006e88fa6b0124d8d7b28208b83c72d7672d5ade44d794525d23b540f3396108c4eb9280dcb7c01f0bef50682f5b4b2c34291f7c5e211fd1417d + languageName: node + linkType: hard + +"ssri@npm:^13.0.0": + version: 13.0.1 + resolution: "ssri@npm:13.0.1" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10c0/cf6408a18676c57ff2ed06b8a20dc64bb3e748e5c7e095332e6aecaa2b8422b1e94a739a8453bf65156a8a47afe23757ba4ab52d3ea3b62322dc40875763e17a + languageName: node + linkType: hard + +"stack-trace@npm:0.0.x": + version: 0.0.10 + resolution: "stack-trace@npm:0.0.10" + checksum: 10c0/9ff3dabfad4049b635a85456f927a075c9d0c210e3ea336412d18220b2a86cbb9b13ec46d6c37b70a302a4ea4d49e30e5d4944dd60ae784073f1cde778ac8f4b + languageName: node + linkType: hard + +"stack-utils@npm:^2.0.3, stack-utils@npm:^2.0.6": + version: 2.0.6 + resolution: "stack-utils@npm:2.0.6" + dependencies: + escape-string-regexp: "npm:^2.0.0" + checksum: 10c0/651c9f87667e077584bbe848acaecc6049bc71979f1e9a46c7b920cad4431c388df0f51b8ad7cfd6eed3db97a2878d0fc8b3122979439ea8bac29c61c95eec8a + languageName: node + linkType: hard + +"standard-as-callback@npm:^2.1.0": + version: 2.1.0 + resolution: "standard-as-callback@npm:2.1.0" + checksum: 10c0/012677236e3d3fdc5689d29e64ea8a599331c4babe86956bf92fc5e127d53f85411c5536ee0079c52c43beb0026b5ce7aa1d834dd35dd026e82a15d1bcaead1f + languageName: node + linkType: hard + +"statuses@npm:^2.0.1, statuses@npm:^2.0.2, statuses@npm:~2.0.1, statuses@npm:~2.0.2": + version: 2.0.2 + resolution: "statuses@npm:2.0.2" + checksum: 10c0/a9947d98ad60d01f6b26727570f3bcceb6c8fa789da64fe6889908fe2e294d57503b14bf2b5af7605c2d36647259e856635cd4c49eab41667658ec9d0080ec3f + languageName: node + linkType: hard + +"streamsearch@npm:^1.1.0": + version: 1.1.0 + resolution: "streamsearch@npm:1.1.0" + checksum: 10c0/fbd9aecc2621364384d157f7e59426f4bfd385e8b424b5aaa79c83a6f5a1c8fd2e4e3289e95de1eb3511cb96bb333d6281a9919fafce760e4edb35b2cd2facab + languageName: node + linkType: hard + +"streamx@npm:^2.12.5, streamx@npm:^2.15.0, streamx@npm:^2.25.0": + version: 2.25.0 + resolution: "streamx@npm:2.25.0" + dependencies: + events-universal: "npm:^1.0.0" + fast-fifo: "npm:^1.3.2" + text-decoder: "npm:^1.1.0" + checksum: 10c0/1ecc4b722050e9088b99cde59d035e846ac97cedc3ef14a00b196d9c0b6f47d9fd18df454a19f56f0f586ab4f23fb7229069b9e8eaf22072a21bd9c909d4e0ea + languageName: node + linkType: hard + +"string-length@npm:^4.0.1, string-length@npm:^4.0.2": + version: 4.0.2 + resolution: "string-length@npm:4.0.2" + dependencies: + char-regex: "npm:^1.0.2" + strip-ansi: "npm:^6.0.0" + checksum: 10c0/1cd77409c3d7db7bc59406f6bcc9ef0783671dcbabb23597a1177c166906ef2ee7c8290f78cae73a8aec858768f189d2cb417797df5e15ec4eb5e16b3346340c + languageName: node + linkType: hard + +"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3": + version: 4.2.3 + resolution: "string-width@npm:4.2.3" + dependencies: + emoji-regex: "npm:^8.0.0" + is-fullwidth-code-point: "npm:^3.0.0" + strip-ansi: "npm:^6.0.1" + checksum: 10c0/1e525e92e5eae0afd7454086eed9c818ee84374bb80328fc41217ae72ff5f065ef1c9d7f72da41de40c75fa8bb3dee63d92373fd492c84260a552c636392a47b + languageName: node + linkType: hard + +"string-width@npm:^5.0.1, string-width@npm:^5.1.2": + version: 5.1.2 + resolution: "string-width@npm:5.1.2" + dependencies: + eastasianwidth: "npm:^0.2.0" + emoji-regex: "npm:^9.2.2" + strip-ansi: "npm:^7.0.1" + checksum: 10c0/ab9c4264443d35b8b923cbdd513a089a60de339216d3b0ed3be3ba57d6880e1a192b70ae17225f764d7adbf5994e9bb8df253a944736c15a0240eff553c678ca + languageName: node + linkType: hard + +"string_decoder@npm:^1.1.1, string_decoder@npm:^1.3.0": + version: 1.3.0 + resolution: "string_decoder@npm:1.3.0" + dependencies: + safe-buffer: "npm:~5.2.0" + checksum: 10c0/810614ddb030e271cd591935dcd5956b2410dd079d64ff92a1844d6b7588bf992b3e1b69b0f4d34a3e06e0bd73046ac646b5264c1987b20d0601f81ef35d731d + languageName: node + linkType: hard + +"string_decoder@npm:~1.1.1": + version: 1.1.1 + resolution: "string_decoder@npm:1.1.1" + dependencies: + safe-buffer: "npm:~5.1.0" + checksum: 10c0/b4f89f3a92fd101b5653ca3c99550e07bdf9e13b35037e9e2a1c7b47cec4e55e06ff3fc468e314a0b5e80bfbaf65c1ca5a84978764884ae9413bec1fc6ca924e + languageName: node + linkType: hard + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": + version: 6.0.1 + resolution: "strip-ansi@npm:6.0.1" + dependencies: + ansi-regex: "npm:^5.0.1" + checksum: 10c0/1ae5f212a126fe5b167707f716942490e3933085a5ff6c008ab97ab2f272c8025d3aa218b7bd6ab25729ca20cc81cddb252102f8751e13482a5199e873680952 + languageName: node + linkType: hard + +"strip-ansi@npm:^7.0.1": + version: 7.2.0 + resolution: "strip-ansi@npm:7.2.0" + dependencies: + ansi-regex: "npm:^6.2.2" + checksum: 10c0/544d13b7582f8254811ea97db202f519e189e59d35740c46095897e254e4f1aa9fe1524a83ad6bc5ad67d4dd6c0281d2e0219ed62b880a6238a16a17d375f221 + languageName: node + linkType: hard + +"strip-bom@npm:^3.0.0": + version: 3.0.0 + resolution: "strip-bom@npm:3.0.0" + checksum: 10c0/51201f50e021ef16672593d7434ca239441b7b760e905d9f33df6e4f3954ff54ec0e0a06f100d028af0982d6f25c35cd5cda2ce34eaebccd0250b8befb90d8f1 + languageName: node + linkType: hard + +"strip-bom@npm:^4.0.0": + version: 4.0.0 + resolution: "strip-bom@npm:4.0.0" + checksum: 10c0/26abad1172d6bc48985ab9a5f96c21e440f6e7e476686de49be813b5a59b3566dccb5c525b831ec54fe348283b47f3ffb8e080bc3f965fde12e84df23f6bb7ef + languageName: node + linkType: hard + +"strip-final-newline@npm:^2.0.0": + version: 2.0.0 + resolution: "strip-final-newline@npm:2.0.0" + checksum: 10c0/bddf8ccd47acd85c0e09ad7375409d81653f645fda13227a9d459642277c253d877b68f2e5e4d819fe75733b0e626bac7e954c04f3236f6d196f79c94fa4a96f + languageName: node + linkType: hard + +"strip-indent@npm:^3.0.0": + version: 3.0.0 + resolution: "strip-indent@npm:3.0.0" + dependencies: + min-indent: "npm:^1.0.0" + checksum: 10c0/ae0deaf41c8d1001c5d4fbe16cb553865c1863da4fae036683b474fa926af9fc121e155cb3fc57a68262b2ae7d5b8420aa752c97a6428c315d00efe2a3875679 + languageName: node + linkType: hard + +"strip-json-comments@npm:^3.1.1": + version: 3.1.1 + resolution: "strip-json-comments@npm:3.1.1" + checksum: 10c0/9681a6257b925a7fa0f285851c0e613cc934a50661fa7bb41ca9cbbff89686bb4a0ee366e6ecedc4daafd01e83eee0720111ab294366fe7c185e935475ebcecd + languageName: node + linkType: hard + +"strtok3@npm:^10.2.0": + version: 10.3.5 + resolution: "strtok3@npm:10.3.5" + dependencies: + "@tokenizer/token": "npm:^0.3.0" + checksum: 10c0/8d2477b239054c9f1f5b14a65d531147ca158ab9887fdc2d0938e77b7ec8891fb683b58254c7643afd5d98a421a59207534d491762b111f58c795071ecbe9fd1 + languageName: node + linkType: hard + +"supports-color@npm:^7.1.0": + version: 7.2.0 + resolution: "supports-color@npm:7.2.0" + dependencies: + has-flag: "npm:^4.0.0" + checksum: 10c0/afb4c88521b8b136b5f5f95160c98dee7243dc79d5432db7efc27efb219385bbc7d9427398e43dd6cc730a0f87d5085ce1652af7efbe391327bc0a7d0f7fc124 + languageName: node + linkType: hard + +"supports-color@npm:^8.0.0, supports-color@npm:^8.1.1": + version: 8.1.1 + resolution: "supports-color@npm:8.1.1" + dependencies: + has-flag: "npm:^4.0.0" + checksum: 10c0/ea1d3c275dd604c974670f63943ed9bd83623edc102430c05adb8efc56ba492746b6e95386e7831b872ec3807fd89dd8eb43f735195f37b5ec343e4234cc7e89 + languageName: node + linkType: hard + +"supports-preserve-symlinks-flag@npm:^1.0.0": + version: 1.0.0 + resolution: "supports-preserve-symlinks-flag@npm:1.0.0" + checksum: 10c0/6c4032340701a9950865f7ae8ef38578d8d7053f5e10518076e6554a9381fa91bd9c6850193695c141f32b21f979c985db07265a758867bac95de05f7d8aeb39 + languageName: node + linkType: hard + +"synckit@npm:^0.11.12, synckit@npm:^0.11.8": + version: 0.11.12 + resolution: "synckit@npm:0.11.12" + dependencies: + "@pkgr/core": "npm:^0.2.9" + checksum: 10c0/cc4d446806688ae0d728ae7bb3f53176d065cf9536647fb85bdd721dcefbd7bf94874df6799ff61580f2b03a392659219b778a9254ad499f9a1f56c34787c235 + languageName: node + linkType: hard + +"tar-fs@npm:^2.1.4": + version: 2.1.4 + resolution: "tar-fs@npm:2.1.4" + dependencies: + chownr: "npm:^1.1.1" + mkdirp-classic: "npm:^0.5.2" + pump: "npm:^3.0.0" + tar-stream: "npm:^2.1.4" + checksum: 10c0/decb25acdc6839182c06ec83cba6136205bda1db984e120c8ffd0d80182bc5baa1d916f9b6c5c663ea3f9975b4dd49e3c6bb7b1707cbcdaba4e76042f43ec84c + languageName: node + linkType: hard + +"tar-fs@npm:^3.0.7, tar-fs@npm:^3.1.2": + version: 3.1.2 + resolution: "tar-fs@npm:3.1.2" + dependencies: + bare-fs: "npm:^4.0.1" + bare-path: "npm:^3.0.0" + pump: "npm:^3.0.0" + tar-stream: "npm:^3.1.5" + dependenciesMeta: + bare-fs: + optional: true + bare-path: + optional: true + checksum: 10c0/9dcbbbef9cdfc27f47651fe679f15952a6a8e6b3c9761c4bf3f416ace41cf462fb6292519bd3e041cadfcc0b89043a6bdecb46ff19f770b6864b77dcde7bad46 + languageName: node + linkType: hard + +"tar-stream@npm:^2.1.4, tar-stream@npm:~2.2.0": + version: 2.2.0 + resolution: "tar-stream@npm:2.2.0" + dependencies: + bl: "npm:^4.0.3" + end-of-stream: "npm:^1.4.1" + fs-constants: "npm:^1.0.0" + inherits: "npm:^2.0.3" + readable-stream: "npm:^3.1.1" + checksum: 10c0/2f4c910b3ee7196502e1ff015a7ba321ec6ea837667220d7bcb8d0852d51cb04b87f7ae471008a6fb8f5b1a1b5078f62f3a82d30c706f20ada1238ac797e7692 + languageName: node + linkType: hard + +"tar-stream@npm:^3.0.0, tar-stream@npm:^3.1.5": + version: 3.1.8 + resolution: "tar-stream@npm:3.1.8" + dependencies: + b4a: "npm:^1.6.4" + bare-fs: "npm:^4.5.5" + fast-fifo: "npm:^1.2.0" + streamx: "npm:^2.15.0" + checksum: 10c0/c4bf369de2302fcf30218d091167a5372ee79b69a1b5bb493ddb7714193ca805719558966334bab1f2775c8142826865f24e25459ff1c5f0a096bc3a3d5c5ce2 + languageName: node + linkType: hard + +"tar@npm:7.5.11": + version: 7.5.11 + resolution: "tar@npm:7.5.11" + dependencies: + "@isaacs/fs-minipass": "npm:^4.0.0" + chownr: "npm:^3.0.0" + minipass: "npm:^7.1.2" + minizlib: "npm:^3.1.0" + yallist: "npm:^5.0.0" + checksum: 10c0/b6bb420550ef50ef23356018155e956cd83282c97b6128d8d5cfe5740c57582d806a244b2ef0bf686a74ce526babe8b8b9061527623e935e850008d86d838929 + languageName: node + linkType: hard + +"tar@npm:^7.4.3, tar@npm:^7.5.4": + version: 7.5.13 + resolution: "tar@npm:7.5.13" + dependencies: + "@isaacs/fs-minipass": "npm:^4.0.0" + chownr: "npm:^3.0.0" + minipass: "npm:^7.1.2" + minizlib: "npm:^3.1.0" + yallist: "npm:^5.0.0" + checksum: 10c0/5c65b8084799bde7a791593a1c1a45d3d6ee98182e3700b24c247b7b8f8654df4191642abbdb07ff25043d45dcff35620827c3997b88ae6c12040f64bed5076b + languageName: node + linkType: hard + +"teex@npm:^1.0.1": + version: 1.0.1 + resolution: "teex@npm:1.0.1" + dependencies: + streamx: "npm:^2.12.5" + checksum: 10c0/8df9166c037ba694b49d32a49858e314c60e513d55ac5e084dbf1ddbb827c5fa43cc389a81e87684419c21283308e9d68bb068798189c767ec4c252f890b8a77 + languageName: node + linkType: hard + +"test-exclude@npm:^6.0.0": + version: 6.0.0 + resolution: "test-exclude@npm:6.0.0" + dependencies: + "@istanbuljs/schema": "npm:^0.1.2" + glob: "npm:^7.1.4" + minimatch: "npm:^3.0.4" + checksum: 10c0/019d33d81adff3f9f1bfcff18125fb2d3c65564f437d9be539270ee74b994986abb8260c7c2ce90e8f30162178b09dbbce33c6389273afac4f36069c48521f57 + languageName: node + linkType: hard + +"testcontainers@npm:^10.24.0": + version: 10.28.0 + resolution: "testcontainers@npm:10.28.0" + dependencies: + "@balena/dockerignore": "npm:^1.0.2" + "@types/dockerode": "npm:^3.3.35" + archiver: "npm:^7.0.1" + async-lock: "npm:^1.4.1" + byline: "npm:^5.0.0" + debug: "npm:^4.3.5" + docker-compose: "npm:^0.24.8" + dockerode: "npm:^4.0.5" + get-port: "npm:^7.1.0" + proper-lockfile: "npm:^4.1.2" + properties-reader: "npm:^2.3.0" + ssh-remote-port-forward: "npm:^1.0.4" + tar-fs: "npm:^3.0.7" + tmp: "npm:^0.2.3" + undici: "npm:^5.29.0" + checksum: 10c0/0bdefbcac5b774df4ed373f7e6f6a4df91f2c7fd2be135571471df6bdfa62919843824d11329a36a53c7446210db1eb17d8fb6658b7616d4b0158c089ed9563b + languageName: node + linkType: hard + +"testcontainers@npm:^11.13.0": + version: 11.13.0 + resolution: "testcontainers@npm:11.13.0" + dependencies: + "@balena/dockerignore": "npm:^1.0.2" + "@types/dockerode": "npm:^4.0.1" + archiver: "npm:^7.0.1" + async-lock: "npm:^1.4.1" + byline: "npm:^5.0.0" + debug: "npm:^4.4.3" + docker-compose: "npm:^1.3.2" + dockerode: "npm:^4.0.9" + get-port: "npm:^7.1.0" + proper-lockfile: "npm:^4.1.2" + properties-reader: "npm:^3.0.1" + ssh-remote-port-forward: "npm:^1.0.4" + tar-fs: "npm:^3.1.2" + tmp: "npm:^0.2.5" + undici: "npm:^7.24.3" + checksum: 10c0/e8945ce6537d6768fddf908730c82aaa783e8ec541382a2c0fee2c2eae9559b3177106938364b92469e18e71b40dc0bdf6224fb346a0ba44f04a398b63fc1cc1 + languageName: node + linkType: hard + +"text-decoder@npm:^1.1.0": + version: 1.2.7 + resolution: "text-decoder@npm:1.2.7" + dependencies: + b4a: "npm:^1.6.4" + checksum: 10c0/929938ed154fbadb660a7f3d1aca30b7e53649a731af7583168fcfba0c158046325d35d945926e2a512bb62d1a49a7818151c987ea38b48853f01e1615722fc5 + languageName: node + linkType: hard + +"text-extensions@npm:^1.0.0": + version: 1.9.0 + resolution: "text-extensions@npm:1.9.0" + checksum: 10c0/9ad5a9f723a871e2d884e132d7e93f281c60b5759c95f3f6b04704856548715d93a36c10dbaf5f12b91bf405f0cf3893bf169d4d143c0f5509563b992d385443 + languageName: node + linkType: hard + +"text-hex@npm:1.0.x": + version: 1.0.0 + resolution: "text-hex@npm:1.0.0" + checksum: 10c0/57d8d320d92c79d7c03ffb8339b825bb9637c2cbccf14304309f51d8950015c44464b6fd1b6820a3d4821241c68825634f09f5a2d9d501e84f7c6fd14376860d + languageName: node + linkType: hard + +"through2@npm:^2.0.0": + version: 2.0.5 + resolution: "through2@npm:2.0.5" + dependencies: + readable-stream: "npm:~2.3.6" + xtend: "npm:~4.0.1" + checksum: 10c0/cbfe5b57943fa12b4f8c043658c2a00476216d79c014895cef1ac7a1d9a8b31f6b438d0e53eecbb81054b93128324a82ecd59ec1a4f91f01f7ac113dcb14eade + languageName: node + linkType: hard + +"through@npm:2, through@npm:2.3.8, through@npm:>=2.2.7 <3": + version: 2.3.8 + resolution: "through@npm:2.3.8" + checksum: 10c0/4b09f3774099de0d4df26d95c5821a62faee32c7e96fb1f4ebd54a2d7c11c57fe88b0a0d49cf375de5fee5ae6bf4eb56dbbf29d07366864e2ee805349970d3cc + languageName: node + linkType: hard + +"tinyglobby@npm:0.2.12": + version: 0.2.12 + resolution: "tinyglobby@npm:0.2.12" + dependencies: + fdir: "npm:^6.4.3" + picomatch: "npm:^4.0.2" + checksum: 10c0/7c9be4fd3625630e262dcb19015302aad3b4ba7fc620f269313e688f2161ea8724d6cb4444baab5ef2826eb6bed72647b169a33ec8eea37501832a2526ff540f + languageName: node + linkType: hard + +"tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.15": + version: 0.2.15 + resolution: "tinyglobby@npm:0.2.15" + dependencies: + fdir: "npm:^6.5.0" + picomatch: "npm:^4.0.3" + checksum: 10c0/869c31490d0d88eedb8305d178d4c75e7463e820df5a9b9d388291daf93e8b1eb5de1dad1c1e139767e4269fe75f3b10d5009b2cc14db96ff98986920a186844 + languageName: node + linkType: hard + +"tmp@npm:^0.2.3, tmp@npm:^0.2.5, tmp@npm:~0.2.1": + version: 0.2.5 + resolution: "tmp@npm:0.2.5" + checksum: 10c0/cee5bb7d674bb4ba3ab3f3841c2ca7e46daeb2109eec395c1ec7329a91d52fcb21032b79ac25161a37b2565c4858fefab927af9735926a113ef7bac9091a6e0e + languageName: node + linkType: hard + +"tmpl@npm:1.0.5": + version: 1.0.5 + resolution: "tmpl@npm:1.0.5" + checksum: 10c0/f935537799c2d1922cb5d6d3805f594388f75338fe7a4a9dac41504dd539704ca4db45b883b52e7b0aa5b2fd5ddadb1452bf95cd23a69da2f793a843f9451cc9 + languageName: node + linkType: hard + +"to-regex-range@npm:^5.0.1": + version: 5.0.1 + resolution: "to-regex-range@npm:5.0.1" + dependencies: + is-number: "npm:^7.0.0" + checksum: 10c0/487988b0a19c654ff3e1961b87f471702e708fa8a8dd02a298ef16da7206692e8552a0250e8b3e8759270f62e9d8314616f6da274734d3b558b1fc7b7724e892 + languageName: node + linkType: hard + +"toidentifier@npm:~1.0.1": + version: 1.0.1 + resolution: "toidentifier@npm:1.0.1" + checksum: 10c0/93937279934bd66cc3270016dd8d0afec14fb7c94a05c72dc57321f8bd1fa97e5bea6d1f7c89e728d077ca31ea125b78320a616a6c6cd0e6b9cb94cb864381c1 + languageName: node + linkType: hard + +"token-types@npm:^6.0.0": + version: 6.1.2 + resolution: "token-types@npm:6.1.2" + dependencies: + "@borewit/text-codec": "npm:^0.2.1" + "@tokenizer/token": "npm:^0.3.0" + ieee754: "npm:^1.2.1" + checksum: 10c0/8786e28e3cb65b9e890bc3c38def98e6dfe4565538237f8c0e47dbe549ed8f5f00de8dc464717868308abb4729f1958f78f69e1c4c3deebbb685729113a6fee8 + languageName: node + linkType: hard + +"toposort-class@npm:^1.0.1": + version: 1.0.1 + resolution: "toposort-class@npm:1.0.1" + checksum: 10c0/75eacd421eca239aa480ead62dfd8966cbfc2483fd39e18893a59fe982cd904aa82ecbd46a0cdcea542f4f0a68799e5fc24bcb987029075f02a75679559fa4d7 + languageName: node + linkType: hard + +"tr46@npm:~0.0.3": + version: 0.0.3 + resolution: "tr46@npm:0.0.3" + checksum: 10c0/047cb209a6b60c742f05c9d3ace8fa510bff609995c129a37ace03476a9b12db4dbf975e74600830ef0796e18882b2381fb5fb1f6b4f96b832c374de3ab91a11 + languageName: node + linkType: hard + +"tree-kill@npm:^1.2.2": + version: 1.2.2 + resolution: "tree-kill@npm:1.2.2" + bin: + tree-kill: cli.js + checksum: 10c0/7b1b7c7f17608a8f8d20a162e7957ac1ef6cd1636db1aba92f4e072dc31818c2ff0efac1e3d91064ede67ed5dc57c565420531a8134090a12ac10cf792ab14d2 + languageName: node + linkType: hard + +"treeverse@npm:^3.0.0": + version: 3.0.0 + resolution: "treeverse@npm:3.0.0" + checksum: 10c0/286479b9c05a8fb0538ee7d67a5502cea7704f258057c784c9c1118a2f598788b2c0f7a8d89e74648af88af0225b31766acecd78e6060736f09b21dd3fa255db + languageName: node + linkType: hard + +"trim-newlines@npm:^3.0.0": + version: 3.0.1 + resolution: "trim-newlines@npm:3.0.1" + checksum: 10c0/03cfefde6c59ff57138412b8c6be922ecc5aec30694d784f2a65ef8dcbd47faef580b7de0c949345abdc56ec4b4abf64dd1e5aea619b200316e471a3dd5bf1f6 + languageName: node + linkType: hard + +"triple-beam@npm:^1.3.0": + version: 1.4.1 + resolution: "triple-beam@npm:1.4.1" + checksum: 10c0/4bf1db71e14fe3ff1c3adbe3c302f1fdb553b74d7591a37323a7badb32dc8e9c290738996cbb64f8b10dc5a3833645b5d8c26221aaaaa12e50d1251c9aba2fea + languageName: node + linkType: hard + +"ts-api-utils@npm:^2.5.0": + version: 2.5.0 + resolution: "ts-api-utils@npm:2.5.0" + peerDependencies: + typescript: ">=4.8.4" + checksum: 10c0/767849383c114e7f1971fa976b20e73ac28fd0c70d8d65c0004790bf4d8f89888c7e4cf6d5949f9c1beae9bc3c64835bef77bbe27fddf45a3c7b60cebcf85c8c + languageName: node + linkType: hard + +"ts-error@npm:^1.0.6": + version: 1.0.6 + resolution: "ts-error@npm:1.0.6" + checksum: 10c0/c46994b0b88eae75d676ab18edcdb3e6c309abb39d8169c2d15286d10f4fc7bfc58c537a81f3efe24701e840247b5e79ac8e21a7335327811a07cfc33f69a72f + languageName: node + linkType: hard + +"ts-jest@npm:^29": + version: 29.4.9 + resolution: "ts-jest@npm:29.4.9" + dependencies: + bs-logger: "npm:^0.2.6" + fast-json-stable-stringify: "npm:^2.1.0" + handlebars: "npm:^4.7.9" + json5: "npm:^2.2.3" + lodash.memoize: "npm:^4.1.2" + make-error: "npm:^1.3.6" + semver: "npm:^7.7.4" + type-fest: "npm:^4.41.0" + yargs-parser: "npm:^21.1.1" + peerDependencies: + "@babel/core": ">=7.0.0-beta.0 <8" + "@jest/transform": ^29.0.0 || ^30.0.0 + "@jest/types": ^29.0.0 || ^30.0.0 + babel-jest: ^29.0.0 || ^30.0.0 + jest: ^29.0.0 || ^30.0.0 + jest-util: ^29.0.0 || ^30.0.0 + typescript: ">=4.3 <7" + peerDependenciesMeta: + "@babel/core": + optional: true + "@jest/transform": + optional: true + "@jest/types": + optional: true + babel-jest: + optional: true + esbuild: + optional: true + jest-util: + optional: true + bin: + ts-jest: cli.js + checksum: 10c0/901eb382817d1f48fc56b6c9b82de989f176660295695ae1fcd55f06f71d2c107766e1413ab24a59fa964c2ef79a60dd23ac1f382b05ae04f2b454fb4eb5ad4f + languageName: node + linkType: hard + +"ts-node@npm:^10.9.2": + version: 10.9.2 + resolution: "ts-node@npm:10.9.2" + dependencies: + "@cspotcode/source-map-support": "npm:^0.8.0" + "@tsconfig/node10": "npm:^1.0.7" + "@tsconfig/node12": "npm:^1.0.7" + "@tsconfig/node14": "npm:^1.0.0" + "@tsconfig/node16": "npm:^1.0.2" + acorn: "npm:^8.4.1" + acorn-walk: "npm:^8.1.1" + arg: "npm:^4.1.0" + create-require: "npm:^1.1.0" + diff: "npm:^4.0.1" + make-error: "npm:^1.1.1" + v8-compile-cache-lib: "npm:^3.0.1" + yn: "npm:3.1.1" + peerDependencies: + "@swc/core": ">=1.2.50" + "@swc/wasm": ">=1.2.50" + "@types/node": "*" + typescript: ">=2.7" + peerDependenciesMeta: + "@swc/core": + optional: true + "@swc/wasm": + optional: true + bin: + ts-node: dist/bin.js + ts-node-cwd: dist/bin-cwd.js + ts-node-esm: dist/bin-esm.js + ts-node-script: dist/bin-script.js + ts-node-transpile-only: dist/bin-transpile.js + ts-script: dist/bin-script-deprecated.js + checksum: 10c0/5f29938489f96982a25ba650b64218e83a3357d76f7bede80195c65ab44ad279c8357264639b7abdd5d7e75fc269a83daa0e9c62fd8637a3def67254ecc9ddc2 + languageName: node + linkType: hard + +"ts-pattern@npm:^5.0.0": + version: 5.9.0 + resolution: "ts-pattern@npm:5.9.0" + checksum: 10c0/7640db25c39d29b287471b2b82d4f7b4674a02098c6ba4d10fed180adfb07d0e0c71930d9e59dc0d90654145e02fd320af63cf0df3c41e100d4154658a612a0a + languageName: node + linkType: hard + +"tsconfig-paths@npm:^4.1.2": + version: 4.2.0 + resolution: "tsconfig-paths@npm:4.2.0" + dependencies: + json5: "npm:^2.2.2" + minimist: "npm:^1.2.6" + strip-bom: "npm:^3.0.0" + checksum: 10c0/09a5877402d082bb1134930c10249edeebc0211f36150c35e1c542e5b91f1047b1ccf7da1e59babca1ef1f014c525510f4f870de7c9bda470c73bb4e2721b3ea + languageName: node + linkType: hard + +"tslib@npm:2.8.1, tslib@npm:^2.1.0, tslib@npm:^2.3.0, tslib@npm:^2.4.0": + version: 2.8.1 + resolution: "tslib@npm:2.8.1" + checksum: 10c0/9c4759110a19c53f992d9aae23aac5ced636e99887b51b9e61def52611732872ff7668757d4e4c61f19691e36f4da981cd9485e869b4a7408d689f6bf1f14e62 + languageName: node + linkType: hard + +"tuf-js@npm:^4.1.0": + version: 4.1.0 + resolution: "tuf-js@npm:4.1.0" + dependencies: + "@tufjs/models": "npm:4.1.0" + debug: "npm:^4.4.3" + make-fetch-happen: "npm:^15.0.1" + checksum: 10c0/38330b0b2d16f7f58eccd49b3a6ff0f87dd20743d6f2c26c2621089d8d83d807808e0e660c5be891122538d32db250e3e88267da4421537253e7aa99a45e5800 + languageName: node + linkType: hard + +"tweetnacl@npm:^0.14.3": + version: 0.14.5 + resolution: "tweetnacl@npm:0.14.5" + checksum: 10c0/4612772653512c7bc19e61923fbf42903f5e0389ec76a4a1f17195859d114671ea4aa3b734c2029ce7e1fa7e5cc8b80580f67b071ecf0b46b5636d030a0102a2 + languageName: node + linkType: hard + +"type-check@npm:^0.4.0, type-check@npm:~0.4.0": + version: 0.4.0 + resolution: "type-check@npm:0.4.0" + dependencies: + prelude-ls: "npm:^1.2.1" + checksum: 10c0/7b3fd0ed43891e2080bf0c5c504b418fbb3e5c7b9708d3d015037ba2e6323a28152ec163bcb65212741fa5d2022e3075ac3c76440dbd344c9035f818e8ecee58 + languageName: node + linkType: hard + +"type-detect@npm:4.0.8": + version: 4.0.8 + resolution: "type-detect@npm:4.0.8" + checksum: 10c0/8fb9a51d3f365a7de84ab7f73b653534b61b622aa6800aecdb0f1095a4a646d3f5eb295322127b6573db7982afcd40ab492d038cf825a42093a58b1e1353e0bd + languageName: node + linkType: hard + +"type-fest@npm:^0.18.0": + version: 0.18.1 + resolution: "type-fest@npm:0.18.1" + checksum: 10c0/303f5ecf40d03e1d5b635ce7660de3b33c18ed8ebc65d64920c02974d9e684c72483c23f9084587e9dd6466a2ece1da42ddc95b412a461794dd30baca95e2bac + languageName: node + linkType: hard + +"type-fest@npm:^0.21.3": + version: 0.21.3 + resolution: "type-fest@npm:0.21.3" + checksum: 10c0/902bd57bfa30d51d4779b641c2bc403cdf1371fb9c91d3c058b0133694fcfdb817aef07a47f40faf79039eecbaa39ee9d3c532deff244f3a19ce68cea71a61e8 + languageName: node + linkType: hard + +"type-fest@npm:^0.6.0": + version: 0.6.0 + resolution: "type-fest@npm:0.6.0" + checksum: 10c0/0c585c26416fce9ecb5691873a1301b5aff54673c7999b6f925691ed01f5b9232db408cdbb0bd003d19f5ae284322523f44092d1f81ca0a48f11f7cf0be8cd38 + languageName: node + linkType: hard + +"type-fest@npm:^0.8.1": + version: 0.8.1 + resolution: "type-fest@npm:0.8.1" + checksum: 10c0/dffbb99329da2aa840f506d376c863bd55f5636f4741ad6e65e82f5ce47e6914108f44f340a0b74009b0cb5d09d6752ae83203e53e98b1192cf80ecee5651636 + languageName: node + linkType: hard + +"type-fest@npm:^4.41.0": + version: 4.41.0 + resolution: "type-fest@npm:4.41.0" + checksum: 10c0/f5ca697797ed5e88d33ac8f1fec21921839871f808dc59345c9cf67345bfb958ce41bd821165dbf3ae591cedec2bf6fe8882098dfdd8dc54320b859711a2c1e4 + languageName: node + linkType: hard + +"type-is@npm:^1.6.18, type-is@npm:~1.6.18": + version: 1.6.18 + resolution: "type-is@npm:1.6.18" + dependencies: + media-typer: "npm:0.3.0" + mime-types: "npm:~2.1.24" + checksum: 10c0/a23daeb538591b7efbd61ecf06b6feb2501b683ffdc9a19c74ef5baba362b4347e42f1b4ed81f5882a8c96a3bfff7f93ce3ffaf0cbbc879b532b04c97a55db9d + languageName: node + linkType: hard + +"type-is@npm:^2.0.1": + version: 2.0.1 + resolution: "type-is@npm:2.0.1" + dependencies: + content-type: "npm:^1.0.5" + media-typer: "npm:^1.1.0" + mime-types: "npm:^3.0.0" + checksum: 10c0/7f7ec0a060b16880bdad36824ab37c26019454b67d73e8a465ed5a3587440fbe158bc765f0da68344498235c877e7dbbb1600beccc94628ed05599d667951b99 + languageName: node + linkType: hard + +"typedarray@npm:^0.0.6": + version: 0.0.6 + resolution: "typedarray@npm:0.0.6" + checksum: 10c0/6005cb31df50eef8b1f3c780eb71a17925f3038a100d82f9406ac2ad1de5eb59f8e6decbdc145b3a1f8e5836e17b0c0002fb698b9fe2516b8f9f9ff602d36412 + languageName: node + linkType: hard + +"typescript@npm:>=3 < 6, typescript@npm:~5.9.2": + version: 5.9.3 + resolution: "typescript@npm:5.9.3" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10c0/6bd7552ce39f97e711db5aa048f6f9995b53f1c52f7d8667c1abdc1700c68a76a308f579cd309ce6b53646deb4e9a1be7c813a93baaf0a28ccd536a30270e1c5 + languageName: node + linkType: hard + +"typescript@npm:~5.8": + version: 5.8.3 + resolution: "typescript@npm:5.8.3" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10c0/5f8bb01196e542e64d44db3d16ee0e4063ce4f3e3966df6005f2588e86d91c03e1fb131c2581baf0fb65ee79669eea6e161cd448178986587e9f6844446dbb48 + languageName: node + linkType: hard + +"typescript@patch:typescript@npm%3A>=3 < 6#optional!builtin, typescript@patch:typescript@npm%3A~5.9.2#optional!builtin": + version: 5.9.3 + resolution: "typescript@patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10c0/ad09fdf7a756814dce65bc60c1657b40d44451346858eea230e10f2e95a289d9183b6e32e5c11e95acc0ccc214b4f36289dcad4bf1886b0adb84d711d336a430 + languageName: node + linkType: hard + +"typescript@patch:typescript@npm%3A~5.8#optional!builtin": + version: 5.8.3 + resolution: "typescript@patch:typescript@npm%3A5.8.3#optional!builtin::version=5.8.3&hash=5786d5" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10c0/39117e346ff8ebd87ae1510b3a77d5d92dae5a89bde588c747d25da5c146603a99c8ee588c7ef80faaf123d89ed46f6dbd918d534d641083177d5fac38b8a1cb + languageName: node + linkType: hard + +"uglify-js@npm:^3.1.4": + version: 3.19.3 + resolution: "uglify-js@npm:3.19.3" + bin: + uglifyjs: bin/uglifyjs + checksum: 10c0/83b0a90eca35f778e07cad9622b80c448b6aad457c9ff8e568afed978212b42930a95f9e1be943a1ffa4258a3340fbb899f41461131c05bb1d0a9c303aed8479 + languageName: node + linkType: hard + +"uid@npm:2.0.2": + version: 2.0.2 + resolution: "uid@npm:2.0.2" + dependencies: + "@lukeed/csprng": "npm:^1.0.0" + checksum: 10c0/e9d02d0562c74e74b5a2519e586db9d7f8204978e476cddd191ee1a9efb85efafdbab2dbf3fc3dde0f5da01fd9da161f37d604dabf513447fd2c03d008f1324c + languageName: node + linkType: hard + +"uint8array-extras@npm:^1.4.0": + version: 1.5.0 + resolution: "uint8array-extras@npm:1.5.0" + checksum: 10c0/0e74641ac7dadb02eadefc1ccdadba6010e007757bda824960de3c72bbe2b04e6d3af75648441f412148c4103261d54fcb60be45a2863beb76643a55fddba3bd + languageName: node + linkType: hard + +"undici-types@npm:~5.26.4": + version: 5.26.5 + resolution: "undici-types@npm:5.26.5" + checksum: 10c0/bb673d7876c2d411b6eb6c560e0c571eef4a01c1c19925175d16e3a30c4c428181fb8d7ae802a261f283e4166a0ac435e2f505743aa9e45d893f9a3df017b501 + languageName: node + linkType: hard + +"undici-types@npm:~6.21.0": + version: 6.21.0 + resolution: "undici-types@npm:6.21.0" + checksum: 10c0/c01ed51829b10aa72fc3ce64b747f8e74ae9b60eafa19a7b46ef624403508a54c526ffab06a14a26b3120d055e1104d7abe7c9017e83ced038ea5cf52f8d5e04 + languageName: node + linkType: hard + +"undici-types@npm:~7.18.0": + version: 7.18.2 + resolution: "undici-types@npm:7.18.2" + checksum: 10c0/85a79189113a238959d7a647368e4f7c5559c3a404ebdb8fc4488145ce9426fcd82252a844a302798dfc0e37e6fb178ff481ed03bc4caf634c5757d9ef43521d + languageName: node + linkType: hard + +"undici@npm:^5.29.0": + version: 5.29.0 + resolution: "undici@npm:5.29.0" + dependencies: + "@fastify/busboy": "npm:^2.0.0" + checksum: 10c0/e4e4d631ca54ee0ad82d2e90e7798fa00a106e27e6c880687e445cc2f13b4bc87c5eba2a88c266c3eecffb18f26e227b778412da74a23acc374fca7caccec49b + languageName: node + linkType: hard + +"undici@npm:^7.24.3": + version: 7.24.7 + resolution: "undici@npm:7.24.7" + checksum: 10c0/779c67e81677324763ea00ea547ba74757472ebe2625d046d592434ee19d9d148fe0eaef7006c0185096614249ac0f179e7f559b202b518af8d587e9548559b6 + languageName: node + linkType: hard + +"unicode-canonical-property-names-ecmascript@npm:^2.0.0": + version: 2.0.1 + resolution: "unicode-canonical-property-names-ecmascript@npm:2.0.1" + checksum: 10c0/f83bc492fdbe662860795ef37a85910944df7310cac91bd778f1c19ebc911e8b9cde84e703de631e5a2fcca3905e39896f8fc5fc6a44ddaf7f4aff1cda24f381 + languageName: node + linkType: hard + +"unicode-match-property-ecmascript@npm:^2.0.0": + version: 2.0.0 + resolution: "unicode-match-property-ecmascript@npm:2.0.0" + dependencies: + unicode-canonical-property-names-ecmascript: "npm:^2.0.0" + unicode-property-aliases-ecmascript: "npm:^2.0.0" + checksum: 10c0/4d05252cecaf5c8e36d78dc5332e03b334c6242faf7cf16b3658525441386c0a03b5f603d42cbec0f09bb63b9fd25c9b3b09667aee75463cac3efadae2cd17ec + languageName: node + linkType: hard + +"unicode-match-property-value-ecmascript@npm:^2.2.1": + version: 2.2.1 + resolution: "unicode-match-property-value-ecmascript@npm:2.2.1" + checksum: 10c0/93acd1ad9496b600e5379d1aaca154cf551c5d6d4a0aefaf0984fc2e6288e99220adbeb82c935cde461457fb6af0264a1774b8dfd4d9a9e31548df3352a4194d + languageName: node + linkType: hard + +"unicode-property-aliases-ecmascript@npm:^2.0.0": + version: 2.2.0 + resolution: "unicode-property-aliases-ecmascript@npm:2.2.0" + checksum: 10c0/b338529831c988ac696f2bdbcd4579d1c5cc844b24eda7269973c457fa81989bdb49a366af37a448eb1a60f1dae89559ea2a5854db2797e972a0162eee0778c6 + languageName: node + linkType: hard + +"universal-user-agent@npm:^6.0.0": + version: 6.0.1 + resolution: "universal-user-agent@npm:6.0.1" + checksum: 10c0/5c9c46ffe19a975e11e6443640ed4c9e0ce48fcc7203325757a8414ac49940ebb0f4667f2b1fa561489d1eb22cb2d05a0f7c82ec20c5cba42e58e188fb19b187 + languageName: node + linkType: hard + +"universalify@npm:^2.0.0": + version: 2.0.1 + resolution: "universalify@npm:2.0.1" + checksum: 10c0/73e8ee3809041ca8b818efb141801a1004e3fc0002727f1531f4de613ea281b494a40909596dae4a042a4fb6cd385af5d4db2e137b1362e0e91384b828effd3a + languageName: node + linkType: hard + +"unpipe@npm:~1.0.0": + version: 1.0.0 + resolution: "unpipe@npm:1.0.0" + checksum: 10c0/193400255bd48968e5c5383730344fbb4fa114cdedfab26e329e50dd2d81b134244bb8a72c6ac1b10ab0281a58b363d06405632c9d49ca9dfd5e90cbd7d0f32c + languageName: node + linkType: hard + +"unrs-resolver@npm:^1.7.11": + version: 1.11.1 + resolution: "unrs-resolver@npm:1.11.1" + dependencies: + "@unrs/resolver-binding-android-arm-eabi": "npm:1.11.1" + "@unrs/resolver-binding-android-arm64": "npm:1.11.1" + "@unrs/resolver-binding-darwin-arm64": "npm:1.11.1" + "@unrs/resolver-binding-darwin-x64": "npm:1.11.1" + "@unrs/resolver-binding-freebsd-x64": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm-gnueabihf": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm-musleabihf": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm64-musl": "npm:1.11.1" + "@unrs/resolver-binding-linux-ppc64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-riscv64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-riscv64-musl": "npm:1.11.1" + "@unrs/resolver-binding-linux-s390x-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-x64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-x64-musl": "npm:1.11.1" + "@unrs/resolver-binding-wasm32-wasi": "npm:1.11.1" + "@unrs/resolver-binding-win32-arm64-msvc": "npm:1.11.1" + "@unrs/resolver-binding-win32-ia32-msvc": "npm:1.11.1" + "@unrs/resolver-binding-win32-x64-msvc": "npm:1.11.1" + napi-postinstall: "npm:^0.3.0" + dependenciesMeta: + "@unrs/resolver-binding-android-arm-eabi": + optional: true + "@unrs/resolver-binding-android-arm64": + optional: true + "@unrs/resolver-binding-darwin-arm64": + optional: true + "@unrs/resolver-binding-darwin-x64": + optional: true + "@unrs/resolver-binding-freebsd-x64": + optional: true + "@unrs/resolver-binding-linux-arm-gnueabihf": + optional: true + "@unrs/resolver-binding-linux-arm-musleabihf": + optional: true + "@unrs/resolver-binding-linux-arm64-gnu": + optional: true + "@unrs/resolver-binding-linux-arm64-musl": + optional: true + "@unrs/resolver-binding-linux-ppc64-gnu": + optional: true + "@unrs/resolver-binding-linux-riscv64-gnu": + optional: true + "@unrs/resolver-binding-linux-riscv64-musl": + optional: true + "@unrs/resolver-binding-linux-s390x-gnu": + optional: true + "@unrs/resolver-binding-linux-x64-gnu": + optional: true + "@unrs/resolver-binding-linux-x64-musl": + optional: true + "@unrs/resolver-binding-wasm32-wasi": + optional: true + "@unrs/resolver-binding-win32-arm64-msvc": + optional: true + "@unrs/resolver-binding-win32-ia32-msvc": + optional: true + "@unrs/resolver-binding-win32-x64-msvc": + optional: true + checksum: 10c0/c91b112c71a33d6b24e5c708dab43ab80911f2df8ee65b87cd7a18fb5af446708e98c4b415ca262026ad8df326debcc7ca6a801b2935504d87fd6f0b9d70dce1 + languageName: node + linkType: hard + +"upath@npm:2.0.1": + version: 2.0.1 + resolution: "upath@npm:2.0.1" + checksum: 10c0/79e8e1296b00e24a093b077cfd7a238712d09290c850ce59a7a01458ec78c8d26dcc2ab50b1b9d6a84dabf6511fb4969afeb8a5c9a001aa7272b9cc74c34670f + languageName: node + linkType: hard + +"update-browserslist-db@npm:^1.2.3": + version: 1.2.3 + resolution: "update-browserslist-db@npm:1.2.3" + dependencies: + escalade: "npm:^3.2.0" + picocolors: "npm:^1.1.1" + peerDependencies: + browserslist: ">= 4.21.0" + bin: + update-browserslist-db: cli.js + checksum: 10c0/13a00355ea822388f68af57410ce3255941d5fb9b7c49342c4709a07c9f230bbef7f7499ae0ca7e0de532e79a82cc0c4edbd125f1a323a1845bf914efddf8bec + languageName: node + linkType: hard + +"uri-js@npm:^4.2.2": + version: 4.4.1 + resolution: "uri-js@npm:4.4.1" + dependencies: + punycode: "npm:^2.1.0" + checksum: 10c0/4ef57b45aa820d7ac6496e9208559986c665e49447cb072744c13b66925a362d96dd5a46c4530a6b8e203e5db5fe849369444440cb22ecfc26c679359e5dfa3c + languageName: node + linkType: hard + +"util-deprecate@npm:^1.0.1, util-deprecate@npm:^1.0.2, util-deprecate@npm:~1.0.1": + version: 1.0.2 + resolution: "util-deprecate@npm:1.0.2" + checksum: 10c0/41a5bdd214df2f6c3ecf8622745e4a366c4adced864bc3c833739791aeeeb1838119af7daed4ba36428114b5c67dcda034a79c882e97e43c03e66a4dd7389942 + languageName: node + linkType: hard + +"utils-merge@npm:1.0.1": + version: 1.0.1 + resolution: "utils-merge@npm:1.0.1" + checksum: 10c0/02ba649de1b7ca8854bfe20a82f1dfbdda3fb57a22ab4a8972a63a34553cf7aa51bc9081cf7e001b035b88186d23689d69e71b510e610a09a4c66f68aa95b672 + languageName: node + linkType: hard + +"uuid@npm:11.1.0, uuid@npm:^11.0.0": + version: 11.1.0 + resolution: "uuid@npm:11.1.0" + bin: + uuid: dist/esm/bin/uuid + checksum: 10c0/34aa51b9874ae398c2b799c88a127701408cd581ee89ec3baa53509dd8728cbb25826f2a038f9465f8b7be446f0fbf11558862965b18d21c993684297628d4d3 + languageName: node + linkType: hard + +"uuid@npm:^10.0.0": + version: 10.0.0 + resolution: "uuid@npm:10.0.0" + bin: + uuid: dist/bin/uuid + checksum: 10c0/eab18c27fe4ab9fb9709a5d5f40119b45f2ec8314f8d4cf12ce27e4c6f4ffa4a6321dc7db6c515068fa373c075b49691ba969f0010bf37f44c37ca40cd6bf7fe + languageName: node + linkType: hard + +"uuid@npm:^8.3.2": + version: 8.3.2 + resolution: "uuid@npm:8.3.2" + bin: + uuid: dist/bin/uuid + checksum: 10c0/bcbb807a917d374a49f475fae2e87fdca7da5e5530820ef53f65ba1d12131bd81a92ecf259cc7ce317cbe0f289e7d79fdfebcef9bfa3087c8c8a2fa304c9be54 + languageName: node + linkType: hard + +"v8-compile-cache-lib@npm:^3.0.1": + version: 3.0.1 + resolution: "v8-compile-cache-lib@npm:3.0.1" + checksum: 10c0/bdc36fb8095d3b41df197f5fb6f11e3a26adf4059df3213e3baa93810d8f0cc76f9a74aaefc18b73e91fe7e19154ed6f134eda6fded2e0f1c8d2272ed2d2d391 + languageName: node + linkType: hard + +"v8-to-istanbul@npm:^9.0.1": + version: 9.3.0 + resolution: "v8-to-istanbul@npm:9.3.0" + dependencies: + "@jridgewell/trace-mapping": "npm:^0.3.12" + "@types/istanbul-lib-coverage": "npm:^2.0.1" + convert-source-map: "npm:^2.0.0" + checksum: 10c0/968bcf1c7c88c04df1ffb463c179558a2ec17aa49e49376120504958239d9e9dad5281aa05f2a78542b8557f2be0b0b4c325710262f3b838b40d703d5ed30c23 + languageName: node + linkType: hard + +"validate-npm-package-license@npm:3.0.4, validate-npm-package-license@npm:^3.0.1, validate-npm-package-license@npm:^3.0.4": + version: 3.0.4 + resolution: "validate-npm-package-license@npm:3.0.4" + dependencies: + spdx-correct: "npm:^3.0.0" + spdx-expression-parse: "npm:^3.0.0" + checksum: 10c0/7b91e455a8de9a0beaa9fe961e536b677da7f48c9a493edf4d4d4a87fd80a7a10267d438723364e432c2fcd00b5650b5378275cded362383ef570276e6312f4f + languageName: node + linkType: hard + +"validate-npm-package-name@npm:6.0.2, validate-npm-package-name@npm:^6.0.0, validate-npm-package-name@npm:^6.0.2": + version: 6.0.2 + resolution: "validate-npm-package-name@npm:6.0.2" + checksum: 10c0/c4c23a8b9fa8deee11eea421d94fbe39f742146c06571b62247212579298186b724ebc5152240a415753bdaf9b8849a487e675ec2968d44660f8a65de6cdef9e + languageName: node + linkType: hard + +"validate-npm-package-name@npm:^7.0.0": + version: 7.0.2 + resolution: "validate-npm-package-name@npm:7.0.2" + checksum: 10c0/adf32e943148e13e8df13d06b855493908e6ae7a847610e8543c6291cbf42f40e653249a5b2275e2e615e3224c574ade5a9064a9e2d1ab629386284ea99e8f39 + languageName: node + linkType: hard + +"validator@npm:^13.15.22, validator@npm:^13.9.0": + version: 13.15.35 + resolution: "validator@npm:13.15.35" + checksum: 10c0/1958ebcad578128d154853a2b9bf5b95e7738dcc7d1d065e50a969812272312ec379dcaf375b9d7545e04a71de6755f60f5a4b49c1405737a9c80e11da297eef + languageName: node + linkType: hard + +"vary@npm:^1, vary@npm:^1.1.2, vary@npm:~1.1.2": + version: 1.1.2 + resolution: "vary@npm:1.1.2" + checksum: 10c0/f15d588d79f3675135ba783c91a4083dcd290a2a5be9fcb6514220a1634e23df116847b1cc51f66bfb0644cf9353b2abb7815ae499bab06e46dd33c1a6bf1f4f + languageName: node + linkType: hard + +"walk-up-path@npm:^4.0.0": + version: 4.0.0 + resolution: "walk-up-path@npm:4.0.0" + checksum: 10c0/fabe344f91387d1d41df230af962ef18bf703dd4178006d55cd6412caacd187b54440002d4d53a982d4f7f0455567dcffb6d3884533c8b2268928eca3ebd8a19 + languageName: node + linkType: hard + +"walker@npm:^1.0.8": + version: 1.0.8 + resolution: "walker@npm:1.0.8" + dependencies: + makeerror: "npm:1.0.12" + checksum: 10c0/a17e037bccd3ca8a25a80cb850903facdfed0de4864bd8728f1782370715d679fa72e0a0f5da7c1c1379365159901e5935f35be531229da53bbfc0efdabdb48e + languageName: node + linkType: hard + +"wcwidth@npm:^1.0.0, wcwidth@npm:^1.0.1": + version: 1.0.1 + resolution: "wcwidth@npm:1.0.1" + dependencies: + defaults: "npm:^1.0.3" + checksum: 10c0/5b61ca583a95e2dd85d7078400190efd452e05751a64accb8c06ce4db65d7e0b0cde9917d705e826a2e05cc2548f61efde115ffa374c3e436d04be45c889e5b4 + languageName: node + linkType: hard + +"web-streams-polyfill@npm:4.0.0-beta.3": + version: 4.0.0-beta.3 + resolution: "web-streams-polyfill@npm:4.0.0-beta.3" + checksum: 10c0/a9596779db2766990117ed3a158e0b0e9f69b887a6d6ba0779940259e95f99dc3922e534acc3e5a117b5f5905300f527d6fbf8a9f0957faf1d8e585ce3452e8e + languageName: node + linkType: hard + +"webidl-conversions@npm:^3.0.0": + version: 3.0.1 + resolution: "webidl-conversions@npm:3.0.1" + checksum: 10c0/5612d5f3e54760a797052eb4927f0ddc01383550f542ccd33d5238cfd65aeed392a45ad38364970d0a0f4fea32e1f4d231b3d8dac4a3bdd385e5cf802ae097db + languageName: node + linkType: hard + +"whatwg-url@npm:^5.0.0": + version: 5.0.0 + resolution: "whatwg-url@npm:5.0.0" + dependencies: + tr46: "npm:~0.0.3" + webidl-conversions: "npm:^3.0.0" + checksum: 10c0/1588bed84d10b72d5eec1d0faa0722ba1962f1821e7539c535558fb5398d223b0c50d8acab950b8c488b4ba69043fd833cc2697056b167d8ad46fac3995a55d5 + languageName: node + linkType: hard + +"which@npm:^2.0.1": + version: 2.0.2 + resolution: "which@npm:2.0.2" + dependencies: + isexe: "npm:^2.0.0" + bin: + node-which: ./bin/node-which + checksum: 10c0/66522872a768b60c2a65a57e8ad184e5372f5b6a9ca6d5f033d4b0dc98aff63995655a7503b9c0a2598936f532120e81dd8cc155e2e92ed662a2b9377cc4374f + languageName: node + linkType: hard + +"which@npm:^5.0.0": + version: 5.0.0 + resolution: "which@npm:5.0.0" + dependencies: + isexe: "npm:^3.1.1" + bin: + node-which: bin/which.js + checksum: 10c0/e556e4cd8b7dbf5df52408c9a9dd5ac6518c8c5267c8953f5b0564073c66ed5bf9503b14d876d0e9c7844d4db9725fb0dcf45d6e911e17e26ab363dc3965ae7b + languageName: node + linkType: hard + +"which@npm:^6.0.0": + version: 6.0.1 + resolution: "which@npm:6.0.1" + dependencies: + isexe: "npm:^4.0.0" + bin: + node-which: bin/which.js + checksum: 10c0/7e710e54ea36d2d6183bee2f9caa27a3b47b9baf8dee55a199b736fcf85eab3b9df7556fca3d02b50af7f3dfba5ea3a45644189836df06267df457e354da66d5 + languageName: node + linkType: hard + +"wide-align@npm:1.1.5": + version: 1.1.5 + resolution: "wide-align@npm:1.1.5" + dependencies: + string-width: "npm:^1.0.2 || 2 || 3 || 4" + checksum: 10c0/1d9c2a3e36dfb09832f38e2e699c367ef190f96b82c71f809bc0822c306f5379df87bab47bed27ea99106d86447e50eb972d3c516c2f95782807a9d082fbea95 + languageName: node + linkType: hard + +"winston-transport@npm:^4.9.0": + version: 4.9.0 + resolution: "winston-transport@npm:4.9.0" + dependencies: + logform: "npm:^2.7.0" + readable-stream: "npm:^3.6.2" + triple-beam: "npm:^1.3.0" + checksum: 10c0/e2990a172e754dbf27e7823772214a22dc8312f7ec9cfba831e5ef30a5d5528792e5ea8f083c7387ccfc5b2af20e3691f64738546c8869086110a26f98671095 + languageName: node + linkType: hard + +"winston@npm:^3.17.0": + version: 3.19.0 + resolution: "winston@npm:3.19.0" + dependencies: + "@colors/colors": "npm:^1.6.0" + "@dabh/diagnostics": "npm:^2.0.8" + async: "npm:^3.2.3" + is-stream: "npm:^2.0.0" + logform: "npm:^2.7.0" + one-time: "npm:^1.0.0" + readable-stream: "npm:^3.4.0" + safe-stable-stringify: "npm:^2.3.1" + stack-trace: "npm:0.0.x" + triple-beam: "npm:^1.3.0" + winston-transport: "npm:^4.9.0" + checksum: 10c0/341a8ccfb726120209d34e2466040e2ca72cadb1a3402c4fc90425facad002b81275675b4ab9b4432a624311bc47ef7c9fb7652c86fca454d2be2f2ee1882226 + languageName: node + linkType: hard + +"wkx@npm:^0.5.0": + version: 0.5.0 + resolution: "wkx@npm:0.5.0" + dependencies: + "@types/node": "npm:*" + checksum: 10c0/9f787ffd2bc83708000f10165a72f0ca121b2e79b279eb44f2f5274eaa6ef819d9e9a00058a3b59dd211fe140d4b47cb6d49683b3a57a2a42ab3a7ccd52247dd + languageName: node + linkType: hard + +"word-wrap@npm:^1.2.5": + version: 1.2.5 + resolution: "word-wrap@npm:1.2.5" + checksum: 10c0/e0e4a1ca27599c92a6ca4c32260e8a92e8a44f4ef6ef93f803f8ed823f486e0889fc0b93be4db59c8d51b3064951d25e43d434e95dc8c960cc3a63d65d00ba20 + languageName: node + linkType: hard + +"wordwrap@npm:^1.0.0": + version: 1.0.0 + resolution: "wordwrap@npm:1.0.0" + checksum: 10c0/7ed2e44f3c33c5c3e3771134d2b0aee4314c9e49c749e37f464bf69f2bcdf0cbf9419ca638098e2717cff4875c47f56a007532f6111c3319f557a2ca91278e92 + languageName: node + linkType: hard + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0": + version: 7.0.0 + resolution: "wrap-ansi@npm:7.0.0" + dependencies: + ansi-styles: "npm:^4.0.0" + string-width: "npm:^4.1.0" + strip-ansi: "npm:^6.0.0" + checksum: 10c0/d15fc12c11e4cbc4044a552129ebc75ee3f57aa9c1958373a4db0292d72282f54373b536103987a4a7594db1ef6a4f10acf92978f79b98c49306a4b58c77d4da + languageName: node + linkType: hard + +"wrap-ansi@npm:^6.2.0": + version: 6.2.0 + resolution: "wrap-ansi@npm:6.2.0" + dependencies: + ansi-styles: "npm:^4.0.0" + string-width: "npm:^4.1.0" + strip-ansi: "npm:^6.0.0" + checksum: 10c0/baad244e6e33335ea24e86e51868fe6823626e3a3c88d9a6674642afff1d34d9a154c917e74af8d845fd25d170c4ea9cf69a47133c3f3656e1252b3d462d9f6c + languageName: node + linkType: hard + +"wrap-ansi@npm:^8.1.0": + version: 8.1.0 + resolution: "wrap-ansi@npm:8.1.0" + dependencies: + ansi-styles: "npm:^6.1.0" + string-width: "npm:^5.0.1" + strip-ansi: "npm:^7.0.1" + checksum: 10c0/138ff58a41d2f877eae87e3282c0630fc2789012fc1af4d6bd626eeb9a2f9a65ca92005e6e69a75c7b85a68479fe7443c7dbe1eb8fbaa681a4491364b7c55c60 + languageName: node + linkType: hard + +"wrappy@npm:1": + version: 1.0.2 + resolution: "wrappy@npm:1.0.2" + checksum: 10c0/56fece1a4018c6a6c8e28fbc88c87e0fbf4ea8fd64fc6c63b18f4acc4bd13e0ad2515189786dd2c30d3eec9663d70f4ecf699330002f8ccb547e4a18231fc9f0 + languageName: node + linkType: hard + +"write-file-atomic@npm:5.0.1, write-file-atomic@npm:^5.0.1": + version: 5.0.1 + resolution: "write-file-atomic@npm:5.0.1" + dependencies: + imurmurhash: "npm:^0.1.4" + signal-exit: "npm:^4.0.1" + checksum: 10c0/e8c850a8e3e74eeadadb8ad23c9d9d63e4e792bd10f4836ed74189ef6e996763959f1249c5650e232f3c77c11169d239cbfc8342fc70f3fe401407d23810505d + languageName: node + linkType: hard + +"write-file-atomic@npm:^4.0.2": + version: 4.0.2 + resolution: "write-file-atomic@npm:4.0.2" + dependencies: + imurmurhash: "npm:^0.1.4" + signal-exit: "npm:^3.0.7" + checksum: 10c0/a2c282c95ef5d8e1c27b335ae897b5eca00e85590d92a3fd69a437919b7b93ff36a69ea04145da55829d2164e724bc62202cdb5f4b208b425aba0807889375c7 + languageName: node + linkType: hard + +"write-file-atomic@npm:^6.0.0": + version: 6.0.0 + resolution: "write-file-atomic@npm:6.0.0" + dependencies: + imurmurhash: "npm:^0.1.4" + signal-exit: "npm:^4.0.1" + checksum: 10c0/ae2f1c27474758a9aca92037df6c1dd9cb94c4e4983451210bd686bfe341f142662f6aa5913095e572ab037df66b1bfe661ed4ce4c0369ed0e8219e28e141786 + languageName: node + linkType: hard + +"ws@npm:^8.18.1": + version: 8.20.0 + resolution: "ws@npm:8.20.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 10c0/956ac5f11738c914089b65878b9223692ace77337ba55379ae68e1ecbeae9b47a0c6eb9403688f609999a58c80d83d99865fe0029b229d308b08c1ef93d4ea14 + languageName: node + linkType: hard + +"xtend@npm:^4.0.0, xtend@npm:^4.0.2, xtend@npm:~4.0.1": + version: 4.0.2 + resolution: "xtend@npm:4.0.2" + checksum: 10c0/366ae4783eec6100f8a02dff02ac907bf29f9a00b82ac0264b4d8b832ead18306797e283cf19de776538babfdcb2101375ec5646b59f08c52128ac4ab812ed0e + languageName: node + linkType: hard + +"y18n@npm:^5.0.5": + version: 5.0.8 + resolution: "y18n@npm:5.0.8" + checksum: 10c0/4df2842c36e468590c3691c894bc9cdbac41f520566e76e24f59401ba7d8b4811eb1e34524d57e54bc6d864bcb66baab7ffd9ca42bf1eda596618f9162b91249 + languageName: node + linkType: hard + +"yallist@npm:4.0.0, yallist@npm:^4.0.0": + version: 4.0.0 + resolution: "yallist@npm:4.0.0" + checksum: 10c0/2286b5e8dbfe22204ab66e2ef5cc9bbb1e55dfc873bbe0d568aa943eb255d131890dfd5bf243637273d31119b870f49c18fcde2c6ffbb7a7a092b870dc90625a + languageName: node + linkType: hard + +"yallist@npm:^3.0.2": + version: 3.1.1 + resolution: "yallist@npm:3.1.1" + checksum: 10c0/c66a5c46bc89af1625476f7f0f2ec3653c1a1791d2f9407cfb4c2ba812a1e1c9941416d71ba9719876530e3340a99925f697142989371b72d93b9ee628afd8c1 + languageName: node + linkType: hard + +"yallist@npm:^5.0.0": + version: 5.0.0 + resolution: "yallist@npm:5.0.0" + checksum: 10c0/a499c81ce6d4a1d260d4ea0f6d49ab4da09681e32c3f0472dee16667ed69d01dae63a3b81745a24bd78476ec4fcf856114cb4896ace738e01da34b2c42235416 + languageName: node + linkType: hard + +"yaml@npm:^1.10.0": + version: 1.10.3 + resolution: "yaml@npm:1.10.3" + checksum: 10c0/c309ff85a0a569a981d71ab9cf0fef68672a16b9cdf40639d1c3b30034f6cd16ee428602bd6d64ecf006f8c8bee499023cac236538f79898aa99fb5db529a2ed + languageName: node + linkType: hard + +"yaml@npm:^2.2.2, yaml@npm:^2.6.0": + version: 2.8.3 + resolution: "yaml@npm:2.8.3" + bin: + yaml: bin.mjs + checksum: 10c0/ddff0e11c1b467728d7eb4633db61c5f5de3d8e9373cf84d08fb0cdee03e1f58f02b9f1c51a4a8a865751695addbd465a77f73f1079be91fe5493b29c305fd77 + languageName: node + linkType: hard + +"yargs-parser@npm:21.1.1, yargs-parser@npm:^21.1.1": + version: 21.1.1 + resolution: "yargs-parser@npm:21.1.1" + checksum: 10c0/f84b5e48169479d2f402239c59f084cfd1c3acc197a05c59b98bab067452e6b3ea46d4dd8ba2985ba7b3d32a343d77df0debd6b343e5dae3da2aab2cdf5886b2 + languageName: node + linkType: hard + +"yargs-parser@npm:^20.2.2, yargs-parser@npm:^20.2.3": + version: 20.2.9 + resolution: "yargs-parser@npm:20.2.9" + checksum: 10c0/0685a8e58bbfb57fab6aefe03c6da904a59769bd803a722bb098bd5b0f29d274a1357762c7258fb487512811b8063fb5d2824a3415a0a4540598335b3b086c72 + languageName: node + linkType: hard + +"yargs@npm:17.7.2, yargs@npm:^17.3.1, yargs@npm:^17.6.2, yargs@npm:^17.7.2": + version: 17.7.2 + resolution: "yargs@npm:17.7.2" + dependencies: + cliui: "npm:^8.0.1" + escalade: "npm:^3.1.1" + get-caller-file: "npm:^2.0.5" + require-directory: "npm:^2.1.1" + string-width: "npm:^4.2.3" + y18n: "npm:^5.0.5" + yargs-parser: "npm:^21.1.1" + checksum: 10c0/ccd7e723e61ad5965fffbb791366db689572b80cca80e0f96aad968dfff4156cd7cd1ad18607afe1046d8241e6fb2d6c08bf7fa7bfb5eaec818735d8feac8f05 + languageName: node + linkType: hard + +"yargs@npm:^16.2.0": + version: 16.2.0 + resolution: "yargs@npm:16.2.0" + dependencies: + cliui: "npm:^7.0.2" + escalade: "npm:^3.1.1" + get-caller-file: "npm:^2.0.5" + require-directory: "npm:^2.1.1" + string-width: "npm:^4.2.0" + y18n: "npm:^5.0.5" + yargs-parser: "npm:^20.2.2" + checksum: 10c0/b1dbfefa679848442454b60053a6c95d62f2d2e21dd28def92b647587f415969173c6e99a0f3bab4f1b67ee8283bf735ebe3544013f09491186ba9e8a9a2b651 + languageName: node + linkType: hard + +"yn@npm:3.1.1": + version: 3.1.1 + resolution: "yn@npm:3.1.1" + checksum: 10c0/0732468dd7622ed8a274f640f191f3eaf1f39d5349a1b72836df484998d7d9807fbea094e2f5486d6b0cd2414aad5775972df0e68f8604db89a239f0f4bf7443 + languageName: node + linkType: hard + +"yocto-queue@npm:^0.1.0": + version: 0.1.0 + resolution: "yocto-queue@npm:0.1.0" + checksum: 10c0/dceb44c28578b31641e13695d200d34ec4ab3966a5729814d5445b194933c096b7ced71494ce53a0e8820685d1d010df8b2422e5bf2cdea7e469d97ffbea306f + languageName: node + linkType: hard + +"yoctocolors-cjs@npm:^2.1.3": + version: 2.1.3 + resolution: "yoctocolors-cjs@npm:2.1.3" + checksum: 10c0/584168ef98eb5d913473a4858dce128803c4a6cd87c0f09e954fa01126a59a33ab9e513b633ad9ab953786ed16efdd8c8700097a51635aafaeed3fef7712fa79 + languageName: node + linkType: hard + +"zip-stream@npm:^6.0.1": + version: 6.0.1 + resolution: "zip-stream@npm:6.0.1" + dependencies: + archiver-utils: "npm:^5.0.0" + compress-commons: "npm:^6.0.2" + readable-stream: "npm:^4.0.0" + checksum: 10c0/50f2fb30327fb9d09879abf7ae2493705313adf403e794b030151aaae00009162419d60d0519e807673ec04d442e140c8879ca14314df0a0192de3b233e8f28b + languageName: node + linkType: hard + +"zod-to-json-schema@npm:^3.25.1": + version: 3.25.2 + resolution: "zod-to-json-schema@npm:3.25.2" + peerDependencies: + zod: ^3.25.28 || ^4 + checksum: 10c0/dd300554393903022487688af14fbda5c719ba8179702bb55b3aa86318830467f0f7beb7d654036975ac963dc4843b72e59636448bfff9a0608f277bb6a14939 + languageName: node + linkType: hard + +"zod@npm:^3.25 || ^4.0": + version: 4.3.6 + resolution: "zod@npm:4.3.6" + checksum: 10c0/860d25a81ab41d33aa25f8d0d07b091a04acb426e605f396227a796e9e800c44723ed96d0f53a512b57be3d1520f45bf69c0cb3b378a232a00787a2609625307 + languageName: node + linkType: hard