From 295ea0303d18e36c64c1f8ba8bc93ced41815eb5 Mon Sep 17 00:00:00 2001 From: Zac Pustejovsky Date: Sun, 5 Apr 2026 09:48:48 -0400 Subject: [PATCH] utils for agents, sql, redis, etc --- .ai/ai-agents.md | 29 + .ai/bull-queues.md | 92 + .ai/configuration.md | 45 + .ai/dependency-injection.md | 74 + .ai/skills/testing-guide.md | 57 + .ai/sql-decorators.md | 87 + .ai/testing.md | 74 + .aiassistant/rules/rules.md | 1 + .claude/commands/testing-guide.md | 1 + .claude/settings.json | 44 + .editorconfig | 8 + .eslintrc.json | 18 + .gitattributes | 4 + .github/workflows/main.yaml | 60 + .github/workflows/pr.yaml | 32 + .gitignore | 56 + .junie/guidelines.md | 1 + .junie/skills/testing-guide/SKILL.md | 1 + .nvmrc | 1 + .prettierrc | 7 + .yarnrc.yml | 1 + AGENTS.md | 1 + AI.md | 64 + CLAUDE.md | 1 + README.md | 33 +- jest.config.ts | 2 + jest.preset.js | 2 + lerna.json | 6 + nx.json | 33 + package.json | 47 + packages/agentic-workflows/.eslintrc.json | 10 + packages/agentic-workflows/index.ts | 16 + packages/agentic-workflows/jest.config.ts | 10 + packages/agentic-workflows/package.json | 20 + packages/agentic-workflows/project.json | 29 + .../agentic-workflows/src/ai-agent-factory.ts | 98 + .../agentic-workflows/src/ai-agent-module.ts | 66 + .../src/config/ai-agent-config.ts | 51 + .../session/conversation-session-model.ts | 17 + .../conversation-session-repository.ts | 27 + ...-memory-conversation-session-repository.ts | 117 + .../repository/session/repository-session.ts | 123 + .../src/service/agent-parameter-mapper.ts | 72 + .../src/service/ai-agent-service-local.ts | 206 + .../src/service/ai-agent-service-ollama.ts | 100 + .../src/service/ai-agent-service-openai.ts | 89 + .../src/service/ai-agent-service.ts | 95 + .../src/service/ai-session-factory.ts | 33 + .../src/service/decorators.ts | 183 + .../src/service/prompt-utils.ts | 150 + .../test/ai-agent-service-local.spec.ts | 256 + ...ry-conversation-session-repository.spec.ts | 286 + .../test/service/decorators.spec.ts | 86 + packages/agentic-workflows/tsconfig.json | 12 + packages/agentic-workflows/tsconfig.lib.json | 10 + packages/agentic-workflows/tsconfig.spec.json | 15 + packages/commons-testing/.eslintrc.json | 10 + packages/commons-testing/index.ts | 6 + packages/commons-testing/jest.config.ts | 10 + packages/commons-testing/package.json | 17 + packages/commons-testing/project.json | 29 + .../src/async/async-test-utils.ts | 26 + .../src/booter/booter-configuration.ts | 3 + .../src/exceptions/jest-exception.ts | 3 + .../src/ollama/ollama-fixture.ts | 110 + .../src/postgres/postgres-container.ts | 135 + .../src/redis/redis-container.ts | 40 + packages/commons-testing/tsconfig.json | 12 + packages/commons-testing/tsconfig.lib.json | 10 + packages/commons-testing/tsconfig.spec.json | 14 + packages/commons/.eslintrc.json | 10 + packages/commons/index.ts | 38 + packages/commons/jest.config.ts | 10 + packages/commons/package.json | 34 + packages/commons/project.json | 34 + .../src/abort-controller/abort-controller.ts | 112 + .../commons/src/bull/bull-error-handler.ts | 16 + packages/commons/src/bull/bull-module.ts | 22 + packages/commons/src/bull/bull-queue.ts | 118 + packages/commons/src/bull/bull-utils.ts | 28 + packages/commons/src/bull/bull-worker.ts | 69 + packages/commons/src/bull/cron-launcher.ts | 77 + .../src/collections/collection-utils.ts | 20 + .../commons/src/config/application-config.ts | 35 + packages/commons/src/config/client-config.ts | 11 + packages/commons/src/config/config-module.ts | 19 + packages/commons/src/config/config-utils.ts | 120 + packages/commons/src/crypto/crypto-utils.ts | 32 + packages/commons/src/date/date-utils.ts | 12 + .../commons/src/decorators/at-least-one-of.ts | 79 + packages/commons/src/decorators/default.ts | 10 + .../src/decorators/future-timestamp.ts | 65 + .../commons/src/decorators/is-bigger-than.ts | 56 + .../commons/src/decorators/is-image-url.ts | 58 + .../commons/src/decorators/is-optional.ts | 9 + .../commons/src/decorators/is-safe-json.ts | 95 + .../commons/src/decorators/is-safe-string.ts | 55 + packages/commons/src/injection-tokens.ts | 7 + packages/commons/src/internal/not-empty.ts | 11 + packages/commons/src/internal/object-utils.ts | 25 + packages/commons/src/internal/string-utils.ts | 2 + packages/commons/src/ip/ip-utils.ts | 58 + .../commons/src/logging/winston-logger.ts | 32 + packages/commons/src/port/port-utils.ts | 50 + .../postgres/postgres-connection-config.ts | 44 + .../postgres/postgres-connection-module.ts | 94 + .../commons/src/postgres/postgres-utils.ts | 84 + packages/commons/src/random/random-utils.ts | 5 + .../commons/src/redis/redis-client-pool.ts | 70 + .../src/redis/redis-connection-config.ts | 39 + .../src/redis/redis-connection-module.ts | 104 + packages/commons/src/resources/closer.ts | 71 + packages/commons/src/server/rest-booter.ts | 29 + packages/commons/src/util/timer-utils.ts | 17 + .../abort-controller/abort-controller.spec.ts | 167 + packages/commons/test/assets/config.yaml | 9 + .../commons/test/bull/bull-module.spec.ts | 97 + .../commons/test/bull/bull-testing-module.ts | 25 + .../commons/test/bull/bull-testing-service.ts | 19 + packages/commons/test/bull/bull-utils.spec.ts | 30 + .../commons/test/bull/testing-bull-queue.ts | 44 + .../commons/test/bull/testing-bull-worker.ts | 78 + .../commons/test/config/config-utils.spec.ts | 94 + packages/commons/test/config/test-config.yaml | 12 + .../commons/test/crypto/crypto-utils.spec.ts | 39 + .../test/decorators/is-safe-string.spec.ts | 53 + packages/commons/test/ip/ip-utils.spec.ts | 47 + packages/commons/test/port/port-utils.spec.ts | 33 + .../redis/redis-connection-module.spec.ts | 100 + packages/commons/test/util/not-empty.spec.ts | 25 + packages/commons/tsconfig.json | 12 + packages/commons/tsconfig.lib.json | 10 + packages/commons/tsconfig.spec.json | 15 + packages/openai-utils/.eslintrc.json | 10 + packages/openai-utils/index.ts | 6 + packages/openai-utils/jest.config.ts | 10 + packages/openai-utils/package.json | 18 + packages/openai-utils/project.json | 29 + .../src/config/openai-client-config.ts | 20 + .../openai-utils/src/openai-client-factory.ts | 23 + .../openai-utils/src/openai-client-module.ts | 31 + .../conversion/openai-service-local.ts | 69 + .../conversion/openai-service-remote.ts | 28 + .../src/service/conversion/openai-service.ts | 59 + packages/openai-utils/test/client-factory.ts | 26 + .../test/service/openai-client.spec.ts | 78 + packages/openai-utils/tsconfig.json | 12 + packages/openai-utils/tsconfig.lib.json | 10 + packages/openai-utils/tsconfig.spec.json | 15 + packages/sql-decorators/.eslintrc.json | 10 + packages/sql-decorators/index.ts | 3 + packages/sql-decorators/jest.config.ts | 10 + packages/sql-decorators/package.json | 18 + packages/sql-decorators/project.json | 29 + packages/sql-decorators/src/decorators.ts | 235 + .../src/query/query-parameter-mapper.ts | 116 + .../sql-decorators/src/query/query-runner.ts | 33 + packages/sql-decorators/src/query/query.ts | 70 + .../src/result/result-mapper.ts | 137 + .../sql-decorators/src/result/result-types.ts | 15 + .../sql-decorators/src/stream-iterator.ts | 77 + .../sql-decorators/test/decorators.spec.ts | 672 + .../test/repository/array-dao.ts | 98 + .../test/repository/broken-dao.ts | 44 + .../test/repository/clazz-dao.ts | 208 + .../test/repository/enum-dao.ts | 63 + .../test/repository/insertQuery.sql | 9 + .../sql-decorators/test/repository/lol-dao.ts | 57 + .../test/repository/nested-dao.ts | 80 + .../test/repository/nullable-dao.ts | 31 + .../repository/some-folder/updateQuery.sql | 4 + .../test/repository/streamThings.sql | 2 + .../test/repository/test-dao.ts | 157 + .../test/repository/unconventional-dao.ts | 29 + .../transaction-repository/test-repository.ts | 91 + packages/sql-decorators/tsconfig.json | 12 + packages/sql-decorators/tsconfig.lib.json | 10 + packages/sql-decorators/tsconfig.spec.json | 15 + packages/tavily-utils/.eslintrc.json | 10 + packages/tavily-utils/index.ts | 8 + packages/tavily-utils/jest.config.ts | 10 + packages/tavily-utils/package.json | 19 + packages/tavily-utils/project.json | 29 + .../src/config/tavily-client-config.ts | 20 + .../src/service/tavily-service-local.ts | 91 + .../src/service/tavily-service-remote.ts | 57 + .../src/service/tavily-service.ts | 40 + .../tavily-utils/src/tavily-client-factory.ts | 21 + .../tavily-utils/src/tavily-client-module.ts | 37 + .../tavily-utils/src/tools/get-web-content.ts | 64 + packages/tavily-utils/src/tools/index.ts | 16 + packages/tavily-utils/src/tools/web-search.ts | 53 + packages/tavily-utils/tsconfig.json | 12 + packages/tavily-utils/tsconfig.lib.json | 10 + packages/tavily-utils/tsconfig.spec.json | 14 + tsconfig.base.json | 36 + yarn.lock | 13790 ++++++++++++++++ 197 files changed, 23494 insertions(+), 1 deletion(-) create mode 100644 .ai/ai-agents.md create mode 100644 .ai/bull-queues.md create mode 100644 .ai/configuration.md create mode 100644 .ai/dependency-injection.md create mode 100644 .ai/skills/testing-guide.md create mode 100644 .ai/sql-decorators.md create mode 100644 .ai/testing.md create mode 120000 .aiassistant/rules/rules.md create mode 120000 .claude/commands/testing-guide.md create mode 100644 .claude/settings.json create mode 100644 .editorconfig create mode 100644 .eslintrc.json create mode 100644 .gitattributes create mode 100644 .github/workflows/main.yaml create mode 100644 .github/workflows/pr.yaml create mode 100644 .gitignore create mode 120000 .junie/guidelines.md create mode 120000 .junie/skills/testing-guide/SKILL.md create mode 100644 .nvmrc create mode 100644 .prettierrc create mode 100644 .yarnrc.yml create mode 120000 AGENTS.md create mode 100644 AI.md create mode 120000 CLAUDE.md create mode 100644 jest.config.ts create mode 100644 jest.preset.js create mode 100644 lerna.json create mode 100644 nx.json create mode 100644 package.json create mode 100644 packages/agentic-workflows/.eslintrc.json create mode 100644 packages/agentic-workflows/index.ts create mode 100644 packages/agentic-workflows/jest.config.ts create mode 100644 packages/agentic-workflows/package.json create mode 100644 packages/agentic-workflows/project.json create mode 100644 packages/agentic-workflows/src/ai-agent-factory.ts create mode 100644 packages/agentic-workflows/src/ai-agent-module.ts create mode 100644 packages/agentic-workflows/src/config/ai-agent-config.ts create mode 100644 packages/agentic-workflows/src/repository/session/conversation-session-model.ts create mode 100644 packages/agentic-workflows/src/repository/session/conversation-session-repository.ts create mode 100644 packages/agentic-workflows/src/repository/session/in-memory-conversation-session-repository.ts create mode 100644 packages/agentic-workflows/src/repository/session/repository-session.ts create mode 100644 packages/agentic-workflows/src/service/agent-parameter-mapper.ts create mode 100644 packages/agentic-workflows/src/service/ai-agent-service-local.ts create mode 100644 packages/agentic-workflows/src/service/ai-agent-service-ollama.ts create mode 100644 packages/agentic-workflows/src/service/ai-agent-service-openai.ts create mode 100644 packages/agentic-workflows/src/service/ai-agent-service.ts create mode 100644 packages/agentic-workflows/src/service/ai-session-factory.ts create mode 100644 packages/agentic-workflows/src/service/decorators.ts create mode 100644 packages/agentic-workflows/src/service/prompt-utils.ts create mode 100644 packages/agentic-workflows/test/ai-agent-service-local.spec.ts create mode 100644 packages/agentic-workflows/test/repository/session/in-memory-conversation-session-repository.spec.ts create mode 100644 packages/agentic-workflows/test/service/decorators.spec.ts create mode 100644 packages/agentic-workflows/tsconfig.json create mode 100644 packages/agentic-workflows/tsconfig.lib.json create mode 100644 packages/agentic-workflows/tsconfig.spec.json create mode 100644 packages/commons-testing/.eslintrc.json create mode 100644 packages/commons-testing/index.ts create mode 100644 packages/commons-testing/jest.config.ts create mode 100644 packages/commons-testing/package.json create mode 100644 packages/commons-testing/project.json create mode 100644 packages/commons-testing/src/async/async-test-utils.ts create mode 100644 packages/commons-testing/src/booter/booter-configuration.ts create mode 100644 packages/commons-testing/src/exceptions/jest-exception.ts create mode 100644 packages/commons-testing/src/ollama/ollama-fixture.ts create mode 100644 packages/commons-testing/src/postgres/postgres-container.ts create mode 100644 packages/commons-testing/src/redis/redis-container.ts create mode 100644 packages/commons-testing/tsconfig.json create mode 100644 packages/commons-testing/tsconfig.lib.json create mode 100644 packages/commons-testing/tsconfig.spec.json create mode 100644 packages/commons/.eslintrc.json create mode 100644 packages/commons/index.ts create mode 100644 packages/commons/jest.config.ts create mode 100644 packages/commons/package.json create mode 100644 packages/commons/project.json create mode 100644 packages/commons/src/abort-controller/abort-controller.ts create mode 100644 packages/commons/src/bull/bull-error-handler.ts create mode 100644 packages/commons/src/bull/bull-module.ts create mode 100644 packages/commons/src/bull/bull-queue.ts create mode 100644 packages/commons/src/bull/bull-utils.ts create mode 100644 packages/commons/src/bull/bull-worker.ts create mode 100644 packages/commons/src/bull/cron-launcher.ts create mode 100644 packages/commons/src/collections/collection-utils.ts create mode 100644 packages/commons/src/config/application-config.ts create mode 100644 packages/commons/src/config/client-config.ts create mode 100644 packages/commons/src/config/config-module.ts create mode 100644 packages/commons/src/config/config-utils.ts create mode 100644 packages/commons/src/crypto/crypto-utils.ts create mode 100644 packages/commons/src/date/date-utils.ts create mode 100644 packages/commons/src/decorators/at-least-one-of.ts create mode 100644 packages/commons/src/decorators/default.ts create mode 100644 packages/commons/src/decorators/future-timestamp.ts create mode 100644 packages/commons/src/decorators/is-bigger-than.ts create mode 100644 packages/commons/src/decorators/is-image-url.ts create mode 100644 packages/commons/src/decorators/is-optional.ts create mode 100644 packages/commons/src/decorators/is-safe-json.ts create mode 100644 packages/commons/src/decorators/is-safe-string.ts create mode 100644 packages/commons/src/injection-tokens.ts create mode 100644 packages/commons/src/internal/not-empty.ts create mode 100644 packages/commons/src/internal/object-utils.ts create mode 100644 packages/commons/src/internal/string-utils.ts create mode 100644 packages/commons/src/ip/ip-utils.ts create mode 100644 packages/commons/src/logging/winston-logger.ts create mode 100644 packages/commons/src/port/port-utils.ts create mode 100644 packages/commons/src/postgres/postgres-connection-config.ts create mode 100644 packages/commons/src/postgres/postgres-connection-module.ts create mode 100644 packages/commons/src/postgres/postgres-utils.ts create mode 100644 packages/commons/src/random/random-utils.ts create mode 100644 packages/commons/src/redis/redis-client-pool.ts create mode 100644 packages/commons/src/redis/redis-connection-config.ts create mode 100644 packages/commons/src/redis/redis-connection-module.ts create mode 100644 packages/commons/src/resources/closer.ts create mode 100644 packages/commons/src/server/rest-booter.ts create mode 100644 packages/commons/src/util/timer-utils.ts create mode 100644 packages/commons/test/abort-controller/abort-controller.spec.ts create mode 100644 packages/commons/test/assets/config.yaml create mode 100644 packages/commons/test/bull/bull-module.spec.ts create mode 100644 packages/commons/test/bull/bull-testing-module.ts create mode 100644 packages/commons/test/bull/bull-testing-service.ts create mode 100644 packages/commons/test/bull/bull-utils.spec.ts create mode 100644 packages/commons/test/bull/testing-bull-queue.ts create mode 100644 packages/commons/test/bull/testing-bull-worker.ts create mode 100644 packages/commons/test/config/config-utils.spec.ts create mode 100644 packages/commons/test/config/test-config.yaml create mode 100644 packages/commons/test/crypto/crypto-utils.spec.ts create mode 100644 packages/commons/test/decorators/is-safe-string.spec.ts create mode 100644 packages/commons/test/ip/ip-utils.spec.ts create mode 100644 packages/commons/test/port/port-utils.spec.ts create mode 100644 packages/commons/test/redis/redis-connection-module.spec.ts create mode 100644 packages/commons/test/util/not-empty.spec.ts create mode 100644 packages/commons/tsconfig.json create mode 100644 packages/commons/tsconfig.lib.json create mode 100644 packages/commons/tsconfig.spec.json create mode 100644 packages/openai-utils/.eslintrc.json create mode 100644 packages/openai-utils/index.ts create mode 100644 packages/openai-utils/jest.config.ts create mode 100644 packages/openai-utils/package.json create mode 100644 packages/openai-utils/project.json create mode 100644 packages/openai-utils/src/config/openai-client-config.ts create mode 100644 packages/openai-utils/src/openai-client-factory.ts create mode 100644 packages/openai-utils/src/openai-client-module.ts create mode 100644 packages/openai-utils/src/service/conversion/openai-service-local.ts create mode 100644 packages/openai-utils/src/service/conversion/openai-service-remote.ts create mode 100644 packages/openai-utils/src/service/conversion/openai-service.ts create mode 100644 packages/openai-utils/test/client-factory.ts create mode 100644 packages/openai-utils/test/service/openai-client.spec.ts create mode 100644 packages/openai-utils/tsconfig.json create mode 100644 packages/openai-utils/tsconfig.lib.json create mode 100644 packages/openai-utils/tsconfig.spec.json create mode 100644 packages/sql-decorators/.eslintrc.json create mode 100644 packages/sql-decorators/index.ts create mode 100644 packages/sql-decorators/jest.config.ts create mode 100644 packages/sql-decorators/package.json create mode 100644 packages/sql-decorators/project.json create mode 100644 packages/sql-decorators/src/decorators.ts create mode 100644 packages/sql-decorators/src/query/query-parameter-mapper.ts create mode 100644 packages/sql-decorators/src/query/query-runner.ts create mode 100644 packages/sql-decorators/src/query/query.ts create mode 100644 packages/sql-decorators/src/result/result-mapper.ts create mode 100644 packages/sql-decorators/src/result/result-types.ts create mode 100644 packages/sql-decorators/src/stream-iterator.ts create mode 100644 packages/sql-decorators/test/decorators.spec.ts create mode 100644 packages/sql-decorators/test/repository/array-dao.ts create mode 100644 packages/sql-decorators/test/repository/broken-dao.ts create mode 100644 packages/sql-decorators/test/repository/clazz-dao.ts create mode 100644 packages/sql-decorators/test/repository/enum-dao.ts create mode 100644 packages/sql-decorators/test/repository/insertQuery.sql create mode 100644 packages/sql-decorators/test/repository/lol-dao.ts create mode 100644 packages/sql-decorators/test/repository/nested-dao.ts create mode 100644 packages/sql-decorators/test/repository/nullable-dao.ts create mode 100644 packages/sql-decorators/test/repository/some-folder/updateQuery.sql create mode 100644 packages/sql-decorators/test/repository/streamThings.sql create mode 100644 packages/sql-decorators/test/repository/test-dao.ts create mode 100644 packages/sql-decorators/test/repository/unconventional-dao.ts create mode 100644 packages/sql-decorators/test/transaction-repository/test-repository.ts create mode 100644 packages/sql-decorators/tsconfig.json create mode 100644 packages/sql-decorators/tsconfig.lib.json create mode 100644 packages/sql-decorators/tsconfig.spec.json create mode 100644 packages/tavily-utils/.eslintrc.json create mode 100644 packages/tavily-utils/index.ts create mode 100644 packages/tavily-utils/jest.config.ts create mode 100644 packages/tavily-utils/package.json create mode 100644 packages/tavily-utils/project.json create mode 100644 packages/tavily-utils/src/config/tavily-client-config.ts create mode 100644 packages/tavily-utils/src/service/tavily-service-local.ts create mode 100644 packages/tavily-utils/src/service/tavily-service-remote.ts create mode 100644 packages/tavily-utils/src/service/tavily-service.ts create mode 100644 packages/tavily-utils/src/tavily-client-factory.ts create mode 100644 packages/tavily-utils/src/tavily-client-module.ts create mode 100644 packages/tavily-utils/src/tools/get-web-content.ts create mode 100644 packages/tavily-utils/src/tools/index.ts create mode 100644 packages/tavily-utils/src/tools/web-search.ts create mode 100644 packages/tavily-utils/tsconfig.json create mode 100644 packages/tavily-utils/tsconfig.lib.json create mode 100644 packages/tavily-utils/tsconfig.spec.json create mode 100644 tsconfig.base.json create mode 100644 yarn.lock 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