diff --git a/.devcontainer/devcontainer-lock.json b/.devcontainer/devcontainer-lock.json index b9f7155..219acb6 100644 --- a/.devcontainer/devcontainer-lock.json +++ b/.devcontainer/devcontainer-lock.json @@ -1,9 +1,3 @@ { - "features": { - "ghcr.io/devcontainers/features/docker-in-docker:4": { - "version": "4.0.0", - "resolved": "ghcr.io/devcontainers/features/docker-in-docker@sha256:4fa87399214366e320d489991769c4f3f461e1ffe461f54eea78a41b34945bb5", - "integrity": "sha256:4fa87399214366e320d489991769c4f3f461e1ffe461f54eea78a41b34945bb5" - } - } + "features": {} } diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index a64368a..db89583 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -4,58 +4,33 @@ "name": "Node.js & TypeScript", // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile "image": "mcr.microsoft.com/devcontainers/typescript-node:1-22-bookworm", - "features": { - "ghcr.io/devcontainers/features/docker-in-docker:4": {}, - }, "runArgs": [ "--net=host" ], - // REGRA: com --net=host todos os devcontainers da máquina compartilham a rede - // do host — porta nova aqui deve evitar faixas já usadas por outros containers. - // Convenção DESTE repo: gateways dos exemplos 36xx (invoke = apiPort + 10000 - // → 136xx), serverless-offline 3002-3003, dashboards dos exemplos 31xx, - // consoles de validação dos exemplos 8620-8622, LocalStack 4567/4571-4572, - // self engine 14566. Os defaults de produto (3100/4566/8000) continuam no - // código, mas o dev neste container usa os overrides do lss.config.json da - // raiz (3101/4567/8001) — por isso os defaults não são forwardados aqui. + // No features: nothing in this repo shells out to Docker — not the + // orchestrator, not the engine, not the test suites (`npm run + // test:integration` boots a real stack in-process). + // + // 14566 LSS — dashboard, REST API and AWS wire, all one listener + // 3101 Vite dev server for the dashboard (dev only) + // 8001 DynamoDB proxy (opt-in via enableDynamoProxy) + // 36xx per-service HTTP APIs · 136xx their invoke listeners + // 8622 validation console of examples/self-hosted (npm run console) "forwardPorts": [ - // Core (dev deste repo) - 3101, // Dashboard/API (lss.config.json raiz) e UI Vite dev - 14566, // Self engine (AWS wire) - 4567, // LocalStack (lss.config.json raiz) - 8001, // Proxy DynamoDB (lss.config.json raiz, opt-in) - // serverless-offline (localstack-ultimate) - 3002, 3003, - // Lambda API por serviço (exemplos) - 3610, 3611, 3612, // localstack-free - 3631, 3632, 3633, 3634, // self-hosted - // Lambda Invoke por serviço (apiPort + 10000) - 13610, 13611, 13612, // localstack-free - 13631, 13632, 13633, 13634, // self-hosted - // Dashboards dos exemplos (serverPort de cada lss.config.json) - 3111, 3120, 3140, - // Consoles de validação dos exemplos (npm run console) - 8620, 8621, 8622, - // LocalStack dos exemplos - 4571, 4572 + 14566, + 3101, + 8001, + 3631, 3632, 3633, 3634, + 13631, 13632, 13633, 13634, + 8622 ], "portsAttributes": { - "3101": { "label": "LSS Dashboard/API (dev) / UI Vite" }, - "14566": { "label": "Self Engine (AWS wire)" }, - "4567": { "label": "LocalStack (config raiz)" }, - "8001": { "label": "DynamoDB Proxy (config raiz)" }, - "3002-3003": { "label": "serverless-offline (localstack-ultimate)" }, - "3610-3612": { "label": "Lambda API (localstack-free)" }, - "3631-3634": { "label": "Lambda API (self-hosted)" }, - "13610-13612": { "label": "Lambda Invoke (localstack-free)" }, - "13631-13634": { "label": "Lambda Invoke (self-hosted)" }, - "3111": { "label": "LSS Dashboard (localstack-ultimate)" }, - "3120": { "label": "LSS Dashboard (localstack-free)" }, - "3140": { "label": "LSS Dashboard (self-hosted)" }, - "8620": { "label": "Console de validação (localstack-free)" }, - "8621": { "label": "Console de validação (localstack-ultimate)" }, - "8622": { "label": "Console de validação (self-hosted)" }, - "4571-4572": { "label": "LocalStack (exemplos)" } + "14566": { "label": "LSS (dashboard + API + AWS wire)" }, + "3101": { "label": "UI Vite dev server" }, + "8001": { "label": "DynamoDB Proxy (opt-in)" }, + "3631-3634": { "label": "Lambda API (example self-hosted)" }, + "13631-13634": { "label": "Lambda Invoke (example self-hosted)" }, + "8622": { "label": "Validation console (example self-hosted)" } } // Use 'postCreateCommand' to run commands after the container is created. // "postCreateCommand": "yarn install", diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml new file mode 100644 index 0000000..9113906 --- /dev/null +++ b/.github/workflows/pr-preview.yml @@ -0,0 +1,180 @@ +name: PR Preview Release + +# Publishes every push on a pull request to npm under a per-PR dist-tag, so a +# reviewer can install the branch instead of building it. The version is the +# manifest version plus the PR number and the run number +# (1.0.0 -> 1.0.0-pr.42.17), which is a semver PRERELEASE: it sorts BELOW the +# real 1.0.0 and no default range (`^1.0.0`) will ever resolve to it. +# +# `latest` is never touched. `npm publish` writes the `latest` dist-tag unless +# `--tag` is given, and it does NOT infer a different tag from a prerelease +# version string — the explicit `--tag` below is the only thing keeping a +# preview out of `npm i local-serverless-stack`. +# +# NOT `pull_request_target`, deliberately. That trigger runs the BASE repo's +# workflow with access to secrets while checking out PR code, which would hand +# NPM_TOKEN to anyone who can open a pull request. With plain `pull_request`, +# GitHub withholds secrets from fork PRs — so the fork case is gated explicitly +# below and skips with a clear reason instead of failing on a missing token. + +# `labeled`/`unlabeled` are in the list because the `publish-preview` label is +# what gates this workflow: without them, applying the label would sit there +# doing nothing until someone happened to push again. +on: + pull_request: + types: [opened, synchronize, reopened, labeled, unlabeled, closed] + +# One preview in flight per PR. Each run composes a unique version, so +# cancelling a superseded run only means that version never lands. +concurrency: + group: pr-preview-${{ github.event.pull_request.number }} + cancel-in-progress: true + +permissions: + contents: read + pull-requests: write + +jobs: + publish: + name: Publish preview to npm + # Two gates: + # - Same-repo branches only: a fork PR has no NPM_TOKEN by design. + # - The `publish-preview` label. Opt-in rather than every-push, because npm + # versions are PERMANENT — `npm unpublish` is restricted to the first 72 + # hours, so a 30-push PR would otherwise leave 30 versions on the + # package's public list forever. + # The last clause keeps an unrelated label ("bug", "wontfix") from + # triggering a republish: on a `labeled` event, only the label we care about + # counts. On push/open/reopen the clause is vacuously true. + if: >- + github.event.action != 'closed' + && github.event.action != 'unlabeled' + && github.event.pull_request.head.repo.full_name == github.repository + && contains(github.event.pull_request.labels.*.name, 'publish-preview') + && (github.event.action != 'labeled' || github.event.label.name == 'publish-preview') + runs-on: ubuntu-latest + steps: + - name: Checkout PR head + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + registry-url: 'https://registry.npmjs.org' + + - name: Compose the preview version + id: version + run: | + set -euo pipefail + BASE=$(jq -r '.version' package.json) + # Drop any prerelease already on the manifest (1.0.0-rc.1 -> 1.0.0) so + # the suffix cannot stack into 1.0.0-rc.1-pr.42.17, which is a + # different — and confusingly lower — semver ordering. + BASE="${BASE%%-*}" + VERSION="${BASE}-pr.${{ github.event.pull_request.number }}.${{ github.run_number }}" + TAG="pr-${{ github.event.pull_request.number }}" + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + echo "tag=$TAG" >> "$GITHUB_OUTPUT" + echo "Publishing $VERSION under dist-tag $TAG" + + # Before the version is stamped: `npm ci` reconciles package.json against + # the lockfile, and the stamped preview version exists in neither. + - name: Install dependencies + run: npm ci + + - name: Stamp the preview version + run: npm pkg set version="${{ steps.version.outputs.version }}" + + # `prepublishOnly` builds again on publish; running it here first turns a + # build failure into its own red step instead of burying it in the + # publish log. + - name: Build project + run: npm run build + + - name: Publish to npm + run: npm publish --access public --tag "${{ steps.version.outputs.tag }}" + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Comment the published version on the PR + uses: actions/github-script@v7 + env: + PREVIEW_VERSION: ${{ steps.version.outputs.version }} + PREVIEW_TAG: ${{ steps.version.outputs.tag }} + with: + script: | + // One sticky comment per PR, edited in place — a comment per push + // would bury the review conversation. + const marker = ''; + const { PREVIEW_VERSION, PREVIEW_TAG } = process.env; + const sha = context.payload.pull_request.head.sha.slice(0, 7); + + const body = [ + marker, + `📦 **Published \`local-serverless-stack@${PREVIEW_VERSION}\`** for homologation.`, + '', + '```bash', + `npm i local-serverless-stack@${PREVIEW_TAG} # always the newest build of this PR`, + `npm i local-serverless-stack@${PREVIEW_VERSION} # pin this exact build`, + '```', + '', + `Built from ${sha} · dist-tag \`${PREVIEW_TAG}\` · **not** \`latest\`.`, + 'The tag is dropped when this PR closes or the `publish-preview` label is removed —', + 'the versions themselves stay on npm and remain installable by their exact number.', + ].join('\n'); + + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + per_page: 100, + }); + const existing = comments.find((c) => c.body?.includes(marker)); + + if (existing) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: existing.id, + body, + }); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + body, + }); + } + + cleanup: + name: Drop the preview dist-tag + # The label is the switch, so turning it off retires the preview too — + # otherwise `@pr-42` would keep resolving to a build nobody is maintaining. + if: >- + github.event.pull_request.head.repo.full_name == github.repository + && ( + github.event.action == 'closed' + || (github.event.action == 'unlabeled' && github.event.label.name == 'publish-preview') + ) + runs-on: ubuntu-latest + steps: + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + registry-url: 'https://registry.npmjs.org' + + # Non-fatal: a PR closed without ever publishing has no tag to remove. + # Removing the tag does not unpublish anything — the versions stay + # installable by their exact number. + - name: Remove the per-PR dist-tag + run: | + npm dist-tag rm local-serverless-stack "pr-${{ github.event.pull_request.number }}" \ + || echo "No dist-tag pr-${{ github.event.pull_request.number }} to remove." + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f71619a..4889c55 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -6,7 +6,6 @@ on: - main paths: - 'package.json' - - 'packages/*/package.json' jobs: check-version: @@ -14,9 +13,7 @@ jobs: runs-on: ubuntu-latest outputs: root-changed: ${{ steps.check-root.outputs.changed }} - plugin-changed: ${{ steps.check-plugin.outputs.changed }} root-version: ${{ steps.get-root-version.outputs.version }} - plugin-version: ${{ steps.get-plugin-version.outputs.version }} steps: - name: Checkout code uses: actions/checkout@v4 @@ -36,19 +33,6 @@ jobs: echo "⏭️ Root package version unchanged: $CURRENT" fi - - name: Check plugin package version change - id: check-plugin - run: | - CURRENT=$(git show HEAD:packages/serverless-plugin/package.json | jq -r '.version') - PREVIOUS=$(git show HEAD~1:packages/serverless-plugin/package.json | jq -r '.version' || echo "0.0.0") - if [ "$CURRENT" != "$PREVIOUS" ]; then - echo "changed=true" >> $GITHUB_OUTPUT - echo "✅ Plugin package version changed: $PREVIOUS -> $CURRENT" - else - echo "changed=false" >> $GITHUB_OUTPUT - echo "⏭️ Plugin package version unchanged: $CURRENT" - fi - - name: Get root package version id: get-root-version run: | @@ -56,34 +40,6 @@ jobs: echo "version=$VERSION" >> $GITHUB_OUTPUT echo "Root version: $VERSION" - - name: Get plugin package version - id: get-plugin-version - run: | - VERSION=$(jq -r '.version' packages/serverless-plugin/package.json) - echo "version=$VERSION" >> $GITHUB_OUTPUT - echo "Plugin version: $VERSION" - - # Skip integration tests - require Docker/LocalStack (not available in GitHub Actions) - # Tests are run locally with: npm run test:coverage - # test: - # name: Run Tests - # needs: check-version - # if: needs.check-version.outputs.root-changed == 'true' || needs.check-version.outputs.plugin-changed == 'true' - # runs-on: ubuntu-latest - # steps: - # - name: Checkout code - # uses: actions/checkout@v4 - # - name: Setup Node.js - # uses: actions/setup-node@v4 - # with: - # node-version: '18' - # - name: Install dependencies - # run: npm ci - # - name: Build project - # run: npm run build - # - name: Run tests - # run: npm test - publish-root: name: Publish Root Package needs: check-version @@ -109,29 +65,3 @@ jobs: run: npm publish --access public env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - - publish-plugin: - name: Publish Plugin Package - needs: check-version - if: needs.check-version.outputs.plugin-changed == 'true' - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: '20' - registry-url: 'https://registry.npmjs.org' - - - name: Install dependencies - run: npm ci - - - name: Build plugin - run: npm run build -w packages/serverless-plugin - - - name: Publish plugin to NPM - run: npm publish -w packages/serverless-plugin --access public - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 613956c..e06b307 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -30,13 +30,13 @@ jobs: run: npm run test:coverage integration: - name: Integration Tests (LocalStack) + name: Integration Tests (self engine) runs-on: ubuntu-latest - timeout-minutes: 25 - # ubuntu-latest runners ship Docker; LocalStack runs as an unprivileged - # container. Gated on the token: community images >= 2026.5 require it. - env: - LOCALSTACK_AUTH_TOKEN: ${{ secrets.LOCALSTACK_AUTH_TOKEN }} + timeout-minutes: 15 + # 1.0 removed the LocalStack backend: the engine runs in the orchestrator + # process, so this job needs no Docker, no service container and no secret. + # It is therefore unconditional — under 0.x it skipped itself whenever the + # LocalStack auth token was absent, which was most of the time. steps: - name: Checkout code uses: actions/checkout@v4 @@ -48,19 +48,15 @@ jobs: cache: 'npm' - name: Install dependencies (root) - if: env.LOCALSTACK_AUTH_TOKEN != '' run: npm ci - name: Install dependencies (sample-microservice fixture) - if: env.LOCALSTACK_AUTH_TOKEN != '' run: npm ci --prefix tests/integration/fixtures/sample-microservice - name: Build project - if: env.LOCALSTACK_AUTH_TOKEN != '' run: npm run build - name: Run integration tests - if: env.LOCALSTACK_AUTH_TOKEN != '' run: npm run test:integration lint: @@ -86,9 +82,6 @@ jobs: - name: Check TypeScript (server) run: npx tsc --project src/server/tsconfig.json --noEmit - - name: Check TypeScript (plugin) - run: npx tsc --project packages/serverless-plugin/tsconfig.json --noEmit - build: name: Build Check runs-on: ubuntu-latest @@ -115,5 +108,4 @@ jobs: test -d dist/ui test -d dist/client test -f dist/client/index.js - test -d packages/serverless-plugin/dist test -f bin/cli.js diff --git a/.gitignore b/.gitignore index 6bf42e1..89ecc16 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,9 @@ tests/.lss-client-integration/ # Cache .cache/ .parcel-cache/ + +# Vendor source packs downloaded for a generator, never committed. The AWS +# Architecture Service Icons pack (41 MB) is unzipped here for +# `npm run icons:aws`; only the curated output in src/ui/src/icons/aws/ is +# versioned — see src/ui/ui-ux.md §3. +temp/ diff --git a/.mcp.json b/.mcp.json new file mode 100644 index 0000000..421344c --- /dev/null +++ b/.mcp.json @@ -0,0 +1,8 @@ +{ + "mcpServers": { + "lss": { + "command": "node", + "args": ["./bin/cli.js", "mcp"] + } + } +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json index ff186d6..55102d6 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -8,7 +8,7 @@ // ------------------------------------------------------------------ { "label": "build: all", - "detail": "UI + server + client + plugin (npm run build)", + "detail": "UI + server + client + MCP (npm run build)", "type": "npm", "script": "build", "group": { "kind": "build", "isDefault": true }, @@ -34,32 +34,13 @@ }, { "label": "dev @ example self-hosted (watch, sem build)", - "detail": "npm run dev lendo examples/self-hosted/lss.config.json — orquestrador forçado em :3100 (a UI dev espera essa porta); registre com LSS_DASHBOARD_PORT=3100 npm run register:all. UI em :3101", + "detail": "npm run dev lendo examples/self-hosted/lss.config.json — LSS em :14566 (dashboard, API e AWS wire), UI Vite em :3101", "type": "shell", - "command": "LSS_DASHBOARD_PORT=3100 LSS_CONFIG_PATH=examples/self-hosted/lss.config.json npm run dev", + "command": "LSS_CONFIG_PATH=examples/self-hosted/lss.config.json npm run dev", "isBackground": true, "icon": { "id": "play-circle", "color": "terminal.ansiCyan" }, "problemMatcher": [] }, - { - "label": "dev @ example localstack-free (watch, sem build)", - "detail": "npm run dev lendo examples/localstack-free/lss.config.json — orquestrador forçado em :3100 (a UI dev espera essa porta); exige Docker. UI em :3101", - "type": "shell", - "command": "LSS_DASHBOARD_PORT=3100 LSS_CONFIG_PATH=examples/localstack-free/lss.config.json npm run dev", - "isBackground": true, - "icon": { "id": "play-circle", "color": "terminal.ansiCyan" }, - "problemMatcher": [] - }, - { - "label": "dev @ example localstack-ultimate (watch, sem build)", - "detail": "Carrega examples/localstack-ultimate/.env (token) + lss.config.json e roda npm run dev — orquestrador forçado em :3100 (a UI dev espera essa porta); exige Docker. UI em :3101", - "type": "shell", - "command": "set -a; [ -f examples/localstack-ultimate/.env ] && . examples/localstack-ultimate/.env; set +a; LSS_DASHBOARD_PORT=3100 LSS_CONFIG_PATH=examples/localstack-ultimate/lss.config.json npm run dev", - "isBackground": true, - "icon": { "id": "play-circle", "color": "terminal.ansiCyan" }, - "problemMatcher": [] - }, - // ------------------------------------------------------------------ // Tests & validation // ------------------------------------------------------------------ @@ -90,8 +71,8 @@ "problemMatcher": [] }, { - "label": "test: integration (Docker + LOCALSTACK_AUTH_TOKEN)", - "detail": "Suite de integração com LocalStack real — exige Docker e token", + "label": "test: integration (self engine, no Docker)", + "detail": "Suite de integração ponta a ponta no self engine — sem Docker, sem token", "type": "npm", "script": "test:integration", "group": "test", @@ -117,9 +98,9 @@ }, { "label": "typecheck: all projects", - "detail": "tsc --noEmit em server/client/plugin + vue-tsc na UI", + "detail": "tsc --noEmit em server/client/mcp + vue-tsc na UI", "type": "shell", - "command": "npx tsc --noEmit -p src/server/tsconfig.json && npx tsc --noEmit -p src/client/tsconfig.json && npx tsc --noEmit -p packages/serverless-plugin/tsconfig.json && cd src/ui && npx vue-tsc --noEmit", + "command": "npx tsc --noEmit -p src/server/tsconfig.json && npx tsc --noEmit -p src/client/tsconfig.json && npx tsc --noEmit -p src/mcp/tsconfig.json && cd src/ui && npx vue-tsc --noEmit", "group": "test", "icon": { "id": "verified", "color": "terminal.ansiBlue" }, "problemMatcher": ["$tsc"] @@ -148,7 +129,7 @@ }, { "label": "example self-hosted: start (no Docker)", - "detail": "Sobe o LSS com a engine própria na porta 14566", + "detail": "Sobe o LSS na 14566 — dashboard, REST API e AWS wire no mesmo listener", "type": "shell", "command": "npm run lss:start", "options": { "cwd": "${workspaceFolder}/examples/self-hosted" }, @@ -214,126 +195,6 @@ ], "icon": { "id": "rocket", "color": "terminal.ansiYellow" }, "problemMatcher": [] - }, - - // ------------------------------------------------------------------ - // Example: localstack-free (LocalStack community 4.0 via Docker) - // ------------------------------------------------------------------ - { - "label": "example localstack-free: start (Docker)", - "detail": "Sobe o LSS com LocalStack community 4.0 gerenciado (exige Docker, sem token)", - "type": "shell", - "command": "npm run lss:start", - "options": { "cwd": "${workspaceFolder}/examples/localstack-free" }, - "icon": { "id": "server-environment", "color": "terminal.ansiGreen" }, - "problemMatcher": [] - }, - { - "label": "example localstack-free: register services", - "type": "shell", - "command": "npm run register:all", - "options": { "cwd": "${workspaceFolder}/examples/localstack-free" }, - "icon": { "id": "cloud-upload", "color": "terminal.ansiBlue" }, - "problemMatcher": [] - }, - { - "label": "example localstack-free: stop", - "type": "shell", - "command": "npm run lss:stop", - "options": { "cwd": "${workspaceFolder}/examples/localstack-free" }, - "icon": { "id": "debug-stop", "color": "terminal.ansiRed" }, - "problemMatcher": [] - }, - { - "label": "example localstack-free: restart (rebuild local)", - "detail": "build: all > stop > start — o CLI roda o dist/ compilado, então este é o caminho para ver mudanças locais no exemplo", - "dependsOrder": "sequence", - "dependsOn": [ - "build: all", - "example localstack-free: stop", - "example localstack-free: start (Docker)" - ], - "icon": { "id": "refresh", "color": "terminal.ansiYellow" }, - "problemMatcher": [] - }, - - // ------------------------------------------------------------------ - // Example: localstack-ultimate (LocalStack Pro via Docker + token) - // ------------------------------------------------------------------ - { - "label": "example localstack-ultimate: setup", - "detail": "npm install no exemplo (SDKs + serverless-offline + plugin LSS)", - "type": "shell", - "command": "npm run setup", - "options": { "cwd": "${workspaceFolder}/examples/localstack-ultimate" }, - "icon": { "id": "desktop-download", "color": "terminal.ansiBlue" }, - "problemMatcher": [] - }, - { - "label": "example localstack-ultimate: start (Docker + token)", - "detail": "Sobe o LSS com LocalStack Pro gerenciado — exige Docker e LOCALSTACK_AUTH_TOKEN obrigatório no .env", - "type": "shell", - "command": "npm run lss:start", - "options": { "cwd": "${workspaceFolder}/examples/localstack-ultimate" }, - "icon": { "id": "server-environment", "color": "terminal.ansiGreen" }, - "problemMatcher": [] - }, - { - "label": "example localstack-ultimate: offline (HTTP :3002)", - "detail": "sls package + RedrivePolicy (wire-dlq) + serverless-offline — fica em primeiro plano, não encadeie em dependsOn", - "type": "shell", - "command": "npm run offline", - "options": { "cwd": "${workspaceFolder}/examples/localstack-ultimate" }, - "isBackground": true, - "icon": { "id": "play-circle", "color": "terminal.ansiCyan" }, - "problemMatcher": [] - }, - { - "label": "example localstack-ultimate: seed", - "detail": "Recarrega os seeds (Users/Orders/Sessions) no LocalStack Pro — LSS precisa estar de pé", - "type": "shell", - "command": "npm run seed", - "options": { "cwd": "${workspaceFolder}/examples/localstack-ultimate" }, - "icon": { "id": "database", "color": "terminal.ansiYellow" }, - "problemMatcher": [] - }, - { - "label": "example localstack-ultimate: drive demo", - "detail": "POST /users e /orders (incl. ordem envenenada p/ DLQ) e lê /users e /audit em :3002", - "type": "shell", - "command": "curl -s -X POST http://localhost:3002/dev/users -H 'content-type: application/json' -d '{\"name\":\"Task Runner\",\"email\":\"task@example.com\"}' && echo && echo '--- USERS:' && curl -s http://localhost:3002/dev/users && echo && echo '--- ORDER (SQS -> DynamoDB -> EventBridge):' && curl -s -X POST http://localhost:3002/dev/orders -H 'content-type: application/json' -d '{\"userId\":\"u-alice\",\"items\":[{\"sku\":\"BOOK-02\",\"price\":42,\"qty\":1}]}' && echo && echo '--- POISON ORDER (total 0 -> DLQ apos 3 tentativas, ~30s):' && curl -s -X POST http://localhost:3002/dev/orders -H 'content-type: application/json' -d '{\"userId\":\"u-alice\",\"items\":[{\"sku\":\"BROKEN\",\"price\":0,\"qty\":1}]}' && echo && sleep 5 && echo '--- AUDIT:' && curl -s http://localhost:3002/dev/audit && echo", - "options": { "cwd": "${workspaceFolder}/examples/localstack-ultimate" }, - "icon": { "id": "run-all", "color": "terminal.ansiCyan" }, - "problemMatcher": [] - }, - { - "label": "example localstack-ultimate: drive catalog (OpenSearch)", - "detail": "Indexa produtos e roda busca full-text, filtros e agregações — coleção aoss servida pelo sidecar do LSS (:14567)", - "type": "shell", - "command": "curl -s -X POST http://localhost:3002/dev/products -H 'content-type: application/json' -d '{\"name\":\"Wireless Mouse\",\"category\":\"peripherals\",\"price\":25,\"tags\":[\"usb\",\"wireless\"]}' && echo && curl -s -X POST http://localhost:3002/dev/products -H 'content-type: application/json' -d '{\"name\":\"Mechanical Keyboard\",\"category\":\"peripherals\",\"price\":90,\"tags\":[\"usb\"]}' && echo && curl -s -X POST http://localhost:3002/dev/products -H 'content-type: application/json' -d '{\"name\":\"USB Hub\",\"category\":\"accessories\",\"price\":15,\"tags\":[\"usb\"]}' && echo && echo '--- SEARCH q=wireless:' && curl -s 'http://localhost:3002/dev/search?q=wireless' && echo && echo '--- SEARCH category+maxPrice:' && curl -s 'http://localhost:3002/dev/search?category=peripherals&maxPrice=50' && echo && echo '--- STATS:' && curl -s http://localhost:3002/dev/stats && echo", - "options": { "cwd": "${workspaceFolder}/examples/localstack-ultimate" }, - "icon": { "id": "search", "color": "terminal.ansiCyan" }, - "problemMatcher": [] - }, - { - "label": "example localstack-ultimate: stop", - "type": "shell", - "command": "npm run lss:stop", - "options": { "cwd": "${workspaceFolder}/examples/localstack-ultimate" }, - "icon": { "id": "debug-stop", "color": "terminal.ansiRed" }, - "problemMatcher": [] - }, - { - "label": "example localstack-ultimate: restart (rebuild local)", - "detail": "build: all > stop > start — o CLI roda o dist/ compilado, então este é o caminho para ver mudanças locais no exemplo", - "dependsOrder": "sequence", - "dependsOn": [ - "build: all", - "example localstack-ultimate: stop", - "example localstack-ultimate: start (Docker + token)" - ], - "icon": { "id": "refresh", "color": "terminal.ansiYellow" }, - "problemMatcher": [] } ] } diff --git a/AGENTS.md b/AGENTS.md index 25da080..d6b90ba 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -10,14 +10,15 @@ LSS is a **local control plane for serverless development**. One orchestrator provisions and serves every AWS resource your services declare, so a monorepo of 15+ microservices needs a single local -stack instead of one LocalStack per service. It ships two interchangeable backends: the **self -engine** (an in-process AWS emulator — no Docker, no token, the project's differentiator) and -**LocalStack** (community or Pro). It also replaces `serverless-offline` with its own Lambda runtime +stack instead of one emulator per service. The AWS provider is the **self engine**: an in-process +emulator — no Docker, no container, no auth token — and since 1.0 the only engine LSS ships. It also +replaces `serverless-offline` with its own Lambda runtime and API Gateway emulation. -Published as the npm package `local-serverless-stack` (CLI: `lss`), plus the workspace package -`serverless-lss` (the Serverless Framework plugin). Node **>= 20**, CommonJS, npm workspaces -(`packages/*`, `src/ui`). +Published as the single npm package `local-serverless-stack` (CLI: `lss`). Services join the stack +through the orchestrator itself — `lss scan` / `lss register`, the dashboard onboarding or +`POST /api/services/register` — there is no Serverless Framework plugin anymore (the `serverless-lss` +package was retired in 1.0). Node **>= 20**, CommonJS, npm workspaces (`src/ui`). --- @@ -28,10 +29,10 @@ Published as the npm package `local-serverless-stack` (CLI: `lss`), plus the wor | `src/server/` | The orchestrator: `index.ts` (boot), `routes/` (HTTP API), `services/` (registrar, CFN parser, provisioner, seeds, gateway/lambda managers), `runtime/` (Lambda workers), `dev/` | | `src/server/engine/` | **The self engine.** `emulators/` (dynamodb, sqs, sns, s3, events, secretsmanager, opensearch, lambda-ctl, sts), `dispatch/` (stream-tailer, sqs-poller, scheduler, dispatcher), `store/` (JSONL snapshot + WAL), `http/` (router, sigv4, protocols), `bus.ts` | | `src/client/` | `LssClient` — the programmatic API | +| `src/mcp/` | MCP server (`lss mcp`) — the stack as tools for an AI coding agent | | `src/ui/` | Vue 3 dashboard (own workspace) | -| `packages/serverless-plugin/` | The `serverless-lss` plugin (separately versioned & published) | -| `examples/` | `self-hosted` (self engine, no Docker), `localstack-free`, `localstack-ultimate` | -| `tests/` | `unit/`, `integration/` (Docker + token gated), `fixtures/` | +| `examples/` | `self-hosted` — four microservices on the engine (DynamoDB, SQS, S3, EventBridge, OpenSearch, Secrets) | +| `tests/` | `unit/`, `integration/` (self engine, no Docker, no token), `fixtures/` | | `docs/` | `FEATURES.md`, `SELF_ENGINE.md`, `CONFIGURATION.md`, `RELEASE.md`, PRDs | --- @@ -63,14 +64,14 @@ it mirrors CI. Shell equivalent: npm run lint \ && npx tsc --noEmit -p src/server/tsconfig.json \ && npx tsc --noEmit -p src/client/tsconfig.json \ - && npx tsc --noEmit -p packages/serverless-plugin/tsconfig.json \ + && npx tsc --noEmit -p src/mcp/tsconfig.json \ && (cd src/ui && npx vue-tsc --noEmit) \ && npm run test:coverage \ && npm run build ``` Running only `jest` + `server:build` is **not** sufficient — it misses lint, `vue-tsc`, and the -UI/client/plugin builds. +UI/client/MCP builds. ### 3. 100% coverage, globally @@ -95,8 +96,6 @@ shipping the change, not an afterthought. End-to-end proof lives in `examples/`, not in ad-hoc scripts: - `examples/self-hosted` — four microservices on the self engine (DynamoDB, SQS, S3, EventBridge). The default target. -- `examples/localstack-free` — API Gateway proxy, cross-service Lambda authorizers, shared bus, streams, S3 notifications. -- `examples/localstack-ultimate` — Pro-only surfaces. A new engine capability should gain (or extend) a fixture in one of these plus an assertion. When a full boot e2e isn't practical, drive the real backend from a `tests/unit/engine/wire-*.test.ts` @@ -107,12 +106,12 @@ instead — that's the established pattern. ## Commands ```bash -npm run build # ui + server + client + plugin +npm run build # ui + server + client + mcp npm run server:build # tsc for orchestrator + engine only npm run dev # tsx watch (server) + vite (UI) npm test # jest, unit suite npm run test:coverage # unit suite + the 100% gate -npm run test:integration # needs Docker + LOCALSTACK_AUTH_TOKEN +npm run test:integration # e2e on the self engine — no Docker, no token; run `npm run build` first npm run lint # eslint (see the warning baseline below) ``` @@ -128,8 +127,10 @@ pipeline — the fastest way to see the self engine work). `tests/unit/routes/…`. Match the neighbouring file's mocking style before inventing your own. - `tests/unit/engine/wire-*.test.ts` drive a **real `SelfEngineBackend`** end to end (through the AWS SDK) rather than mocks — use this shape when proving a provisioning/dispatch behaviour. -- `tests/integration/` requires Docker and `LOCALSTACK_AUTH_TOKEN`; it skips cleanly without them, so - never treat "it skipped" as "it passed". +- `tests/integration/` boots an isolated orchestrator on the self engine (own ports + `stateDir`) and + drives it over HTTP. It runs **unconditionally** — no Docker, no auth token, nothing to gate on, so + a skip there is a real problem, not the old 0.x "no token, never mind". `client.test.ts` imports the + **built** `dist/client`, so run `npm run build` before `npm run test:integration`. - `tests/fixtures/` holds committed CloudFormation templates and sample microservices. ## Code conventions @@ -167,5 +168,6 @@ pipeline — the fastest way to see the self engine work). under parallel load. They pass in isolation. Don't chase them as regressions of your change, but don't use them as cover for a real failure either. - CI (`.github/workflows/tests.yml`) runs unit + coverage gate, lint + tsc, build-artifact - verification, and (token-gated) integration. `publish.yml` publishes to npm when the version - changes — so a version bump is a release action, not routine housekeeping. + verification, and integration — the last one unconditionally, since 1.0 left nothing to gate it on. + `publish.yml` publishes to npm when the version changes — so a version bump is a release action, + not routine housekeeping. diff --git a/CHANGELOG.md b/CHANGELOG.md index 814e0ae..f5a4912 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,333 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.0.0] - 2026-07-31 + +**LSS runs on one engine.** The LocalStack backend is gone — not deprecated, removed. The self +engine, an in-process AWS emulator with no Docker, no container and no auth token, is what LSS is. +Migration guide: [docs/MIGRATION-v1.md](docs/MIGRATION-v1.md); for a project already on +`engine: "self"` it is a matter of deleting a few config keys. + +The trigger was evidence, not preference. Both shipped LocalStack examples were run end to end +against the self engine first: `localstack-ultimate` (45 resources, `eu-west-1`) exercised REST +payload-v1 routes, a DynamoDB composite key + GSI + stream, SQS with DLQ redrive at +`maxReceiveCount: 3`, `SNS Publish` from a stream handler, an EventBridge bus with a pattern rule, +a `rate(2 minutes)` schedule, an S3 notification with a prefix filter and an OpenSearch Serverless +catalog — **every path fired, zero errors**. `localstack-free` added a REST v1 authorizer, an +httpApi v2 simple-response authorizer written in TypeScript, and a cross-service authorizer +resolved by ARN. Nothing the project supported on LocalStack needed LocalStack. + +### Removed +- **The 0.x migration guards.** `engine: "localstack"` (file or `LSS_ENGINE`) and the retired + `--external` / `--pro` / `--self-engine` / `--localstack-token` flags no longer raise a dedicated + migration error — 1.0 has shipped, so an unknown key or flag is simply an unknown key or flag. + [docs/MIGRATION-v1.md](docs/MIGRATION-v1.md) still documents the move. +- **The LocalStack backend**: `src/server/engine/backends/localstack-backend.ts`, + `src/server/services/localstack-manager.ts`, `src/server/engine/aoss-sidecar.ts` and the + `EngineBackend` interface. `EngineManager` now owns the one engine. +- **Config keys**: `engine` (accepted only to reject a 0.x `"localstack"` with a migration error), + `mode`, `localstackPort`, `localstackEndpoint`, `localstackEdition`, `localstackVersion`, + `localstackImage`, `localstackAuthToken`, `services`, `aossSidecar`. Editing any of them through + `PUT /api/config` now answers `unknown config key`. +- **Env vars**: `LSS_LOCALSTACK_*`, `LOCALSTACK_AUTH_TOKEN`, `LSS_SERVICES`. `LSS_ENGINE` survives + only to reject `localstack`. +- **CLI flags**: `--self-engine`, `--external`, `--pro`, `--localstack-token`. Each exits 1 naming + the migration guide — checked before the already-running short-circuit, so a stale script fails + visibly instead of looking like a successful no-op. +- **API fields**: `GET /api/health` → `localstack` (use `engineRunning`); `GET /api/config` → + the `localstack` block, `aossSidecar` and `services`. `LssClient`: `HealthStatus.localstack` and + `lifecycle.start({ external, pro, localstackToken })`. +- **Examples**: `examples/localstack-free` and `examples/localstack-ultimate` (760 MB). Their raw + `AWS::ApiGatewayV2::*` cross-stack topology was preserved at + `tests/integration/fixtures/apigw-raw/`, where its end-to-end test still runs. +- **The `serverless-lss` plugin package** (`packages/serverless-plugin/`, published separately as + `serverless-lss`): services no longer announce themselves from inside `sls package` — a bare + `POST /api/services/register { servicePath }` is a complete registration, because the orchestrator + packages on demand (`autoPackage`) and reads the service name, `provider.region` and `custom.lss` + ports from the packaged `serverless-state.json` itself. Every `plugins: - serverless-lss` entry + and `custom.orchestrator` block is dead config; `custom.lss` stays, now read server-side. The npm + workspace, the publish lane, the CI typecheck and the example/fixture wiring all went with it. +- **`serverless-offline` compatibility**: `custom.serverless-offline.httpPort/lambdaPort` are no + longer read as port fallbacks (declare `custom.lss.apiPort`/`invokePort`), and nothing registers + on `sls offline` anymore — the retired plugin was the only piece that ever did. The LSS runtime + replaced offline's execution model back in 0.7.x; this removes the last vestige. + +### Added +- **A live load panel on the Overview.** Which workers are actually resident (against the + `maxWarmWorkers` ceiling), what ran in the last 1/2/10 minutes, **how much of it overlapped**, and + what that costs the host — resident memory, free/total RAM, 1-minute load normalised by core + count. Backed by `GET /api/lambdas/activity` and a stack-wide, log-free ring of invocation spans + (`src/server/services/invocation-activity.ts`, capped at 1000): parallelism is reported as the + **peak** per time bucket, because an average hides exactly the burst that saturates a laptop. The + timeline puts service identity on the row axis rather than on colour (a 40-service monorepo has no + readable categorical palette), and a failed invocation carries a shape marker and a counted label + as well as the status colour — red/green sit at ΔE 4.4 under deuteranopia, so colour alone would + hide every error from a colourblind reader. +- **One port for everything.** The dashboard, the REST API **and the AWS wire protocols** share one + listener on `14566` by default: requests carrying positive AWS evidence (SigV4 `Authorization`, + `X-Amz-Target`, any `x-amz-*` header, engine paths like `/_aoss` or `/2015-03-31/`) are demuxed to + the engine, everything else to the dashboard/API. Setting `selfEngine.port` different from + `serverPort` splits them back into two listeners. `AWS_ENDPOINT`, the dashboard URL and the + registration URL are now the same string. +- **Guided onboarding.** First dashboard visit with no services registered opens a 3-step flow — + ports, branding (applied live), then a project scan where you tick services and take them from + freshly cloned to registered without a terminal: **Install selected** (`POST + /api/services/install`, default `npm install`, first token whitelisted), **Package selected** + (`POST /api/services/package`, the effective package command) and **Register selected**. + Per-service API/invoke ports and package commands are editable inline and persist to + `lss.config.json` as `serviceRuntime`/`servicePackaging` entries — `updateConfig` now merges + map blocks **per entry**, so saving one field never drops that entry's or another service's + siblings. Reopenable anytime from Settings. This is the plugin's replacement for humans. +- **Three languages, dashboard and CLI**: English, Brazilian Portuguese and Spanish. The dashboard + follows a stored choice, else the browser (`pt` → `pt-BR`, `es-AR` → `es`), switchable from the ⋮ + menu and remembered per browser; the CLI follows `LSS_LANG`, else `LC_ALL`/`LC_MESSAGES`/`LANG`. + Both layers are hand-rolled and dependency-free (`src/ui/src/i18n/`, `bin/i18n.js`) — LSS ships as + one npm package and a translation runtime is not a cost to put on every install. A missing key + falls back to English and then to the key itself, so an untranslated screen still renders. AWS + proper nouns, config keys, commands and flags are deliberately never translated. This also fixes a + smaller wart: parts of the CLI (the seed diagnostic, `lss scan`) printed Brazilian Portuguese + regardless of environment; the CLI is now English by default and Portuguese on request. +- **Official AWS service icons in the dashboard.** 64 marks from AWS's own **Architecture Service + Icons** pack (the 16 variant — `viewBox 0 0 24 24`, which is TreeUI's icon grid) are vendored as + geometry under `src/ui/src/icons/aws/` and registered into the TreeUI icon registry with + `registerTreeIcons()`, plus a `TIconRegistry` augmentation so `` + typechecks like a built-in. 12 cover what LSS provides today (Lambda, DynamoDB, S3, SQS, SNS, + EventBridge, OpenSearch, Secrets Manager, API Gateway, CloudFormation, IAM — also standing for + STS — and CloudWatch — also standing for CloudWatch Logs); 52 more are a registered reserve. They + replace the generic glyphs on the sidebar, the Overview tiles and coverage rows, every + per-service resource breakdown, the Lambda trigger tags and each explorer's headers and empty + states — a screen listing eight AWS services no longer distinguishes them by a database/inbox/ + target vocabulary. The artwork is an AWS trademark, reproduced unmodified and deliberately + theme-blind (`src/ui/src/icons/aws/NOTICE.md`); the ~41 MB pack is not committed, and + `npm run icons:aws` regenerates the checked-in output from it. +- **Service discovery**: `GET /api/services/scan` + `lss scan` walk the project root (depth ≤ 6, + dependency/build/VCS trees skipped, a service root is a leaf) and report every Serverless/osls + service with `installed`/`packaged`/`registered` flags, the effective ports and package command + (`serviceRuntime`/`servicePackaging` overlays win over the yml hints — the same precedence + registration applies) — hints only, the packaged state stays the authority at register time. `lss register [path...]` (defaults to + `.`) is the CLI replacement for automation; `LssClient.services.scan()` and the MCP tools + `lss_scan_services`/`lss_register_service` expose the same pair to code and to agents. +- **MCP server** (`lss mcp`, `src/mcp/`): the running stack as **25 tools** for any Model Context + Protocol client (Claude Code included) — inspect resources/queues/tables/buckets/secrets, scan + and register services, invoke Lambdas, send messages, block on `await-idle`. Hand-rolled JSON-RPC + 2.0 over stdio, zero new dependencies, off until a client is configured ([docs/MCP.md](docs/MCP.md)). +- **Lambdas are lazy by default**: `lambdaRuntime.lazy` forks a worker on first invocation instead + of at registration, `idleTimeoutMs` (60 s) unloads it when quiet, `maxWarmWorkers` (one per GB of + RAM, clamped 2–12) caps residency. Measured on 40 services / 400 lambdas / 400 tables: + **2.0 GB → 128 MB** at rest, ~20 ms cold start. The host never chokes on a monorepo again; slow + is acceptable, swapping is not. +- **`LSS_ENGINE_DATA_DIR`**: the engine data directory as an env var, so each LSS instance gets its + own store with no config file. A second instance needs only + `LSS_DASHBOARD_PORT` + `LSS_ENGINE_PORT` + `LSS_ENGINE_DATA_DIR`. + +### Changed +- **The integration suite runs everywhere.** It boots an isolated orchestrator on the self engine + instead of a LocalStack container, so it needs no Docker and no secret: **19 end-to-end + assertions in ~20 s**, unconditional locally and in CI. Under 0.x the same suite skipped itself + whenever the LocalStack auth token was absent — which was most of the time, meaning the project's + only end-to-end coverage usually did not run. +- OpenSearch Serverless is served natively by the engine on its own endpoint; the sidecar that + existed only because no LocalStack edition provides `aoss` is gone. +- `lambdaRuntime.invokeHost` defaults to `127.0.0.1` (nothing runs in a container). +- The dashboard, the CLI and every log line name the engine instead of LocalStack. + +### Security +- **`POST /api/services/:name/start` was an arbitrary command runner — and it shipped.** This is not + a new-in-1.0 defect: the endpoint is present in **0.17.2 and every earlier release**, so any + install of those versions carries it. The handler read `command`, `args`, `cwd` and `env` straight + off the request body and passed them to `spawn()`; the only check was a four-entry command + allowlist that contained `node` and `npx`, and nothing at all validated the rest. So + `{"command":"node","args":["-e",""],"cwd":"/"}` ran that JavaScript as the user running + the orchestrator, in any directory on the host, with an attacker-chosen environment — the classic + full-host compromise, not a sandbox escape. No caller ever sent those fields (the dashboard calls + `startService(name)` with no payload, and the CLI has no equivalent), so the whole input surface + was reachable only by an attacker. `args`, `cwd` and `env` are now **derived by the server**: a + start runs the registered service's own npm start script from the root recorded in that service's + cached metadata, and the command allowlist is package managers only — `node` and `npx` are gone, + since neither can express "run this service's start script" without also expressing "run this + arbitrary program". The request body no longer contributes argv, working directory or environment + at all, which is the only shape of this endpoint that is safe to expose on a port with no + authentication. +- **The orchestrator was reachable by anything, from anywhere.** It bound every interface + (`listen(PORT)` with no host argument) and answered every origin with + `Access-Control-Allow-Origin: *`, with no authentication on any route. That turned the endpoint + above from "local privilege you already had" into two remote paths: anyone on the same LAN, VPN or + hotel Wi-Fi could POST to it directly, and **any web page you happened to visit** could do it from + your own browser — a simple JSON `POST` clears the permissive preflight, and the service name it + needs is served, unauthenticated and cross-origin, by `GET /api/services`. The listener now binds + **`127.0.0.1` by default**, and CORS defaults to loopback origins (`http://localhost`, + `http://127.0.0.1`, `http://[::1]`, any port — the Vite dev dashboard is the only cross-origin + caller a default install has), so a page on the internet gets no CORS headers and its preflight + fails before the real request is ever sent. Requests without an `Origin` — curl, the CLI, + `LssClient`, the MCP server, an AWS SDK — are not browser cross-origin requests and are + unaffected. Both halves are **deliberately widenable**, because a loopback-only stack would break + the layout LSS is actually used in — see the next bullet. Both are env-only by design: + `PUT /api/config` can set neither, because widening a boundary through the API it protects would + hand the exposure back to whoever already reached the API. +- **New: `LSS_CORS_ORIGINS`, and `LSS_BIND_HOST` now means the whole process.** Hardening the + default is only half the job; the other half is that the safe default must have a documented way + out, or people paste `--disable-web-security` into a browser flag and everyone loses. The common + real layout is *LSS in a container, browser on the host, and the developer's own frontends calling + LSS directly* — inspecting queues, hitting the emulated API Gateway, invoking Lambdas. A loopback + bind refuses the published port, and a loopback-only origin list refuses the frontend. So the + opt-in is now **one coherent line** that turns network access on everywhere at once: + `LSS_BIND_HOST=0.0.0.0 LSS_CORS_ORIGINS='*' lss start` — or, better, with the origins named: + `LSS_CORS_ORIGINS=http://localhost:5173,http://192.168.1.20:5173`. `LSS_CORS_ORIGINS` takes a + comma-separated list of exact origins (case and trailing slash forgiven, since a hand-typed env + var that silently matches nothing is the worst failure mode for a knob whose job is to unblock a + frontend) or a single `*`; unset keeps the loopback default; setting it **replaces** that default + rather than extending it. `LSS_BIND_HOST` covers **every** listener the process opens — the + orchestrator, each service's API Gateway and Lambda Invoke API port, the split-listener engine and + the DynamoDB proxy — so widening is one decision, not four, and there is no half-open state where + the dashboard is fenced and the invoke ports are not. Boot prints a single warning naming whichever + knobs were widened and how to undo them; an explicit origin list prints nothing, because naming + your callers is the outcome the variable is trying to encourage. What widening costs is now a + bounded, statable thing: an unauthenticated API on the network, where callers can read and write + your local emulator data and read secret values out of the emulated Secrets Manager. The + arbitrary-binary paths are gone in this same release — `/start` derives argv, cwd and env + server-side, `/install` is shape- and flag-allowlisted, and `packageCommand`/`packageArgs` must + match the packaging grammar — so the residual is data exposure in a local dev stack rather than a + shell on the host. It is not zero: a caller who can reach the API can still ask the project's own + build to run (`npm run - - diff --git a/examples/localstack-free/lss.config.json b/examples/localstack-free/lss.config.json deleted file mode 100644 index 6c042fe..0000000 --- a/examples/localstack-free/lss.config.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "serverPort": 3120, - "localstackPort": 4572, - "localstackEndpoint": "http://localhost:4572", - "mode": "managed", - "localstackEdition": "community", - "localstackVersion": "4.0", - "region": "sa-east-1", - "services": ["dynamodb", "sqs", "sns", "s3", "lambda", "events"], - "persistence": false, - "debug": false, - "seedsDir": "./seeds", - "stateDir": ".lss", - "autoPackage": true, - "lambdaRuntime": { - "enabled": true, - "execution": "source", - "watch": true - }, - "branding": { - "title": "LocalStack Free Sandbox", - "subtitle": "LSS + LocalStack Community — full event-driven stack", - "logo": "./assets/logo.svg", - "favicon": "./assets/logo.svg", - "defaultTheme": "dark", - "colors": { - "brand-primary": "#7c3aed", - "brand-hover": "#6d28d9", - "brand-soft": "#ede9fe" - } - } -} diff --git a/examples/localstack-free/orders-service/package-lock.json b/examples/localstack-free/orders-service/package-lock.json deleted file mode 100644 index 96789d7..0000000 --- a/examples/localstack-free/orders-service/package-lock.json +++ /dev/null @@ -1,2800 +0,0 @@ -{ - "name": "orders-service-example", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "orders-service-example", - "version": "0.0.0", - "dependencies": { - "@aws-sdk/client-dynamodb": "^3.0.0", - "@aws-sdk/client-s3": "^3.0.0", - "@aws-sdk/client-sns": "^3.0.0", - "@aws-sdk/client-sqs": "^3.0.0", - "@aws-sdk/lib-dynamodb": "^3.0.0", - "@aws-sdk/util-dynamodb": "^3.0.0" - }, - "devDependencies": { - "dotenv-cli": "^7.4.4", - "osls": "4.0.0", - "serverless-lss": "file:../../../packages/serverless-plugin" - } - }, - "../../../packages/serverless-plugin": { - "name": "serverless-lss", - "version": "0.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2" - }, - "devDependencies": { - "@types/node": "^22.10.5", - "typescript": "^5.7.3" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "osls": "4.0.0" - }, - "peerDependenciesMeta": { - "osls": { - "optional": true - } - } - }, - "node_modules/@apidevtools/json-schema-ref-parser": { - "version": "15.5.0", - "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-15.5.0.tgz", - "integrity": "sha512-Ps4w0FwrDoeVK6hfYxWkVbkmxm+zN+6xoXF2ZfEhfiox0ZNbcSAiUWO6iAIvP5bc3DB270r+EaKcoT1IUyzfxw==", - "dev": true, - "license": "MIT", - "dependencies": { - "js-yaml": "^4.2.0" - }, - "engines": { - "node": ">=20" - }, - "peerDependencies": { - "@types/json-schema": "^7.0.15" - } - }, - "node_modules/@aws-sdk/checksums": { - "version": "3.1000.16", - "resolved": "https://registry.npmjs.org/@aws-sdk/checksums/-/checksums-3.1000.16.tgz", - "integrity": "sha512-EKnvkXSmz3IpA99tCNuI+dLFXyZyClSm8zns9sB/elvkU+MTuomAs6toJMPMBf98/fICG/urXDkzGz0/c3yyAQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-api-gateway": { - "version": "3.1081.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-api-gateway/-/client-api-gateway-3.1081.0.tgz", - "integrity": "sha512-uKUrTUNc0VaVMslK/vJ6qg4LBnynHnvb9pu7gLtFe06+g4rT2IseJWed6xrdfa0t8iSW00rrLoTVbHNEukjETg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.974.29", - "@aws-sdk/credential-provider-node": "^3.972.64", - "@aws-sdk/middleware-sdk-api-gateway": "^3.972.21", - "@aws-sdk/types": "^3.973.15", - "@smithy/core": "^3.29.0", - "@smithy/fetch-http-handler": "^5.6.2", - "@smithy/node-http-handler": "^4.9.2", - "@smithy/types": "^4.15.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-apigatewayv2": { - "version": "3.1085.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-apigatewayv2/-/client-apigatewayv2-3.1085.0.tgz", - "integrity": "sha512-IeDwKOit9IndGVNOcEAAIxwj5z+YhX4aGVNXU+C0sZvALnSOI83rGMekPGxGrZf6tDxpmwtIrSm6qYWPbFkNXA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/credential-provider-node": "^3.972.66", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/fetch-http-handler": "^5.6.4", - "@smithy/node-http-handler": "^4.9.4", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudformation": { - "version": "3.1081.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudformation/-/client-cloudformation-3.1081.0.tgz", - "integrity": "sha512-i+lK0BnbX8JdFI/7HV/JY6XmrZsEmmLffuJRyn+J+gP9zzAiNOdraOnMi0eVcJE8CraTt5fixyxBO8AalFW8rw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.974.29", - "@aws-sdk/credential-provider-node": "^3.972.64", - "@aws-sdk/types": "^3.973.15", - "@smithy/core": "^3.29.0", - "@smithy/fetch-http-handler": "^5.6.2", - "@smithy/node-http-handler": "^4.9.2", - "@smithy/types": "^4.15.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch": { - "version": "3.1085.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudwatch/-/client-cloudwatch-3.1085.0.tgz", - "integrity": "sha512-2WyjUH6zdRvPSvL/8JJYo6BJfK4hNn9RA3+3XEfPczQ/uYxhFfIR8hbNIrRQe7ffb9X8CCxN6YpSQtw8iXQboA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/credential-provider-node": "^3.972.66", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/fetch-http-handler": "^5.6.4", - "@smithy/middleware-compression": "^4.5.7", - "@smithy/node-http-handler": "^4.9.4", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs": { - "version": "3.1085.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudwatch-logs/-/client-cloudwatch-logs-3.1085.0.tgz", - "integrity": "sha512-jNMt5zMsnJ6X0fZJKKNU5/qTQ98OIsUSFLqDh+FTXQTiEI3NTq95gAdsaAwXVWO9hTaT5gY7fbwF5Ally69bwg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/credential-provider-node": "^3.972.66", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/fetch-http-handler": "^5.6.4", - "@smithy/node-http-handler": "^4.9.4", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity": { - "version": "3.1081.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.1081.0.tgz", - "integrity": "sha512-ipDgvZ3Hy8kaFrkwj62yuoghKkZi5WrWTiJnaqGc/ntbuAuijIkRWhzSb8d1MGEE+qb+vFFTrWVFwGSqt76TCA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.974.29", - "@aws-sdk/credential-provider-node": "^3.972.64", - "@aws-sdk/types": "^3.973.15", - "@smithy/core": "^3.29.0", - "@smithy/fetch-http-handler": "^5.6.2", - "@smithy/node-http-handler": "^4.9.2", - "@smithy/types": "^4.15.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity-provider": { - "version": "3.1081.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity-provider/-/client-cognito-identity-provider-3.1081.0.tgz", - "integrity": "sha512-uBvMQ2gLiNphTjmZKHz0WAq4mESC9OCngmzE4FJSVnm6bjUZMWSBU4rJCEjYh/gzZ5BLRk1TV1BzTdMuU78kFQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.974.29", - "@aws-sdk/credential-provider-node": "^3.972.64", - "@aws-sdk/types": "^3.973.15", - "@smithy/core": "^3.29.0", - "@smithy/fetch-http-handler": "^5.6.2", - "@smithy/node-http-handler": "^4.9.2", - "@smithy/types": "^4.15.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-dynamodb": { - "version": "3.1081.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.1081.0.tgz", - "integrity": "sha512-gQ2XvMVY+5Co6znCODeCuLVaGRPKTeRQ+lATsw4Cm4/v+HHVQ3OJacE3wwO5FRg7shgYswOTusPM5icLEzsv9w==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.974.29", - "@aws-sdk/credential-provider-node": "^3.972.64", - "@aws-sdk/dynamodb-codec": "^3.973.29", - "@aws-sdk/middleware-endpoint-discovery": "^3.972.22", - "@aws-sdk/types": "^3.973.15", - "@smithy/core": "^3.29.0", - "@smithy/fetch-http-handler": "^5.6.2", - "@smithy/node-http-handler": "^4.9.2", - "@smithy/types": "^4.15.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-ecr": { - "version": "3.1085.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-ecr/-/client-ecr-3.1085.0.tgz", - "integrity": "sha512-I1MWQNb01MlfC2MENTll+GrRV2RSGmkQSyB289CEY2QGf4ImqeEsySWFtpau/39zqTxqOyx/jfXrT5vdr3hOyQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/credential-provider-node": "^3.972.66", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/fetch-http-handler": "^5.6.4", - "@smithy/node-http-handler": "^4.9.4", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-eventbridge": { - "version": "3.1081.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-eventbridge/-/client-eventbridge-3.1081.0.tgz", - "integrity": "sha512-yfApvz19TIF27sZqnhYr/jGbMF2sg4r0L2HEbKzM+KqLFdqE8um/IDBgbEL++WDr4qtGIRL9OodoyFKbhAfNyg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.974.29", - "@aws-sdk/credential-provider-node": "^3.972.64", - "@aws-sdk/signature-v4-multi-region": "^3.996.38", - "@aws-sdk/types": "^3.973.15", - "@smithy/core": "^3.29.0", - "@smithy/fetch-http-handler": "^5.6.2", - "@smithy/node-http-handler": "^4.9.2", - "@smithy/types": "^4.15.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-iam": { - "version": "3.1081.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-iam/-/client-iam-3.1081.0.tgz", - "integrity": "sha512-PR9jz6r6+inwSHrdwI9O4Vgolkd6+lTQ+H+YS2s4uyC2J8FGUDMCJO40ycszcvy8o8EWwFS/ACA/HotY+OAHLQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.974.29", - "@aws-sdk/credential-provider-node": "^3.972.64", - "@aws-sdk/types": "^3.973.15", - "@smithy/core": "^3.29.0", - "@smithy/fetch-http-handler": "^5.6.2", - "@smithy/node-http-handler": "^4.9.2", - "@smithy/types": "^4.15.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-lambda": { - "version": "3.1081.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.1081.0.tgz", - "integrity": "sha512-DlFiHPVHQsGz+2Zyli25tA4SQW1xPggko/lZMCsFwxzXeTyoW4X+EHkcRul1K7Z/Rf2zpGnwZWS+PWZYTFRaSw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.974.29", - "@aws-sdk/credential-provider-node": "^3.972.64", - "@aws-sdk/types": "^3.973.15", - "@smithy/core": "^3.29.0", - "@smithy/fetch-http-handler": "^5.6.2", - "@smithy/node-http-handler": "^4.9.2", - "@smithy/types": "^4.15.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-s3": { - "version": "3.1085.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.1085.0.tgz", - "integrity": "sha512-O0xe8sR50AYkwxlvRRsV0qytEO2dtXQTQ1CF3YBBdE5xtVkbu27H0vGa1mjQi1/+fbYM80AWEIPai5jZmXyubw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/checksums": "^3.1000.16", - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/credential-provider-node": "^3.972.66", - "@aws-sdk/middleware-sdk-s3": "^3.972.62", - "@aws-sdk/signature-v4-multi-region": "^3.996.39", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/fetch-http-handler": "^5.6.4", - "@smithy/node-http-handler": "^4.9.4", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-sns": { - "version": "3.1085.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sns/-/client-sns-3.1085.0.tgz", - "integrity": "sha512-F9AOKvav/zv8uukLXSgqG/EQErB/UMEahadT47iWqAWa0FahvxcchnzthN8kECoBCTsUn16N/1+wSvGTgJ9hWQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/credential-provider-node": "^3.972.66", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/fetch-http-handler": "^5.6.4", - "@smithy/node-http-handler": "^4.9.4", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-sqs": { - "version": "3.1081.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sqs/-/client-sqs-3.1081.0.tgz", - "integrity": "sha512-mfUL0RBECAesJTA8JfXcFUg3ve/E6ztSEsewBC3tfuFR3aFAgXOiIqDUmntzQoLxf5LabdAyXv5Uu6seC0jjYQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.974.29", - "@aws-sdk/credential-provider-node": "^3.972.64", - "@aws-sdk/middleware-sdk-sqs": "^3.972.34", - "@aws-sdk/types": "^3.973.15", - "@smithy/core": "^3.29.0", - "@smithy/fetch-http-handler": "^5.6.2", - "@smithy/node-http-handler": "^4.9.2", - "@smithy/types": "^4.15.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-ssm": { - "version": "3.1085.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-ssm/-/client-ssm-3.1085.0.tgz", - "integrity": "sha512-vFYFncOReqEtOj110hdTQK/4JzNEHdVR90Ob6FjdEeb8cNer+HShI64Nuw9J4gTUQAWJ0eErHZqqxQPTViplew==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/credential-provider-node": "^3.972.66", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/fetch-http-handler": "^5.6.4", - "@smithy/node-http-handler": "^4.9.4", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-sts": { - "version": "3.1081.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.1081.0.tgz", - "integrity": "sha512-URSoqhxMGf4Mv6MMyR6pcerTjbVKKqKLU7GGpZddxiOJ/Ca1qeUz3hvjuF2m/AMaw3e28bUdMvo7ZDh3aMX/ig==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.974.29", - "@aws-sdk/credential-provider-node": "^3.972.64", - "@aws-sdk/signature-v4-multi-region": "^3.996.38", - "@aws-sdk/types": "^3.973.15", - "@smithy/core": "^3.29.0", - "@smithy/fetch-http-handler": "^5.6.2", - "@smithy/node-http-handler": "^4.9.2", - "@smithy/types": "^4.15.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/core": { - "version": "3.975.1", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.975.1.tgz", - "integrity": "sha512-8qh/6EYb7hl/ZwVfQufhbMEZs1gQIc7GbdrIf4eprQJ7cv042+74nE6l3YDfyWNzb9iPXb8fRyYSHkNIk5eE6Q==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "^3.974.0", - "@aws-sdk/xml-builder": "^3.972.34", - "@aws/lambda-invoke-store": "^0.3.0", - "@smithy/core": "^3.29.2", - "@smithy/signature-v4": "^5.6.3", - "@smithy/types": "^4.16.0", - "bowser": "^2.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-cognito-identity": { - "version": "3.972.56", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.972.56.tgz", - "integrity": "sha512-nedaZz6Wz2FGUBMsWhlvBPGIkTMfRuMJ99YDHJI4CaC31JS8WPyTavEAio74cfd5nGhi0A8XASB4fZA5VqTdOQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/nested-clients": "^3.997.31", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.972.57", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.57.tgz", - "integrity": "sha512-1RfJaF7SW1TOnvNGU7kaYjwUf5H3sfm+synGH1bHhRlqcnxCt3szebH3dmKEyY4tuGcbQ6ffzUT89cRitBV8OQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.972.59", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.59.tgz", - "integrity": "sha512-sRCkpTiFnCdQvuaRVjQ6SVoHu6i7RUpurVo1c4F81HWhPvUJ7Wdp5MNtSdX1O29CNXc8em3O5m52hCjVtAD9SA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/fetch-http-handler": "^5.6.4", - "@smithy/node-http-handler": "^4.9.4", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.973.1", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.973.1.tgz", - "integrity": "sha512-6d8H6ZAh3ZPKZ6fe1nG2OWeZEZPtt9ravoD1dezPdPtsSkJRoxGAnFSHwKT3E/Te6fHE30zRzjV6TD12rvF6yQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/credential-provider-env": "^3.972.57", - "@aws-sdk/credential-provider-http": "^3.972.59", - "@aws-sdk/credential-provider-login": "^3.972.63", - "@aws-sdk/credential-provider-process": "^3.972.57", - "@aws-sdk/credential-provider-sso": "^3.973.1", - "@aws-sdk/credential-provider-web-identity": "^3.972.63", - "@aws-sdk/nested-clients": "^3.997.31", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/credential-provider-imds": "^4.4.7", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-login": { - "version": "3.972.63", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.63.tgz", - "integrity": "sha512-GREWRrMj0XnNKMaVa/Mauoaui26qBEHu71WWqXbwZOu/jFQOnPZjTf7u0KtGKC8VGa6VUs9kDWGgocrKNLS9vw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/nested-clients": "^3.997.31", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.972.66", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.66.tgz", - "integrity": "sha512-f+qjRXZpz7sgzbc4QB+6nLKfyKFgRRXzWdXbsKPv/VhVRyHsDyq4yBWC/B75BAJpFIcUeI2XR/3gdWJ677zB4A==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/credential-provider-env": "^3.972.57", - "@aws-sdk/credential-provider-http": "^3.972.59", - "@aws-sdk/credential-provider-ini": "^3.973.1", - "@aws-sdk/credential-provider-process": "^3.972.57", - "@aws-sdk/credential-provider-sso": "^3.973.1", - "@aws-sdk/credential-provider-web-identity": "^3.972.63", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/credential-provider-imds": "^4.4.7", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.972.57", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.57.tgz", - "integrity": "sha512-TiVQhuU0pbhIZAUZacbPHMyzrIdiH+lnx+PMY/Pu/b93dJrq3wdZwzUJ0TPpvNxaqbHsxJvQZW3/h/beLiKq7Q==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.973.1", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.973.1.tgz", - "integrity": "sha512-3foTZUJ4821Ij60X7K3NJroygiZLnbBmarN+T//O2cjkISan90zElN3NBmgSlDrTQ7Gs6z/yO8V7h60QNcDZHQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/nested-clients": "^3.997.31", - "@aws-sdk/token-providers": "3.1083.0", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.972.63", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.63.tgz", - "integrity": "sha512-8qZLFhM69eKcS37m459ctPR05Qimycm/74OPVioe6wNZabMT54GYhwBju0+J656RkMasNSawWQu+c8CmBe3TUQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/nested-clients": "^3.997.31", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers": { - "version": "3.1081.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.1081.0.tgz", - "integrity": "sha512-UHWvxd1F5nfBXBRXtQaXWoNT8CYKXZovLQOyz6XZlgFTGc2mWzzPGspOfnh49jwvB2qzsdH046i9jnnmND+64w==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/client-cognito-identity": "3.1081.0", - "@aws-sdk/core": "^3.974.29", - "@aws-sdk/credential-provider-cognito-identity": "^3.972.54", - "@aws-sdk/credential-provider-env": "^3.972.55", - "@aws-sdk/credential-provider-http": "^3.972.57", - "@aws-sdk/credential-provider-ini": "^3.972.62", - "@aws-sdk/credential-provider-login": "^3.972.61", - "@aws-sdk/credential-provider-node": "^3.972.64", - "@aws-sdk/credential-provider-process": "^3.972.55", - "@aws-sdk/credential-provider-sso": "^3.972.61", - "@aws-sdk/credential-provider-web-identity": "^3.972.61", - "@aws-sdk/nested-clients": "^3.997.29", - "@aws-sdk/types": "^3.973.15", - "@smithy/core": "^3.29.0", - "@smithy/credential-provider-imds": "^4.4.5", - "@smithy/types": "^4.15.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/dynamodb-codec": { - "version": "3.973.29", - "resolved": "https://registry.npmjs.org/@aws-sdk/dynamodb-codec/-/dynamodb-codec-3.973.29.tgz", - "integrity": "sha512-1Eprv8BD2cOsVccCpEGm+hyZzj3LjthLoDOXHuvH6Vz8GJPZWknrmn05kICyZpx7srfe/KOm4GQXrJgXkPUJuA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.974.29", - "@smithy/core": "^3.29.0", - "@smithy/types": "^4.15.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/endpoint-cache": { - "version": "3.972.8", - "resolved": "https://registry.npmjs.org/@aws-sdk/endpoint-cache/-/endpoint-cache-3.972.8.tgz", - "integrity": "sha512-bBmkG0Dnhfq0/T4Z0PpUr7HkncBVaWvvCbvafeaUM+yC9wa8GGjLJmonq0QL17REB9WivgGeYgWQ5A80Uw5UnQ==", - "license": "Apache-2.0", - "dependencies": { - "mnemonist": "0.38.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/lib-dynamodb": { - "version": "3.1081.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/lib-dynamodb/-/lib-dynamodb-3.1081.0.tgz", - "integrity": "sha512-o9hjLKJBhjspX52P9vIngEsr12YNyBzfiVbmPHQhrgOEN3BGZjd0wa9ufRzHF2jygFZak66dlPx5AeK+4qI/eg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.974.29", - "@aws-sdk/util-dynamodb": "^3.996.5", - "@smithy/core": "^3.29.0", - "@smithy/types": "^4.15.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-dynamodb": "^3.1081.0" - } - }, - "node_modules/@aws-sdk/lib-storage": { - "version": "3.1085.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.1085.0.tgz", - "integrity": "sha512-S+yCGIMxQ5Zs2A5ZDdYfXwOxu5kKjBaCQVOxp6+mnwCQYXUNkBD/aKCnW1eniMTavzz3YidhD5eTFpDlcUv2gQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.29.2", - "@smithy/types": "^4.16.0", - "buffer": "5.6.0", - "events": "3.3.0", - "stream-browserify": "3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-s3": "^3.1085.0" - } - }, - "node_modules/@aws-sdk/lib-storage/node_modules/buffer": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", - "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", - "dev": true, - "license": "MIT", - "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - }, - "node_modules/@aws-sdk/lib-storage/node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/@aws-sdk/middleware-endpoint-discovery": { - "version": "3.972.22", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.972.22.tgz", - "integrity": "sha512-GMoLg4XAnkiwevqcOfgz0lOTYmIdM7MJK/BL9EAvsoMFqKIGRpyNIvuSNg5gdFzP57yB+EklMlK0+TwBqj1tCg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/endpoint-cache": "^3.972.8", - "@aws-sdk/types": "^3.973.15", - "@smithy/core": "^3.29.0", - "@smithy/types": "^4.15.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/middleware-sdk-api-gateway": { - "version": "3.972.21", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-api-gateway/-/middleware-sdk-api-gateway-3.972.21.tgz", - "integrity": "sha512-tlu8JAcbrhh4jnoQXczWQ2QIOaev3ZdVBdU4RRaNBfJmVyuBbMKdh6mdrunEdSFgm2GlJW1lIhE4BHTL0A55dw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "^3.973.15", - "@smithy/core": "^3.29.0", - "@smithy/types": "^4.15.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/middleware-sdk-s3": { - "version": "3.972.62", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.972.62.tgz", - "integrity": "sha512-k8JJwYXVYlOOjWnPZDThQS1xDFJgi5Dokt73qFlDtrZAbdcint5aIdjB9XgJAAQVP5OoqcefQmh1FYXiPpvsvw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/signature-v4-multi-region": "^3.996.39", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/middleware-sdk-sqs": { - "version": "3.972.34", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sqs/-/middleware-sdk-sqs-3.972.34.tgz", - "integrity": "sha512-BgCMs873RWtMe8LlNY5hxJjVbZtaHR6nY3BtQZk14drRJb3Iqecp5VADpw3eF5cnBvlZLWblAjCjJFU1mTjoeQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "^3.973.15", - "@smithy/core": "^3.29.0", - "@smithy/types": "^4.15.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/nested-clients": { - "version": "3.997.31", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.997.31.tgz", - "integrity": "sha512-BDHTpwcsZHEBNEJzOg/B1BkFYJxAXY50dau/NyVWs3d51F0WgIUGSWZot/Os+N3KpDhXeaXnz37mWffAvduREw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/signature-v4-multi-region": "^3.996.39", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/fetch-http-handler": "^5.6.4", - "@smithy/node-http-handler": "^4.9.4", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/signature-v4-multi-region": { - "version": "3.996.39", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.39.tgz", - "integrity": "sha512-8+srXqYIF8KYMLC4FxMLEM5Ek7kUNibJu1R4m8/fUhhNYIZZz26oGtKkCr8I/HiG2fFQxBvaGgQZT4/mqRCSnA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "^3.974.0", - "@smithy/signature-v4": "^5.6.3", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/token-providers": { - "version": "3.1083.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1083.0.tgz", - "integrity": "sha512-s0woKnxuHrExLc5L2ArIH5BMkbonHPtt+5hSBM8oknp9M6QTuUmmAmJ2E0EdzCGONrO+8+ADPqvv6UX0nNcc7A==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/nested-clients": "^3.997.31", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/types": { - "version": "3.974.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.974.0.tgz", - "integrity": "sha512-QIBrw90CDm4O0UaIIzkU6DrFdeJzEb2Va5EPEVpyldj6sHJxB6cshhStJuhZxk3wR3PmjJlYsjPmY1kNb+KGBg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/util-dynamodb": { - "version": "3.996.5", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-dynamodb/-/util-dynamodb-3.996.5.tgz", - "integrity": "sha512-m9bdmYq3WtbMHAKGALw9XWiMBfKu5T8ukgdJT7Mc/d2oOwDGNFmhsnnkQ18xomoXo/ZHxAuIDi3Y6slsblW1Mg==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-dynamodb": "^3.1069.0" - } - }, - "node_modules/@aws-sdk/xml-builder": { - "version": "3.972.34", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.34.tgz", - "integrity": "sha512-wHhWL1y7sN3enBA8POrPpQM5jCcmu2ozyhbRei4c8OjVcEaEs6yLucLa/pla457ggS/ysuy7bosagz3HaJkZXA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws/lambda-invoke-store": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.3.0.tgz", - "integrity": "sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", - "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", - "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", - "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", - "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", - "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", - "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", - "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", - "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", - "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", - "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", - "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", - "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", - "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", - "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", - "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", - "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", - "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", - "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", - "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", - "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", - "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", - "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", - "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", - "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", - "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", - "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@smithy/core": { - "version": "3.29.3", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.29.3.tgz", - "integrity": "sha512-L+Ys6ecjk5vwPMAKHBpPKlJ3DkqwNcnfEISXBZIsVvWG/XKXfsAP8mwIYlTeLcd2ElHdesPI8OuOmJSFAPhm6A==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/credential-provider-imds": { - "version": "4.4.7", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.4.7.tgz", - "integrity": "sha512-UEMLOoA0Fl4uYBxh6l0uN0H6EJe/A89OGeDNTteQeXpJ20BcpfIr4wlCY9pel1jEAUHAxaYwuqrYlrKdXE1GKQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.29.2", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/fetch-http-handler": { - "version": "5.6.4", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.6.4.tgz", - "integrity": "sha512-psnst7NZWdAEvJvyW8YZEE7xNVMyLrQFfHtyrVFrxNyy+dKWkQ+rqC6oI5ZhxThpUy9RSfEshgm34zqbOxzsRw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.29.2", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-compression": { - "version": "4.5.8", - "resolved": "https://registry.npmjs.org/@smithy/middleware-compression/-/middleware-compression-4.5.8.tgz", - "integrity": "sha512-ODHXD5tDW3+25pfiLjJ2ZTIHRfWWxqVGPqIMz1NjmiV4bG4i1S0kuibHxik6WXibR03nmDGMiI1/hF6647F/Zg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.29.3", - "@smithy/types": "^4.16.1", - "fflate": "0.8.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/node-http-handler": { - "version": "4.9.4", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.9.4.tgz", - "integrity": "sha512-BNTop/fSOptmoVk8g+efwHCofFh37g70OWGAFES1TeAAJja1K5aAI8rTE26ETSc5k8IQuWY2kAIoPla01NgYrA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.29.2", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/signature-v4": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.6.3.tgz", - "integrity": "sha512-8qVKKzqh7naF27ePmx0SkUfnGP/wBI9dyaeAmhHvopnbIlItUAmB/e6PkPCU3rRb2v9BY8D4EZXSoydSibatvw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.29.2", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/types": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.16.1.tgz", - "integrity": "sha512-0JFs3V2y2M9tKW5na/qxe69Zv+uxLMO7QBbhxF/FHu/Gp2NFZAAL9tWl9PU02xxo07pb3G9FTyjNc6D5uZrJIg==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/ajv": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", - "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/bowser": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.14.1.tgz", - "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==", - "license": "MIT" - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-color": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.4.tgz", - "integrity": "sha512-zlnpg0jNcibNrO7GG9IeHH7maWFeCz+Ja1wx/7tZNU5ASSSSZ+/qZciM0/LHCYxSdqv5h2sdbQ/PXYdOuetXvA==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "^1.0.1", - "es5-ext": "^0.10.64", - "es6-iterator": "^2.0.3", - "memoizee": "^0.4.15", - "timers-ext": "^0.1.7" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/cli-sprintf-format": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cli-sprintf-format/-/cli-sprintf-format-1.1.1.tgz", - "integrity": "sha512-BbEjY9BEdA6wagVwTqPvmAwGB24U93rQPBFZUT8lNCDxXzre5LFHQUTJc70czjgUomVg8u8R5kW8oY9DYRFNeg==", - "dev": true, - "license": "ISC", - "dependencies": { - "cli-color": "^2.0.1", - "es5-ext": "^0.10.53", - "sprintf-kit": "^2.0.1", - "supports-color": "^6.1.0" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/cli-sprintf-format/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/cli-sprintf-format/node_modules/supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/d": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", - "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", - "dev": true, - "license": "ISC", - "dependencies": { - "es5-ext": "^0.10.64", - "type": "^2.7.2" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/dotenv": { - "version": "16.6.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/dotenv-cli": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/dotenv-cli/-/dotenv-cli-7.4.4.tgz", - "integrity": "sha512-XkBYCG0tPIes+YZr4SpfFv76SQrV/LeCE8CI7JSEMi3VR9MvTihCGTOtbIexD6i2mXF+6px7trb1imVCXSNMDw==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.6", - "dotenv": "^16.3.0", - "dotenv-expand": "^10.0.0", - "minimist": "^1.2.6" - }, - "bin": { - "dotenv": "cli.js" - } - }, - "node_modules/dotenv-expand": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", - "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - } - }, - "node_modules/duration": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/duration/-/duration-0.2.2.tgz", - "integrity": "sha512-06kgtea+bGreF5eKYgI/36A6pLXggY7oR4p1pq4SmdFBn1ReOL5D8RhG64VrqfTTKNucqqtBAwEj8aB88mcqrg==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "1", - "es5-ext": "~0.10.46" - } - }, - "node_modules/es5-ext": { - "version": "0.10.64", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", - "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", - "dev": true, - "hasInstallScript": true, - "license": "ISC", - "dependencies": { - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.3", - "esniff": "^2.0.1", - "next-tick": "^1.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", - "dev": true, - "license": "MIT", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-symbol": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", - "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "^1.0.2", - "ext": "^1.7.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/esbuild": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", - "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.28.1", - "@esbuild/android-arm": "0.28.1", - "@esbuild/android-arm64": "0.28.1", - "@esbuild/android-x64": "0.28.1", - "@esbuild/darwin-arm64": "0.28.1", - "@esbuild/darwin-x64": "0.28.1", - "@esbuild/freebsd-arm64": "0.28.1", - "@esbuild/freebsd-x64": "0.28.1", - "@esbuild/linux-arm": "0.28.1", - "@esbuild/linux-arm64": "0.28.1", - "@esbuild/linux-ia32": "0.28.1", - "@esbuild/linux-loong64": "0.28.1", - "@esbuild/linux-mips64el": "0.28.1", - "@esbuild/linux-ppc64": "0.28.1", - "@esbuild/linux-riscv64": "0.28.1", - "@esbuild/linux-s390x": "0.28.1", - "@esbuild/linux-x64": "0.28.1", - "@esbuild/netbsd-arm64": "0.28.1", - "@esbuild/netbsd-x64": "0.28.1", - "@esbuild/openbsd-arm64": "0.28.1", - "@esbuild/openbsd-x64": "0.28.1", - "@esbuild/openharmony-arm64": "0.28.1", - "@esbuild/sunos-x64": "0.28.1", - "@esbuild/win32-arm64": "0.28.1", - "@esbuild/win32-ia32": "0.28.1", - "@esbuild/win32-x64": "0.28.1" - } - }, - "node_modules/esniff": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", - "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "^1.0.1", - "es5-ext": "^0.10.62", - "event-emitter": "^0.3.5", - "type": "^2.7.2" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "node_modules/ext": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", - "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", - "dev": true, - "license": "ISC", - "dependencies": { - "type": "^2.7.2" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-uri": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.3.tgz", - "integrity": "sha512-i70LwGWUduXqzicKXWshooq+sWL1K3WUU5rKZNG/0i3a1OSoX3HqhH5WbWwTmqWfor4urUakGPiRQcleRZTwOg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4.9.1" - } - }, - "node_modules/fastq": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", - "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fflate": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.1.tgz", - "integrity": "sha512-/exOvEuc+/iaUm105QIiOt4LpBdMTWsXxqR0HDF35vx3fmaKzw7354gTilCh5rkzEt8WYyG//ku3h3nRmd7CHQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/js-yaml": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", - "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/puzrin" - }, - { - "type": "github", - "url": "https://github.com/sponsors/nodeca" - } - ], - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-cycle": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/json-cycle/-/json-cycle-1.5.0.tgz", - "integrity": "sha512-GOehvd5PO2FeZ5T4c+RxobeT5a1PiGpF4u9/3+UvrMU4bhnVqzJY7hm39wg8PDCqkU91fWGH8qjWR4bn+wgq9w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "license": "MIT" - }, - "node_modules/log": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/log/-/log-6.3.2.tgz", - "integrity": "sha512-ek8NRg/OPvS9ISOJNWNAz5vZcpYacWNFDWNJjj5OXsc6YuKacfey6wF04cXz/tOJIVrZ2nGSkHpAY5qKtF6ISg==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "^1.0.2", - "duration": "^0.2.2", - "es5-ext": "^0.10.64", - "event-emitter": "^0.3.5", - "sprintf-kit": "^2.0.2", - "type": "^2.7.3", - "uni-global": "^1.0.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/log-node": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/log-node/-/log-node-8.0.3.tgz", - "integrity": "sha512-1UBwzgYiCIDFs8A0rM2QdBFo8Wd8UQ0HrSTu/MNI+/2zN3NoHRj2fhplurAyuxTYUXu3Oohugq1jAn5s05u1MQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "ansi-regex": "^5.0.1", - "cli-color": "^2.0.1", - "cli-sprintf-format": "^1.1.1", - "d": "^1.0.1", - "es5-ext": "^0.10.53", - "sprintf-kit": "^2.0.1", - "supports-color": "^8.1.1", - "type": "^2.5.0" - }, - "engines": { - "node": ">=10.0" - }, - "peerDependencies": { - "log": "^6.0.0" - } - }, - "node_modules/lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "es5-ext": "~0.10.2" - } - }, - "node_modules/memoizee": { - "version": "0.4.17", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.17.tgz", - "integrity": "sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "^1.0.2", - "es5-ext": "^0.10.64", - "es6-weak-map": "^2.0.3", - "event-emitter": "^0.3.5", - "is-promise": "^2.2.2", - "lru-queue": "^0.1.0", - "next-tick": "^1.1.0", - "timers-ext": "^0.1.7" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/mnemonist": { - "version": "0.38.3", - "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.3.tgz", - "integrity": "sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw==", - "license": "MIT", - "dependencies": { - "obliterator": "^1.6.1" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/obliterator": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-1.6.1.tgz", - "integrity": "sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig==", - "license": "MIT" - }, - "node_modules/osls": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/osls/-/osls-4.0.0.tgz", - "integrity": "sha512-ti1s4IhJLfpdWtgyb3gj8slDs1KoucRU0jNyqGIaEGPGCODiJtFXXVM3cs52pQLi3Ig2RBeqHzhD84vWOLvSeQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@apidevtools/json-schema-ref-parser": "^15.3.5", - "@aws-sdk/client-api-gateway": "^3.1034.0", - "@aws-sdk/client-apigatewayv2": "^3.1034.0", - "@aws-sdk/client-cloudformation": "^3.1034.0", - "@aws-sdk/client-cloudwatch": "^3.1034.0", - "@aws-sdk/client-cloudwatch-logs": "^3.1034.0", - "@aws-sdk/client-cognito-identity-provider": "^3.1034.0", - "@aws-sdk/client-ecr": "^3.1034.0", - "@aws-sdk/client-eventbridge": "^3.1034.0", - "@aws-sdk/client-iam": "^3.1034.0", - "@aws-sdk/client-lambda": "^3.1034.0", - "@aws-sdk/client-s3": "^3.1034.0", - "@aws-sdk/client-ssm": "^3.1034.0", - "@aws-sdk/client-sts": "^3.1034.0", - "@aws-sdk/credential-providers": "^3.1034.0", - "@aws-sdk/lib-storage": "^3.1034.0", - "@smithy/core": "^3.23.16", - "@smithy/node-http-handler": "^4.6.1", - "ajv": "^8.12.0", - "ajv-formats": "^3.0.1", - "content-disposition": "^2.0.1", - "cross-spawn": "^7.0.6", - "dotenv": "^17.4.2", - "dotenv-expand": "^13.0.0", - "ext": "^1.7.0", - "fast-glob": "^3.3.3", - "fastest-levenshtein": "^1.0.16", - "filenamify": "^7.0.1", - "https-proxy-agent": "^9.0.0", - "js-yaml": "^4.3.0", - "json-cycle": "^1.5.0", - "log": "^6.3.1", - "log-node": "^8.0.3", - "memoizee": "^0.4.15", - "micromatch": "^4.0.5", - "mime-types": "^3.0.2", - "semver": "^7.5.3", - "signal-exit": "^4.1.0", - "tsx": "^4.20.3", - "type": "^2.7.2", - "undici": "^7.25.0", - "write-file-atomic": "^7.0.1", - "yauzl": "^3.3.0", - "yazl": "^3.3.1" - }, - "bin": { - "osls": "bin/serverless.js", - "serverless": "bin/serverless.js", - "sls": "bin/serverless.js" - }, - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - } - }, - "node_modules/osls/node_modules/agent-base": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-9.0.0.tgz", - "integrity": "sha512-TQf59BsZnytt8GdJKLPfUZ54g/iaUL2OWDSFCCvMOhsHduDQxO8xC4PNeyIkVcA5KwL2phPSv0douC0fgWzmnA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 20" - } - }, - "node_modules/osls/node_modules/ajv-formats": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", - "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/osls/node_modules/content-disposition": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-2.0.1.tgz", - "integrity": "sha512-e+H0ZXHSWYrENhQzw1LPuP4oF5MzVKmDU6d3hxlvaPEYLLg62MxtQNPRx4SYSuYJSBUgnQIG4HIN2tEtNv7Dog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/osls/node_modules/dotenv": { - "version": "17.4.2", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz", - "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/osls/node_modules/dotenv-expand": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-13.0.0.tgz", - "integrity": "sha512-aBfBS8eYIeXmpHI9ThIlA7/WLq+SLt18iXUZhb52rW89QLKQFoIpPG1bPeewoPZsTyjSSO3T7234FBVUM1V2rA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "dotenv": "^17.4.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/osls/node_modules/filename-reserved-regex": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-4.0.0.tgz", - "integrity": "sha512-9ZT504KxEQDamsOogZImAWGEN24R1uFAxU3ZS4AZqn2ooidmN68Olh7n4/RcA4lLatZztjA0ZSuxeLHVoCc8JA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/osls/node_modules/filenamify": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-7.0.2.tgz", - "integrity": "sha512-fz10TUqSZ1lG7ftW1KnRotJzMD8YRb6kaAQKpZJBLvqXXfFgIEpuazy1w2lK3zhMiBSdH/uF9LFlv5smJ2Jl1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "filename-reserved-regex": "^4.0.0" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/osls/node_modules/https-proxy-agent": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-9.1.0.tgz", - "integrity": "sha512-ag87y7cJJ9/3+GxFr8Oy4O5faDsGRGnBGsJj/YjOSsSx/5eadKLYTMPlzuR6obgoCDDm0abAAZitXXQkMOPSpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "9.0.0", - "debug": "^4.3.4", - "proxy-agent-negotiate": "1.1.0" - }, - "engines": { - "node": ">= 20" - } - }, - "node_modules/osls/node_modules/mime-types": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", - "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/osls/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/osls/node_modules/write-file-atomic": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-7.0.1.tgz", - "integrity": "sha512-OTIk8iR8/aCRWBqvxrzxR0hgxWpnYBblY1S5hDWBQfk/VFmJwzmJgQFN3WsoUKHISv2eAwe+PpbUzyL1CKTLXg==", - "dev": true, - "license": "ISC", - "dependencies": { - "signal-exit": "^4.0.1" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/osls/node_modules/yauzl": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.4.0.tgz", - "integrity": "sha512-jIH9yLR9wqr0wOS0TpBvo/g/2UgZH5qePVbjgRliiF0BYvOZyaBknKsF+x9Iht0O6sqgnB93rCICdOZFecJuDw==", - "dev": true, - "license": "MIT", - "dependencies": { - "pend": "~1.2.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true, - "license": "MIT" - }, - "node_modules/picomatch": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", - "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/proxy-agent-negotiate": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-agent-negotiate/-/proxy-agent-negotiate-1.1.0.tgz", - "integrity": "sha512-N8IBcM3UgCVzz2L2Lqv8DVntDnnC8/hiV4nEDUPkqq72TPUgYWjQc+bdZlBPZK9LzPAvOY//gAt0S0DApoOXWQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 20" - }, - "peerDependencies": { - "kerberos": "^2.0.0" - }, - "peerDependenciesMeta": { - "kerberos": { - "optional": true - } - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/semver": { - "version": "7.8.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", - "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/serverless-lss": { - "resolved": "../../../packages/serverless-plugin", - "link": true - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/sprintf-kit": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/sprintf-kit/-/sprintf-kit-2.0.2.tgz", - "integrity": "sha512-lnapdj6W4LflHZGKvl9eVkz5YF0xaTrqpRWVA4cNVOTedwqifIP8ooGImldzT/4IAN5KXFQAyXTdLidYVQdyag==", - "dev": true, - "license": "ISC", - "dependencies": { - "es5-ext": "^0.10.64" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/stream-browserify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", - "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "~2.0.4", - "readable-stream": "^3.5.0" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/timers-ext": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.8.tgz", - "integrity": "sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==", - "dev": true, - "license": "ISC", - "dependencies": { - "es5-ext": "^0.10.64", - "next-tick": "^1.1.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/tsx": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.0.tgz", - "integrity": "sha512-eUdUIaCr963q2h5u3+QwvYp0+eqPvn+egeqZUm0hwERCqqx1E3kK5ehbGCvqSE5MQAULr67ww0cA3jKc3YkM1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "~0.28.0" - }, - "bin": { - "tsx": "dist/cli.mjs" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - } - }, - "node_modules/type": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz", - "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/undici": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.28.0.tgz", - "integrity": "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=20.18.1" - } - }, - "node_modules/uni-global": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/uni-global/-/uni-global-1.0.0.tgz", - "integrity": "sha512-WWM3HP+siTxzIWPNUg7hZ4XO8clKi6NoCAJJWnuRL+BAqyFXF8gC03WNyTefGoUXYc47uYgXxpKLIEvo65PEHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "type": "^2.5.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, - "license": "MIT" - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/yazl": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/yazl/-/yazl-3.3.1.tgz", - "integrity": "sha512-BbETDVWG+VcMUle37k5Fqp//7SDOK2/1+T7X8TD96M3D9G8jK5VLUdQVdVjGi8im7FGkazX7kk5hkU8X4L5Bng==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-crc32": "^1.0.0" - } - }, - "node_modules/yazl/node_modules/buffer-crc32": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", - "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - } - } -} diff --git a/examples/localstack-free/orders-service/package.json b/examples/localstack-free/orders-service/package.json deleted file mode 100644 index 5916fd9..0000000 --- a/examples/localstack-free/orders-service/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "orders-service-example", - "version": "0.0.0", - "private": true, - "description": "JavaScript REST API (payload v1) guarded by auth-service's authorizer (cross-service, by ARN), with an SQS consumer, a scheduled cleanup Lambda, a DynamoDB stream → SNS fan-out, and an S3 upload bucket with a notification-triggered Lambda. Port 3612 (invoke 13612).", - "scripts": { - "package": "serverless package", - "register": "serverless package" - }, - "dependencies": { - "@aws-sdk/client-dynamodb": "^3.0.0", - "@aws-sdk/client-s3": "^3.0.0", - "@aws-sdk/client-sns": "^3.0.0", - "@aws-sdk/client-sqs": "^3.0.0", - "@aws-sdk/lib-dynamodb": "^3.0.0", - "@aws-sdk/util-dynamodb": "^3.0.0" - }, - "devDependencies": { - "dotenv-cli": "^7.4.4", - "osls": "4.0.0", - "serverless-lss": "file:../../../packages/serverless-plugin" - } -} diff --git a/examples/localstack-free/orders-service/serverless.yml b/examples/localstack-free/orders-service/serverless.yml deleted file mode 100644 index ac3ef19..0000000 --- a/examples/localstack-free/orders-service/serverless.yml +++ /dev/null @@ -1,167 +0,0 @@ -service: orders-service - -frameworkVersion: '>=3' - -provider: - name: aws - runtime: nodejs20.x - region: sa-east-1 - stage: dev - environment: - ORDERS_TABLE: orders-Orders - ORDER_QUEUE_URL: http://localhost:4572/000000000000/orders-OrderQueue - ORDER_EVENTS_TOPIC_ARN: arn:aws:sns:${self:provider.region}:${self:custom.accountId}:orders-OrderEvents - UPLOADS_BUCKET: orders-uploads - AWS_ENDPOINT: http://localhost:4572 - -plugins: - - serverless-lss - -custom: - accountId: '000000000000' - orchestrator: - enabled: true - orchestratorUrl: http://localhost:3120 - lss: - apiPort: 3612 - invokePort: 13612 - -functions: - # POST /orders — protected by a CROSS-SERVICE authorizer: the Lambda behind - # the ARN lives in auth-service. LSS resolves the ARN against its global - # function registry, so one authorizer can guard many services. - createOrder: - handler: src/handlers/createOrder.handler - events: - - http: - path: /orders - method: post - cors: true - authorizer: - name: sessionAuthorizer - arn: arn:aws:lambda:${self:provider.region}:${self:custom.accountId}:function:auth-service-${self:provider.stage}-sessionAuthorizer - type: request - identitySource: method.request.header.code - resultTtlInSeconds: 3600 - - listOrders: - handler: src/handlers/listOrders.handler - events: - - http: - path: /orders - method: get - cors: true - authorizer: - name: sessionAuthorizer - arn: arn:aws:lambda:${self:provider.region}:${self:custom.accountId}:function:auth-service-${self:provider.stage}-sessionAuthorizer - type: request - identitySource: method.request.header.code - resultTtlInSeconds: 3600 - - # SQS consumer — LSS provisions the queue in LocalStack and pipes messages to - # the runtime worker, no serverless-offline involved. - processOrderQueue: - handler: src/handlers/processOrderQueue.handler - events: - - sqs: - arn: - Fn::GetAtt: - - OrderQueue - - Arn - batchSize: 5 - - # Schedule trigger emulation is a documented TODO — LSS still registers the - # function, so it is invocable through the Lambda Invoke API on port 13612. - cleanupExpiredOrders: - handler: src/handlers/cleanupExpiredOrders.handler - events: - - schedule: rate(1 hour) - - # DynamoDB stream consumer — every write to orders-Orders (SQS consumer, - # seeds, onUpload) flows through the table stream to this handler, which - # publishes an order.* message to the orders-OrderEvents SNS topic. - onOrderStream: - handler: src/handlers/onOrderStream.handler - events: - - stream: - type: dynamodb - arn: - Fn::GetAtt: - - OrdersTable - - StreamArn - batchSize: 10 - - # POST /uploads — public; writes the payload to s3://orders-uploads under - # "incoming/" so the bucket notification below fires onUpload. - uploadFile: - handler: src/handlers/uploadFile.handler - events: - - http: - path: /uploads - method: post - cors: true - - # GET /uploads — public; lists the bucket so the S3 round-trip is observable. - listUploads: - handler: src/handlers/listUploads.handler - events: - - http: - path: /uploads - method: get - cors: true - - # Triggered when an object is created under "incoming/" in the uploads - # bucket. The notification is wired via NotificationConfiguration below. - onUpload: - handler: src/handlers/onUpload.handler - -resources: - Resources: - # Orders — PK only, plus a stream (NEW_AND_OLD_IMAGES) feeding onOrderStream. - OrdersTable: - Type: AWS::DynamoDB::Table - Properties: - TableName: orders-Orders - BillingMode: PAY_PER_REQUEST - AttributeDefinitions: - - AttributeName: id - AttributeType: S - KeySchema: - - AttributeName: id - KeyType: HASH - StreamSpecification: - StreamViewType: NEW_AND_OLD_IMAGES - - OrderQueue: - Type: AWS::SQS::Queue - Properties: - QueueName: orders-OrderQueue - VisibilityTimeout: 60 - MessageRetentionPeriod: 345600 - - OrderEventsTopic: - Type: AWS::SNS::Topic - Properties: - TopicName: orders-OrderEvents - - # S3 bucket with a notification that fires the onUpload Lambda whenever a - # new object is created under the "incoming/" prefix. - UploadsBucket: - Type: AWS::S3::Bucket - Properties: - BucketName: orders-uploads - NotificationConfiguration: - LambdaConfigurations: - - Event: s3:ObjectCreated:* - Function: - Fn::GetAtt: - - OnUploadLambdaFunction - - Arn - Filter: - S3Key: - Rules: - - Name: prefix - Value: incoming/ - -package: - individually: false diff --git a/examples/localstack-free/orders-service/src/handlers/aws.js b/examples/localstack-free/orders-service/src/handlers/aws.js deleted file mode 100644 index 1f36a8e..0000000 --- a/examples/localstack-free/orders-service/src/handlers/aws.js +++ /dev/null @@ -1,23 +0,0 @@ -const { DynamoDBClient } = require('@aws-sdk/client-dynamodb'); -const { DynamoDBDocumentClient } = require('@aws-sdk/lib-dynamodb'); -const { SQSClient } = require('@aws-sdk/client-sqs'); -const { SNSClient } = require('@aws-sdk/client-sns'); -const { S3Client } = require('@aws-sdk/client-s3'); - -const baseConfig = { - region: process.env.AWS_REGION || 'sa-east-1', - endpoint: process.env.AWS_ENDPOINT || 'http://localhost:4572', - credentials: { accessKeyId: 'test', secretAccessKey: 'test' }, -}; - -const dynamo = new DynamoDBClient(baseConfig); - -module.exports = { - dynamo, - doc: DynamoDBDocumentClient.from(dynamo), - sqs: new SQSClient(baseConfig), - sns: new SNSClient(baseConfig), - // forcePathStyle is required so LocalStack sees the bucket name in the URL - // path rather than as a virtual-host subdomain. - s3: new S3Client({ ...baseConfig, forcePathStyle: true }), -}; diff --git a/examples/localstack-free/orders-service/src/handlers/cleanupExpiredOrders.js b/examples/localstack-free/orders-service/src/handlers/cleanupExpiredOrders.js deleted file mode 100644 index 9a15364..0000000 --- a/examples/localstack-free/orders-service/src/handlers/cleanupExpiredOrders.js +++ /dev/null @@ -1,28 +0,0 @@ -const { ScanCommand, DeleteCommand } = require('@aws-sdk/lib-dynamodb'); -const { doc } = require('./aws'); - -const ONE_HOUR_MS = 60 * 60 * 1000; - -// schedule: rate(1 hour). LSS does not fire schedules yet (documented TODO), -// but the function is registered and invocable via the Lambda Invoke API on -// port 13612 — handy for exercising it on demand. -exports.handler = async () => { - const res = await doc.send(new ScanCommand({ TableName: process.env.ORDERS_TABLE })); - const items = res.Items || []; - const cutoff = Date.now() - ONE_HOUR_MS; - - const expired = items.filter((item) => { - const created = Date.parse(item.createdAt || ''); - return Number.isFinite(created) && created < cutoff; - }); - - for (const item of expired) { - await doc.send(new DeleteCommand({ - TableName: process.env.ORDERS_TABLE, - Key: { id: item.id }, - })); - } - - console.log(`[cleanupExpiredOrders] deleted ${expired.length} of ${items.length} order(s) older than 1 hour`); - return { scanned: items.length, deleted: expired.length }; -}; diff --git a/examples/localstack-free/orders-service/src/handlers/createOrder.js b/examples/localstack-free/orders-service/src/handlers/createOrder.js deleted file mode 100644 index 46a2abe..0000000 --- a/examples/localstack-free/orders-service/src/handlers/createOrder.js +++ /dev/null @@ -1,39 +0,0 @@ -const { SendMessageCommand } = require('@aws-sdk/client-sqs'); -const { randomUUID } = require('crypto'); -const { sqs } = require('./aws'); - -// POST /orders — the cross-service authorizer (auth-service) already ran and -// put the session user on event.requestContext.authorizer. The order goes -// through SQS; processOrderQueue persists it. -exports.handler = async (event) => { - let payload = {}; - try { - payload = event.body ? JSON.parse(event.body) : {}; - } catch { - return { statusCode: 400, body: JSON.stringify({ error: 'invalid json' }) }; - } - - const { item } = payload; - if (!item) { - return { statusCode: 400, body: JSON.stringify({ error: 'item is required' }) }; - } - - const authorizer = (event.requestContext && event.requestContext.authorizer) || {}; - const order = { - id: randomUUID(), - item, - user: authorizer.user, - createdAt: new Date().toISOString(), - }; - - await sqs.send(new SendMessageCommand({ - QueueUrl: process.env.ORDER_QUEUE_URL, - MessageBody: JSON.stringify(order), - })); - - return { - statusCode: 202, - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ queued: true, id: order.id }), - }; -}; diff --git a/examples/localstack-free/orders-service/src/handlers/listOrders.js b/examples/localstack-free/orders-service/src/handlers/listOrders.js deleted file mode 100644 index 0233400..0000000 --- a/examples/localstack-free/orders-service/src/handlers/listOrders.js +++ /dev/null @@ -1,13 +0,0 @@ -const { ScanCommand } = require('@aws-sdk/lib-dynamodb'); -const { doc } = require('./aws'); - -// GET /orders — protected by the same cross-service authorizer as createOrder. -exports.handler = async () => { - const res = await doc.send(new ScanCommand({ TableName: process.env.ORDERS_TABLE })); - const items = res.Items || []; - return { - statusCode: 200, - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ count: items.length, items }), - }; -}; diff --git a/examples/localstack-free/orders-service/src/handlers/listUploads.js b/examples/localstack-free/orders-service/src/handlers/listUploads.js deleted file mode 100644 index b02ebfd..0000000 --- a/examples/localstack-free/orders-service/src/handlers/listUploads.js +++ /dev/null @@ -1,25 +0,0 @@ -const { ListObjectsV2Command } = require('@aws-sdk/client-s3'); -const { s3 } = require('./aws'); - -// GET /uploads?prefix=incoming/ -exports.handler = async (event) => { - const prefix = (event.queryStringParameters && event.queryStringParameters.prefix) || undefined; - - const response = await s3.send(new ListObjectsV2Command({ - Bucket: process.env.UPLOADS_BUCKET, - Prefix: prefix, - MaxKeys: 100, - })); - - const objects = (response.Contents || []).map(o => ({ - key: o.Key, - size: o.Size, - lastModified: o.LastModified, - })); - - return { - statusCode: 200, - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ bucket: process.env.UPLOADS_BUCKET, count: objects.length, objects }), - }; -}; diff --git a/examples/localstack-free/orders-service/src/handlers/onOrderStream.js b/examples/localstack-free/orders-service/src/handlers/onOrderStream.js deleted file mode 100644 index 78df96c..0000000 --- a/examples/localstack-free/orders-service/src/handlers/onOrderStream.js +++ /dev/null @@ -1,34 +0,0 @@ -const { PublishCommand } = require('@aws-sdk/client-sns'); -const { unmarshall } = require('@aws-sdk/util-dynamodb'); -const { sns } = require('./aws'); - -// DynamoDB stream consumer — every INSERT/MODIFY/REMOVE on orders-Orders lands -// here (NEW_AND_OLD_IMAGES), and each record is fanned out as an order.* SNS -// message on the orders-OrderEvents topic. -exports.handler = async (event) => { - const records = event.Records || []; - console.log(`[onOrderStream] received ${records.length} stream record(s)`); - - for (const record of records) { - const eventName = record.eventName; // INSERT | MODIFY | REMOVE - const newImage = record.dynamodb?.NewImage ? unmarshall(record.dynamodb.NewImage) : null; - const oldImage = record.dynamodb?.OldImage ? unmarshall(record.dynamodb.OldImage) : null; - - const message = { - type: `order.${eventName.toLowerCase()}`, - orderId: (newImage || oldImage)?.id, - item: (newImage || oldImage)?.item, - user: (newImage || oldImage)?.user, - status: newImage?.status, - occurredAt: new Date().toISOString(), - }; - - await sns.send(new PublishCommand({ - TopicArn: process.env.ORDER_EVENTS_TOPIC_ARN, - Subject: message.type, - Message: JSON.stringify(message), - })); - - console.log(`[onOrderStream] published ${message.type} for ${message.orderId}`); - } -}; diff --git a/examples/localstack-free/orders-service/src/handlers/onUpload.js b/examples/localstack-free/orders-service/src/handlers/onUpload.js deleted file mode 100644 index caa591d..0000000 --- a/examples/localstack-free/orders-service/src/handlers/onUpload.js +++ /dev/null @@ -1,53 +0,0 @@ -const { GetObjectCommand } = require('@aws-sdk/client-s3'); -const { PutCommand } = require('@aws-sdk/lib-dynamodb'); -const { s3, doc } = require('./aws'); - -// Triggered by the S3 bucket notification when an object is created under -// "incoming/". This handler reads the object back, derives some metadata, and -// records it in orders-Orders to prove the round-trip works end-to-end (the -// write also flows through the table stream → onOrderStream → SNS). -exports.handler = async (event) => { - const records = event.Records || []; - console.log(`[onUpload] received ${records.length} S3 event(s)`); - - for (const record of records) { - const bucket = record.s3 && record.s3.bucket && record.s3.bucket.name; - const key = record.s3 && record.s3.object && decodeURIComponent(record.s3.object.key.replace(/\+/g, ' ')); - if (!bucket || !key) { - console.warn('[onUpload] skipping malformed record'); - continue; - } - - let size = (record.s3.object && record.s3.object.size) || 0; - let preview; - try { - const obj = await s3.send(new GetObjectCommand({ Bucket: bucket, Key: key })); - const chunks = []; - for await (const chunk of obj.Body) chunks.push(chunk); - const body = Buffer.concat(chunks); - size = body.length; - preview = body.slice(0, 120).toString('utf-8'); - } catch (err) { - console.warn(`[onUpload] could not read s3://${bucket}/${key}: ${err.message}`); - } - - // Stash an entry in orders-Orders so the trigger is observable from the - // dashboard's DynamoDB explorer without adding a dedicated table. - await doc.send(new PutCommand({ - TableName: process.env.ORDERS_TABLE, - Item: { - id: `upload:${bucket}/${key}`, - item: key, - user: 's3-upload', - status: 'uploaded', - size, - ...(preview ? { preview } : {}), - processedAt: new Date().toISOString(), - }, - })); - - console.log(`[onUpload] indexed s3://${bucket}/${key} (${size} bytes)`); - } - - return { batchItemFailures: [] }; -}; diff --git a/examples/localstack-free/orders-service/src/handlers/processOrderQueue.js b/examples/localstack-free/orders-service/src/handlers/processOrderQueue.js deleted file mode 100644 index ee7e6b4..0000000 --- a/examples/localstack-free/orders-service/src/handlers/processOrderQueue.js +++ /dev/null @@ -1,31 +0,0 @@ -const { PutCommand } = require('@aws-sdk/lib-dynamodb'); -const { doc } = require('./aws'); - -// SQS consumer — persists each queued order with status "processed". -exports.handler = async (event) => { - const records = event.Records || []; - console.log(`[processOrderQueue] received ${records.length} message(s)`); - - for (const record of records) { - let order; - try { - order = JSON.parse(record.body); - } catch { - console.error('[processOrderQueue] invalid body, dropping:', record.body); - continue; - } - - await doc.send(new PutCommand({ - TableName: process.env.ORDERS_TABLE, - Item: { - ...order, - status: 'processed', - processedAt: new Date().toISOString(), - }, - })); - - console.log(`[processOrderQueue] stored order ${order.id} (processed)`); - } - - return { batchItemFailures: [] }; -}; diff --git a/examples/localstack-free/orders-service/src/handlers/uploadFile.js b/examples/localstack-free/orders-service/src/handlers/uploadFile.js deleted file mode 100644 index 7c89996..0000000 --- a/examples/localstack-free/orders-service/src/handlers/uploadFile.js +++ /dev/null @@ -1,37 +0,0 @@ -const { PutObjectCommand } = require('@aws-sdk/client-s3'); -const { randomUUID } = require('crypto'); -const { s3 } = require('./aws'); - -// POST /uploads -// Body: { "filename": "report.txt", "content": "...", "encoding": "base64" | undefined } -exports.handler = async (event) => { - let payload = {}; - try { - payload = event.body ? JSON.parse(event.body) : {}; - } catch { - return { statusCode: 400, body: JSON.stringify({ error: 'invalid json' }) }; - } - - const { filename, content, encoding, contentType } = payload; - if (!content) { - return { statusCode: 400, body: JSON.stringify({ error: 'content is required' }) }; - } - - // Files land under "incoming/" so the S3 → Lambda notification fires. - const safeName = (filename || `${randomUUID()}.txt`).replace(/[^a-zA-Z0-9._/-]/g, '_'); - const key = `incoming/${safeName}`; - const body = encoding === 'base64' ? Buffer.from(content, 'base64') : content; - - await s3.send(new PutObjectCommand({ - Bucket: process.env.UPLOADS_BUCKET, - Key: key, - Body: body, - ContentType: contentType || 'text/plain', - })); - - return { - statusCode: 201, - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ uploaded: true, bucket: process.env.UPLOADS_BUCKET, key }), - }; -}; diff --git a/examples/localstack-free/package.json b/examples/localstack-free/package.json deleted file mode 100644 index 26d0014..0000000 --- a/examples/localstack-free/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "localstack-free", - "version": "0.0.0", - "private": true, - "description": "The LocalStack community example: four services on LSS's API Gateway + Lambda emulation — authorizers (local and cross-service), TypeScript from source, SQS, a shared EventBridge bus, DynamoDB streams → SNS, and S3 notifications. No serverless-offline, no serverless deploy.", - "scripts": { - "lss:start": "node ../../bin/cli.js start", - "lss:stop": "node ../../bin/cli.js stop", - "lss:status": "node ../../bin/cli.js status", - "lss:seed": "node ../../bin/cli.js seed", - "register:events": "npm --prefix events-stack run package", - "register:auth": "npm --prefix auth-service run package", - "register:users": "npm --prefix users-service run package", - "register:orders": "npm --prefix orders-service run package", - "register:gateway": "npm --prefix gateway-stack run package", - "register:all": "npm run register:events && npm run register:auth && npm run register:users && npm run register:orders && npm run register:gateway", - "setup": "npm --prefix events-stack install && npm --prefix auth-service install && npm --prefix users-service install && npm --prefix orders-service install && npm --prefix gateway-stack install", - "console": "npx -y http-server . -p 8620 -c-1" - } -} diff --git a/examples/localstack-free/seeds/auth-Sessions.json b/examples/localstack-free/seeds/auth-Sessions.json deleted file mode 100644 index 0d5a9ec..0000000 --- a/examples/localstack-free/seeds/auth-Sessions.json +++ /dev/null @@ -1,7 +0,0 @@ -[ - { - "code": "code-admin", - "user": "admin", - "createdAt": "2026-01-01T00:00:00.000Z" - } -] diff --git a/examples/localstack-free/seeds/orders-Orders.json b/examples/localstack-free/seeds/orders-Orders.json deleted file mode 100644 index e6bc8d7..0000000 --- a/examples/localstack-free/seeds/orders-Orders.json +++ /dev/null @@ -1,29 +0,0 @@ -[ - { - "id": "o-1001", - "item": "BOOK-01 x2", - "user": "alice", - "status": "processed", - "total": 50, - "createdAt": "2026-05-10T09:00:00.000Z", - "processedAt": "2026-05-10T09:00:02.000Z" - }, - { - "id": "o-1002", - "item": "LAPTOP-XL x1", - "user": "alice", - "status": "pending_review", - "total": 1500, - "createdAt": "2026-05-12T14:20:00.000Z", - "processedAt": "2026-05-12T14:20:01.000Z" - }, - { - "id": "o-1003", - "item": "MUG-RED x3 + STICKER-PK x4", - "user": "bob", - "status": "processed", - "total": 56, - "createdAt": "2026-05-13T16:45:00.000Z", - "processedAt": "2026-05-13T16:45:01.000Z" - } -] diff --git a/examples/localstack-free/seeds/users-Users.json b/examples/localstack-free/seeds/users-Users.json deleted file mode 100644 index d04db8e..0000000 --- a/examples/localstack-free/seeds/users-Users.json +++ /dev/null @@ -1,14 +0,0 @@ -[ - { - "id": "u-ada", - "name": "Ada Lovelace", - "email": "ada@example.com", - "createdAt": "2026-01-01T10:00:00.000Z" - }, - { - "id": "u-grace", - "name": "Grace Hopper", - "email": "grace@example.com", - "createdAt": "2026-01-02T11:30:00.000Z" - } -] diff --git a/examples/localstack-ultimate/.env.example b/examples/localstack-ultimate/.env.example deleted file mode 100644 index 03a71c8..0000000 --- a/examples/localstack-ultimate/.env.example +++ /dev/null @@ -1,7 +0,0 @@ -# Copy to `.env` (which is gitignored) and fill in. -# -# REQUIRED for this example: localstack/localstack-pro refuses to start without -# a valid token (it exits with code 55). Grab a token at -# https://app.localstack.cloud (Personal access tokens). A free Hobby token -# covers everything this example provisions. -LOCALSTACK_AUTH_TOKEN= diff --git a/examples/localstack-ultimate/.gitignore b/examples/localstack-ultimate/.gitignore deleted file mode 100644 index d23b859..0000000 --- a/examples/localstack-ultimate/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules/ -.serverless/ -.lss/ -.dynamodb/ -.esbuild/ -*.log -.env -.env.local diff --git a/examples/localstack-ultimate/README.md b/examples/localstack-ultimate/README.md deleted file mode 100644 index a68c88b..0000000 --- a/examples/localstack-ultimate/README.md +++ /dev/null @@ -1,237 +0,0 @@ -# localstack-ultimate - -End-to-end LSS example pointed at the **LocalStack paid tier**. LocalStack renamed its -paid plans — the top plan is now **Ultimate** — but the Docker image those plans use is -still `localstack/localstack-pro:latest`, and that is exactly what this example boots. - -This is also the one example that deliberately keeps the **serverless-offline -integration path**: the HTTP API is served by `serverless-offline` (not by the LSS -gateway), while the `serverless-lss` plugin registers the service with the orchestrator, -which provisions every CloudFormation resource into the Pro LocalStack and wires the -S3 → Lambda notification. Use it to confirm LSS plays nicely with an offline-based -workflow you may already have. - -## What this exercises - -- **LocalStack Pro image** — `localstackEdition: "pro"` in `lss.config.json`; the - container refuses to start without a valid `LOCALSTACK_AUTH_TOKEN` (exit code 55). -- **serverless-offline compatibility** — REST (v1) routes with `cors: true` served by - the offline server on `3002`; registration with LSS fires on `sls package` and on - offline startup. -- **Region `eu-west-1`** — the whole example (LSS config, provider, SDK clients) runs - outside the default region, proving nothing is hardwired to it. -- **DynamoDB** — PK-only tables, composite key + GSI (`ByStatus`), a stream feeding - the `onOrderStream` Lambda, seeds auto-loaded from `seeds/`. The Users table has - deliberately **no TTL** (surfacing a UI warning); the Sessions table carries an - `expiresAt` attribute so you can enable **TTL from the UI** (Settings tab). -- **SQS + DLQ redrive** — `enqueueOrder` sends to the queue, `processOrderQueue` - consumes in batches (`ReportBatchItemFailures`) and persists orders with a computed - `status`/`total`; poison orders (computed total ≤ 0) are re-received every 10s - (short `VisibilityTimeout`) and redriven to `-OrderProcessingDLQ` after 3 receives — - watch them pile up in the dashboard's Queues tab. -- **SNS** — stream handler publishes `order.*` events to a topic. -- **EventBridge custom bus + pattern rule + audit trail** — `processOrderQueue` - (`order.processed`) and `purgeSessions` (`sessions.purged`) `PutEvents` onto the - `ultimate-order-events` bus; the `auditEvents` rule (pattern filter on `source`) - writes each matched event into the AuditTrail table, readable via `GET /audit`. -- **Schedule** — `purgeSessions` (`rate(2 minutes)`), provisioned as an EventBridge - rule fired by LocalStack, purges expired sessions and leaves an audit entry. -- **S3 + Lambda notification** — uploads under `incoming/` trigger `onUpload`, which - reads the object back and indexes it in the Orders table. -- **OpenSearch Serverless (LSS aoss sidecar)** — LocalStack has **no aoss support in - any edition**, so LSS serves the `ultimate-products` collection in-process on - `14567`; the catalog routes (`/products`, `/search`, `/stats`) cover indexing, - full-text search + filters and aggregations against it. -- **Seeds & persistence** — tables pre-filled from `seeds/`; `persistence: true` - keeps data across `lss:stop`/`lss:start` cycles. -- **Dashboard branding** — per-theme brand tokens with a light default (see below). - -## Prerequisites - -- Docker -- Node.js ≥ 20 -- A **LocalStack auth token**. Paid-tier images refuse to start without one. Grab a - token at → *Personal access tokens*. A free Hobby - token is enough for the resources this example uses. - -## Setup - -```bash -cd examples/localstack-ultimate -npm install - -# Drop your token into a local .env (gitignored). The npm scripts wrap commands -# with dotenv-cli so LOCALSTACK_AUTH_TOKEN reaches both LSS and serverless-offline. -cp .env.example .env -$EDITOR .env # set LOCALSTACK_AUTH_TOKEN=ls-xxxxxxxx -``` - -## Ports used - -| Concern | Port | -|---|---| -| LSS dashboard / API | `3111` | -| LocalStack (Pro image) | `4571` | -| serverless-offline HTTP | `3002` | -| serverless-offline Lambda invoke | `3003` | -| LSS aoss sidecar (OpenSearch Serverless) | `14567` | -| Validation console (`npm run console`) | `8621` | - -These are all different from [`localstack-free`](../localstack-free/) (which uses -LSS `3120`, LocalStack `4572`, service APIs `3610`–`3612`) **and** from a default -external LocalStack on `4566`, so -you can run any combination at the same time without conflict — unless your external -LocalStack publishes the whole `4566–4599` range (a common install default), in which -case `4571` sits inside it and will collide. - -## Run - -```bash -# 1. Boot LSS — pulls localstack/localstack-pro:latest on first run. -npm run lss:start - -# 2. Package + start serverless-offline. The plugin registers this service with -# LSS (3111), which provisions every CloudFormation resource into the Pro -# LocalStack on 4571 and wires the S3 -> onUpload notification, the -# EventBridge bus/rules and the SQS event source mapping. In between, the -# script re-applies the queue's RedrivePolicy via scripts/wire-dlq.js — a -# no-op safety net now that LSS carries that attribute from the template. -npm run offline -``` - -Dashboard: . - -## Try the HTTP routes - -The offline server binds to **port 3002** and prefixes routes with the stage (`/dev`): - -```bash -curl http://localhost:3002/dev/health - -# Create a user -curl -X POST http://localhost:3002/dev/users \ - -H 'Content-Type: application/json' \ - -d '{"name":"Dora","email":"dora@example.com"}' - -# Enqueue an order — the SQS consumer stores it and publishes order.processed -# onto the ultimate-order-events bus -curl -X POST http://localhost:3002/dev/orders \ - -H 'Content-Type: application/json' \ - -d '{"userId":"u-alice","items":[{"sku":"BOOK-02","price":42,"qty":1}]}' - -# The auditEvents rule wrote it into the AuditTrail table (sessions.purged -# entries from the rate(2 minutes) schedule show up here too) -curl http://localhost:3002/dev/audit - -# Poison order: computed total is 0, so processOrderQueue throws and reports -# the message as a batch item failure — after 3 receives (~30s at a 10s -# visibility timeout) SQS redrives it to localstack-ultimate-OrderProcessingDLQ -# (dashboard -> Queues tab). -curl -X POST http://localhost:3002/dev/orders \ - -H 'Content-Type: application/json' \ - -d '{"userId":"u-alice","items":[{"sku":"BROKEN","price":0,"qty":1}]}' - -# Upload to S3 -> triggers the onUpload Lambda via bucket notification -curl -X POST http://localhost:3002/dev/uploads \ - -H 'Content-Type: application/json' \ - -d '{"filename":"hello.txt","content":"hello from ultimate"}' - -curl http://localhost:3002/dev/uploads - -# Index a product into the ultimate-products collection — served by the LSS -# aoss sidecar on :14567 (LocalStack has no OpenSearch Serverless) -curl -X POST http://localhost:3002/dev/products \ - -H 'Content-Type: application/json' \ - -d '{"name":"Wireless Mouse","category":"peripherals","price":25,"tags":["usb","wireless"]}' - -# Fetch / delete it by the id returned above -curl http://localhost:3002/dev/products/ -curl -X DELETE http://localhost:3002/dev/products/ - -# Full-text search + filters, then aggregations (count + avg price per category) -curl 'http://localhost:3002/dev/search?q=wireless&category=peripherals&maxPrice=50' -curl http://localhost:3002/dev/stats -``` - -## Validation console - -`index.html` at the example root is a small browser console that pings every port and -runs the flows above end to end (create user → list, enqueue → verify the SQS consumer -wrote the order, order → audit trail via EventBridge, poison order → DLQ, schedule -observation, upload → verify the S3 notification fired, catalog index → search → -stats → delete against the aoss sidecar). Open it directly from the -filesystem (`file://…/index.html`) or serve it: - -```bash -npm run console # http://localhost:8621 -``` - -CORS is pre-wired for it: every `http` event declares `cors: true` (serverless-offline -answers the preflight) and every handler response carries -`Access-Control-Allow-Origin: *` via the shared `src/handlers/respond.js` helper. - -## Dashboard branding - -The example also showcases [dashboard branding](../../docs/CONFIGURATION.md#configuration-properties): -`lss.config.json` sets a custom title/subtitle, points `logo`/`favicon` at -`assets/logo.svg`, forces `defaultTheme: "light"`, and overrides the brand tokens -(`brand-primary`/`brand-hover`/`brand-soft`, plus `brand-contrast` in dark) **per -theme** with amber tones — the dashboard at `http://localhost:3111` opens light with an -amber accent. Each example in this folder uses a different branding mechanism, so -compare them to see what the dashboard supports. - -## Reset - -```bash -npm run lss:seed:clear # empties seeded tables — prompts for confirmation - # (type "confirmar"); append -- --yes for - # non-interactive use -npm run lss:stop # stops orchestrator + LocalStack Pro container -``` - -Persistence is on, so a `lss:stop` / `lss:start` cycle preserves data. To wipe -completely, also `docker volume rm lss-localstack-4571-data` (the `--rm` container is -removed automatically on stop). - -## What's different from localstack-free - -- `lss.config.json` -> `"localstackEdition": "pro"`, `serverPort: 3111`, `localstackPort: 4571`. -- Region is **`eu-west-1`** — each example runs in its own region (localstack-free: - `sa-east-1`, self-hosted: `us-west-2`), so they also prove multi-region coherence - side by side. -- Service name is `localstack-ultimate`, so resources live under a separate namespace - (`localstack-ultimate-Users`, `localstack-ultimate-uploads`, etc.). -- All ports shifted to dodge the community example, so both can run side by side. -- `LOCALSTACK_AUTH_TOKEN` is **required**; without it the Pro image exits with code 55. -- The HTTP API is served by **serverless-offline** — the other examples route HTTP - through the LSS gateway instead. -- Shape: this is a single service (one `serverless.yml`) owning its own EventBridge - bus, while `localstack-free` is a four-service stack exercising authorizers and a - **shared** bus across services. -- **OpenSearch Serverless** — LocalStack has no aoss support in any edition (not even - paid ones), so LSS serves the `ultimate-products` collection **in-process** via its - aoss sidecar on `14567` (on by default for LocalStack engines; the port is pinned in - `lss.config.json`) while everything else lives in the Pro container. - -Run both side by side when you want to confirm a behavior is or isn't gated behind a -paid plan. - -## File map - -``` -serverless.yml ← REST routes + SQS/DLQ + streams + EventBridge bus, - pattern rule, rate(2 minutes) schedule, aoss - collection + policies (eu-west-1) -lss.config.json ← edition: pro, region eu-west-1, services incl. - "events", ports 3111/4571 (+ aoss sidecar 14567), - branding block -.env / .env.example ← LOCALSTACK_AUTH_TOKEN (gitignored) -index.html ← validation console (file:// or npm run console) -assets/logo.svg ← dashboard logo/favicon -scripts/wire-dlq.js ← applies the RedrivePolicy to the live queue -src/handlers/ ← HTTP + event handlers, shared respond.js CORS helper -src/handlers/opensearch.js ← fetch-based OpenSearch helper (aoss sidecar :14567) -src/handlers/createProduct.js ← + getProduct/deleteProduct/searchProducts/ - productStats — the OpenSearch catalog routes -seeds/ ← localstack-ultimate-Users / -Orders / -Sessions seeds -``` diff --git a/examples/localstack-ultimate/assets/logo.svg b/examples/localstack-ultimate/assets/logo.svg deleted file mode 100644 index 723ab82..0000000 --- a/examples/localstack-ultimate/assets/logo.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - LU - diff --git a/examples/localstack-ultimate/index.html b/examples/localstack-ultimate/index.html deleted file mode 100644 index 6f8bfdb..0000000 --- a/examples/localstack-ultimate/index.html +++ /dev/null @@ -1,320 +0,0 @@ - - - - - - -localstack-ultimate · validation console - - - -
- -
-

localstack-ultimate

-

LSS + LocalStack Pro image (Ultimate) — serverless-offline integration path

-
- -
-
-
-

Status

-
-
-
-

Flows

-
-
-
-

Request log

-
-
-
-
Generated for the LSS example "localstack-ultimate" — open this file directly or via npm run console.
- - - diff --git a/examples/localstack-ultimate/lss.config.json b/examples/localstack-ultimate/lss.config.json deleted file mode 100644 index d4423cd..0000000 --- a/examples/localstack-ultimate/lss.config.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "serverPort": 3111, - "localstackPort": 4571, - "localstackEndpoint": "http://localhost:4571", - "mode": "managed", - "localstackEdition": "pro", - "region": "eu-west-1", - "services": ["dynamodb", "sqs", "sns", "s3", "lambda", "events"], - "aossSidecar": { "port": 14567 }, - "persistence": true, - "stateDir": ".lss", - "seedsDir": "./seeds", - "autoPackage": true, - "packageCommand": "npx serverless package", - "packageTimeoutMs": 300000, - "branding": { - "title": "LocalStack Ultimate Lab", - "subtitle": "LSS + LocalStack Pro image — paid-tier features, serverless-offline path", - "logo": "./assets/logo.svg", - "favicon": "./assets/logo.svg", - "defaultTheme": "light", - "themeColors": { - "light": { "brand-primary": "#b45309", "brand-hover": "#92400e", "brand-soft": "#fef3c7" }, - "dark": { "brand-primary": "#fbbf24", "brand-hover": "#fcd34d", "brand-soft": "#78350f", "brand-contrast": "#451a03" } - } - } -} diff --git a/examples/localstack-ultimate/package-lock.json b/examples/localstack-ultimate/package-lock.json deleted file mode 100644 index 14c8c63..0000000 --- a/examples/localstack-ultimate/package-lock.json +++ /dev/null @@ -1,4790 +0,0 @@ -{ - "name": "localstack-ultimate", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "localstack-ultimate", - "version": "0.0.0", - "dependencies": { - "@aws-sdk/client-dynamodb": "3.974.0", - "@aws-sdk/client-eventbridge": "^3.974.0", - "@aws-sdk/client-s3": "^3.974.0", - "@aws-sdk/client-sns": "3.974.0", - "@aws-sdk/client-sqs": "3.974.0", - "@aws-sdk/util-dynamodb": "3.974.0" - }, - "devDependencies": { - "dotenv-cli": "^7.4.4", - "osls": "4.0.0", - "serverless-lss": "file:../../packages/serverless-plugin", - "serverless-offline": "^13.6.0" - } - }, - "../../packages/serverless-plugin": { - "name": "serverless-lss", - "version": "0.2.2", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2" - }, - "devDependencies": { - "@types/node": "^22.10.5", - "typescript": "^5.7.3" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "osls": "4.0.0" - }, - "peerDependenciesMeta": { - "osls": { - "optional": true - } - } - }, - "node_modules/@apidevtools/json-schema-ref-parser": { - "version": "15.5.0", - "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-15.5.0.tgz", - "integrity": "sha512-Ps4w0FwrDoeVK6hfYxWkVbkmxm+zN+6xoXF2ZfEhfiox0ZNbcSAiUWO6iAIvP5bc3DB270r+EaKcoT1IUyzfxw==", - "dev": true, - "license": "MIT", - "dependencies": { - "js-yaml": "^4.2.0" - }, - "engines": { - "node": ">=20" - }, - "peerDependencies": { - "@types/json-schema": "^7.0.15" - } - }, - "node_modules/@aws-crypto/sha256-browser": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", - "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-js": "^5.2.0", - "@aws-crypto/supports-web-crypto": "^5.2.0", - "@aws-crypto/util": "^5.2.0", - "@aws-sdk/types": "^3.222.0", - "@aws-sdk/util-locate-window": "^3.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.6.2" - } - }, - "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", - "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/util-buffer-from": "^2.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-crypto/sha256-js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", - "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/util": "^5.2.0", - "@aws-sdk/types": "^3.222.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-crypto/supports-web-crypto": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", - "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - } - }, - "node_modules/@aws-crypto/util": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", - "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "^3.222.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.6.2" - } - }, - "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", - "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/util-buffer-from": "^2.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/checksums": { - "version": "3.1000.16", - "resolved": "https://registry.npmjs.org/@aws-sdk/checksums/-/checksums-3.1000.16.tgz", - "integrity": "sha512-EKnvkXSmz3IpA99tCNuI+dLFXyZyClSm8zns9sB/elvkU+MTuomAs6toJMPMBf98/fICG/urXDkzGz0/c3yyAQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-api-gateway": { - "version": "3.1051.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-api-gateway/-/client-api-gateway-3.1051.0.tgz", - "integrity": "sha512-eYUubuiRmlf+YVyyP6CjRmBmpelDzYNL5i8wkR3tLR7yVRHi8l54Ft9Kesn8FON+OAeFNK2O5rbXMG2X8f6ACg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.974.12", - "@aws-sdk/credential-provider-node": "^3.972.43", - "@aws-sdk/middleware-sdk-api-gateway": "^3.972.12", - "@aws-sdk/types": "^3.973.8", - "@smithy/core": "^3.24.2", - "@smithy/fetch-http-handler": "^5.4.2", - "@smithy/node-http-handler": "^4.7.2", - "@smithy/types": "^4.14.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-apigatewayv2": { - "version": "3.1085.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-apigatewayv2/-/client-apigatewayv2-3.1085.0.tgz", - "integrity": "sha512-IeDwKOit9IndGVNOcEAAIxwj5z+YhX4aGVNXU+C0sZvALnSOI83rGMekPGxGrZf6tDxpmwtIrSm6qYWPbFkNXA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/credential-provider-node": "^3.972.66", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/fetch-http-handler": "^5.6.4", - "@smithy/node-http-handler": "^4.9.4", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudformation": { - "version": "3.1051.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudformation/-/client-cloudformation-3.1051.0.tgz", - "integrity": "sha512-5R6SFqCkJitoatw7FV6BjefxFhkvRyW9FHhr9H89kcvqPIx8Ah433giyiPEMVsdmmb9msOWCpHsC81CELPJp6g==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.974.12", - "@aws-sdk/credential-provider-node": "^3.972.43", - "@aws-sdk/types": "^3.973.8", - "@smithy/core": "^3.24.2", - "@smithy/fetch-http-handler": "^5.4.2", - "@smithy/node-http-handler": "^4.7.2", - "@smithy/types": "^4.14.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch": { - "version": "3.1085.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudwatch/-/client-cloudwatch-3.1085.0.tgz", - "integrity": "sha512-2WyjUH6zdRvPSvL/8JJYo6BJfK4hNn9RA3+3XEfPczQ/uYxhFfIR8hbNIrRQe7ffb9X8CCxN6YpSQtw8iXQboA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/credential-provider-node": "^3.972.66", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/fetch-http-handler": "^5.6.4", - "@smithy/middleware-compression": "^4.5.7", - "@smithy/node-http-handler": "^4.9.4", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs": { - "version": "3.1085.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudwatch-logs/-/client-cloudwatch-logs-3.1085.0.tgz", - "integrity": "sha512-jNMt5zMsnJ6X0fZJKKNU5/qTQ98OIsUSFLqDh+FTXQTiEI3NTq95gAdsaAwXVWO9hTaT5gY7fbwF5Ally69bwg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/credential-provider-node": "^3.972.66", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/fetch-http-handler": "^5.6.4", - "@smithy/node-http-handler": "^4.9.4", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity": { - "version": "3.1081.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.1081.0.tgz", - "integrity": "sha512-ipDgvZ3Hy8kaFrkwj62yuoghKkZi5WrWTiJnaqGc/ntbuAuijIkRWhzSb8d1MGEE+qb+vFFTrWVFwGSqt76TCA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.974.29", - "@aws-sdk/credential-provider-node": "^3.972.64", - "@aws-sdk/types": "^3.973.15", - "@smithy/core": "^3.29.0", - "@smithy/fetch-http-handler": "^5.6.2", - "@smithy/node-http-handler": "^4.9.2", - "@smithy/types": "^4.15.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity-provider": { - "version": "3.1051.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity-provider/-/client-cognito-identity-provider-3.1051.0.tgz", - "integrity": "sha512-7bJ2fxeEVNtrxH/kL5Tk8H2EGuNbPtuI4BfpwogHmJfn7oUrIODlnJJL43l/LU2i6d5MoXCZKJf18EufkGpgVw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.974.12", - "@aws-sdk/credential-provider-node": "^3.972.43", - "@aws-sdk/types": "^3.973.8", - "@smithy/core": "^3.24.2", - "@smithy/fetch-http-handler": "^5.4.2", - "@smithy/node-http-handler": "^4.7.2", - "@smithy/types": "^4.14.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-dynamodb": { - "version": "3.974.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.974.0.tgz", - "integrity": "sha512-Nw4/sL0IbBMvQdBvLlnBTFBrG+Aqg22ewMVJWOXSVdktfomtpPJ+jpJXBMJDMF9LsrgTNF/zsSVRJSEHYlBkOA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.0", - "@aws-sdk/credential-provider-node": "^3.972.1", - "@aws-sdk/dynamodb-codec": "^3.972.1", - "@aws-sdk/middleware-endpoint-discovery": "^3.972.1", - "@aws-sdk/middleware-host-header": "^3.972.1", - "@aws-sdk/middleware-logger": "^3.972.1", - "@aws-sdk/middleware-recursion-detection": "^3.972.1", - "@aws-sdk/middleware-user-agent": "^3.972.1", - "@aws-sdk/region-config-resolver": "^3.972.1", - "@aws-sdk/types": "^3.973.0", - "@aws-sdk/util-endpoints": "3.972.0", - "@aws-sdk/util-user-agent-browser": "^3.972.1", - "@aws-sdk/util-user-agent-node": "^3.972.1", - "@smithy/config-resolver": "^4.4.6", - "@smithy/core": "^3.21.0", - "@smithy/fetch-http-handler": "^5.3.9", - "@smithy/hash-node": "^4.2.8", - "@smithy/invalid-dependency": "^4.2.8", - "@smithy/middleware-content-length": "^4.2.8", - "@smithy/middleware-endpoint": "^4.4.10", - "@smithy/middleware-retry": "^4.4.26", - "@smithy/middleware-serde": "^4.2.9", - "@smithy/middleware-stack": "^4.2.8", - "@smithy/node-config-provider": "^4.3.8", - "@smithy/node-http-handler": "^4.4.8", - "@smithy/protocol-http": "^5.3.8", - "@smithy/smithy-client": "^4.10.11", - "@smithy/types": "^4.12.0", - "@smithy/url-parser": "^4.2.8", - "@smithy/util-base64": "^4.3.0", - "@smithy/util-body-length-browser": "^4.2.0", - "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.25", - "@smithy/util-defaults-mode-node": "^4.2.28", - "@smithy/util-endpoints": "^3.2.8", - "@smithy/util-middleware": "^4.2.8", - "@smithy/util-retry": "^4.2.8", - "@smithy/util-utf8": "^4.2.0", - "@smithy/util-waiter": "^4.2.8", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-ecr": { - "version": "3.1085.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-ecr/-/client-ecr-3.1085.0.tgz", - "integrity": "sha512-I1MWQNb01MlfC2MENTll+GrRV2RSGmkQSyB289CEY2QGf4ImqeEsySWFtpau/39zqTxqOyx/jfXrT5vdr3hOyQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/credential-provider-node": "^3.972.66", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/fetch-http-handler": "^5.6.4", - "@smithy/node-http-handler": "^4.9.4", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-eventbridge": { - "version": "3.1051.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-eventbridge/-/client-eventbridge-3.1051.0.tgz", - "integrity": "sha512-lF356sBGSoeI5bDkDBUrS4lVERZE2lRiankELUCKcfRARoas0Wvn4gCFunisKQjf4Za+RywZMC+PP0Zp1P3Z4w==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.974.12", - "@aws-sdk/credential-provider-node": "^3.972.43", - "@aws-sdk/signature-v4-multi-region": "^3.996.27", - "@aws-sdk/types": "^3.973.8", - "@smithy/core": "^3.24.2", - "@smithy/fetch-http-handler": "^5.4.2", - "@smithy/node-http-handler": "^4.7.2", - "@smithy/types": "^4.14.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-iam": { - "version": "3.1051.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-iam/-/client-iam-3.1051.0.tgz", - "integrity": "sha512-9MRigaj8/9/ZofuICTc8vUa2v+SOAFaeKkt7Fmom0pzbob3LaJquMkT4RmawevJQ/T6UHJmC6F1s6xon/lZrZQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.974.12", - "@aws-sdk/credential-provider-node": "^3.972.43", - "@aws-sdk/types": "^3.973.8", - "@smithy/core": "^3.24.2", - "@smithy/fetch-http-handler": "^5.4.2", - "@smithy/node-http-handler": "^4.7.2", - "@smithy/types": "^4.14.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-lambda": { - "version": "3.1051.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.1051.0.tgz", - "integrity": "sha512-Oc7Rc9R6BbltJGYUls4xYswIujugscTbjAao51izJvW+UKAzgoYg0TenVDslXoPQbkkIAnZjAF6ehLxB8eui4g==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.974.12", - "@aws-sdk/credential-provider-node": "^3.972.43", - "@aws-sdk/types": "^3.973.8", - "@smithy/core": "^3.24.2", - "@smithy/fetch-http-handler": "^5.4.2", - "@smithy/node-http-handler": "^4.7.2", - "@smithy/types": "^4.14.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-s3": { - "version": "3.1085.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.1085.0.tgz", - "integrity": "sha512-O0xe8sR50AYkwxlvRRsV0qytEO2dtXQTQ1CF3YBBdE5xtVkbu27H0vGa1mjQi1/+fbYM80AWEIPai5jZmXyubw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/checksums": "^3.1000.16", - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/credential-provider-node": "^3.972.66", - "@aws-sdk/middleware-sdk-s3": "^3.972.62", - "@aws-sdk/signature-v4-multi-region": "^3.996.39", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/fetch-http-handler": "^5.6.4", - "@smithy/node-http-handler": "^4.9.4", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-sns": { - "version": "3.974.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sns/-/client-sns-3.974.0.tgz", - "integrity": "sha512-k2PFHgJ1qs7MpTnvkrQciaU2YIlYkOPkPCyt/SfA3I8Gi+1Q8CDQUfMbBPWeSFhQuNIE/U3Sl/F5j1SGqjclsg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.0", - "@aws-sdk/credential-provider-node": "^3.972.1", - "@aws-sdk/middleware-host-header": "^3.972.1", - "@aws-sdk/middleware-logger": "^3.972.1", - "@aws-sdk/middleware-recursion-detection": "^3.972.1", - "@aws-sdk/middleware-user-agent": "^3.972.1", - "@aws-sdk/region-config-resolver": "^3.972.1", - "@aws-sdk/types": "^3.973.0", - "@aws-sdk/util-endpoints": "3.972.0", - "@aws-sdk/util-user-agent-browser": "^3.972.1", - "@aws-sdk/util-user-agent-node": "^3.972.1", - "@smithy/config-resolver": "^4.4.6", - "@smithy/core": "^3.21.0", - "@smithy/fetch-http-handler": "^5.3.9", - "@smithy/hash-node": "^4.2.8", - "@smithy/invalid-dependency": "^4.2.8", - "@smithy/middleware-content-length": "^4.2.8", - "@smithy/middleware-endpoint": "^4.4.10", - "@smithy/middleware-retry": "^4.4.26", - "@smithy/middleware-serde": "^4.2.9", - "@smithy/middleware-stack": "^4.2.8", - "@smithy/node-config-provider": "^4.3.8", - "@smithy/node-http-handler": "^4.4.8", - "@smithy/protocol-http": "^5.3.8", - "@smithy/smithy-client": "^4.10.11", - "@smithy/types": "^4.12.0", - "@smithy/url-parser": "^4.2.8", - "@smithy/util-base64": "^4.3.0", - "@smithy/util-body-length-browser": "^4.2.0", - "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.25", - "@smithy/util-defaults-mode-node": "^4.2.28", - "@smithy/util-endpoints": "^3.2.8", - "@smithy/util-middleware": "^4.2.8", - "@smithy/util-retry": "^4.2.8", - "@smithy/util-utf8": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-sqs": { - "version": "3.974.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sqs/-/client-sqs-3.974.0.tgz", - "integrity": "sha512-dfJcrDwEGxOB2fea4IhhMdr7WL7OKY+fWegrlf91ewG7h7Lk0Zws/6yLQP2GCNECoLwveGQkYNZTUT2rfF52Gw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.0", - "@aws-sdk/credential-provider-node": "^3.972.1", - "@aws-sdk/middleware-host-header": "^3.972.1", - "@aws-sdk/middleware-logger": "^3.972.1", - "@aws-sdk/middleware-recursion-detection": "^3.972.1", - "@aws-sdk/middleware-sdk-sqs": "^3.972.1", - "@aws-sdk/middleware-user-agent": "^3.972.1", - "@aws-sdk/region-config-resolver": "^3.972.1", - "@aws-sdk/types": "^3.973.0", - "@aws-sdk/util-endpoints": "3.972.0", - "@aws-sdk/util-user-agent-browser": "^3.972.1", - "@aws-sdk/util-user-agent-node": "^3.972.1", - "@smithy/config-resolver": "^4.4.6", - "@smithy/core": "^3.21.0", - "@smithy/fetch-http-handler": "^5.3.9", - "@smithy/hash-node": "^4.2.8", - "@smithy/invalid-dependency": "^4.2.8", - "@smithy/md5-js": "^4.2.8", - "@smithy/middleware-content-length": "^4.2.8", - "@smithy/middleware-endpoint": "^4.4.10", - "@smithy/middleware-retry": "^4.4.26", - "@smithy/middleware-serde": "^4.2.9", - "@smithy/middleware-stack": "^4.2.8", - "@smithy/node-config-provider": "^4.3.8", - "@smithy/node-http-handler": "^4.4.8", - "@smithy/protocol-http": "^5.3.8", - "@smithy/smithy-client": "^4.10.11", - "@smithy/types": "^4.12.0", - "@smithy/url-parser": "^4.2.8", - "@smithy/util-base64": "^4.3.0", - "@smithy/util-body-length-browser": "^4.2.0", - "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.25", - "@smithy/util-defaults-mode-node": "^4.2.28", - "@smithy/util-endpoints": "^3.2.8", - "@smithy/util-middleware": "^4.2.8", - "@smithy/util-retry": "^4.2.8", - "@smithy/util-utf8": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-ssm": { - "version": "3.1085.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-ssm/-/client-ssm-3.1085.0.tgz", - "integrity": "sha512-vFYFncOReqEtOj110hdTQK/4JzNEHdVR90Ob6FjdEeb8cNer+HShI64Nuw9J4gTUQAWJ0eErHZqqxQPTViplew==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/credential-provider-node": "^3.972.66", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/fetch-http-handler": "^5.6.4", - "@smithy/node-http-handler": "^4.9.4", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/client-sts": { - "version": "3.1051.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.1051.0.tgz", - "integrity": "sha512-7A3YcLSGNXqCMI4/W6NkMCgqDi0H+mER4d6wqGCk2PsgzpePgXzG2ufa4EAXFEH5qAhYft8PmAJZczhjhDmM2A==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.974.12", - "@aws-sdk/credential-provider-node": "^3.972.43", - "@aws-sdk/signature-v4-multi-region": "^3.996.27", - "@aws-sdk/types": "^3.973.8", - "@smithy/core": "^3.24.2", - "@smithy/fetch-http-handler": "^5.4.2", - "@smithy/node-http-handler": "^4.7.2", - "@smithy/types": "^4.14.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/core": { - "version": "3.975.1", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.975.1.tgz", - "integrity": "sha512-8qh/6EYb7hl/ZwVfQufhbMEZs1gQIc7GbdrIf4eprQJ7cv042+74nE6l3YDfyWNzb9iPXb8fRyYSHkNIk5eE6Q==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "^3.974.0", - "@aws-sdk/xml-builder": "^3.972.34", - "@aws/lambda-invoke-store": "^0.3.0", - "@smithy/core": "^3.29.2", - "@smithy/signature-v4": "^5.6.3", - "@smithy/types": "^4.16.0", - "bowser": "^2.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-cognito-identity": { - "version": "3.972.56", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.972.56.tgz", - "integrity": "sha512-nedaZz6Wz2FGUBMsWhlvBPGIkTMfRuMJ99YDHJI4CaC31JS8WPyTavEAio74cfd5nGhi0A8XASB4fZA5VqTdOQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/nested-clients": "^3.997.31", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.972.57", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.57.tgz", - "integrity": "sha512-1RfJaF7SW1TOnvNGU7kaYjwUf5H3sfm+synGH1bHhRlqcnxCt3szebH3dmKEyY4tuGcbQ6ffzUT89cRitBV8OQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.972.59", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.59.tgz", - "integrity": "sha512-sRCkpTiFnCdQvuaRVjQ6SVoHu6i7RUpurVo1c4F81HWhPvUJ7Wdp5MNtSdX1O29CNXc8em3O5m52hCjVtAD9SA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/fetch-http-handler": "^5.6.4", - "@smithy/node-http-handler": "^4.9.4", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.973.1", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.973.1.tgz", - "integrity": "sha512-6d8H6ZAh3ZPKZ6fe1nG2OWeZEZPtt9ravoD1dezPdPtsSkJRoxGAnFSHwKT3E/Te6fHE30zRzjV6TD12rvF6yQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/credential-provider-env": "^3.972.57", - "@aws-sdk/credential-provider-http": "^3.972.59", - "@aws-sdk/credential-provider-login": "^3.972.63", - "@aws-sdk/credential-provider-process": "^3.972.57", - "@aws-sdk/credential-provider-sso": "^3.973.1", - "@aws-sdk/credential-provider-web-identity": "^3.972.63", - "@aws-sdk/nested-clients": "^3.997.31", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/credential-provider-imds": "^4.4.7", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-login": { - "version": "3.972.63", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.63.tgz", - "integrity": "sha512-GREWRrMj0XnNKMaVa/Mauoaui26qBEHu71WWqXbwZOu/jFQOnPZjTf7u0KtGKC8VGa6VUs9kDWGgocrKNLS9vw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/nested-clients": "^3.997.31", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.972.66", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.66.tgz", - "integrity": "sha512-f+qjRXZpz7sgzbc4QB+6nLKfyKFgRRXzWdXbsKPv/VhVRyHsDyq4yBWC/B75BAJpFIcUeI2XR/3gdWJ677zB4A==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/credential-provider-env": "^3.972.57", - "@aws-sdk/credential-provider-http": "^3.972.59", - "@aws-sdk/credential-provider-ini": "^3.973.1", - "@aws-sdk/credential-provider-process": "^3.972.57", - "@aws-sdk/credential-provider-sso": "^3.973.1", - "@aws-sdk/credential-provider-web-identity": "^3.972.63", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/credential-provider-imds": "^4.4.7", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.972.57", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.57.tgz", - "integrity": "sha512-TiVQhuU0pbhIZAUZacbPHMyzrIdiH+lnx+PMY/Pu/b93dJrq3wdZwzUJ0TPpvNxaqbHsxJvQZW3/h/beLiKq7Q==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.973.1", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.973.1.tgz", - "integrity": "sha512-3foTZUJ4821Ij60X7K3NJroygiZLnbBmarN+T//O2cjkISan90zElN3NBmgSlDrTQ7Gs6z/yO8V7h60QNcDZHQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/nested-clients": "^3.997.31", - "@aws-sdk/token-providers": "3.1083.0", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.972.63", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.63.tgz", - "integrity": "sha512-8qZLFhM69eKcS37m459ctPR05Qimycm/74OPVioe6wNZabMT54GYhwBju0+J656RkMasNSawWQu+c8CmBe3TUQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/nested-clients": "^3.997.31", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers": { - "version": "3.1081.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.1081.0.tgz", - "integrity": "sha512-UHWvxd1F5nfBXBRXtQaXWoNT8CYKXZovLQOyz6XZlgFTGc2mWzzPGspOfnh49jwvB2qzsdH046i9jnnmND+64w==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/client-cognito-identity": "3.1081.0", - "@aws-sdk/core": "^3.974.29", - "@aws-sdk/credential-provider-cognito-identity": "^3.972.54", - "@aws-sdk/credential-provider-env": "^3.972.55", - "@aws-sdk/credential-provider-http": "^3.972.57", - "@aws-sdk/credential-provider-ini": "^3.972.62", - "@aws-sdk/credential-provider-login": "^3.972.61", - "@aws-sdk/credential-provider-node": "^3.972.64", - "@aws-sdk/credential-provider-process": "^3.972.55", - "@aws-sdk/credential-provider-sso": "^3.972.61", - "@aws-sdk/credential-provider-web-identity": "^3.972.61", - "@aws-sdk/nested-clients": "^3.997.29", - "@aws-sdk/types": "^3.973.15", - "@smithy/core": "^3.29.0", - "@smithy/credential-provider-imds": "^4.4.5", - "@smithy/types": "^4.15.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/dynamodb-codec": { - "version": "3.973.12", - "resolved": "https://registry.npmjs.org/@aws-sdk/dynamodb-codec/-/dynamodb-codec-3.973.12.tgz", - "integrity": "sha512-E+qpJPN1QLzfeVDQe1gVmMiHu9PTJWwXqSQjIt8mH5OQXmds2J/IN+Ar6Oa9ZhhuPZb4fPkcgZg4UEpwJM90NA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.974.12", - "@smithy/core": "^3.24.2", - "@smithy/types": "^4.14.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/endpoint-cache": { - "version": "3.972.5", - "resolved": "https://registry.npmjs.org/@aws-sdk/endpoint-cache/-/endpoint-cache-3.972.5.tgz", - "integrity": "sha512-itVdge0NozgtgmtbZ25FVwWU3vGlE7x7feE/aOEJNkQfEpbkrF8Rj1QmnK+2blFfYE1xWt/iU+6/jUp/pv1+MA==", - "license": "Apache-2.0", - "dependencies": { - "mnemonist": "0.38.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/lib-storage": { - "version": "3.1085.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.1085.0.tgz", - "integrity": "sha512-S+yCGIMxQ5Zs2A5ZDdYfXwOxu5kKjBaCQVOxp6+mnwCQYXUNkBD/aKCnW1eniMTavzz3YidhD5eTFpDlcUv2gQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.29.2", - "@smithy/types": "^4.16.0", - "buffer": "5.6.0", - "events": "3.3.0", - "stream-browserify": "3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-s3": "^3.1085.0" - } - }, - "node_modules/@aws-sdk/lib-storage/node_modules/buffer": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", - "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", - "dev": true, - "license": "MIT", - "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - }, - "node_modules/@aws-sdk/lib-storage/node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/@aws-sdk/middleware-endpoint-discovery": { - "version": "3.972.13", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.972.13.tgz", - "integrity": "sha512-1r6EkFdSQ4quTP3pW8yWIcYuyDwdwdBxGr+kfuPFYE3DqR+1gBc6NyJneAyoIs+wc/cUfnyJ4ZYC0T2SQTxP9A==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/endpoint-cache": "^3.972.5", - "@aws-sdk/types": "^3.973.8", - "@smithy/core": "^3.24.2", - "@smithy/types": "^4.14.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.972.13", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.972.13.tgz", - "integrity": "sha512-EA3+u2LD3kGcfRNmCSjyJuzX4XvG4zYv57i4ZksH+1IEciuSyHQGvzivEz7vZ+jbRPdAAe7WWKy/4M8InCKDcw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.974.12", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/middleware-logger": { - "version": "3.972.12", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.972.12.tgz", - "integrity": "sha512-NxB2dS4/mV3380hNkC72TkhMaLLjWGGBeTAEucqlJptVVovTbNmQWZLwaMC74ICo9NZHmFiBVVTHzDfAh/3y6Q==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.974.12", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.972.14", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.972.14.tgz", - "integrity": "sha512-bqL+upATpOJ/7px4IVfMVxcM6Lyt9uRizmEx3mNg4N6+IQlnOaYXXOJ4TNX6P0mKPPW0lwn9ZW8QEhXwQuCH9A==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.974.12", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/middleware-sdk-api-gateway": { - "version": "3.972.12", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-api-gateway/-/middleware-sdk-api-gateway-3.972.12.tgz", - "integrity": "sha512-Fb9oEuB3875hI/187dj4MclC/nlBzc/iTEOYecUjFoipRGxqBE38XPqiE0g8oshs9rJXCZJousW0e/aElDFuDA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "^3.973.8", - "@smithy/core": "^3.24.2", - "@smithy/types": "^4.14.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/middleware-sdk-s3": { - "version": "3.972.62", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.972.62.tgz", - "integrity": "sha512-k8JJwYXVYlOOjWnPZDThQS1xDFJgi5Dokt73qFlDtrZAbdcint5aIdjB9XgJAAQVP5OoqcefQmh1FYXiPpvsvw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/signature-v4-multi-region": "^3.996.39", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/middleware-sdk-sqs": { - "version": "3.972.24", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sqs/-/middleware-sdk-sqs-3.972.24.tgz", - "integrity": "sha512-ej3vwWFzTP2B0FxlU2JelMaxplEncflFv2ARsoMQ9TXI/yfmsPEZw8zkOdsQp3rMEJ/vN7iKTYDYIcpeMmDRoQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "^3.973.8", - "@smithy/core": "^3.24.2", - "@smithy/types": "^4.14.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.972.42", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.42.tgz", - "integrity": "sha512-U7jjlJKQnuUlI2swC2umFLFzLAxMLudSRFv+Bqk2F8ORmr5bG25qsFxGm4GEFwoZeGaFFnAFmTY0xReVRfyl2A==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.974.12", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/nested-clients": { - "version": "3.997.31", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.997.31.tgz", - "integrity": "sha512-BDHTpwcsZHEBNEJzOg/B1BkFYJxAXY50dau/NyVWs3d51F0WgIUGSWZot/Os+N3KpDhXeaXnz37mWffAvduREw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/signature-v4-multi-region": "^3.996.39", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/fetch-http-handler": "^5.6.4", - "@smithy/node-http-handler": "^4.9.4", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/region-config-resolver": { - "version": "3.972.16", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.972.16.tgz", - "integrity": "sha512-/YaivCvKUkEeMN9VTKBSvBn5w/4osAM1YboM58DKaLF/vqFGf/FdJCLmppqiPPJWZaXcASqByVjc3evE7KHKdA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.974.12", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/signature-v4-multi-region": { - "version": "3.996.39", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.39.tgz", - "integrity": "sha512-8+srXqYIF8KYMLC4FxMLEM5Ek7kUNibJu1R4m8/fUhhNYIZZz26oGtKkCr8I/HiG2fFQxBvaGgQZT4/mqRCSnA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "^3.974.0", - "@smithy/signature-v4": "^5.6.3", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/token-providers": { - "version": "3.1083.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1083.0.tgz", - "integrity": "sha512-s0woKnxuHrExLc5L2ArIH5BMkbonHPtt+5hSBM8oknp9M6QTuUmmAmJ2E0EdzCGONrO+8+ADPqvv6UX0nNcc7A==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.975.1", - "@aws-sdk/nested-clients": "^3.997.31", - "@aws-sdk/types": "^3.974.0", - "@smithy/core": "^3.29.2", - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/types": { - "version": "3.974.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.974.0.tgz", - "integrity": "sha512-QIBrw90CDm4O0UaIIzkU6DrFdeJzEb2Va5EPEVpyldj6sHJxB6cshhStJuhZxk3wR3PmjJlYsjPmY1kNb+KGBg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/util-dynamodb": { - "version": "3.974.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-dynamodb/-/util-dynamodb-3.974.0.tgz", - "integrity": "sha512-n/VlmXl4Yp9RS3i9+ALSr7Y+f1VrKJGX88Q8C67cg+xWzgv0n1+sE/7ZAxJZKEBNpP9tjmpgqWej8f1pWalbIA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-dynamodb": "3.974.0" - } - }, - "node_modules/@aws-sdk/util-endpoints": { - "version": "3.972.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.972.0.tgz", - "integrity": "sha512-6JHsl1V/a1ZW8D8AFfd4R52fwZPnZ5H4U6DS8m/bWT8qad72NvbOFAC7U2cDtFs2TShqUO3TEiX/EJibtY3ijg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.972.0", - "@smithy/types": "^4.12.0", - "@smithy/url-parser": "^4.2.8", - "@smithy/util-endpoints": "^3.2.8", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/util-endpoints/node_modules/@aws-sdk/types": { - "version": "3.972.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.972.0.tgz", - "integrity": "sha512-U7xBIbLSetONxb2bNzHyDgND3oKGoIfmknrEVnoEU4GUSs+0augUOIn9DIWGUO2ETcRFdsRUnmx9KhPT9Ojbug==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.12.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/util-locate-window": { - "version": "3.965.5", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.965.5.tgz", - "integrity": "sha512-WhlJNNINQB+9qtLtZJcpQdgZw3SCDCpXdUJP7cToGwHbCWCnRckGlc6Bx/OhWwIYFNAn+FIydY8SZ0QmVu3xTQ==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.972.13", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.972.13.tgz", - "integrity": "sha512-wfk9ZdVwh187gdGXB1EyAoprwjSMt/bSfVtva+OaZx+LyNdKD7smlZf611yMd42UpfQ9vaS8NOftjSajgpdd+w==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.974.12", - "tslib": "^2.6.2" - } - }, - "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.973.28", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.973.28.tgz", - "integrity": "sha512-A2l/PTRzsOS9L8dmZbXtDyJQgeeX+qjqLJ+fr0UU5Dz0AUQMuxgZCPSLKZgUDlHAmLFuk34owdMEvJxmDTBgRg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.974.12", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/xml-builder": { - "version": "3.972.34", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.34.tgz", - "integrity": "sha512-wHhWL1y7sN3enBA8POrPpQM5jCcmu2ozyhbRei4c8OjVcEaEs6yLucLa/pla457ggS/ysuy7bosagz3HaJkZXA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.16.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws/lambda-invoke-store": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.3.0.tgz", - "integrity": "sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", - "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", - "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", - "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", - "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", - "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", - "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", - "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", - "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", - "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", - "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", - "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", - "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", - "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", - "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", - "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", - "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", - "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", - "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", - "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", - "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", - "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", - "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", - "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", - "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", - "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", - "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@hapi/accept": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@hapi/accept/-/accept-6.0.3.tgz", - "integrity": "sha512-p72f9k56EuF0n3MwlBNThyVE5PXX40g+aQh+C/xbKrfzahM2Oispv3AXmOIU51t3j77zay1qrX7IIziZXspMlw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/boom": "^10.0.1", - "@hapi/hoek": "^11.0.2" - } - }, - "node_modules/@hapi/ammo": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@hapi/ammo/-/ammo-6.0.1.tgz", - "integrity": "sha512-pmL+nPod4g58kXrMcsGLp05O2jF4P2Q3GiL8qYV7nKYEh3cGf+rV4P5Jyi2Uq0agGhVU63GtaSAfBEZOlrJn9w==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/hoek": "^11.0.2" - } - }, - "node_modules/@hapi/b64": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@hapi/b64/-/b64-6.0.1.tgz", - "integrity": "sha512-ZvjX4JQReUmBheeCq+S9YavcnMMHWqx3S0jHNXWIM1kQDxB9cyfSycpVvjfrKcIS8Mh5N3hmu/YKo4Iag9g2Kw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/hoek": "^11.0.2" - } - }, - "node_modules/@hapi/boom": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/@hapi/boom/-/boom-10.0.1.tgz", - "integrity": "sha512-ERcCZaEjdH3OgSJlyjVk8pHIFeus91CjKP3v+MpgBNp5IvGzP2l/bRiD78nqYcKPaZdbKkK5vDBVPd2ohHBlsA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/hoek": "^11.0.2" - } - }, - "node_modules/@hapi/bounce": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@hapi/bounce/-/bounce-3.0.2.tgz", - "integrity": "sha512-d0XmlTi3H9HFDHhQLjg4F4auL1EY3Wqj7j7/hGDhFFe6xAbnm3qiGrXeT93zZnPH8gH+SKAFYiRzu26xkXcH3g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/boom": "^10.0.1", - "@hapi/hoek": "^11.0.2" - } - }, - "node_modules/@hapi/bourne": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-3.0.0.tgz", - "integrity": "sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@hapi/call": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@hapi/call/-/call-9.0.1.tgz", - "integrity": "sha512-uPojQRqEL1GRZR4xXPqcLMujQGaEpyVPRyBlD8Pp5rqgIwLhtveF9PkixiKru2THXvuN8mUrLeet5fqxKAAMGg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/boom": "^10.0.1", - "@hapi/hoek": "^11.0.2" - } - }, - "node_modules/@hapi/catbox": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/@hapi/catbox/-/catbox-12.1.1.tgz", - "integrity": "sha512-hDqYB1J+R0HtZg4iPH3LEnldoaBsar6bYp0EonBmNQ9t5CO+1CqgCul2ZtFveW1ReA5SQuze9GPSU7/aecERhw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/boom": "^10.0.1", - "@hapi/hoek": "^11.0.2", - "@hapi/podium": "^5.0.0", - "@hapi/validate": "^2.0.1" - } - }, - "node_modules/@hapi/catbox-memory": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@hapi/catbox-memory/-/catbox-memory-6.0.2.tgz", - "integrity": "sha512-H1l4ugoFW/ZRkqeFrIo8p1rWN0PA4MDTfu4JmcoNDvnY975o29mqoZblqFTotxNHlEkMPpIiIBJTV+Mbi+aF0g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/boom": "^10.0.1", - "@hapi/hoek": "^11.0.2" - } - }, - "node_modules/@hapi/content": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@hapi/content/-/content-6.0.2.tgz", - "integrity": "sha512-OKyCOTjNR1hftwSjk9ueyAQTw8AwapvzBrPIWMGn39vhR5PmqLdYFmLc35bsSBye7gSMnlkXfc679bUdMIcRyQ==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/boom": "^10.0.0" - } - }, - "node_modules/@hapi/cryptiles": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@hapi/cryptiles/-/cryptiles-6.0.3.tgz", - "integrity": "sha512-r6VKalpbMHz4ci3gFjFysBmhwCg70RpYZy6OkjEpdXzAYnYFX5XsW7n4YMJvuIYpnMwLxGUjK/cBhA7X3JDvXw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/boom": "^10.0.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@hapi/file": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@hapi/file/-/file-3.0.0.tgz", - "integrity": "sha512-w+lKW+yRrLhJu620jT3y+5g2mHqnKfepreykvdOcl9/6up8GrQQn+l3FRTsjHTKbkbfQFkuksHpdv2EcpKcJ4Q==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@hapi/h2o2": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/@hapi/h2o2/-/h2o2-10.0.4.tgz", - "integrity": "sha512-dvD8+Y/Okc0fh0blqaYCLIrcy0+1LqIhMr7hjk8elLQZ9mkw2hKFB9dFKuRfWf+1nvHpGlW+PwccqkdebynQbg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/boom": "^10.0.1", - "@hapi/hoek": "^11.0.2", - "@hapi/validate": "^2.0.1", - "@hapi/wreck": "^18.0.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@hapi/hapi": { - "version": "21.4.9", - "resolved": "https://registry.npmjs.org/@hapi/hapi/-/hapi-21.4.9.tgz", - "integrity": "sha512-YnecZOVx2AD08VvPl0ZaFS0MjEHqg+InGRmBRli731ct+VwI++dpu3BIYA1Z4SMr6HUAnpyvbQ1aq5woe3fBWg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/accept": "^6.0.3", - "@hapi/ammo": "^6.0.1", - "@hapi/boom": "^10.0.1", - "@hapi/bounce": "^3.0.2", - "@hapi/call": "^9.0.1", - "@hapi/catbox": "^12.1.1", - "@hapi/catbox-memory": "^6.0.2", - "@hapi/heavy": "^8.0.1", - "@hapi/hoek": "^11.0.7", - "@hapi/mimos": "^7.0.1", - "@hapi/podium": "^5.0.2", - "@hapi/shot": "^6.0.2", - "@hapi/somever": "^4.1.1", - "@hapi/statehood": "^8.2.1", - "@hapi/subtext": "^8.1.3", - "@hapi/teamwork": "^6.0.1", - "@hapi/topo": "^6.0.2", - "@hapi/validate": "^2.0.1" - }, - "engines": { - "node": ">=14.15.0" - } - }, - "node_modules/@hapi/heavy": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@hapi/heavy/-/heavy-8.0.1.tgz", - "integrity": "sha512-gBD/NANosNCOp6RsYTsjo2vhr5eYA3BEuogk6cxY0QdhllkkTaJFYtTXv46xd6qhBVMbMMqcSdtqey+UQU3//w==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/boom": "^10.0.1", - "@hapi/hoek": "^11.0.2", - "@hapi/validate": "^2.0.1" - } - }, - "node_modules/@hapi/hoek": { - "version": "11.0.7", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-11.0.7.tgz", - "integrity": "sha512-HV5undWkKzcB4RZUusqOpcgxOaq6VOAH7zhhIr2g3G8NF/MlFO75SjOr2NfuSx0Mh40+1FqCkagKLJRykUWoFQ==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@hapi/iron": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@hapi/iron/-/iron-7.0.1.tgz", - "integrity": "sha512-tEZnrOujKpS6jLKliyWBl3A9PaE+ppuL/+gkbyPPDb/l2KSKQyH4lhMkVb+sBhwN+qaxxlig01JRqB8dk/mPxQ==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/b64": "^6.0.1", - "@hapi/boom": "^10.0.1", - "@hapi/bourne": "^3.0.0", - "@hapi/cryptiles": "^6.0.1", - "@hapi/hoek": "^11.0.2" - } - }, - "node_modules/@hapi/mimos": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@hapi/mimos/-/mimos-7.0.1.tgz", - "integrity": "sha512-b79V+BrG0gJ9zcRx1VGcCI6r6GEzzZUgiGEJVoq5gwzuB2Ig9Cax8dUuBauQCFKvl2YWSWyOc8mZ8HDaJOtkew==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/hoek": "^11.0.2", - "mime-db": "^1.52.0" - } - }, - "node_modules/@hapi/nigel": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@hapi/nigel/-/nigel-5.0.1.tgz", - "integrity": "sha512-uv3dtYuB4IsNaha+tigWmN8mQw/O9Qzl5U26Gm4ZcJVtDdB1AVJOwX3X5wOX+A07qzpEZnOMBAm8jjSqGsU6Nw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/hoek": "^11.0.2", - "@hapi/vise": "^5.0.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@hapi/pez": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@hapi/pez/-/pez-6.1.1.tgz", - "integrity": "sha512-yg2OS1tC0S1sHXvhUtWsfRn6lrKl9jKtRhZ+EI0woOW/gqX5vM2PZ1459ypCvCYDRLJ9nIyueeEH5MJV1ZDqIg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/b64": "^6.0.1", - "@hapi/boom": "^10.0.1", - "@hapi/content": "^6.0.1", - "@hapi/hoek": "^11.0.7", - "@hapi/nigel": "^5.0.1" - } - }, - "node_modules/@hapi/podium": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@hapi/podium/-/podium-5.0.2.tgz", - "integrity": "sha512-T7gf2JYHQQfEfewTQFbsaXoZxSvuXO/QBIGljucUQ/lmPnTTNAepoIKOakWNVWvo2fMEDjycu77r8k6dhreqHA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/hoek": "^11.0.2", - "@hapi/teamwork": "^6.0.0", - "@hapi/validate": "^2.0.1" - } - }, - "node_modules/@hapi/shot": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@hapi/shot/-/shot-6.0.2.tgz", - "integrity": "sha512-WKK1ShfJTrL1oXC0skoIZQYzvLsyMDEF8lfcWuQBjpjCN29qivr9U36ld1z0nt6edvzv28etNMOqUF4klnHryw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/hoek": "^11.0.2", - "@hapi/validate": "^2.0.1" - } - }, - "node_modules/@hapi/somever": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@hapi/somever/-/somever-4.1.1.tgz", - "integrity": "sha512-lt3QQiDDOVRatS0ionFDNrDIv4eXz58IibQaZQDOg4DqqdNme8oa0iPWcE0+hkq/KTeBCPtEOjDOBKBKwDumVg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/bounce": "^3.0.1", - "@hapi/hoek": "^11.0.2" - } - }, - "node_modules/@hapi/statehood": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/@hapi/statehood/-/statehood-8.2.1.tgz", - "integrity": "sha512-xf72TG/QINW26jUu+uL5H+crE1o8GplIgfPWwPZhnAGJzetIVAQEQYvzq+C0aEVHg5/lMMtQ+L9UryuSa5Yjkg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/boom": "^10.0.1", - "@hapi/bounce": "^3.0.1", - "@hapi/bourne": "^3.0.0", - "@hapi/cryptiles": "^6.0.1", - "@hapi/hoek": "^11.0.2", - "@hapi/iron": "^7.0.1", - "@hapi/validate": "^2.0.1" - } - }, - "node_modules/@hapi/subtext": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@hapi/subtext/-/subtext-8.1.3.tgz", - "integrity": "sha512-WTpEZQjBP3UJ3gGunNl3w5Ao1EOJsuu2vttZ2KEcG+csSLxc0dI6VIkl2md2jDlHiQ2ARAoqdSUScy05A/NHtA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/boom": "^10.0.1", - "@hapi/bourne": "^3.0.0", - "@hapi/content": "^6.0.2", - "@hapi/file": "^3.0.0", - "@hapi/hoek": "^11.0.7", - "@hapi/pez": "^6.1.1", - "@hapi/wreck": "^18.1.1" - } - }, - "node_modules/@hapi/teamwork": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@hapi/teamwork/-/teamwork-6.0.1.tgz", - "integrity": "sha512-52OXRslUfYwXAOG8k58f2h2ngXYQGP0x5RPOo+eWA/FtyLgHjGMrE3+e9LSXP/0q2YfHAK5wj9aA9DTy1K+kyQ==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@hapi/topo": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-6.0.2.tgz", - "integrity": "sha512-KR3rD5inZbGMrHmgPxsJ9dbi6zEK+C3ZwUwTa+eMwWLz7oijWUTWD2pMSNNYJAU6Qq+65NkxXjqHr/7LM2Xkqg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/hoek": "^11.0.2" - } - }, - "node_modules/@hapi/validate": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@hapi/validate/-/validate-2.0.1.tgz", - "integrity": "sha512-NZmXRnrSLK8MQ9y/CMqE9WSspgB9xA41/LlYR0k967aSZebWr4yNrpxIbov12ICwKy4APSlWXZga9jN5p6puPA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/hoek": "^11.0.2", - "@hapi/topo": "^6.0.1" - } - }, - "node_modules/@hapi/vise": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@hapi/vise/-/vise-5.0.1.tgz", - "integrity": "sha512-XZYWzzRtINQLedPYlIkSkUr7m5Ddwlu99V9elh8CSygXstfv3UnWIXT0QD+wmR0VAG34d2Vx3olqcEhRRoTu9A==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/hoek": "^11.0.2" - } - }, - "node_modules/@hapi/wreck": { - "version": "18.1.2", - "resolved": "https://registry.npmjs.org/@hapi/wreck/-/wreck-18.1.2.tgz", - "integrity": "sha512-3dMnV2pfhQiyEqu8DL3VBmxkdLiRDiiUDuG79Dp+UK1gL9ZxAfDOUhB6k3D5MLqcgJJ1IARyGFhwoc1NITr/pg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/boom": "^10.0.1", - "@hapi/bourne": "^3.0.0", - "@hapi/hoek": "^11.0.2" - } - }, - "node_modules/@jsep-plugin/assignment": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@jsep-plugin/assignment/-/assignment-1.3.0.tgz", - "integrity": "sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.16.0" - }, - "peerDependencies": { - "jsep": "^0.4.0||^1.0.0" - } - }, - "node_modules/@jsep-plugin/regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@jsep-plugin/regex/-/regex-1.0.4.tgz", - "integrity": "sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.16.0" - }, - "peerDependencies": { - "jsep": "^0.4.0||^1.0.0" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@smithy/config-resolver": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.5.3.tgz", - "integrity": "sha512-TpS6Am5zSEtx3ow7VynThEL7UwRM06zZZcmFaP6Ij9hqKPfsFhTYCLcgU7gjFjw9QAI2kzwXrfS7InH8BivJTA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/core": { - "version": "3.29.3", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.29.3.tgz", - "integrity": "sha512-L+Ys6ecjk5vwPMAKHBpPKlJ3DkqwNcnfEISXBZIsVvWG/XKXfsAP8mwIYlTeLcd2ElHdesPI8OuOmJSFAPhm6A==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/credential-provider-imds": { - "version": "4.4.8", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.4.8.tgz", - "integrity": "sha512-q9J7JTiXrAhB8sDp4px97uEPT7CwKH61Co78grdNQvU8QZAdiuaSRhP0tUVf2ogy36RZTrlMU1rBmDEH+cnkiA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.29.3", - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/fetch-http-handler": { - "version": "5.6.5", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.6.5.tgz", - "integrity": "sha512-SuqeisTyPoiIPtIYru/sGxGyXzmZ+8nnFOhC+qRPglt06Ebd1yH//CDltZB2J/3WBNVhwfUaZ0EtHB3cm2X32g==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.29.3", - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/hash-node": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.3.3.tgz", - "integrity": "sha512-tSUA38sM7kzMoLhqQ2aCGTwLXovjurz3jjG+a0sxqD4qT/4FhQr/wxMdhCumT70giM+axC1pPjimAHLlEQCfzw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/invalid-dependency": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.3.3.tgz", - "integrity": "sha512-wUWowbCm7DGczl6bfLI6wGGtoxwN5Pon8DhF0Q8AA4NvgLwYfLo3h2DWI7sHr33lLcEsyTLQKeUeTHydqSfQ5Q==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/is-array-buffer": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", - "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/md5-js": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.3.3.tgz", - "integrity": "sha512-pFw8gEMrHw9BbRwNm//UU4WgnVO7+dhfFRaSAkFPfwslWU2LXt0mM+oap3iFwGbdD8kuAWIeOAxqSiamOcM3Dw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-compression": { - "version": "4.5.8", - "resolved": "https://registry.npmjs.org/@smithy/middleware-compression/-/middleware-compression-4.5.8.tgz", - "integrity": "sha512-ODHXD5tDW3+25pfiLjJ2ZTIHRfWWxqVGPqIMz1NjmiV4bG4i1S0kuibHxik6WXibR03nmDGMiI1/hF6647F/Zg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.29.3", - "@smithy/types": "^4.16.1", - "fflate": "0.8.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-content-length": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.3.3.tgz", - "integrity": "sha512-Up1XAYnj6oxFBypWpkhNpgX+yReQxkKAV/iLaeP0KVLb2oTkmA9X+UJuGBVvEA9uZIN06y0irDi7sBMuTZMVJg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-endpoint": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.5.3.tgz", - "integrity": "sha512-p60HGFflWsJC6V9GAYeFgbfORn+9ILx8FqgMa/8PzA0rhIUxF57EKoOR4Irs6oe1oy8RLzhjhcGS8CBtPv/t+Q==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-retry": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.6.3.tgz", - "integrity": "sha512-MnfYnJs3cBXK3ZBqbPzXRPHIp+QtgpkX5NogcUOWHPU5GbgTAQSIfPLi91lTcEbkFDcH2YbgjLPQjWeyQ689rA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-serde": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.3.3.tgz", - "integrity": "sha512-RUVCZgn92izDAARs5OJSM2+KWSfTRvQWwN9t0MmiybT3pquRgDx9vD9t/YZjd/5lwcFbsNuPojJSddYQEZGeWw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-stack": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.3.3.tgz", - "integrity": "sha512-+BPabWluqxo3EfMMvOgnAmPtWnCSzj+gf5mJ27wTZUbvS0hpdUIU1g80R01bEGKZx4JCi8P58jAXD9FUGMjhwA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/node-config-provider": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.4.3.tgz", - "integrity": "sha512-vDtz5OuytrjP4o9GtAOz1JloN003p94utJIQeO0WAjorhpafFFjpbDOrP6btPoCN3UxaU/U84OIEt5dM7ZRRLA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/node-http-handler": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.9.5.tgz", - "integrity": "sha512-bNqdxTQTxmLbomSmlkZFz8L6B/feQ2HHzw4L2zY7Ecp2XffYAZq2uzdWDdxJHJFbEvqd+SRuluJso0P8+xPdbw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.29.3", - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/protocol-http": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.4.3.tgz", - "integrity": "sha512-P16TBD/d8ZcD9MHQ0ubQ9BbOYSd5HZKbHOLsyFWxKk2oBEoghbRFPfGOoqToZX1yrfLITXRylL16EyPP4IzLPg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/signature-v4": { - "version": "5.6.4", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.6.4.tgz", - "integrity": "sha512-B89bpf2t/y/wia6LZ+4JfHXYQT9PnVftsH05rgJKKIStS7r/4XSs9HOjtPoLtgcA6HCW9jVqX5DBbq7E0PAkiQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.29.3", - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/smithy-client": { - "version": "4.13.3", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.13.3.tgz", - "integrity": "sha512-Z8mQ+YryjP5krDadV6unnp5035L4S1brafXpTiRmjPweKSaQ6X9CYDYWvmEggXjDIa1oufX/2a/bdwu8EIz/lw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.3", - "@smithy/types": "^4.14.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/types": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.16.1.tgz", - "integrity": "sha512-0JFs3V2y2M9tKW5na/qxe69Zv+uxLMO7QBbhxF/FHu/Gp2NFZAAL9tWl9PU02xxo07pb3G9FTyjNc6D5uZrJIg==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/url-parser": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.3.3.tgz", - "integrity": "sha512-TsMTAOnjuMOv1zJBw8cfYGWhopyc3og8tZX/KuyCPjg7V3ji3f4YjFOVu843UjBmrfS/+X6kwFv5ZKg7sSm1bQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-base64": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.4.3.tgz", - "integrity": "sha512-91lxjhFpAktA9yPBxniqVR/NSH9zyjMjLmoa+jbQHQFR9WiJA+n61T7HBrfh5APdEoAledJwGq8l4cS+ZJFUnQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-body-length-browser": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.3.3.tgz", - "integrity": "sha512-/M6Ya1Fjq8hg3rYjiwwqTen6s1bAa3U3g/2eicBaBQfaoa4ymLUke/x4T8mwb9dSq/L8TQ4YgndS0MaB9ShgmA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-body-length-node": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.3.3.tgz", - "integrity": "sha512-M+zdSrevWj0grtZx2RBULPUyjTq1aB+n+13Hrm9owiGpow6DqY/WqiSj6sHVQy/rKp0j7NzV3TNf2LrwDel8JQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-buffer-from": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", - "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/is-array-buffer": "^2.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/util-defaults-mode-browser": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.4.3.tgz", - "integrity": "sha512-Q60hxKkMEkmBsOEzxlMWEymBWov0dtWGgoJhOUs6mE8k2FDPjK8NlsRdMkmO80n2pwzreHtrYcX5jiRP7ZkP3w==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-defaults-mode-node": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.3.3.tgz", - "integrity": "sha512-RYj+8gr95WiiBqvVghoRvL12NS9ryvLyufp7FOs7EzKwGX0W5gOVlXdCrFkJScSf8gxdjQMRyIZ3Y82/MvXQ3Q==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-endpoints": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.5.3.tgz", - "integrity": "sha512-2JqSmzQtKDKqBckLl/9NXTL1fY+zQBU5fNGMpud7AT65vql0tVFhb2UEZNZmLSHayLeD+X/Qzn84oXw5KS+KSQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-middleware": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.3.3.tgz", - "integrity": "sha512-8NZwlQ+nyAIWn9YZxH14FC8ca0i6ZGW1aJyPjD+zMZz3k9jOhXXKhdCSRvjmcSYLW42uhbrxavXqMkrTKHyY3A==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-retry": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.4.3.tgz", - "integrity": "sha512-8RJXeU5lEhdNfXm4XAuHlf6VtNzd279Z2FJZSR7VaELYCR46ffgjJBSjc+3UAy7V1YqBOLV0G9gWhLB/nA44nA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-utf8": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.3.3.tgz", - "integrity": "sha512-c1QpRBn3aMsoqE64dd4Imgjy8Pynfw+eR7GkjElquxUFSnezwYVaOFm8JcYa+Bo/5ssbEyPKcT3+4bmrWYh6eQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-waiter": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.4.3.tgz", - "integrity": "sha512-WSHSF865zDGFGtJdMmYPI2Blq/MbUrn5CB4bLDg4ARbQ9z7oA87ZZ/FSiwNZbQrU/EiVyl9lpINswALgI4lZXA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/agent-base": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-9.0.0.tgz", - "integrity": "sha512-TQf59BsZnytt8GdJKLPfUZ54g/iaUL2OWDSFCCvMOhsHduDQxO8xC4PNeyIkVcA5KwL2phPSv0douC0fgWzmnA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 20" - } - }, - "node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", - "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.1.0" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/array-unflat-js": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/array-unflat-js/-/array-unflat-js-0.1.3.tgz", - "integrity": "sha512-8pljkLj4vfz2i7Tf3yB31tRrszjP8/kwIyABGfcZ1GcHlvdUB0Sbx0WzQkOPMqUBxa/bu4+/NAyHEpDtZJzlJw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.18.0" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/bowser": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.14.1.tgz", - "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==", - "license": "MIT" - }, - "node_modules/boxen": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.1.1.tgz", - "integrity": "sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-align": "^3.0.1", - "camelcase": "^7.0.1", - "chalk": "^5.2.0", - "cli-boxes": "^3.0.0", - "string-width": "^5.1.2", - "type-fest": "^2.13.0", - "widest-line": "^4.0.1", - "wrap-ansi": "^8.1.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/boxen/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/boxen/node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/boxen/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "license": "MIT" - }, - "node_modules/boxen/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/boxen/node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/camelcase": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", - "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-boxes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", - "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-color": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.4.tgz", - "integrity": "sha512-zlnpg0jNcibNrO7GG9IeHH7maWFeCz+Ja1wx/7tZNU5ASSSSZ+/qZciM0/LHCYxSdqv5h2sdbQ/PXYdOuetXvA==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "^1.0.1", - "es5-ext": "^0.10.64", - "es6-iterator": "^2.0.3", - "memoizee": "^0.4.15", - "timers-ext": "^0.1.7" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/cli-sprintf-format": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cli-sprintf-format/-/cli-sprintf-format-1.1.1.tgz", - "integrity": "sha512-BbEjY9BEdA6wagVwTqPvmAwGB24U93rQPBFZUT8lNCDxXzre5LFHQUTJc70czjgUomVg8u8R5kW8oY9DYRFNeg==", - "dev": true, - "license": "ISC", - "dependencies": { - "cli-color": "^2.0.1", - "es5-ext": "^0.10.53", - "sprintf-kit": "^2.0.1", - "supports-color": "^6.1.0" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/cli-sprintf-format/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/cli-sprintf-format/node_modules/supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/content-disposition": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-2.0.1.tgz", - "integrity": "sha512-e+H0ZXHSWYrENhQzw1LPuP4oF5MzVKmDU6d3hxlvaPEYLLg62MxtQNPRx4SYSuYJSBUgnQIG4HIN2tEtNv7Dog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/cron-parser": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz", - "integrity": "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "luxon": "^3.2.1" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/d": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", - "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", - "dev": true, - "license": "ISC", - "dependencies": { - "es5-ext": "^0.10.64", - "type": "^2.7.2" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/desm": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/desm/-/desm-1.3.1.tgz", - "integrity": "sha512-vgTAOosB1aHrmzjGnzFCbjvXbk8QAOC/36JxJhcBkeAuUy8QwRFxAWBHemiDpUB3cbrBruFUdzpUS21aocvaWg==", - "dev": true, - "license": "MIT" - }, - "node_modules/dotenv": { - "version": "16.6.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/dotenv-cli": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/dotenv-cli/-/dotenv-cli-7.4.4.tgz", - "integrity": "sha512-XkBYCG0tPIes+YZr4SpfFv76SQrV/LeCE8CI7JSEMi3VR9MvTihCGTOtbIexD6i2mXF+6px7trb1imVCXSNMDw==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.6", - "dotenv": "^16.3.0", - "dotenv-expand": "^10.0.0", - "minimist": "^1.2.6" - }, - "bin": { - "dotenv": "cli.js" - } - }, - "node_modules/dotenv-expand": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", - "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - } - }, - "node_modules/duration": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/duration/-/duration-0.2.2.tgz", - "integrity": "sha512-06kgtea+bGreF5eKYgI/36A6pLXggY7oR4p1pq4SmdFBn1ReOL5D8RhG64VrqfTTKNucqqtBAwEj8aB88mcqrg==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "1", - "es5-ext": "~0.10.46" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true, - "license": "MIT" - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/es5-ext": { - "version": "0.10.64", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", - "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", - "dev": true, - "hasInstallScript": true, - "license": "ISC", - "dependencies": { - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.3", - "esniff": "^2.0.1", - "next-tick": "^1.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", - "dev": true, - "license": "MIT", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-symbol": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", - "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "^1.0.2", - "ext": "^1.7.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/esbuild": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", - "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.28.1", - "@esbuild/android-arm": "0.28.1", - "@esbuild/android-arm64": "0.28.1", - "@esbuild/android-x64": "0.28.1", - "@esbuild/darwin-arm64": "0.28.1", - "@esbuild/darwin-x64": "0.28.1", - "@esbuild/freebsd-arm64": "0.28.1", - "@esbuild/freebsd-x64": "0.28.1", - "@esbuild/linux-arm": "0.28.1", - "@esbuild/linux-arm64": "0.28.1", - "@esbuild/linux-ia32": "0.28.1", - "@esbuild/linux-loong64": "0.28.1", - "@esbuild/linux-mips64el": "0.28.1", - "@esbuild/linux-ppc64": "0.28.1", - "@esbuild/linux-riscv64": "0.28.1", - "@esbuild/linux-s390x": "0.28.1", - "@esbuild/linux-x64": "0.28.1", - "@esbuild/netbsd-arm64": "0.28.1", - "@esbuild/netbsd-x64": "0.28.1", - "@esbuild/openbsd-arm64": "0.28.1", - "@esbuild/openbsd-x64": "0.28.1", - "@esbuild/openharmony-arm64": "0.28.1", - "@esbuild/sunos-x64": "0.28.1", - "@esbuild/win32-arm64": "0.28.1", - "@esbuild/win32-ia32": "0.28.1", - "@esbuild/win32-x64": "0.28.1" - } - }, - "node_modules/esniff": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", - "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "^1.0.1", - "es5-ext": "^0.10.62", - "event-emitter": "^0.3.5", - "type": "^2.7.2" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/execa/node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/execa/node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/execa/node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/execa/node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ext": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", - "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", - "dev": true, - "license": "ISC", - "dependencies": { - "type": "^2.7.2" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", - "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4.9.1" - } - }, - "node_modules/fastq": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", - "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fflate": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.1.tgz", - "integrity": "sha512-/exOvEuc+/iaUm105QIiOt4LpBdMTWsXxqR0HDF35vx3fmaKzw7354gTilCh5rkzEt8WYyG//ku3h3nRmd7CHQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/filename-reserved-regex": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-4.0.0.tgz", - "integrity": "sha512-9ZT504KxEQDamsOogZImAWGEN24R1uFAxU3ZS4AZqn2ooidmN68Olh7n4/RcA4lLatZztjA0ZSuxeLHVoCc8JA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/filenamify": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-7.0.2.tgz", - "integrity": "sha512-fz10TUqSZ1lG7ftW1KnRotJzMD8YRb6kaAQKpZJBLvqXXfFgIEpuazy1w2lK3zhMiBSdH/uF9LFlv5smJ2Jl1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "filename-reserved-regex": "^4.0.0" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/https-proxy-agent": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-9.1.0.tgz", - "integrity": "sha512-ag87y7cJJ9/3+GxFr8Oy4O5faDsGRGnBGsJj/YjOSsSx/5eadKLYTMPlzuR6obgoCDDm0abAAZitXXQkMOPSpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "9.0.0", - "debug": "^4.3.4", - "proxy-agent-negotiate": "1.1.0" - }, - "engines": { - "node": ">= 20" - } - }, - "node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=16.17.0" - } - }, - "node_modules/ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-inside-container/node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true, - "license": "MIT", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/java-invoke-local": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/java-invoke-local/-/java-invoke-local-0.0.6.tgz", - "integrity": "sha512-gZmQKe1QrfkkMjCn8Qv9cpyJFyogTYqkP5WCobX5RNaHsJzIV/6NvAnlnouOcwKr29QrxLGDGcqYuJ+ae98s1A==", - "dev": true, - "license": "MIT", - "bin": { - "java-invoke-local": "lib/cli.js" - } - }, - "node_modules/jose": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/jose/-/jose-5.10.0.tgz", - "integrity": "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, - "node_modules/js-string-escape": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", - "integrity": "sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/js-yaml": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", - "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/puzrin" - }, - { - "type": "github", - "url": "https://github.com/sponsors/nodeca" - } - ], - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsep": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jsep/-/jsep-1.4.0.tgz", - "integrity": "sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.16.0" - } - }, - "node_modules/json-cycle": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/json-cycle/-/json-cycle-1.5.0.tgz", - "integrity": "sha512-GOehvd5PO2FeZ5T4c+RxobeT5a1PiGpF4u9/3+UvrMU4bhnVqzJY7hm39wg8PDCqkU91fWGH8qjWR4bn+wgq9w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "license": "MIT" - }, - "node_modules/jsonfile": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", - "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonpath-plus": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-10.4.0.tgz", - "integrity": "sha512-T92WWatJXmhBbKsgH/0hl+jxjdXrifi5IKeMY02DWggRxX0UElcbVzPlmgLTbvsPeW1PasQ6xE2Q75stkhGbsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jsep-plugin/assignment": "^1.3.0", - "@jsep-plugin/regex": "^1.0.4", - "jsep": "^1.4.0" - }, - "bin": { - "jsonpath": "bin/jsonpath-cli.js", - "jsonpath-plus": "bin/jsonpath-cli.js" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/jsonschema": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.5.0.tgz", - "integrity": "sha512-K+A9hhqbn0f3pJX17Q/7H6yQfD/5OXgdrR5UE12gMXCiN9D5Xq2o5mddV2QEcX/bjla99ASsAAQUyMCCRWAEhw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/jszip": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", - "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", - "dev": true, - "license": "(MIT OR GPL-3.0-or-later)", - "dependencies": { - "lie": "~3.3.0", - "pako": "~1.0.2", - "readable-stream": "~2.3.6", - "setimmediate": "^1.0.5" - } - }, - "node_modules/jszip/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/jszip/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/jszip/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/lie": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", - "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "immediate": "~3.0.5" - } - }, - "node_modules/log": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/log/-/log-6.3.2.tgz", - "integrity": "sha512-ek8NRg/OPvS9ISOJNWNAz5vZcpYacWNFDWNJjj5OXsc6YuKacfey6wF04cXz/tOJIVrZ2nGSkHpAY5qKtF6ISg==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "^1.0.2", - "duration": "^0.2.2", - "es5-ext": "^0.10.64", - "event-emitter": "^0.3.5", - "sprintf-kit": "^2.0.2", - "type": "^2.7.3", - "uni-global": "^1.0.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/log-node": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/log-node/-/log-node-8.0.3.tgz", - "integrity": "sha512-1UBwzgYiCIDFs8A0rM2QdBFo8Wd8UQ0HrSTu/MNI+/2zN3NoHRj2fhplurAyuxTYUXu3Oohugq1jAn5s05u1MQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "ansi-regex": "^5.0.1", - "cli-color": "^2.0.1", - "cli-sprintf-format": "^1.1.1", - "d": "^1.0.1", - "es5-ext": "^0.10.53", - "sprintf-kit": "^2.0.1", - "supports-color": "^8.1.1", - "type": "^2.5.0" - }, - "engines": { - "node": ">=10.0" - }, - "peerDependencies": { - "log": "^6.0.0" - } - }, - "node_modules/long-timeout": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/long-timeout/-/long-timeout-0.1.1.tgz", - "integrity": "sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w==", - "dev": true, - "license": "MIT" - }, - "node_modules/lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "es5-ext": "~0.10.2" - } - }, - "node_modules/luxon": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz", - "integrity": "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/memoizee": { - "version": "0.4.17", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.17.tgz", - "integrity": "sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "^1.0.2", - "es5-ext": "^0.10.64", - "es6-weak-map": "^2.0.3", - "event-emitter": "^0.3.5", - "is-promise": "^2.2.2", - "lru-queue": "^0.1.0", - "next-tick": "^1.1.0", - "timers-ext": "^0.1.7" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, - "license": "MIT" - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", - "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/mnemonist": { - "version": "0.38.3", - "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.3.tgz", - "integrity": "sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw==", - "license": "MIT", - "dependencies": { - "obliterator": "^1.6.1" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/node-schedule": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/node-schedule/-/node-schedule-2.1.1.tgz", - "integrity": "sha512-OXdegQq03OmXEjt2hZP33W2YPs/E5BcFQks46+G2gAxs4gHOIVD1u7EqlYLYSKsaIpyKCK9Gbk0ta1/gjRSMRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "cron-parser": "^4.2.0", - "long-timeout": "0.1.1", - "sorted-array-functions": "^1.3.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/obliterator": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-1.6.1.tgz", - "integrity": "sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig==", - "license": "MIT" - }, - "node_modules/osls": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/osls/-/osls-4.0.0.tgz", - "integrity": "sha512-ti1s4IhJLfpdWtgyb3gj8slDs1KoucRU0jNyqGIaEGPGCODiJtFXXVM3cs52pQLi3Ig2RBeqHzhD84vWOLvSeQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@apidevtools/json-schema-ref-parser": "^15.3.5", - "@aws-sdk/client-api-gateway": "^3.1034.0", - "@aws-sdk/client-apigatewayv2": "^3.1034.0", - "@aws-sdk/client-cloudformation": "^3.1034.0", - "@aws-sdk/client-cloudwatch": "^3.1034.0", - "@aws-sdk/client-cloudwatch-logs": "^3.1034.0", - "@aws-sdk/client-cognito-identity-provider": "^3.1034.0", - "@aws-sdk/client-ecr": "^3.1034.0", - "@aws-sdk/client-eventbridge": "^3.1034.0", - "@aws-sdk/client-iam": "^3.1034.0", - "@aws-sdk/client-lambda": "^3.1034.0", - "@aws-sdk/client-s3": "^3.1034.0", - "@aws-sdk/client-ssm": "^3.1034.0", - "@aws-sdk/client-sts": "^3.1034.0", - "@aws-sdk/credential-providers": "^3.1034.0", - "@aws-sdk/lib-storage": "^3.1034.0", - "@smithy/core": "^3.23.16", - "@smithy/node-http-handler": "^4.6.1", - "ajv": "^8.12.0", - "ajv-formats": "^3.0.1", - "content-disposition": "^2.0.1", - "cross-spawn": "^7.0.6", - "dotenv": "^17.4.2", - "dotenv-expand": "^13.0.0", - "ext": "^1.7.0", - "fast-glob": "^3.3.3", - "fastest-levenshtein": "^1.0.16", - "filenamify": "^7.0.1", - "https-proxy-agent": "^9.0.0", - "js-yaml": "^4.3.0", - "json-cycle": "^1.5.0", - "log": "^6.3.1", - "log-node": "^8.0.3", - "memoizee": "^0.4.15", - "micromatch": "^4.0.5", - "mime-types": "^3.0.2", - "semver": "^7.5.3", - "signal-exit": "^4.1.0", - "tsx": "^4.20.3", - "type": "^2.7.2", - "undici": "^7.25.0", - "write-file-atomic": "^7.0.1", - "yauzl": "^3.3.0", - "yazl": "^3.3.1" - }, - "bin": { - "osls": "bin/serverless.js", - "serverless": "bin/serverless.js", - "sls": "bin/serverless.js" - }, - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - } - }, - "node_modules/osls/node_modules/dotenv": { - "version": "17.4.2", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz", - "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/osls/node_modules/dotenv-expand": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-13.0.0.tgz", - "integrity": "sha512-aBfBS8eYIeXmpHI9ThIlA7/WLq+SLt18iXUZhb52rW89QLKQFoIpPG1bPeewoPZsTyjSSO3T7234FBVUM1V2rA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "dotenv": "^17.4.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/p-memoize": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/p-memoize/-/p-memoize-7.1.1.tgz", - "integrity": "sha512-DZ/bONJILHkQ721hSr/E9wMz5Am/OTJ9P6LhLFo2Tu+jL8044tgc9LwHO8g4PiaYePnlVVRAJcKmgy8J9MVFrA==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^4.0.0", - "type-fest": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/p-memoize?sponsor=1" - } - }, - "node_modules/p-memoize/node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-memoize/node_modules/type-fest": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", - "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true, - "license": "(MIT AND Zlib)" - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true, - "license": "MIT" - }, - "node_modules/picomatch": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", - "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, - "license": "MIT" - }, - "node_modules/proxy-agent-negotiate": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-agent-negotiate/-/proxy-agent-negotiate-1.1.0.tgz", - "integrity": "sha512-N8IBcM3UgCVzz2L2Lqv8DVntDnnC8/hiV4nEDUPkqq72TPUgYWjQc+bdZlBPZK9LzPAvOY//gAt0S0DApoOXWQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 20" - }, - "peerDependencies": { - "kerberos": "^2.0.0" - }, - "peerDependenciesMeta": { - "kerberos": { - "optional": true - } - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/serverless": { - "name": "osls", - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/osls/-/osls-4.0.0.tgz", - "integrity": "sha512-ti1s4IhJLfpdWtgyb3gj8slDs1KoucRU0jNyqGIaEGPGCODiJtFXXVM3cs52pQLi3Ig2RBeqHzhD84vWOLvSeQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@apidevtools/json-schema-ref-parser": "^15.3.5", - "@aws-sdk/client-api-gateway": "^3.1034.0", - "@aws-sdk/client-apigatewayv2": "^3.1034.0", - "@aws-sdk/client-cloudformation": "^3.1034.0", - "@aws-sdk/client-cloudwatch": "^3.1034.0", - "@aws-sdk/client-cloudwatch-logs": "^3.1034.0", - "@aws-sdk/client-cognito-identity-provider": "^3.1034.0", - "@aws-sdk/client-ecr": "^3.1034.0", - "@aws-sdk/client-eventbridge": "^3.1034.0", - "@aws-sdk/client-iam": "^3.1034.0", - "@aws-sdk/client-lambda": "^3.1034.0", - "@aws-sdk/client-s3": "^3.1034.0", - "@aws-sdk/client-ssm": "^3.1034.0", - "@aws-sdk/client-sts": "^3.1034.0", - "@aws-sdk/credential-providers": "^3.1034.0", - "@aws-sdk/lib-storage": "^3.1034.0", - "@smithy/core": "^3.23.16", - "@smithy/node-http-handler": "^4.6.1", - "ajv": "^8.12.0", - "ajv-formats": "^3.0.1", - "content-disposition": "^2.0.1", - "cross-spawn": "^7.0.6", - "dotenv": "^17.4.2", - "dotenv-expand": "^13.0.0", - "ext": "^1.7.0", - "fast-glob": "^3.3.3", - "fastest-levenshtein": "^1.0.16", - "filenamify": "^7.0.1", - "https-proxy-agent": "^9.0.0", - "js-yaml": "^4.3.0", - "json-cycle": "^1.5.0", - "log": "^6.3.1", - "log-node": "^8.0.3", - "memoizee": "^0.4.15", - "micromatch": "^4.0.5", - "mime-types": "^3.0.2", - "semver": "^7.5.3", - "signal-exit": "^4.1.0", - "tsx": "^4.20.3", - "type": "^2.7.2", - "undici": "^7.25.0", - "write-file-atomic": "^7.0.1", - "yauzl": "^3.3.0", - "yazl": "^3.3.1" - }, - "bin": { - "osls": "bin/serverless.js", - "serverless": "bin/serverless.js", - "sls": "bin/serverless.js" - }, - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - } - }, - "node_modules/serverless-lss": { - "resolved": "../../packages/serverless-plugin", - "link": true - }, - "node_modules/serverless-offline": { - "version": "13.10.0", - "resolved": "https://registry.npmjs.org/serverless-offline/-/serverless-offline-13.10.0.tgz", - "integrity": "sha512-TchZKgG9bLos347h4lHbuXgVLoODxx5mafcCTDT3CGWWcbv0k92L7/xoMTMCCvWGzeOC+7DMcXxJ0vSGbMjT7w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@aws-sdk/client-lambda": "^3.636.0", - "@hapi/boom": "^10.0.1", - "@hapi/h2o2": "^10.0.4", - "@hapi/hapi": "^21.3.10", - "array-unflat-js": "^0.1.3", - "boxen": "^7.1.1", - "chalk": "^5.3.0", - "desm": "^1.3.1", - "execa": "^8.0.1", - "fs-extra": "^11.2.0", - "is-wsl": "^3.1.0", - "java-invoke-local": "0.0.6", - "jose": "^5.7.0", - "js-string-escape": "^1.0.1", - "jsonpath-plus": "^10.2.0", - "jsonschema": "^1.4.1", - "jszip": "^3.10.1", - "luxon": "^3.5.0", - "node-schedule": "^2.1.1", - "p-memoize": "^7.1.1", - "velocityjs": "^2.0.6", - "ws": "^8.18.0" - }, - "engines": { - "node": ">=18.12.0" - }, - "peerDependencies": { - "serverless": "^3.2.0" - } - }, - "node_modules/serverless-offline/node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/serverless-offline/node_modules/fs-extra": { - "version": "11.3.5", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.5.tgz", - "integrity": "sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/serverless-offline/node_modules/is-wsl": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", - "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-inside-container": "^1.0.0" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/serverless-offline/node_modules/ws": { - "version": "8.20.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz", - "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/serverless/node_modules/dotenv": { - "version": "17.4.2", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz", - "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/serverless/node_modules/dotenv-expand": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-13.0.0.tgz", - "integrity": "sha512-aBfBS8eYIeXmpHI9ThIlA7/WLq+SLt18iXUZhb52rW89QLKQFoIpPG1bPeewoPZsTyjSSO3T7234FBVUM1V2rA==", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "dotenv": "^17.4.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "dev": true, - "license": "MIT" - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/sorted-array-functions": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz", - "integrity": "sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==", - "dev": true, - "license": "MIT" - }, - "node_modules/sprintf-kit": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/sprintf-kit/-/sprintf-kit-2.0.2.tgz", - "integrity": "sha512-lnapdj6W4LflHZGKvl9eVkz5YF0xaTrqpRWVA4cNVOTedwqifIP8ooGImldzT/4IAN5KXFQAyXTdLidYVQdyag==", - "dev": true, - "license": "ISC", - "dependencies": { - "es5-ext": "^0.10.64" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/stream-browserify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", - "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "~2.0.4", - "readable-stream": "^3.5.0" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/timers-ext": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.8.tgz", - "integrity": "sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==", - "dev": true, - "license": "ISC", - "dependencies": { - "es5-ext": "^0.10.64", - "next-tick": "^1.1.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/tsx": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.0.tgz", - "integrity": "sha512-eUdUIaCr963q2h5u3+QwvYp0+eqPvn+egeqZUm0hwERCqqx1E3kK5ehbGCvqSE5MQAULr67ww0cA3jKc3YkM1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "~0.28.0" - }, - "bin": { - "tsx": "dist/cli.mjs" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - } - }, - "node_modules/type": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz", - "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/undici": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.28.0.tgz", - "integrity": "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=20.18.1" - } - }, - "node_modules/uni-global": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/uni-global/-/uni-global-1.0.0.tgz", - "integrity": "sha512-WWM3HP+siTxzIWPNUg7hZ4XO8clKi6NoCAJJWnuRL+BAqyFXF8gC03WNyTefGoUXYc47uYgXxpKLIEvo65PEHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "type": "^2.5.0" - } - }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, - "license": "MIT" - }, - "node_modules/velocityjs": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/velocityjs/-/velocityjs-2.1.6.tgz", - "integrity": "sha512-8bc+yDR2NjwPioMqOLsAs5VBMT16xr/jTfStHMmr7btRPvbCCiEoZ9k9k/7Uhxl3bUxIHY7uDNbvm5rTwPZlXg==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/widest-line": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", - "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", - "dev": true, - "license": "MIT", - "dependencies": { - "string-width": "^5.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/widest-line/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/widest-line/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "license": "MIT" - }, - "node_modules/widest-line/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/widest-line/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/write-file-atomic": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-7.0.1.tgz", - "integrity": "sha512-OTIk8iR8/aCRWBqvxrzxR0hgxWpnYBblY1S5hDWBQfk/VFmJwzmJgQFN3WsoUKHISv2eAwe+PpbUzyL1CKTLXg==", - "dev": true, - "license": "ISC", - "dependencies": { - "signal-exit": "^4.0.1" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/yauzl": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.4.0.tgz", - "integrity": "sha512-jIH9yLR9wqr0wOS0TpBvo/g/2UgZH5qePVbjgRliiF0BYvOZyaBknKsF+x9Iht0O6sqgnB93rCICdOZFecJuDw==", - "dev": true, - "license": "MIT", - "dependencies": { - "pend": "~1.2.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yazl": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/yazl/-/yazl-3.3.1.tgz", - "integrity": "sha512-BbETDVWG+VcMUle37k5Fqp//7SDOK2/1+T7X8TD96M3D9G8jK5VLUdQVdVjGi8im7FGkazX7kk5hkU8X4L5Bng==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-crc32": "^1.0.0" - } - }, - "node_modules/yazl/node_modules/buffer-crc32": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", - "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - } - } -} diff --git a/examples/localstack-ultimate/package.json b/examples/localstack-ultimate/package.json deleted file mode 100644 index 9862739..0000000 --- a/examples/localstack-ultimate/package.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "localstack-ultimate", - "version": "0.0.0", - "private": true, - "description": "LocalStack Ultimate (paid-tier) example for Local Serverless Stack — runs against localstack/localstack-pro with LOCALSTACK_AUTH_TOKEN and keeps the serverless-offline integration path.", - "scripts": { - "setup": "npm install", - "offline": "dotenv -- serverless package && npm run dlq:wire && dotenv -- serverless offline start", - "package": "dotenv -- serverless package", - "deploy": "dotenv -- serverless deploy", - "console": "npx -y http-server . -p 8621 -c-1", - "dlq:wire": "node scripts/wire-dlq.js", - "seed": "npm run lss:seed", - "lss:start": "dotenv -- node ../../bin/cli.js start", - "lss:stop": "dotenv -- node ../../bin/cli.js stop", - "lss:status": "dotenv -- node ../../bin/cli.js status", - "lss:logs": "dotenv -- node ../../bin/cli.js logs", - "lss:seed": "dotenv -- node ../../bin/cli.js seed", - "lss:seed:clear": "dotenv -- node ../../bin/cli.js seed:clear" - }, - "dependencies": { - "@aws-sdk/client-dynamodb": "3.974.0", - "@aws-sdk/client-eventbridge": "^3.974.0", - "@aws-sdk/client-s3": "^3.974.0", - "@aws-sdk/client-sns": "3.974.0", - "@aws-sdk/client-sqs": "3.974.0", - "@aws-sdk/util-dynamodb": "3.974.0" - }, - "devDependencies": { - "dotenv-cli": "^7.4.4", - "serverless-lss": "file:../../packages/serverless-plugin", - "osls": "4.0.0", - "serverless-offline": "^13.6.0" - }, - "overrides": { - "serverless": "npm:osls@4.0.0" - } -} diff --git a/examples/localstack-ultimate/scripts/wire-dlq.js b/examples/localstack-ultimate/scripts/wire-dlq.js deleted file mode 100644 index b2ebaff..0000000 --- a/examples/localstack-ultimate/scripts/wire-dlq.js +++ /dev/null @@ -1,73 +0,0 @@ -// Applies the RedrivePolicy declared in serverless.yml to the LIVE LocalStack -// queue. LSS now carries RedrivePolicy from the CloudFormation template into -// CreateQueue, so this is a no-op safety net: it re-applies the same policy, -// which matters only for a queue provisioned by an older LSS (CreateQueue -// cannot change the attributes of a queue that already exists). -// `npm run offline` runs this right after `serverless package` (which -// registers the service and provisions the queues); it is also available -// standalone as `npm run dlq:wire`. -const { - SQSClient, - GetQueueUrlCommand, - GetQueueAttributesCommand, - SetQueueAttributesCommand, -} = require('@aws-sdk/client-sqs'); - -const sqs = new SQSClient({ - region: process.env.AWS_REGION || 'eu-west-1', - endpoint: process.env.AWS_ENDPOINT || 'http://localhost:4571', - credentials: { accessKeyId: 'test', secretAccessKey: 'test' }, -}); - -const QUEUE = 'localstack-ultimate-OrderProcessing'; -const DLQ = 'localstack-ultimate-OrderProcessingDLQ'; -const MAX_RECEIVE_COUNT = 3; - -const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); - -// Registration provisions the queues asynchronously to this script, so poll -// for up to ~30s before giving up. -async function getQueueUrlWithRetry(name) { - for (let attempt = 1; attempt <= 30; attempt++) { - try { - const res = await sqs.send(new GetQueueUrlCommand({ QueueName: name })); - return res.QueueUrl; - } catch { - await sleep(1000); - } - } - return undefined; -} - -async function main() { - const queueUrl = await getQueueUrlWithRetry(QUEUE); - const dlqUrl = await getQueueUrlWithRetry(DLQ); - if (!queueUrl || !dlqUrl) { - // Fail soft: don't block `npm run offline` when LSS/LocalStack isn't up - // yet — re-run `npm run dlq:wire` once it is. - console.warn(`[wire-dlq] ⚠ queues not found on ${process.env.AWS_ENDPOINT || 'http://localhost:4571'} — is LSS running (npm run lss:start)? Skipping.`); - return; - } - - const attrs = await sqs.send(new GetQueueAttributesCommand({ - QueueUrl: dlqUrl, - AttributeNames: ['QueueArn'], - })); - const dlqArn = attrs.Attributes && attrs.Attributes.QueueArn; - - await sqs.send(new SetQueueAttributesCommand({ - QueueUrl: queueUrl, - Attributes: { - RedrivePolicy: JSON.stringify({ - deadLetterTargetArn: dlqArn, - maxReceiveCount: MAX_RECEIVE_COUNT, - }), - }, - })); - - console.log(`[wire-dlq] ✓ RedrivePolicy set on ${QUEUE} → ${DLQ} (maxReceiveCount: ${MAX_RECEIVE_COUNT})`); -} - -main().catch((err) => { - console.warn(`[wire-dlq] ⚠ ${err.message} — skipping.`); -}); diff --git a/examples/localstack-ultimate/seeds/localstack-ultimate-Orders.json b/examples/localstack-ultimate/seeds/localstack-ultimate-Orders.json deleted file mode 100644 index d2dd3e7..0000000 --- a/examples/localstack-ultimate/seeds/localstack-ultimate-Orders.json +++ /dev/null @@ -1,32 +0,0 @@ -[ - { - "userId": "u-alice", - "orderId": "o-1001", - "status": "CONFIRMED", - "items": [{ "sku": "BOOK-01", "price": 25, "qty": 2 }], - "total": 50, - "createdAt": "2026-05-10T09:00:00.000Z", - "processedAt": "2026-05-10T09:00:02.000Z" - }, - { - "userId": "u-alice", - "orderId": "o-1002", - "status": "PENDING_REVIEW", - "items": [{ "sku": "LAPTOP-XL", "price": 1500, "qty": 1 }], - "total": 1500, - "createdAt": "2026-05-12T14:20:00.000Z", - "processedAt": "2026-05-12T14:20:01.000Z" - }, - { - "userId": "u-bob", - "orderId": "o-1003", - "status": "CONFIRMED", - "items": [ - { "sku": "MUG-RED", "price": 12, "qty": 3 }, - { "sku": "STICKER-PK", "price": 5, "qty": 4 } - ], - "total": 56, - "createdAt": "2026-05-13T16:45:00.000Z", - "processedAt": "2026-05-13T16:45:01.000Z" - } -] diff --git a/examples/localstack-ultimate/seeds/localstack-ultimate-Sessions.json b/examples/localstack-ultimate/seeds/localstack-ultimate-Sessions.json deleted file mode 100644 index 5f13c6a..0000000 --- a/examples/localstack-ultimate/seeds/localstack-ultimate-Sessions.json +++ /dev/null @@ -1,20 +0,0 @@ -[ - { - "sessionId": "s-expired-demo", - "userId": "u-carol", - "createdAt": "2026-01-01T08:00:00.000Z", - "expiresAt": 1767261600 - }, - { - "sessionId": "s-alice-forever", - "userId": "u-alice", - "createdAt": "2026-05-01T10:05:00.000Z", - "expiresAt": 4102444800 - }, - { - "sessionId": "s-bob-forever", - "userId": "u-bob", - "createdAt": "2026-05-02T11:35:00.000Z", - "expiresAt": 4102444800 - } -] diff --git a/examples/localstack-ultimate/seeds/localstack-ultimate-Users.json b/examples/localstack-ultimate/seeds/localstack-ultimate-Users.json deleted file mode 100644 index ae5cead..0000000 --- a/examples/localstack-ultimate/seeds/localstack-ultimate-Users.json +++ /dev/null @@ -1,26 +0,0 @@ -[ - { - "userId": "u-alice", - "name": "Alice Hopper", - "email": "alice@example.com", - "active": true, - "createdAt": "2026-05-01T10:00:00.000Z", - "roles": ["admin", "founder"] - }, - { - "userId": "u-bob", - "name": "Bob Turing", - "email": "bob@example.com", - "active": true, - "createdAt": "2026-05-02T11:30:00.000Z", - "roles": ["engineer"] - }, - { - "userId": "u-carol", - "name": "Carol Lovelace", - "email": "carol@example.com", - "active": false, - "createdAt": "2026-05-03T08:15:00.000Z", - "roles": ["intern"] - } -] diff --git a/examples/localstack-ultimate/serverless.yml b/examples/localstack-ultimate/serverless.yml deleted file mode 100644 index 8abab75..0000000 --- a/examples/localstack-ultimate/serverless.yml +++ /dev/null @@ -1,359 +0,0 @@ -service: localstack-ultimate - -frameworkVersion: '>=3' - -provider: - name: aws - runtime: nodejs20.x - region: eu-west-1 - environment: - USERS_TABLE: ${self:service}-Users - SESSIONS_TABLE: ${self:service}-Sessions - ORDERS_TABLE: ${self:service}-Orders - AUDIT_TABLE: ${self:service}-AuditTrail - ORDER_QUEUE_URL: http://localhost:4571/000000000000/${self:service}-OrderProcessing - ORDER_EVENTS_TOPIC_ARN: arn:aws:sns:${self:provider.region}:${self:custom.accountId}:${self:service}-OrderEvents - ORDER_EVENTS_BUS: ultimate-order-events - UPLOADS_BUCKET: localstack-ultimate-uploads - AWS_ENDPOINT: http://localhost:4571 - # Served by the LSS aoss sidecar (LocalStack has no OpenSearch Serverless - # in any edition): /_aoss/. On real AWS you would - # read it from GetAtt ProductsCollection.CollectionEndpoint. - OPENSEARCH_ENDPOINT: http://localhost:14567/_aoss/ultimate-products - PRODUCTS_INDEX: products - -plugins: - - serverless-lss - - serverless-offline - -custom: - accountId: '000000000000' - orchestrator: - enabled: true - orchestratorUrl: http://localhost:3111 - serverless-offline: - httpPort: 3002 - lambdaPort: 3003 - -functions: - health: - handler: src/handlers/health.handler - events: - - http: - path: /health - method: get - cors: true - - createUser: - handler: src/handlers/createUser.handler - events: - - http: - path: /users - method: post - cors: true - - listUsers: - handler: src/handlers/listUsers.handler - events: - - http: - path: /users - method: get - cors: true - - enqueueOrder: - handler: src/handlers/enqueueOrder.handler - events: - - http: - path: /orders - method: post - cors: true - - # SQS consumer. ReportBatchItemFailures makes the redrive demo work: poison - # orders (total <= 0 / missing userId) are reported as batch item failures, - # SQS keeps re-delivering them and, after maxReceiveCount receives, moves - # them to the OrderProcessingDLQ (RedrivePolicy below). - processOrderQueue: - handler: src/handlers/processOrderQueue.handler - events: - - sqs: - arn: - Fn::GetAtt: - - OrderProcessingQueue - - Arn - batchSize: 5 - functionResponseType: ReportBatchItemFailures - - onOrderStream: - handler: src/handlers/onOrderStream.handler - events: - - stream: - type: dynamodb - arn: - Fn::GetAtt: - - OrdersTable - - StreamArn - batchSize: 10 - - uploadFile: - handler: src/handlers/uploadFile.handler - events: - - http: - path: /uploads - method: post - cors: true - - listUploads: - handler: src/handlers/listUploads.handler - events: - - http: - path: /uploads - method: get - cors: true - - # Triggered when an object is created in the uploads bucket. - # The bucket notification is wired via NotificationConfiguration below. - onUpload: - handler: src/handlers/onUpload.handler - - # eventBridge trigger with pattern filtering against the custom bus declared - # in resources (referenced by ARN so Serverless does not create a second - # bus). processOrderQueue and purgeSessions publish onto the bus with plain - # SDK PutEvents calls; events from any other source are not delivered here. - # The handler receives the REAL EventBridge envelope (source, detail-type, - # detail) — no Records wrapper. - auditEvents: - handler: src/handlers/auditEvents.handler - events: - - eventBridge: - eventBus: arn:aws:events:${self:provider.region}:${self:custom.accountId}:event-bus/ultimate-order-events - pattern: - source: - - ultimate.orders - - ultimate.scheduler - - # GET /audit — lists the AuditTrail entries written by auditEvents so the - # bus → rule → Lambda flow is observable over plain HTTP. - getAudit: - handler: src/handlers/getAudit.handler - events: - - http: - path: /audit - method: get - cors: true - - # Scheduled function — compiled to an EventBridge rule on the default bus; - # LocalStack fires it every 2 minutes through the LSS proxy → Invoke API. - # Purges Sessions rows whose expiresAt (epoch seconds) is in the past and - # publishes a sessions.purged event onto the custom bus (→ audit trail). - purgeSessions: - handler: src/handlers/purgeSessions.handler - events: - - schedule: rate(2 minutes) - - # OpenSearch Serverless product catalog. LocalStack has NO aoss support in - # any edition, so these handlers talk straight to the LSS aoss sidecar - # (OPENSEARCH_ENDPOINT above) — the ultimate-products collection declared in - # resources is provisioned there on registration. - createProduct: - handler: src/handlers/createProduct.handler - events: - - http: - path: /products - method: post - cors: true - - getProduct: - handler: src/handlers/getProduct.handler - events: - - http: - path: /products/{id} - method: get - cors: true - - deleteProduct: - handler: src/handlers/deleteProduct.handler - events: - - http: - path: /products/{id} - method: delete - cors: true - - # GET /search?q=&category=&maxPrice= — full-text search + filters. - searchProducts: - handler: src/handlers/searchProducts.handler - events: - - http: - path: /search - method: get - cors: true - - # GET /stats — terms + avg aggregations over the whole catalog. - productStats: - handler: src/handlers/productStats.handler - events: - - http: - path: /stats - method: get - cors: true - -resources: - Resources: - # Users — PK only, NO TTL configured (will surface a warning in the UI). - UsersTable: - Type: AWS::DynamoDB::Table - Properties: - TableName: ${self:service}-Users - BillingMode: PAY_PER_REQUEST - AttributeDefinitions: - - AttributeName: userId - AttributeType: S - KeySchema: - - AttributeName: userId - KeyType: HASH - - # Sessions — PK only, intended for TTL (you can enable it from the Settings tab in the UI). - SessionsTable: - Type: AWS::DynamoDB::Table - Properties: - TableName: ${self:service}-Sessions - BillingMode: PAY_PER_REQUEST - AttributeDefinitions: - - AttributeName: sessionId - AttributeType: S - KeySchema: - - AttributeName: sessionId - KeyType: HASH - - # Orders — composite key + GSI on status + DynamoDB stream. - OrdersTable: - Type: AWS::DynamoDB::Table - Properties: - TableName: ${self:service}-Orders - BillingMode: PAY_PER_REQUEST - AttributeDefinitions: - - AttributeName: userId - AttributeType: S - - AttributeName: orderId - AttributeType: S - - AttributeName: status - AttributeType: S - KeySchema: - - AttributeName: userId - KeyType: HASH - - AttributeName: orderId - KeyType: RANGE - GlobalSecondaryIndexes: - - IndexName: ByStatus - KeySchema: - - AttributeName: status - KeyType: HASH - - AttributeName: orderId - KeyType: RANGE - Projection: - ProjectionType: ALL - StreamSpecification: - StreamViewType: NEW_AND_OLD_IMAGES - - # AuditTrail — filled by the auditEvents eventBridge trigger; read back - # over GET /audit. - AuditTrailTable: - Type: AWS::DynamoDB::Table - Properties: - TableName: ${self:service}-AuditTrail - BillingMode: PAY_PER_REQUEST - AttributeDefinitions: - - AttributeName: auditId - AttributeType: S - KeySchema: - - AttributeName: auditId - KeyType: HASH - - # VisibilityTimeout is deliberately short (10s) so the DLQ demo resolves in - # ~30s instead of minutes: a poison message is re-received every 10s and - # redriven to the DLQ after the 3rd receive. LSS's CloudFormation parser now - # carries RedrivePolicy through to CreateQueue, so `npm run offline`'s - # scripts/wire-dlq.js step is only a no-op safety net (it re-applies the same - # policy to a queue provisioned by an older LSS). - OrderProcessingQueue: - Type: AWS::SQS::Queue - Properties: - QueueName: ${self:service}-OrderProcessing - VisibilityTimeout: 10 - MessageRetentionPeriod: 345600 - RedrivePolicy: - deadLetterTargetArn: - Fn::GetAtt: - - OrderProcessingDLQ - - Arn - maxReceiveCount: 3 - - # Dead-letter queue — poison orders land here; watch them accumulate in - # the dashboard's Queues tab. - OrderProcessingDLQ: - Type: AWS::SQS::Queue - Properties: - QueueName: ${self:service}-OrderProcessingDLQ - MessageRetentionPeriod: 345600 - - OrderEventsTopic: - Type: AWS::SNS::Topic - Properties: - TopicName: ${self:service}-OrderEvents - - # Custom EventBridge bus — processOrderQueue (order.processed) and - # purgeSessions (sessions.purged) publish here; the auditEvents rule - # (pattern-filtered) consumes. - OrderEventsBus: - Type: AWS::Events::EventBus - Properties: - Name: ultimate-order-events - - # S3 bucket with a notification that fires the onUpload Lambda whenever a - # new object is created under the "incoming/" prefix. - UploadsBucket: - Type: AWS::S3::Bucket - Properties: - BucketName: localstack-ultimate-uploads - NotificationConfiguration: - LambdaConfigurations: - - Event: s3:ObjectCreated:* - Function: - Fn::GetAtt: - - OnUploadLambdaFunction - - Arn - Filter: - S3Key: - Rules: - - Name: prefix - Value: incoming/ - - # OpenSearch Serverless collection — LocalStack cannot provision this - # (no aoss in any edition), so LSS serves it in-process via the aoss - # sidecar on 14567; the data plane is /_aoss/ultimate-products. - ProductsCollection: - Type: AWS::OpenSearchServerless::Collection - Properties: - Name: ultimate-products - Type: SEARCH - Description: Ultimate product catalog full-text search - - # On AWS a collection cannot be created without an encryption policy and is - # unreachable without a data-access policy. LSS accepts and skips both with - # a registration warning — nothing enforces them locally — so the template - # stays deployable as-is to the real cloud. - ProductsEncryptionPolicy: - Type: AWS::OpenSearchServerless::SecurityPolicy - Properties: - Name: ultimate-products-encryption - Type: encryption - Policy: '{"Rules":[{"ResourceType":"collection","Resource":["collection/ultimate-products"]}],"AWSOwnedKey":true}' - - ProductsAccessPolicy: - Type: AWS::OpenSearchServerless::AccessPolicy - Properties: - Name: ultimate-products-access - Type: data - Policy: '[{"Rules":[{"ResourceType":"index","Resource":["index/ultimate-products/*"],"Permission":["aoss:*"]}],"Principal":["arn:aws:iam::000000000000:role/local-dev"]}]' - -package: - individually: false diff --git a/examples/localstack-ultimate/src/handlers/auditEvents.js b/examples/localstack-ultimate/src/handlers/auditEvents.js deleted file mode 100644 index dec79aa..0000000 --- a/examples/localstack-ultimate/src/handlers/auditEvents.js +++ /dev/null @@ -1,27 +0,0 @@ -const { PutItemCommand } = require('@aws-sdk/client-dynamodb'); -const { marshall } = require('@aws-sdk/util-dynamodb'); -const { dynamo } = require('./aws'); - -// EventBridge target — receives the event exactly as AWS delivers it: -// { version, id, source, "detail-type", detail, ... }. No Records wrapper. -// The rule pattern (source: ultimate.orders | ultimate.scheduler) on the -// ultimate-order-events bus filtered it here; each matched event becomes a -// row in the AuditTrail table, readable via GET /audit. -exports.handler = async (event) => { - console.log(`[auditEvents] ${event.source} → ${event['detail-type']} (${event.id})`); - - const entry = { - auditId: event.id, - source: event.source, - detailType: event['detail-type'], - detail: event.detail, - receivedAt: new Date().toISOString(), - }; - - await dynamo.send(new PutItemCommand({ - TableName: process.env.AUDIT_TABLE, - Item: marshall(entry, { removeUndefinedValues: true }), - })); - - return { stored: entry.auditId }; -}; diff --git a/examples/localstack-ultimate/src/handlers/aws.js b/examples/localstack-ultimate/src/handlers/aws.js deleted file mode 100644 index 976048a..0000000 --- a/examples/localstack-ultimate/src/handlers/aws.js +++ /dev/null @@ -1,21 +0,0 @@ -const { DynamoDBClient } = require('@aws-sdk/client-dynamodb'); -const { SQSClient } = require('@aws-sdk/client-sqs'); -const { SNSClient } = require('@aws-sdk/client-sns'); -const { S3Client } = require('@aws-sdk/client-s3'); -const { EventBridgeClient } = require('@aws-sdk/client-eventbridge'); - -const baseConfig = { - region: process.env.AWS_REGION || 'eu-west-1', - endpoint: process.env.AWS_ENDPOINT || 'http://localhost:4571', - credentials: { accessKeyId: 'test', secretAccessKey: 'test' }, -}; - -module.exports = { - dynamo: new DynamoDBClient(baseConfig), - sqs: new SQSClient(baseConfig), - sns: new SNSClient(baseConfig), - eventBridge: new EventBridgeClient(baseConfig), - // forcePathStyle is required so LocalStack sees the bucket name in the URL path - // rather than as a virtual-host subdomain. - s3: new S3Client({ ...baseConfig, forcePathStyle: true }), -}; diff --git a/examples/localstack-ultimate/src/handlers/createProduct.js b/examples/localstack-ultimate/src/handlers/createProduct.js deleted file mode 100644 index 28bb11c..0000000 --- a/examples/localstack-ultimate/src/handlers/createProduct.js +++ /dev/null @@ -1,35 +0,0 @@ -const { randomUUID } = require('crypto'); -const { request, INDEX } = require('./opensearch'); -const respond = require('./respond'); - -// POST /products — body: { "name": "...", "category": "...", "price": 12.5, "tags": ["..."] } -exports.handler = async (event) => { - let payload = {}; - try { - payload = event.body ? JSON.parse(event.body) : {}; - } catch { - return respond(400, { error: 'invalid json' }); - } - - const { name, category, price, tags } = payload; - if (!name || !category || typeof price !== 'number') { - return respond(400, { error: 'name, category and numeric price are required' }); - } - - const id = payload.id || randomUUID(); - const product = { - name, - category, - price, - tags: Array.isArray(tags) ? tags : [], - createdAt: new Date().toISOString(), - }; - - const { status, json } = await request('PUT', `/${INDEX}/_doc/${encodeURIComponent(id)}`, product); - if (status >= 400) { - return respond(502, { error: 'indexing failed', detail: json }); - } - - console.log(`[createProduct] ${id} indexed (${json.result})`); - return respond(201, { id, ...product }); -}; diff --git a/examples/localstack-ultimate/src/handlers/createUser.js b/examples/localstack-ultimate/src/handlers/createUser.js deleted file mode 100644 index 841218b..0000000 --- a/examples/localstack-ultimate/src/handlers/createUser.js +++ /dev/null @@ -1,34 +0,0 @@ -const { PutItemCommand } = require('@aws-sdk/client-dynamodb'); -const { marshall } = require('@aws-sdk/util-dynamodb'); -const { randomUUID } = require('crypto'); -const { dynamo } = require('./aws'); -const respond = require('./respond'); - -exports.handler = async (event) => { - let payload = {}; - try { - payload = event.body ? JSON.parse(event.body) : {}; - } catch { - return respond(400, { error: 'invalid json' }); - } - - const { name, email } = payload; - if (!name || !email) { - return respond(400, { error: 'name and email are required' }); - } - - const user = { - userId: randomUUID(), - name, - email, - createdAt: new Date().toISOString(), - active: true, - }; - - await dynamo.send(new PutItemCommand({ - TableName: process.env.USERS_TABLE, - Item: marshall(user), - })); - - return respond(201, user); -}; diff --git a/examples/localstack-ultimate/src/handlers/deleteProduct.js b/examples/localstack-ultimate/src/handlers/deleteProduct.js deleted file mode 100644 index bb0fcbc..0000000 --- a/examples/localstack-ultimate/src/handlers/deleteProduct.js +++ /dev/null @@ -1,14 +0,0 @@ -const { request, INDEX } = require('./opensearch'); -const respond = require('./respond'); - -// DELETE /products/{id} -exports.handler = async (event) => { - const id = event.pathParameters && event.pathParameters.id; - const { status } = await request('DELETE', `/${INDEX}/_doc/${encodeURIComponent(id)}`); - - if (status === 404) { - return respond(404, { error: `product ${id} not found` }); - } - console.log(`[deleteProduct] ${id} deleted`); - return respond(200, { deleted: id }); -}; diff --git a/examples/localstack-ultimate/src/handlers/enqueueOrder.js b/examples/localstack-ultimate/src/handlers/enqueueOrder.js deleted file mode 100644 index e615665..0000000 --- a/examples/localstack-ultimate/src/handlers/enqueueOrder.js +++ /dev/null @@ -1,32 +0,0 @@ -const { SendMessageCommand } = require('@aws-sdk/client-sqs'); -const { randomUUID } = require('crypto'); -const { sqs } = require('./aws'); -const respond = require('./respond'); - -exports.handler = async (event) => { - let payload = {}; - try { - payload = event.body ? JSON.parse(event.body) : {}; - } catch { - return respond(400, { error: 'invalid json' }); - } - - const { userId, items } = payload; - if (!userId || !Array.isArray(items) || items.length === 0) { - return respond(400, { error: 'userId and non-empty items[] are required' }); - } - - const order = { - orderId: randomUUID(), - userId, - items, - createdAt: new Date().toISOString(), - }; - - await sqs.send(new SendMessageCommand({ - QueueUrl: process.env.ORDER_QUEUE_URL, - MessageBody: JSON.stringify(order), - })); - - return respond(202, { enqueued: true, order }); -}; diff --git a/examples/localstack-ultimate/src/handlers/getAudit.js b/examples/localstack-ultimate/src/handlers/getAudit.js deleted file mode 100644 index e6b8f29..0000000 --- a/examples/localstack-ultimate/src/handlers/getAudit.js +++ /dev/null @@ -1,15 +0,0 @@ -const { ScanCommand } = require('@aws-sdk/client-dynamodb'); -const { unmarshall } = require('@aws-sdk/util-dynamodb'); -const { dynamo } = require('./aws'); -const respond = require('./respond'); - -// GET /audit — makes the bus → rule → auditEvents flow observable: whatever -// the eventBridge trigger stored shows up here, newest first. -exports.handler = async () => { - const res = await dynamo.send(new ScanCommand({ TableName: process.env.AUDIT_TABLE })); - const entries = (res.Items || []) - .map((i) => unmarshall(i)) - .sort((a, b) => String(b.receivedAt || '').localeCompare(String(a.receivedAt || ''))) - .slice(0, 50); - return respond(200, { count: entries.length, entries }); -}; diff --git a/examples/localstack-ultimate/src/handlers/getProduct.js b/examples/localstack-ultimate/src/handlers/getProduct.js deleted file mode 100644 index 0d4fd52..0000000 --- a/examples/localstack-ultimate/src/handlers/getProduct.js +++ /dev/null @@ -1,13 +0,0 @@ -const { request, INDEX } = require('./opensearch'); -const respond = require('./respond'); - -// GET /products/{id} -exports.handler = async (event) => { - const id = event.pathParameters && event.pathParameters.id; - const { status, json } = await request('GET', `/${INDEX}/_doc/${encodeURIComponent(id)}`); - - if (status === 404) { - return respond(404, { error: `product ${id} not found` }); - } - return respond(200, { id: json._id, ...json._source }); -}; diff --git a/examples/localstack-ultimate/src/handlers/health.js b/examples/localstack-ultimate/src/handlers/health.js deleted file mode 100644 index 26271c8..0000000 --- a/examples/localstack-ultimate/src/handlers/health.js +++ /dev/null @@ -1,3 +0,0 @@ -const respond = require('./respond'); - -exports.handler = async () => respond(200, { ok: true, service: 'localstack-ultimate', ts: Date.now() }); diff --git a/examples/localstack-ultimate/src/handlers/listUploads.js b/examples/localstack-ultimate/src/handlers/listUploads.js deleted file mode 100644 index 6f37636..0000000 --- a/examples/localstack-ultimate/src/handlers/listUploads.js +++ /dev/null @@ -1,22 +0,0 @@ -const { ListObjectsV2Command } = require('@aws-sdk/client-s3'); -const { s3 } = require('./aws'); -const respond = require('./respond'); - -// GET /uploads?prefix=incoming/ -exports.handler = async (event) => { - const prefix = (event.queryStringParameters && event.queryStringParameters.prefix) || undefined; - - const response = await s3.send(new ListObjectsV2Command({ - Bucket: process.env.UPLOADS_BUCKET, - Prefix: prefix, - MaxKeys: 100, - })); - - const objects = (response.Contents || []).map(o => ({ - key: o.Key, - size: o.Size, - lastModified: o.LastModified, - })); - - return respond(200, { bucket: process.env.UPLOADS_BUCKET, count: objects.length, objects }); -}; diff --git a/examples/localstack-ultimate/src/handlers/listUsers.js b/examples/localstack-ultimate/src/handlers/listUsers.js deleted file mode 100644 index c9fcf88..0000000 --- a/examples/localstack-ultimate/src/handlers/listUsers.js +++ /dev/null @@ -1,10 +0,0 @@ -const { ScanCommand } = require('@aws-sdk/client-dynamodb'); -const { unmarshall } = require('@aws-sdk/util-dynamodb'); -const { dynamo } = require('./aws'); -const respond = require('./respond'); - -exports.handler = async () => { - const res = await dynamo.send(new ScanCommand({ TableName: process.env.USERS_TABLE })); - const users = (res.Items || []).map((i) => unmarshall(i)); - return respond(200, { count: users.length, users }); -}; diff --git a/examples/localstack-ultimate/src/handlers/onOrderStream.js b/examples/localstack-ultimate/src/handlers/onOrderStream.js deleted file mode 100644 index 79a428c..0000000 --- a/examples/localstack-ultimate/src/handlers/onOrderStream.js +++ /dev/null @@ -1,31 +0,0 @@ -const { PublishCommand } = require('@aws-sdk/client-sns'); -const { unmarshall } = require('@aws-sdk/util-dynamodb'); -const { sns } = require('./aws'); - -exports.handler = async (event) => { - const records = event.Records || []; - console.log(`[onOrderStream] received ${records.length} stream record(s)`); - - for (const record of records) { - const eventName = record.eventName; // INSERT | MODIFY | REMOVE - const newImage = record.dynamodb?.NewImage ? unmarshall(record.dynamodb.NewImage) : null; - const oldImage = record.dynamodb?.OldImage ? unmarshall(record.dynamodb.OldImage) : null; - - const message = { - type: `order.${eventName.toLowerCase()}`, - orderId: (newImage || oldImage)?.orderId, - userId: (newImage || oldImage)?.userId, - status: newImage?.status, - total: newImage?.total, - occurredAt: new Date().toISOString(), - }; - - await sns.send(new PublishCommand({ - TopicArn: process.env.ORDER_EVENTS_TOPIC_ARN, - Subject: message.type, - Message: JSON.stringify(message), - })); - - console.log(`[onOrderStream] published ${message.type} for ${message.orderId}`); - } -}; diff --git a/examples/localstack-ultimate/src/handlers/onUpload.js b/examples/localstack-ultimate/src/handlers/onUpload.js deleted file mode 100644 index 96d7919..0000000 --- a/examples/localstack-ultimate/src/handlers/onUpload.js +++ /dev/null @@ -1,54 +0,0 @@ -const { GetObjectCommand } = require('@aws-sdk/client-s3'); -const { PutItemCommand } = require('@aws-sdk/client-dynamodb'); -const { marshall } = require('@aws-sdk/util-dynamodb'); -const { s3, dynamo } = require('./aws'); - -// Triggered by the S3 bucket notification when an object is created under -// "incoming/". This handler reads the object back, derives some metadata, and -// records it in the Orders table to prove the round-trip works end-to-end. -exports.handler = async (event) => { - const records = event.Records || []; - console.log(`[onUpload] received ${records.length} S3 event(s)`); - - for (const record of records) { - const bucket = record.s3 && record.s3.bucket && record.s3.bucket.name; - const key = record.s3 && record.s3.object && decodeURIComponent(record.s3.object.key.replace(/\+/g, ' ')); - if (!bucket || !key) { - console.warn('[onUpload] skipping malformed record'); - continue; - } - - let size = (record.s3.object && record.s3.object.size) || 0; - let preview; - try { - const obj = await s3.send(new GetObjectCommand({ Bucket: bucket, Key: key })); - const chunks = []; - for await (const chunk of obj.Body) chunks.push(chunk); - const body = Buffer.concat(chunks); - size = body.length; - preview = body.slice(0, 120).toString('utf-8'); - } catch (err) { - console.warn(`[onUpload] could not read s3://${bucket}/${key}: ${err.message}`); - } - - // Stash an entry in Orders so the trigger is observable from the UI's - // DynamoDB explorer without adding a dedicated table. - const item = { - userId: 's3-upload', - orderId: `${bucket}/${key}`, - status: 'UPLOADED', - total: size, - items: preview ? [{ preview }] : [], - processedAt: new Date().toISOString(), - }; - - await dynamo.send(new PutItemCommand({ - TableName: process.env.ORDERS_TABLE, - Item: marshall(item, { removeUndefinedValues: true }), - })); - - console.log(`[onUpload] indexed s3://${bucket}/${key} (${size} bytes)`); - } - - return { batchItemFailures: [] }; -}; diff --git a/examples/localstack-ultimate/src/handlers/opensearch.js b/examples/localstack-ultimate/src/handlers/opensearch.js deleted file mode 100644 index a155f89..0000000 --- a/examples/localstack-ultimate/src/handlers/opensearch.js +++ /dev/null @@ -1,25 +0,0 @@ -// Minimal OpenSearch REST helper over Node's global fetch. LocalStack has no -// OpenSearch Serverless (aoss) in any edition, so the LSS orchestrator serves -// the ultimate-products collection in-process (aoss sidecar on :14567) and -// skips SigV4 verification — plain HTTP is enough locally. Against real -// OpenSearch Serverless swap this for @opensearch-project/opensearch with -// AwsSigv4Signer({service: 'aoss'}) — the calls themselves are identical. -const ENDPOINT = process.env.OPENSEARCH_ENDPOINT || 'http://localhost:14567/_aoss/ultimate-products'; -const INDEX = process.env.PRODUCTS_INDEX || 'products'; - -async function request(method, path, body) { - const res = await fetch(`${ENDPOINT}${path}`, { - method, - headers: { 'content-type': 'application/json' }, - body: body === undefined ? undefined : JSON.stringify(body), - }); - let json = {}; - try { - json = await res.json(); - } catch { - // HEAD/empty responses have no body - } - return { status: res.status, json }; -} - -module.exports = { request, INDEX }; diff --git a/examples/localstack-ultimate/src/handlers/processOrderQueue.js b/examples/localstack-ultimate/src/handlers/processOrderQueue.js deleted file mode 100644 index 456dffc..0000000 --- a/examples/localstack-ultimate/src/handlers/processOrderQueue.js +++ /dev/null @@ -1,74 +0,0 @@ -const { PutItemCommand } = require('@aws-sdk/client-dynamodb'); -const { PutEventsCommand } = require('@aws-sdk/client-eventbridge'); -const { marshall } = require('@aws-sdk/util-dynamodb'); -const { dynamo, eventBridge } = require('./aws'); - -exports.handler = async (event) => { - const records = event.Records || []; - console.log(`[processOrderQueue] received ${records.length} message(s)`); - - // ReportBatchItemFailures contract: only the messageIds listed here are kept - // on the queue; everything else is deleted. A poison message is re-received - // until maxReceiveCount, then SQS redrives it to the OrderProcessingDLQ. - const batchItemFailures = []; - - for (const record of records) { - try { - let order; - try { - order = JSON.parse(record.body); - } catch (e) { - throw new Error(`invalid body: ${record.body}`); - } - - const total = (order.items || []).reduce( - (s, it) => s + (Number(it.price) || 0) * (Number(it.qty) || 1), - 0, - ); - - // Obviously invalid orders are poison messages: throwing (instead of - // dropping) keeps them on the queue so the DLQ redrive is observable. - if (!order.userId) { - throw new Error('poison order: missing userId'); - } - if (total <= 0) { - throw new Error(`poison order ${order.orderId}: total ${total} <= 0`); - } - - const persisted = { - ...order, - status: total > 100 ? 'PENDING_REVIEW' : 'CONFIRMED', - total, - processedAt: new Date().toISOString(), - }; - - await dynamo.send(new PutItemCommand({ - TableName: process.env.ORDERS_TABLE, - Item: marshall(persisted, { removeUndefinedValues: true }), - })); - - // Announce the processed order on the custom EventBridge bus — the - // auditEvents rule (source: ultimate.orders) picks it up. - await eventBridge.send(new PutEventsCommand({ - Entries: [{ - EventBusName: process.env.ORDER_EVENTS_BUS, - Source: 'ultimate.orders', - DetailType: 'order.processed', - Detail: JSON.stringify({ - orderId: persisted.orderId, - userId: persisted.userId, - status: persisted.status, - total: persisted.total, - }), - }], - })); - - console.log(`[processOrderQueue] stored order ${persisted.orderId} (${persisted.status})`); - } catch (err) { - console.error(`[processOrderQueue] message ${record.messageId} failed: ${err.message}`); - batchItemFailures.push({ itemIdentifier: record.messageId }); - } - } - - return { batchItemFailures }; -}; diff --git a/examples/localstack-ultimate/src/handlers/productStats.js b/examples/localstack-ultimate/src/handlers/productStats.js deleted file mode 100644 index 5d9f5aa..0000000 --- a/examples/localstack-ultimate/src/handlers/productStats.js +++ /dev/null @@ -1,30 +0,0 @@ -const { request, INDEX } = require('./opensearch'); -const respond = require('./respond'); - -// GET /stats — product count and average price per category (aggregations). -exports.handler = async () => { - const { status, json } = await request('POST', `/${INDEX}/_search`, { - size: 0, - aggs: { - by_category: { terms: { field: 'category' } }, - avg_price: { avg: { field: 'price' } }, - }, - }); - - // No index yet (nothing was ever created) → empty stats, not an error. - if (status === 404) { - return respond(200, { total: 0, averagePrice: null, categories: [] }); - } - if (status >= 400) { - return respond(502, { error: 'aggregation failed', detail: json }); - } - - return respond(200, { - total: json.hits.total.value, - averagePrice: json.aggregations.avg_price.value, - categories: json.aggregations.by_category.buckets.map((bucket) => ({ - category: bucket.key, - products: bucket.doc_count, - })), - }); -}; diff --git a/examples/localstack-ultimate/src/handlers/purgeSessions.js b/examples/localstack-ultimate/src/handlers/purgeSessions.js deleted file mode 100644 index e7e72b5..0000000 --- a/examples/localstack-ultimate/src/handlers/purgeSessions.js +++ /dev/null @@ -1,41 +0,0 @@ -const { ScanCommand, DeleteItemCommand } = require('@aws-sdk/client-dynamodb'); -const { PutEventsCommand } = require('@aws-sdk/client-eventbridge'); -const { marshall, unmarshall } = require('@aws-sdk/util-dynamodb'); -const { dynamo, eventBridge } = require('./aws'); - -// schedule: rate(2 minutes) — compiled to an EventBridge rule on the default -// bus and fired by LocalStack through the LSS proxy. Deletes Sessions rows -// whose expiresAt (epoch seconds) is in the past — the poor man's TTL; the -// Settings tab in the UI can enable real DynamoDB TTL on the same attribute. -exports.handler = async () => { - const res = await dynamo.send(new ScanCommand({ TableName: process.env.SESSIONS_TABLE })); - const sessions = (res.Items || []).map((i) => unmarshall(i)); - const nowSeconds = Math.floor(Date.now() / 1000); - - const expired = sessions.filter((s) => Number(s.expiresAt) > 0 && Number(s.expiresAt) < nowSeconds); - - for (const session of expired) { - await dynamo.send(new DeleteItemCommand({ - TableName: process.env.SESSIONS_TABLE, - Key: marshall({ sessionId: session.sessionId }), - })); - } - - // Leave a trace on the custom bus so every run shows up in GET /audit via - // the auditEvents rule (source: ultimate.scheduler). - await eventBridge.send(new PutEventsCommand({ - Entries: [{ - EventBusName: process.env.ORDER_EVENTS_BUS, - Source: 'ultimate.scheduler', - DetailType: 'sessions.purged', - Detail: JSON.stringify({ - scanned: sessions.length, - purged: expired.length, - purgedIds: expired.map((s) => s.sessionId), - }), - }], - })); - - console.log(`[purgeSessions] purged ${expired.length} of ${sessions.length} session(s)`); - return { scanned: sessions.length, purged: expired.length }; -}; diff --git a/examples/localstack-ultimate/src/handlers/respond.js b/examples/localstack-ultimate/src/handlers/respond.js deleted file mode 100644 index e402161..0000000 --- a/examples/localstack-ultimate/src/handlers/respond.js +++ /dev/null @@ -1,11 +0,0 @@ -// Shared HTTP response helper. Every response carries a permissive CORS header -// so the validation console (index.html) can call these routes straight from -// the browser; serverless-offline answers the preflight (cors: true per event). -module.exports = (statusCode, payload) => ({ - statusCode, - headers: { - 'Content-Type': 'application/json', - 'Access-Control-Allow-Origin': '*', - }, - body: JSON.stringify(payload), -}); diff --git a/examples/localstack-ultimate/src/handlers/searchProducts.js b/examples/localstack-ultimate/src/handlers/searchProducts.js deleted file mode 100644 index 5e7d788..0000000 --- a/examples/localstack-ultimate/src/handlers/searchProducts.js +++ /dev/null @@ -1,42 +0,0 @@ -const { request, INDEX } = require('./opensearch'); -const respond = require('./respond'); - -// GET /search?q=&category=&maxPrice= -// Composes a bool query: full-text match on name/tags, term filter on -// category, range filter on price — the everyday OpenSearch search shape. -exports.handler = async (event) => { - const params = event.queryStringParameters || {}; - const must = []; - const filter = []; - - if (params.q) { - must.push({ multi_match: { query: params.q, fields: ['name', 'tags'] } }); - } - if (params.category) { - filter.push({ term: { category: params.category } }); - } - if (params.maxPrice) { - filter.push({ range: { price: { lte: Number(params.maxPrice) } } }); - } - - const query = must.length + filter.length > 0 ? { bool: { must, filter } } : { match_all: {} }; - const { status, json } = await request('POST', `/${INDEX}/_search`, { - query, - sort: [{ price: 'asc' }], - size: 20, - }); - - // The index only exists after the first product is created — an empty - // catalog is an empty result, not an error. - if (status === 404) { - return respond(200, { total: 0, products: [] }); - } - if (status >= 400) { - return respond(502, { error: 'search failed', detail: json }); - } - - return respond(200, { - total: json.hits.total.value, - products: json.hits.hits.map((hit) => ({ id: hit._id, ...hit._source })), - }); -}; diff --git a/examples/localstack-ultimate/src/handlers/uploadFile.js b/examples/localstack-ultimate/src/handlers/uploadFile.js deleted file mode 100644 index 4d3e9fc..0000000 --- a/examples/localstack-ultimate/src/handlers/uploadFile.js +++ /dev/null @@ -1,34 +0,0 @@ -const { PutObjectCommand } = require('@aws-sdk/client-s3'); -const { randomUUID } = require('crypto'); -const { s3 } = require('./aws'); -const respond = require('./respond'); - -// POST /uploads -// Body: { "filename": "report.txt", "content": "...", "encoding": "base64" | undefined } -exports.handler = async (event) => { - let payload = {}; - try { - payload = event.body ? JSON.parse(event.body) : {}; - } catch { - return respond(400, { error: 'invalid json' }); - } - - const { filename, content, encoding, contentType } = payload; - if (!content) { - return respond(400, { error: 'content is required' }); - } - - // Files land under "incoming/" so the S3 → Lambda notification fires. - const safeName = (filename || `${randomUUID()}.txt`).replace(/[^a-zA-Z0-9._/-]/g, '_'); - const key = `incoming/${safeName}`; - const body = encoding === 'base64' ? Buffer.from(content, 'base64') : content; - - await s3.send(new PutObjectCommand({ - Bucket: process.env.UPLOADS_BUCKET, - Key: key, - Body: body, - ContentType: contentType || 'text/plain', - })); - - return respond(201, { uploaded: true, bucket: process.env.UPLOADS_BUCKET, key }); -}; diff --git a/examples/self-hosted/README.md b/examples/self-hosted/README.md index cf78de1..009ab1f 100644 --- a/examples/self-hosted/README.md +++ b/examples/self-hosted/README.md @@ -63,7 +63,7 @@ What this exercises on the self engine: tables and queues, JSON catalogs + a JSONL table per index for OpenSearch); everything survives an orchestrator restart. Delete the folder for a clean slate. -> **Ports** — LSS server `3140`, self engine `14566`, service APIs `3631`–`3634`, invoke +> **Ports** — LSS `14566` (dashboard, REST API and AWS wire on one listener), service APIs `3631`–`3634`, invoke > `13631`–`13634`. The engine's default port sits **outside 4566–4599** on purpose: a real > LocalStack install intercepts that whole range on some hosts. @@ -72,7 +72,7 @@ in its fullest form: `lss.config.json` sets a custom `title`/`subtitle`, points `favicon` at `assets/logo.svg`, defaults the dashboard to the dark theme, overrides the TreeUI brand tokens (`brand-primary`/`brand-hover`/`brand-soft`) with teal tones — plus per-theme dark overrides and a raw custom property (`--tree-radius-md`) — so the dashboard -at `http://localhost:3140` opens dark with a teal accent and the example's own identity. +at `http://localhost:14566` opens dark with a teal accent and the example's own identity. ## Prerequisites @@ -89,7 +89,7 @@ npm run setup # 1. Start LSS with the self engine (boots in milliseconds) npm run lss:start -# 2. Register the four services (plain `sls package` — never `deploy`) +# 2. Register the four services (`lss register` — packages on demand, no plugin) npm run register:all # 3. Drive the pipeline @@ -102,7 +102,7 @@ curl http://localhost:3631/orders # order stored (plus the seeded one) curl http://localhost:3632/receipts # receipt written to S3 by billing curl http://localhost:3633/notifications # notification created via EventBridge -# 5. Dashboard: http://localhost:3140 (services, queues, tables, lambdas, APIs, Secrets) +# 5. Dashboard: http://localhost:14566 (services, queues, tables, lambdas, APIs, Secrets) npm run lss:stop ``` @@ -134,8 +134,8 @@ curl -s -X POST http://localhost:3631/orders \ # has been delivered twice and moved to the dead-letter queue. sleep 13 -curl -s http://localhost:3140/api/queues/orders-to-process-dlq # 1 message -curl -s http://localhost:3140/api/queues/orders-to-process # drained +curl -s http://localhost:14566/api/queues/orders-to-process-dlq # 1 message +curl -s http://localhost:14566/api/queues/orders-to-process # drained ``` The redriven message keeps its original `MessageId`, body and MD5 digests; its diff --git a/examples/self-hosted/billing-service/package-lock.json b/examples/self-hosted/billing-service/package-lock.json index 75cb1e7..5851f69 100644 --- a/examples/self-hosted/billing-service/package-lock.json +++ b/examples/self-hosted/billing-service/package-lock.json @@ -14,32 +14,7 @@ "@aws-sdk/s3-presigned-post": "^3.0.0" }, "devDependencies": { - "osls": "4.0.0", - "serverless-lss": "file:../../../packages/serverless-plugin" - } - }, - "../../../packages/serverless-plugin": { - "name": "serverless-lss", - "version": "0.2.2", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2" - }, - "devDependencies": { - "@types/node": "^22.10.5", - "typescript": "^5.7.3" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { "osls": "4.0.0" - }, - "peerDependenciesMeta": { - "osls": { - "optional": true - } } }, "node_modules/@apidevtools/json-schema-ref-parser": { @@ -1688,9 +1663,9 @@ } }, "node_modules/fast-uri": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.3.tgz", - "integrity": "sha512-i70LwGWUduXqzicKXWshooq+sWL1K3WUU5rKZNG/0i3a1OSoX3HqhH5WbWwTmqWfor4urUakGPiRQcleRZTwOg==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz", + "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==", "dev": true, "funding": [ { @@ -2452,10 +2427,6 @@ "node": ">=10" } }, - "node_modules/serverless-lss": { - "resolved": "../../../packages/serverless-plugin", - "link": true - }, "node_modules/sprintf-kit": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/sprintf-kit/-/sprintf-kit-2.0.2.tgz", diff --git a/examples/self-hosted/billing-service/package.json b/examples/self-hosted/billing-service/package.json index 21d01ab..3568ec5 100644 --- a/examples/self-hosted/billing-service/package.json +++ b/examples/self-hosted/billing-service/package.json @@ -4,8 +4,7 @@ "private": true, "description": "SQS consumer that writes a receipt to S3 and publishes OrderBilled to the billing-events bus; GET /receipts lists receipts. Port 3632 (invoke 13632).", "scripts": { - "package": "serverless package", - "register": "serverless package" + "package": "serverless package" }, "dependencies": { "@aws-sdk/client-eventbridge": "^3.0.0", @@ -14,7 +13,6 @@ "@aws-sdk/s3-presigned-post": "^3.0.0" }, "devDependencies": { - "osls": "4.0.0", - "serverless-lss": "file:../../../packages/serverless-plugin" + "osls": "4.0.0" } } diff --git a/examples/self-hosted/billing-service/serverless.yml b/examples/self-hosted/billing-service/serverless.yml index e602b9e..794675f 100644 --- a/examples/self-hosted/billing-service/serverless.yml +++ b/examples/self-hosted/billing-service/serverless.yml @@ -14,14 +14,8 @@ provider: BILLING_BUS: billing-events AWS_ENDPOINT: http://localhost:14566 -plugins: - - serverless-lss - custom: accountId: '000000000000' - orchestrator: - enabled: true - orchestratorUrl: http://localhost:3140 lss: apiPort: 3632 invokePort: 13632 diff --git a/examples/self-hosted/catalog-service/package-lock.json b/examples/self-hosted/catalog-service/package-lock.json index d235178..41a6735 100644 --- a/examples/self-hosted/catalog-service/package-lock.json +++ b/examples/self-hosted/catalog-service/package-lock.json @@ -8,32 +8,7 @@ "name": "catalog-service-example", "version": "0.0.0", "devDependencies": { - "osls": "4.0.0", - "serverless-lss": "file:../../../packages/serverless-plugin" - } - }, - "../../../packages/serverless-plugin": { - "name": "serverless-lss", - "version": "0.2.2", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2" - }, - "devDependencies": { - "@types/node": "^22.10.5", - "typescript": "^5.7.3" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { "osls": "4.0.0" - }, - "peerDependenciesMeta": { - "osls": { - "optional": true - } } }, "node_modules/@apidevtools/json-schema-ref-parser": { @@ -1671,9 +1646,9 @@ } }, "node_modules/fast-uri": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.3.tgz", - "integrity": "sha512-i70LwGWUduXqzicKXWshooq+sWL1K3WUU5rKZNG/0i3a1OSoX3HqhH5WbWwTmqWfor4urUakGPiRQcleRZTwOg==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz", + "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==", "dev": true, "funding": [ { @@ -2435,10 +2410,6 @@ "node": ">=10" } }, - "node_modules/serverless-lss": { - "resolved": "../../../packages/serverless-plugin", - "link": true - }, "node_modules/sprintf-kit": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/sprintf-kit/-/sprintf-kit-2.0.2.tgz", diff --git a/examples/self-hosted/catalog-service/package.json b/examples/self-hosted/catalog-service/package.json index a041db9..8d6bdad 100644 --- a/examples/self-hosted/catalog-service/package.json +++ b/examples/self-hosted/catalog-service/package.json @@ -2,13 +2,11 @@ "name": "catalog-service-example", "version": "0.0.0", "private": true, - "description": "POST /products indexes into OpenSearch; GET /search runs full-text + filtered queries; GET /stats aggregates. Port 3634 (invoke 13634). No runtime dependencies — the handlers speak the OpenSearch REST API with Node's global fetch.", + "description": "POST /products indexes into OpenSearch; GET /search runs full-text + filtered queries; GET /stats aggregates. Port 3634 (invoke 13634). No runtime dependencies \u2014 the handlers speak the OpenSearch REST API with Node's global fetch.", "scripts": { - "package": "serverless package", - "register": "serverless package" + "package": "serverless package" }, "devDependencies": { - "osls": "4.0.0", - "serverless-lss": "file:../../../packages/serverless-plugin" + "osls": "4.0.0" } } diff --git a/examples/self-hosted/catalog-service/serverless.yml b/examples/self-hosted/catalog-service/serverless.yml index e844a4e..a384da3 100644 --- a/examples/self-hosted/catalog-service/serverless.yml +++ b/examples/self-hosted/catalog-service/serverless.yml @@ -15,13 +15,7 @@ provider: OPENSEARCH_ENDPOINT: http://localhost:14566/_aoss/products-catalog PRODUCTS_INDEX: products -plugins: - - serverless-lss - custom: - orchestrator: - enabled: true - orchestratorUrl: http://localhost:3140 lss: apiPort: 3634 invokePort: 13634 diff --git a/examples/self-hosted/index.html b/examples/self-hosted/index.html index e555e23..e36a1c8 100644 --- a/examples/self-hosted/index.html +++ b/examples/self-hosted/index.html @@ -91,12 +91,12 @@

Request log

const CONFIG = { // Links shown top-right: [label, url] links: [ - ['Dashboard', 'http://localhost:3140'], + ['Dashboard', 'http://localhost:14566'], ], // Health checks: {label, url, note} (any 2xx/3xx/4xx response counts as "up"; // only network failure marks it down — LocalStack/engine endpoints often 404.) statuses: [ - { label: 'LSS orchestrator', url: 'http://localhost:3140/api/health', note: ':3140' }, + { label: 'LSS orchestrator', url: 'http://localhost:14566/api/health', note: ':14566' }, { label: 'orders-service', url: 'http://localhost:3631/orders', note: ':3631' }, { label: 'billing-service', url: 'http://localhost:3632/receipts', note: ':3632' }, { label: 'notifications-service', url: 'http://localhost:3633/notifications', note: ':3633' }, @@ -140,8 +140,8 @@

Request log

{ name: 'Create poison order (total: -1)', method: 'POST', url: 'http://localhost:3631/orders', body: { customerId: 'u-poison', total: -1 }, extract: { poisonOrderId: 'id' }, pause: 13000 }, - { name: 'peek DLQ (message count > 0 after redrive)', method: 'GET', url: 'http://localhost:3140/api/queues/orders-to-process-dlq' }, - { name: 'peek source queue (drained)', method: 'GET', url: 'http://localhost:3140/api/queues/orders-to-process' }, + { name: 'peek DLQ (message count > 0 after redrive)', method: 'GET', url: 'http://localhost:14566/api/queues/orders-to-process-dlq' }, + { name: 'peek source queue (drained)', method: 'GET', url: 'http://localhost:14566/api/queues/orders-to-process' }, { name: 'No receipt was written for it', method: 'GET', url: 'http://localhost:3632/receipts' }, ], }, diff --git a/examples/self-hosted/lss.config.json b/examples/self-hosted/lss.config.json index ca4288e..5567d11 100644 --- a/examples/self-hosted/lss.config.json +++ b/examples/self-hosted/lss.config.json @@ -1,9 +1,4 @@ { - "serverPort": 3140, - "engine": "self", - "selfEngine": { - "port": 14566 - }, "region": "us-west-2", "persistence": true, "debug": false, @@ -22,10 +17,7 @@ "favicon": "./assets/logo.svg", "defaultTheme": "dark", "colors": { - "brand-primary": "#0d9488", - "brand-hover": "#0f766e", - "brand-soft": "#ccfbf1", - "--tree-radius-md": "4px" + "brand-primary": "#0d9488" }, "themeColors": { "dark": { @@ -35,5 +27,6 @@ "brand-contrast": "#042f2e" } } - } + }, + "serviceRuntime": {} } diff --git a/examples/self-hosted/notifications-service/package-lock.json b/examples/self-hosted/notifications-service/package-lock.json index a61cbaa..0860779 100644 --- a/examples/self-hosted/notifications-service/package-lock.json +++ b/examples/self-hosted/notifications-service/package-lock.json @@ -12,32 +12,7 @@ "@aws-sdk/lib-dynamodb": "^3.0.0" }, "devDependencies": { - "osls": "4.0.0", - "serverless-lss": "file:../../../packages/serverless-plugin" - } - }, - "../../../packages/serverless-plugin": { - "name": "serverless-lss", - "version": "0.2.2", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2" - }, - "devDependencies": { - "@types/node": "^22.10.5", - "typescript": "^5.7.3" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { "osls": "4.0.0" - }, - "peerDependenciesMeta": { - "osls": { - "optional": true - } } }, "node_modules/@apidevtools/json-schema-ref-parser": { @@ -1752,9 +1727,9 @@ } }, "node_modules/fast-uri": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.3.tgz", - "integrity": "sha512-i70LwGWUduXqzicKXWshooq+sWL1K3WUU5rKZNG/0i3a1OSoX3HqhH5WbWwTmqWfor4urUakGPiRQcleRZTwOg==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz", + "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==", "dev": true, "funding": [ { @@ -2531,10 +2506,6 @@ "node": ">=10" } }, - "node_modules/serverless-lss": { - "resolved": "../../../packages/serverless-plugin", - "link": true - }, "node_modules/sprintf-kit": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/sprintf-kit/-/sprintf-kit-2.0.2.tgz", diff --git a/examples/self-hosted/notifications-service/package.json b/examples/self-hosted/notifications-service/package.json index 29dae5b..224c2d6 100644 --- a/examples/self-hosted/notifications-service/package.json +++ b/examples/self-hosted/notifications-service/package.json @@ -4,15 +4,13 @@ "private": true, "description": "EventBridge rule on billing-events (OrderBilled) stores a notification in DynamoDB; GET /notifications lists them. Port 3633 (invoke 13633).", "scripts": { - "package": "serverless package", - "register": "serverless package" + "package": "serverless package" }, "dependencies": { "@aws-sdk/client-dynamodb": "^3.0.0", "@aws-sdk/lib-dynamodb": "^3.0.0" }, "devDependencies": { - "osls": "4.0.0", - "serverless-lss": "file:../../../packages/serverless-plugin" + "osls": "4.0.0" } } diff --git a/examples/self-hosted/notifications-service/serverless.yml b/examples/self-hosted/notifications-service/serverless.yml index 0d0f2de..74d9131 100644 --- a/examples/self-hosted/notifications-service/serverless.yml +++ b/examples/self-hosted/notifications-service/serverless.yml @@ -13,14 +13,8 @@ provider: NOTIFICATIONS_TABLE: notifications-Notifications AWS_ENDPOINT: http://localhost:14566 -plugins: - - serverless-lss - custom: accountId: '000000000000' - orchestrator: - enabled: true - orchestratorUrl: http://localhost:3140 lss: apiPort: 3633 invokePort: 13633 diff --git a/examples/self-hosted/orders-service/package-lock.json b/examples/self-hosted/orders-service/package-lock.json index c9b9bed..4b327ab 100644 --- a/examples/self-hosted/orders-service/package-lock.json +++ b/examples/self-hosted/orders-service/package-lock.json @@ -13,32 +13,7 @@ "@aws-sdk/lib-dynamodb": "^3.0.0" }, "devDependencies": { - "osls": "4.0.0", - "serverless-lss": "file:../../../packages/serverless-plugin" - } - }, - "../../../packages/serverless-plugin": { - "name": "serverless-lss", - "version": "0.2.2", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2" - }, - "devDependencies": { - "@types/node": "^22.10.5", - "typescript": "^5.7.3" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { "osls": "4.0.0" - }, - "peerDependenciesMeta": { - "osls": { - "optional": true - } } }, "node_modules/@apidevtools/json-schema-ref-parser": { @@ -1788,9 +1763,9 @@ } }, "node_modules/fast-uri": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.3.tgz", - "integrity": "sha512-i70LwGWUduXqzicKXWshooq+sWL1K3WUU5rKZNG/0i3a1OSoX3HqhH5WbWwTmqWfor4urUakGPiRQcleRZTwOg==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz", + "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==", "dev": true, "funding": [ { @@ -2567,10 +2542,6 @@ "node": ">=10" } }, - "node_modules/serverless-lss": { - "resolved": "../../../packages/serverless-plugin", - "link": true - }, "node_modules/sprintf-kit": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/sprintf-kit/-/sprintf-kit-2.0.2.tgz", diff --git a/examples/self-hosted/orders-service/package.json b/examples/self-hosted/orders-service/package.json index 1bebe3c..8eda95d 100644 --- a/examples/self-hosted/orders-service/package.json +++ b/examples/self-hosted/orders-service/package.json @@ -4,8 +4,7 @@ "private": true, "description": "POST /orders stores the order in DynamoDB and enqueues it on SQS for billing; GET /orders lists them. Port 3631 (invoke 13631).", "scripts": { - "package": "serverless package", - "register": "serverless package" + "package": "serverless package" }, "dependencies": { "@aws-sdk/client-dynamodb": "^3.0.0", @@ -13,7 +12,6 @@ "@aws-sdk/lib-dynamodb": "^3.0.0" }, "devDependencies": { - "osls": "4.0.0", - "serverless-lss": "file:../../../packages/serverless-plugin" + "osls": "4.0.0" } } diff --git a/examples/self-hosted/orders-service/serverless.yml b/examples/self-hosted/orders-service/serverless.yml index b1df049..1fd2e9a 100644 --- a/examples/self-hosted/orders-service/serverless.yml +++ b/examples/self-hosted/orders-service/serverless.yml @@ -15,13 +15,7 @@ provider: ORDERS_QUEUE_URL: http://localhost:14566/000000000000/orders-to-process AWS_ENDPOINT: http://localhost:14566 -plugins: - - serverless-lss - custom: - orchestrator: - enabled: true - orchestratorUrl: http://localhost:3140 lss: apiPort: 3631 invokePort: 13631 diff --git a/examples/self-hosted/package.json b/examples/self-hosted/package.json index e25daad..4b7d97e 100644 --- a/examples/self-hosted/package.json +++ b/examples/self-hosted/package.json @@ -2,17 +2,18 @@ "name": "self-hosted", "version": "0.0.0", "private": true, - "description": "Four microservices (orders → billing → notifications pipeline + product catalog) running entirely on the LSS self engine: DynamoDB, SQS, S3, EventBridge and OpenSearch Serverless emulated in-process — no Docker, no LocalStack, no auth token.", + "description": "Four microservices (orders \u2192 billing \u2192 notifications pipeline + product catalog) running entirely on the LSS self engine: DynamoDB, SQS, S3, EventBridge and OpenSearch Serverless emulated in-process \u2014 no Docker, no LocalStack, no auth token.", "scripts": { - "lss:start": "node ../../bin/cli.js start --self-engine", + "lss:start": "node ../../bin/cli.js start", "lss:stop": "node ../../bin/cli.js stop", "lss:status": "node ../../bin/cli.js status", - "register:orders": "npm --prefix orders-service run package", - "register:billing": "npm --prefix billing-service run package", - "register:notifications": "npm --prefix notifications-service run package", - "register:catalog": "npm --prefix catalog-service run package", - "register:all": "npm run register:orders && npm run register:billing && npm run register:notifications && npm run register:catalog", + "register:orders": "node ../../bin/cli.js register orders-service", + "register:billing": "node ../../bin/cli.js register billing-service", + "register:notifications": "node ../../bin/cli.js register notifications-service", + "register:catalog": "node ../../bin/cli.js register catalog-service", + "register:all": "node ../../bin/cli.js register orders-service billing-service notifications-service catalog-service", "setup": "npm --prefix orders-service install && npm --prefix billing-service install && npm --prefix notifications-service install && npm --prefix catalog-service install", - "console": "npx -y http-server . -p 8622 -c-1" + "console": "npx -y http-server . -p 8622 -c-1", + "scan": "node ../../bin/cli.js scan" } } diff --git a/jest.config.js b/jest.config.js index 7544af1..8b46983 100644 --- a/jest.config.js +++ b/jest.config.js @@ -11,8 +11,9 @@ module.exports = { 'src/server/routes/**/*.ts', 'src/server/dev/**/*.ts', 'src/client/**/*.ts', - 'packages/serverless-plugin/src/**/*.ts', + 'src/mcp/**/*.ts', 'bin/cli.js', + 'bin/i18n.js', // Integration-only by nature — excluded from the coverage denominator: '!src/server/index.ts', // calls start()/listens at import '!src/server/services/localstack-manager.ts', // drives Docker diff --git a/jest.integration.config.js b/jest.integration.config.js index 47e32d8..16de710 100644 --- a/jest.integration.config.js +++ b/jest.integration.config.js @@ -1,6 +1,6 @@ -// Integration test config: boots a real isolated LSS + LocalStack (Docker). +// Integration test config: boots a real isolated LSS on the self engine. // No coverage gate; long timeouts. Run with `npm run test:integration`. -// Requires Docker and a LOCALSTACK_AUTH_TOKEN (community images >= 2026.5). +// No Docker and no auth token — it runs on any machine and in any CI job. module.exports = { preset: 'ts-jest', testEnvironment: 'node', @@ -11,8 +11,8 @@ module.exports = { '^(\\.{1,2}/.*)\\.js$': '$1', }, testTimeout: 120000, - // Docker-bound suites must not run in parallel workers (they would fight over - // LocalStack containers/ports). Run serially. + // Each suite binds real ports (orchestrator, engine, per-service listeners), + // so they must not overlap. Run serially. maxWorkers: 1, setupFilesAfterEnv: ['/tests/setup.integration.ts'], verbose: true, diff --git a/lss.config.json b/lss.config.json index 04e9c53..2b5a9e9 100644 --- a/lss.config.json +++ b/lss.config.json @@ -1,21 +1,8 @@ { - "serverPort": 3101, - "localstackPort": 4567, - "localstackEndpoint": "http://localhost:4567", - "mode": "managed", - "localstackEdition": "community", - "localstackVersion": "latest", - "enableDynamoProxy": false, - "dynamoProxyPort": 8001, + "stateDir": ".lss", "region": "us-east-1", - "services": [ - "dynamodb", - "sqs", - "sns", - "s3", - "lambda", - "events" - ], "persistence": true, - "debug": true + "debug": true, + "enableDynamoProxy": false, + "dynamoProxyPort": 8001 } diff --git a/lss.config.json.example b/lss.config.json.example index d394841..b3550c3 100644 --- a/lss.config.json.example +++ b/lss.config.json.example @@ -1,15 +1,16 @@ { "serverPort": 3100, - "engine": "localstack", - "mode": "managed", - "localstackEdition": "community", - "localstackVersion": "latest", - "localstackPort": 4566, - "localstackEndpoint": "http://localhost:4566", + "selfEngine": { + "port": 14566, + "account": "000000000000", + "idleUnloadMs": 300000, + "memoryBudgetMb": 128, + "fsync": false, + "fallbackEndpoint": null + }, "enableDynamoProxy": false, "dynamoProxyPort": 8000, "region": "us-east-1", - "services": ["dynamodb", "sqs", "sns", "s3", "lambda", "events"], "persistence": true, "debug": false, "seedsDir": "./seeds", @@ -25,15 +26,14 @@ "lambdaRuntime": { "enabled": true, "execution": "auto", - "invokePortOffset": 10000 + "invokePortOffset": 10000, + "lazy": true, + "idleTimeoutMs": 60000, + "maxWarmWorkers": 8 }, "serviceRuntime": { "users-service": { "apiPort": 3010, "invokePort": 13010 } }, - "selfEngine": { - "port": 14566, - "fallbackEndpoint": null - }, "branding": { "title": "Local Serverless Stack", "subtitle": "Local development control plane", @@ -41,12 +41,12 @@ "favicon": "./assets/favicon.ico", "defaultTheme": "dark", "colors": { - "brand-primary": "#3b82f6", - "brand-hover": "#2563eb" + "brand-primary": "#0d9488", + "brand-hover": "#0f766e" }, "themeColors": { - "dark": { "bg-primary": "#0d1117" }, - "light": { "bg-primary": "#f8fafc" } + "dark": { "brand-primary": "#2dd4bf" }, + "light": { "brand-primary": "#0d9488" } } } } diff --git a/package-lock.json b/package-lock.json index e810f9e..a2bb515 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,14 @@ { "name": "local-serverless-stack", - "version": "0.17.2", + "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "local-serverless-stack", - "version": "0.17.2", + "version": "1.0.0", "license": "MIT", "workspaces": [ - "packages/*", "src/ui" ], "dependencies": { @@ -919,12 +918,13 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", - "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.28.5", + "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" }, @@ -933,29 +933,31 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.29.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.3.tgz", - "integrity": "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", - "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helpers": "^7.28.6", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.29.0", - "@babel/types": "^7.29.0", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", @@ -972,13 +974,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.29.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", - "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz", + "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/parser": "^7.29.0", - "@babel/types": "^7.29.0", + "@babel/parser": "^7.29.8", + "@babel/types": "^7.29.8", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -988,13 +991,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -1004,36 +1008,39 @@ } }, "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.6" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1052,49 +1059,54 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", - "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0" + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.29.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz", - "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz", + "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", + "license": "MIT", "dependencies": { - "@babel/types": "^7.29.0" + "@babel/types": "^7.29.8" }, "bin": { "parser": "bin/babel-parser.js" @@ -1326,31 +1338,33 @@ } }, "node_modules/@babel/template": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", - "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz", + "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0", + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.8", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.8", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.8", "debug": "^4.3.1" }, "engines": { @@ -1358,12 +1372,13 @@ } }, "node_modules/@babel/types": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1917,10 +1932,21 @@ } }, "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -3388,23 +3414,25 @@ } }, "node_modules/@treeui/tokens": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@treeui/tokens/-/tokens-0.15.0.tgz", - "integrity": "sha512-5sKMhIcnevCCYNAbDucXsMqNuo6k7yQZGuMv3cLhzyuFNKjEUyHGQitamuzQFzwU2cZbWv/s8WQnSoTei0xDZg==" + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@treeui/tokens/-/tokens-0.25.0.tgz", + "integrity": "sha512-1SUax16rfklxcwInOwaa904yty91ncTRXFTBk6f3yoc2KwESvCeYhv1MbZJqePw7dtjlQzWOmw5f9mJBXTOELQ==", + "license": "MIT" }, "node_modules/@treeui/utils": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@treeui/utils/-/utils-0.13.0.tgz", - "integrity": "sha512-E/ZWsq/CDb1y3L8hn+PFTKvGMp5E5R9yyH2o4mSwf/dL3DykQ8bu7hVDLzJVk6T82jYvVtSEvQClh82ZJZsCuQ==" + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@treeui/utils/-/utils-0.24.0.tgz", + "integrity": "sha512-Q/KoWmCvZJKaS/ilGu2VsX3m9f89cGOl4totonbT5Gddy3iYAMNUj5v63I/WGS0rHQ/mey+47owuYhfnyC4dcw==" }, "node_modules/@treeui/vue": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@treeui/vue/-/vue-0.23.0.tgz", - "integrity": "sha512-CP0sRN1Q8kzbqGEN/E4fdfuKlVTPQsnZv3sOnQCED87dCrgu4ixDus8wdbsoLe8ki2zVF9Ji2mUtON6V8i2IDw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@treeui/vue/-/vue-0.25.0.tgz", + "integrity": "sha512-Evzj56Yk1+L6MsdwRsIkMj4EBa9gkwrUS8atEmPKDL0Xt2nSmzBhJ7gfV9FfqAEAug+QyjrpCFMH8xUnTGUhWg==", + "license": "MIT", "dependencies": { "@treeui/icons": "0.18.0", - "@treeui/tokens": "0.15.0", - "@treeui/utils": "0.13.0" + "@treeui/tokens": "0.25.0", + "@treeui/utils": "0.24.0" }, "peerDependencies": { "vue": "^3.5.13" @@ -3987,10 +4015,11 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", - "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", + "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -4400,6 +4429,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -4674,10 +4704,11 @@ "dev": true }, "node_modules/baseline-browser-mapping": { - "version": "2.10.31", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.31.tgz", - "integrity": "sha512-MujYO3eP72uvmSE0i4wltsodRfIpZATP3jvzRNRGGxgzId7aVocVJJV3nf01qnzzKFGxQVC9bpWxl5cjxTr/7Q==", + "version": "2.11.9", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.9.tgz", + "integrity": "sha512-cp447VUsGS07+n1Dqf7YSQ8maeJrjEhaDxTm1ZefbqDtypHBC5GzGMQbklR6IPR13Y8OAJRHZWEMtZipJLCttg==", "dev": true, + "license": "Apache-2.0", "bin": { "baseline-browser-mapping": "dist/cli.cjs" }, @@ -4736,10 +4767,11 @@ "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==" }, "node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4758,9 +4790,9 @@ } }, "node_modules/browserslist": { - "version": "4.28.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", - "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "version": "4.28.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.7.tgz", + "integrity": "sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw==", "dev": true, "funding": [ { @@ -4776,11 +4808,12 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.10.12", - "caniuse-lite": "^1.0.30001782", - "electron-to-chromium": "^1.5.328", - "node-releases": "^2.0.36", + "baseline-browser-mapping": "^2.10.44", + "caniuse-lite": "^1.0.30001806", + "electron-to-chromium": "^1.5.393", + "node-releases": "^2.0.51", "update-browserslist-db": "^1.2.3" }, "bin": { @@ -4873,9 +4906,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001793", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz", - "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==", + "version": "1.0.30001806", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001806.tgz", + "integrity": "sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==", "dev": true, "funding": [ { @@ -4890,7 +4923,8 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/chai": { "version": "6.2.2", @@ -4906,6 +4940,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -4981,6 +5016,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -4991,7 +5027,8 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "node_modules/combined-stream": { "version": "1.0.8", @@ -5313,10 +5350,11 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.5.357", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.357.tgz", - "integrity": "sha512-NHlTIQDK8fmVwHwuIzmXYEJ1Ewq3D9wDNc0cWXxDGysP6Pb21giwGNkxiTifyKy/4SoPuN5l6GLP1W9Sv7zB2g==", - "dev": true + "version": "1.5.399", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.399.tgz", + "integrity": "sha512-lEcqhErbHjXRvd41rnWLpzbyU/IXfIYo7QwaFWmxGeLiLyY2TBCdHnWY88vB+p3ubnihRypDm66panXl7TylLA==", + "dev": true, + "license": "ISC" }, "node_modules/emittery": { "version": "0.13.1", @@ -6257,6 +6295,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { "node": ">=8" } @@ -7265,10 +7304,11 @@ "dev": true }, "node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.1.tgz", + "integrity": "sha512-S99WuO3HlhO3XN41EtYUNl9zzXjoJx7QvmipxsJVxtCBT0YHEFy+iOJhjSvrmV12nYhWpZaM8lPHkJm0yUMbag==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -7407,6 +7447,7 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^3.0.2" } @@ -7690,10 +7731,14 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.44", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.44.tgz", - "integrity": "sha512-5WUyunoPMsvvEhS8AxHtRzP+oA8UCkJ7YRxatWKjngndhDGLiqEVAQKWjFAiAiuL8zMRGzGSJxFnLetoa43qGQ==", - "dev": true + "version": "2.0.51", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.51.tgz", + "integrity": "sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/normalize-path": { "version": "3.0.0", @@ -8356,10 +8401,6 @@ "node": ">= 0.8.0" } }, - "node_modules/serverless-lss": { - "resolved": "packages/serverless-plugin", - "link": true - }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -8735,6 +8776,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -9112,6 +9154,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" @@ -9943,7 +9986,8 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/yargs": { "version": "17.7.2", @@ -9993,51 +10037,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/serverless-plugin": { - "name": "serverless-lss", - "version": "0.2.2", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2" - }, - "devDependencies": { - "@types/node": "^22.10.5", - "typescript": "^5.7.3" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "osls": "4.0.0" - }, - "peerDependenciesMeta": { - "osls": { - "optional": true - } - } - }, - "packages/serverless-plugin/node_modules/@types/node": { - "version": "22.19.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.19.tgz", - "integrity": "sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "packages/serverless-plugin/node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "dev": true, - "license": "MIT" - }, "src/ui": { "name": "lss-orchestrator-ui", "version": "0.1.2", "dependencies": { - "@treeui/vue": "^0.23.0", + "@treeui/vue": "^0.25.0", "vue": "^3.5.13", "vue-router": "^4.6.4" }, diff --git a/package.json b/package.json index 1914507..a15f27c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "local-serverless-stack", - "version": "0.17.2", - "description": "Local control plane for serverless development with LocalStack orchestration", + "version": "1.0.0", + "description": "Local control plane for serverless development — an in-process AWS emulator, no Docker required", "author": "LSS Contributors", "license": "MIT", "bin": { @@ -33,25 +33,24 @@ "local" ], "files": [ - "bin/", - "dist/", - "packages/serverless-plugin/dist/", - "README.md", + "CHANGELOG.md", "LICENSE", - "CHANGELOG.md" + "README.md", + "assets/", + "bin/", + "dist/" ], "workspaces": [ - "packages/*", "src/ui" ], "scripts": { - "build": "npm run ui:build && npm run server:build && npm run client:build && npm run plugin:build", + "build": "npm run ui:build && npm run server:build && npm run client:build && npm run mcp:build", "server:dev": "tsx watch src/server/index.ts", "server:build": "tsc --project src/server/tsconfig.json", "client:build": "tsc --project src/client/tsconfig.json", "ui:dev": "cd src/ui && npm run dev", "ui:build": "cd src/ui && npm run build", - "plugin:build": "npm run build -w packages/serverless-plugin", + "icons:aws": "node scripts/generate-aws-icons.mjs", "dev": "concurrently \"npm run server:dev\" \"npm run ui:dev\"", "setup": "npm install && cd src/ui && npm install", "prepublishOnly": "npm run build", @@ -61,7 +60,8 @@ "test:coverage": "jest -c jest.config.js --coverage", "test:integration": "jest -c jest.integration.config.js", "lint": "eslint .", - "lint:fix": "eslint . --fix" + "lint:fix": "eslint . --fix", + "mcp:build": "tsc --project src/mcp/tsconfig.json" }, "dependencies": { "@aws-sdk/client-dynamodb": "^3.709.0", diff --git a/packages/serverless-plugin/README.md b/packages/serverless-plugin/README.md deleted file mode 100644 index 4967d22..0000000 --- a/packages/serverless-plugin/README.md +++ /dev/null @@ -1,115 +0,0 @@ -# Serverless Orchestrator Plugin - -[![npm version](https://img.shields.io/npm/v/serverless-lss.svg)](https://www.npmjs.com/package/serverless-lss) - -Automatically register your Serverless microservices with the Local Serverless Stack Local Orchestrator. - -## Installation - -```bash -npm install --save-dev serverless-lss -``` - -## Usage - -Add the plugin to your `serverless.yml`: - -```yaml -plugins: - - serverless-lss - -custom: - orchestrator: - enabled: true - orchestratorUrl: http://localhost:3100 -``` - -## How it works - -After running `sls package` or `sls deploy`: - -1. The plugin sends a registration request to the Orchestrator (service path, ports, region) -2. The Orchestrator reads the `sls package` artifacts from `.serverless/` (CloudFormation template + `serverless-state.json`) -3. It provisions resources (DynamoDB, SQS, SNS, S3) to LocalStack -4. It registers the service's Lambda functions, HTTP routes and authorizers, starts a runtime worker, and binds the service's API port (30xx) and Lambda-invoke port (130xx) — replacing `serverless-offline` - -## Configuration Options - -- `enabled` (boolean, default: `true`): Enable/disable the plugin -- `orchestratorUrl` (string, default: `http://localhost:3100`): Orchestrator API endpoint - -### Service ports - -The plugin reports which ports LSS should serve the service on: - -```yaml -custom: - lss: # preferred — explicit LSS ports - apiPort: 3010 # API Gateway emulator (HTTP routes) - invokePort: 13010 # AWS Lambda Invoke API - serverless-offline: # fallback — drop-in for services already using offline - httpPort: 3010 - lambdaPort: 13010 -``` - -If only `apiPort` is known, the orchestrator derives `invokePort = apiPort + 10000` -(configurable via `lambdaRuntime.invokePortOffset`). - -### Example with custom config: - -```yaml -plugins: - - serverless-lss - -custom: - orchestrator: - enabled: true - orchestratorUrl: http://my-orchestrator:3100 -``` - -## Environment Variables (optional) - -You can also use environment variables to override the configuration: - -```bash -ORCHESTRATOR_URL=http://localhost:3100 sls package -``` - -## Features - -✅ Auto-registers on `sls package` -✅ Auto-registers on `sls deploy` -✅ Non-blocking: deployment continues even if orchestrator is unavailable -✅ Colored console output -✅ Minimal dependencies - -## Behavior - -- If the Orchestrator is unavailable, the plugin logs a warning but doesn't fail the deployment -- The plugin is compatible with all Serverless Framework providers -- It only reads existing `.serverless/cloudformation-template-update-stack.json` files (doesn't create them) - -## Troubleshooting - -**"Orchestrator unavailable" message** - -Make sure the Orchestrator is running: - -```bash -cd orchestrator -npm run server -``` - -**Plugin not found** - -Make sure you're using a recent version of Serverless Framework (3.0+) and that the plugin is installed in `node_modules`. - -## Development - -```bash -# Build -npm run build - -# Watch mode -npm run dev -``` diff --git a/packages/serverless-plugin/package.json b/packages/serverless-plugin/package.json deleted file mode 100644 index 87ff03e..0000000 --- a/packages/serverless-plugin/package.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "name": "serverless-lss", - "version": "0.2.2", - "description": "Serverless plugin to auto-register services with Local Serverless Stack (LSS) Orchestrator", - "main": "dist/index.js", - "types": "dist/index.d.ts", - "scripts": { - "build": "tsc", - "dev": "tsc --watch", - "prepublishOnly": "npm run build" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "osls": "4.0.0" - }, - "peerDependenciesMeta": { - "osls": { - "optional": true - } - }, - "dependencies": { - "chalk": "^4.1.2" - }, - "devDependencies": { - "@types/node": "^22.10.5", - "typescript": "^5.7.3" - }, - "keywords": [ - "serverless", - "plugin", - "orchestrator", - "localstack", - "local-serverless-stack", - "lss" - ], - "author": "LSS Contributors", - "license": "MIT" -} diff --git a/packages/serverless-plugin/src/index.ts b/packages/serverless-plugin/src/index.ts deleted file mode 100644 index 2a9b5db..0000000 --- a/packages/serverless-plugin/src/index.ts +++ /dev/null @@ -1,143 +0,0 @@ -import chalk from 'chalk'; - -interface ServerlessInstance { - config: { - servicePath: string; - service?: string; - }; - service?: { - service?: string; - custom?: Record; - provider?: { - region?: string; - }; - }; - utils?: { - log?: { - notice?: (msg: string) => void; - error?: (msg: string) => void; - }; - }; -} - -interface PluginOptions { - orchestratorUrl?: string; - enabled?: boolean; -} - -class ServerlessOrchestratorPlugin { - private serverless: ServerlessInstance; - private orchestratorUrl: string; - private enabled: boolean; - public hooks: Record Promise>; - - constructor(serverless: ServerlessInstance, options: PluginOptions = {}) { - this.serverless = serverless; - const customConfig = (this.serverless.service?.custom || {}).orchestrator || {}; - - // Merge priority: env > options > custom > defaults - const merged = { - enabled: true, - orchestratorUrl: 'http://localhost:3100', - ...customConfig, - ...options, - } as PluginOptions; - - // Env overrides win over file/options so the same serverless.yml can register - // against different LSS instances at runtime (e.g. an isolated e2e stack). - // ORCHESTRATOR_URL (a full URL) is the most explicit and wins over - // LSS_DASHBOARD_PORT (just the dashboard port of the target instance). - if (process.env.ORCHESTRATOR_URL) { - merged.orchestratorUrl = process.env.ORCHESTRATOR_URL; - } else if (process.env.LSS_DASHBOARD_PORT) { - merged.orchestratorUrl = `http://localhost:${process.env.LSS_DASHBOARD_PORT}`; - } - if (process.env.ORCHESTRATOR_ENABLED) { - merged.enabled = process.env.ORCHESTRATOR_ENABLED !== 'false'; - } - - this.orchestratorUrl = merged.orchestratorUrl!; - this.enabled = merged.enabled !== false; - - this.hooks = { - 'after:package:finalize': this.registerWithOrchestrator.bind(this), - // 'after:deploy:deploy': this.registerWithOrchestrator.bind(this), - 'before:offline:start': this.registerWithOrchestrator.bind(this), - 'before:offline:start:init': this.registerWithOrchestrator.bind(this), - }; - } - - private log(message: string, type: 'info' | 'success' | 'error' = 'info'): void { - const timestamp = new Date().toLocaleTimeString(); - - let formattedMessage = ''; - switch (type) { - case 'success': - formattedMessage = chalk.green(`✓ [${timestamp}] ${message}`); - break; - case 'error': - formattedMessage = chalk.red(`✗ [${timestamp}] ${message}`); - break; - default: - formattedMessage = chalk.blue(`ℹ [${timestamp}] ${message}`); - } - - console.log(formattedMessage); - } - - private async registerWithOrchestrator(): Promise { - if (!this.enabled) { - return; - } - - const servicePath = this.serverless.config.servicePath; - const serviceName = this.serverless.service?.service || this.serverless.config.service || 'unknown'; - const region = this.serverless.service?.provider?.region; // Don't use fallback, let orchestrator handle it - - // Port discovery: custom.lss wins; custom.serverless-offline keeps drop-in - // compatibility for services already configured for offline (httpPort → - // apiPort, lambdaPort → invokePort). - const lssConfig = this.serverless.service?.custom?.lss || {}; - const serverlessOfflineConfig = this.serverless.service?.custom?.['serverless-offline'] || {}; - const invokePort = lssConfig.invokePort ?? serverlessOfflineConfig.lambdaPort; - const apiPort = lssConfig.apiPort ?? serverlessOfflineConfig.httpPort; - - if (region) { - this.log(`Registering service "${serviceName}" (region: ${region} from Serverless Framework) with orchestrator at ${this.orchestratorUrl}...`, 'info'); - } else { - this.log(`Registering service "${serviceName}" (region will use orchestrator configuration) with orchestrator at ${this.orchestratorUrl}...`, 'info'); - } - - try { - const response = await fetch(`${this.orchestratorUrl}/api/services/register`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - servicePath, - invokePort, - ...(apiPort !== undefined && { apiPort }), - ...(region && { region }), // Only include region if defined in Serverless Framework - }), - }); - - if (!response.ok) { - const error = (await response.json().catch(() => ({ error: response.statusText }))) as any; - throw new Error(error.error || `HTTP ${response.status}`); - } - - const result = (await response.json()) as any; - this.log(`Orchestrator: Registered ${result.resourcesCount} resources for "${serviceName}"`, 'success'); - } catch (error: any) { - // Non-blocking error: log but don't fail the deployment - this.log( - `Orchestrator unavailable or registration failed: ${error.message}. Continuing without orchestrator sync.`, - 'error', - ); - } - } -} - -// Export for serverless framework (CommonJS) -module.exports = ServerlessOrchestratorPlugin; diff --git a/packages/serverless-plugin/tsconfig.json b/packages/serverless-plugin/tsconfig.json deleted file mode 100644 index 5c099fe..0000000 --- a/packages/serverless-plugin/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "module": "CommonJS", - "moduleResolution": "node", - "outDir": "./dist", - "rootDir": "./src" - }, - "include": [ - "src/**/*" - ] -} diff --git a/scripts/generate-aws-icons.mjs b/scripts/generate-aws-icons.mjs new file mode 100644 index 0000000..17aa0d4 --- /dev/null +++ b/scripts/generate-aws-icons.mjs @@ -0,0 +1,534 @@ +#!/usr/bin/env node +/** + * Vendors the official AWS Architecture Service Icons into the dashboard. + * + * WHY THIS EXISTS + * --------------- + * The dashboard names AWS services all over the place (nav entries, resource + * counters, service detail pages). `ui-ux.md` rule 3 says brands are NOT + * TreeUI's job — they come from a standardised external source — and for AWS + * marks the canonical source is AWS's own pack: + * + * https://aws.amazon.com/architecture/icons/ (pack 07312025, "16" variant) + * + * The pack is a 41 MB download that we deliberately do NOT keep in the repo. + * This script reads it once and emits the geometry as a committed TypeScript + * module, so the build never depends on the download being present. The default + * unzip location (`temp/`) is in `.gitignore` precisely so that reading the pack + * can never turn into redistributing it: LSS is a public MIT repo, the artwork + * is AWS's trademark, and a stray `git add -A` must not be able to pick it up. + * + * WHY THE "16" VARIANT + * -------------------- + * The 16/32/48/64 variants are structurally identical artwork (a background + * in the category colour plus a white glyph). Only the "16" files are + * authored on a `viewBox="0 0 24 24"` grid — exactly the grid TreeUI's own + * Branchline icons use — so they drop into the TreeUI registry with no + * scaling wrapper and no fidelity loss. + * + * WHY A NESTED NODE TREE AND NOT `TIconNodes` + * ------------------------------------------- + * TreeUI's raw geometry type is FLAT (`TIconNode = [tag, attrs]`, rendered by + * `createTreeIcon` with no children), so a `` wrapper cannot + * be expressed and its inherited fill would have to be flattened onto every + * leaf. AWS's terms require the marks to be used unmodified, so instead of + * rewriting the artwork we keep the source tree and register each icon as a + * Vue *component* — `registerTreeIcons` accepts `TIconNodes | Component` and + * stores a component verbatim. See `createAwsBrandIcon.ts` for the component + * contract (it mirrors `createTreeIcon`'s props so `` keeps + * working). + * + * USAGE + * ----- + * npm run icons:aws # default pack location (temp/…, gitignored) + * node scripts/generate-aws-icons.mjs /path/to/Architecture-Service-Icons_07312025 + * + * An explicit path should live OUTSIDE the repo — `temp/` is the only in-repo + * directory ignored for this, so any other one leaves the pack stageable. + * + * TO ADD A SERVICE: add one line to the CATALOGUE table below and re-run. + * The table IS the curated catalogue — nothing else selects icons. + * + * NOTE: `eslint.config.mjs` ignores `**\/*.mjs`, so this file is lint-exempt. + * Keep it clean anyway. + */ + +import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'; +import { dirname, join, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url)); +const REPO_ROOT = resolve(SCRIPT_DIR, '..'); + +/** The pack we vendor from — recorded in the generated banner and in NOTICE.md. */ +const PACK_NAME = 'AWS Architecture Service Icons'; +const PACK_DATE = '07312025'; +const PACK_VARIANT = '16'; +const PACK_URL = 'https://aws.amazon.com/architecture/icons/'; +/** Default unzip target. `temp/` is gitignored, so the pack stays un-committable. */ +const DEFAULT_PACK_DIR = resolve(REPO_ROOT, 'temp', `Architecture-Service-Icons_${PACK_DATE}`); +const OUT_DIR = resolve(REPO_ROOT, 'src/ui/src/icons/aws'); + +/** + * THE CURATED CATALOGUE. + * + * `tier: 'core'` — an AWS service LSS actually provides today (emulated by the + * self engine, or served by the orchestrator). `tier: 'reserve'` — imported + * ahead of need so a future screen never has to re-download the pack. + * + * `name` is the key the icon is registered under in the TreeUI registry. + * Naming rule: always `aws-` + kebab-case; use the acronym when the acronym is + * what developers say (s3, sqs, sns, iam, kms, ecs…), otherwise the short + * product name in words (secrets-manager, api-gateway, step-functions). Never + * the legal long form (`aws-s3`, not `aws-simple-storage-service`). + */ +const CATALOGUE = [ + // --------------------------------------------------------------------- + // Tier A — services LSS provides today. Each one has a live LSS surface. + // --------------------------------------------------------------------- + // Emulated control plane (engine/emulators/lambda-ctl) + the in-process runtime. + { name: 'aws-lambda', label: 'AWS Lambda', category: 'Compute', tier: 'core', file: 'Arch_Compute/16/Arch_AWS-Lambda_16.svg' }, + // Emulated (engine/emulators/dynamodb): streams, GSI/LSI, TTL, transactions. + { name: 'aws-dynamodb', label: 'Amazon DynamoDB', category: 'Database', tier: 'core', file: 'Arch_Database/16/Arch_Amazon-DynamoDB_16.svg' }, + // Emulated (engine/emulators/s3): presigned POST/GET, CORS, notifications. + { name: 'aws-s3', label: 'Amazon S3', category: 'Storage', tier: 'core', file: 'Arch_Storage/16/Arch_Amazon-Simple-Storage-Service_16.svg' }, + // Emulated (engine/emulators/sqs) + SQS->Lambda dispatch (dispatch/sqs-poller). + { name: 'aws-sqs', label: 'Amazon SQS', category: 'App Integration', tier: 'core', file: 'Arch_App-Integration/16/Arch_Amazon-Simple-Queue-Service_16.svg' }, + // Emulated, minimal (engine/emulators/sns): topics + Publish, no fan-out yet. + { name: 'aws-sns', label: 'Amazon SNS', category: 'App Integration', tier: 'core', file: 'Arch_App-Integration/16/Arch_Amazon-Simple-Notification-Service_16.svg' }, + // Emulated (engine/emulators/events): buses, rules, patterns, scheduled targets. + { name: 'aws-eventbridge', label: 'Amazon EventBridge', category: 'App Integration', tier: 'core', file: 'Arch_App-Integration/16/Arch_Amazon-EventBridge_16.svg' }, + // OpenSearch Serverless emulated (engine/emulators/opensearch, service 'aoss'). + // The pack ships no separate Serverless mark; this is the OpenSearch mark. + { name: 'aws-opensearch', label: 'Amazon OpenSearch Service', category: 'Analytics', tier: 'core', file: 'Arch_Analytics/16/Arch_Amazon-OpenSearch-Service_16.svg' }, + // Emulated (engine/emulators/secretsmanager) with real AWSCURRENT/AWSPREVIOUS. + { name: 'aws-secrets-manager', label: 'AWS Secrets Manager', category: 'Security, Identity & Compliance', tier: 'core', file: 'Arch_Security-Identity-Compliance/16/Arch_AWS-Secrets-Manager_16.svg' }, + // Served, not emulated on the AWS wire: LSS's own HTTP API emulation. + { name: 'aws-api-gateway', label: 'Amazon API Gateway', category: 'Networking & Content Delivery', tier: 'core', file: 'Arch_Networking-Content-Delivery/16/Arch_Amazon-API-Gateway_16.svg' }, + // The provisioning source of truth (services/cloudformation-parser.ts). + { name: 'aws-cloudformation', label: 'AWS CloudFormation', category: 'Management & Governance', tier: 'core', file: 'Arch_Management-Governance/16/Arch_AWS-CloudFormation_16.svg' }, + // Identity surface. ALSO CARRIES STS (engine/emulators/sts.ts): the + // Architecture pack has no STS mark at all — AWS folds STS into IAM. + { name: 'aws-iam', label: 'AWS Identity and Access Management', category: 'Security, Identity & Compliance', tier: 'core', file: 'Arch_Security-Identity-Compliance/16/Arch_AWS-Identity-and-Access-Management_16.svg' }, + // Log/observability surfaces only — there is no CloudWatch emulator. ALSO + // CARRIES CLOUDWATCH LOGS: the Architecture pack only has the umbrella mark. + { name: 'aws-cloudwatch', label: 'Amazon CloudWatch', category: 'Management & Governance', tier: 'core', file: 'Arch_Management-Governance/16/Arch_Amazon-CloudWatch_16.svg' }, + + // --------------------------------------------------------------------- + // Tier B — reserve. Not provided by LSS today; vendored so a future screen + // (or a service whose template references them) has the mark on hand. + // --------------------------------------------------------------------- + { name: 'aws-step-functions', label: 'AWS Step Functions', category: 'App Integration', tier: 'reserve', file: 'Arch_App-Integration/16/Arch_AWS-Step-Functions_16.svg' }, + { name: 'aws-express-workflows', label: 'AWS Express Workflows', category: 'App Integration', tier: 'reserve', file: 'Arch_App-Integration/16/Arch_AWS-Express-Workflows_16.svg' }, + { name: 'aws-appsync', label: 'AWS AppSync', category: 'App Integration', tier: 'reserve', file: 'Arch_App-Integration/16/Arch_AWS-AppSync_16.svg' }, + { name: 'aws-mq', label: 'Amazon MQ', category: 'App Integration', tier: 'reserve', file: 'Arch_App-Integration/16/Arch_Amazon-MQ_16.svg' }, + { name: 'aws-iot-core', label: 'AWS IoT Core', category: 'Internet of Things', tier: 'reserve', file: 'Arch_Internet-of-Things/16/Arch_AWS-IoT-Core_16.svg' }, + { name: 'aws-iot-events', label: 'AWS IoT Events', category: 'Internet of Things', tier: 'reserve', file: 'Arch_Internet-of-Things/16/Arch_AWS-IoT-Events_16.svg' }, + { name: 'aws-iot-greengrass', label: 'AWS IoT Greengrass', category: 'Internet of Things', tier: 'reserve', file: 'Arch_Internet-of-Things/16/Arch_AWS-IoT-Greengrass_16.svg' }, + { name: 'aws-kinesis', label: 'Amazon Kinesis', category: 'Analytics', tier: 'reserve', file: 'Arch_Analytics/16/Arch_Amazon-Kinesis_16.svg' }, + { name: 'aws-kinesis-data-streams', label: 'Amazon Kinesis Data Streams', category: 'Analytics', tier: 'reserve', file: 'Arch_Analytics/16/Arch_Amazon-Kinesis-Data-Streams_16.svg' }, + { name: 'aws-data-firehose', label: 'Amazon Data Firehose', category: 'Analytics', tier: 'reserve', file: 'Arch_Analytics/16/Arch_Amazon-Data-Firehose_16.svg' }, + { name: 'aws-athena', label: 'Amazon Athena', category: 'Analytics', tier: 'reserve', file: 'Arch_Analytics/16/Arch_Amazon-Athena_16.svg' }, + { name: 'aws-glue', label: 'AWS Glue', category: 'Analytics', tier: 'reserve', file: 'Arch_Analytics/16/Arch_AWS-Glue_16.svg' }, + { name: 'aws-msk', label: 'Amazon MSK', category: 'Analytics', tier: 'reserve', file: 'Arch_Analytics/16/Arch_Amazon-Managed-Streaming-for-Apache-Kafka_16.svg' }, + { name: 'aws-cognito', label: 'Amazon Cognito', category: 'Security, Identity & Compliance', tier: 'reserve', file: 'Arch_Security-Identity-Compliance/16/Arch_Amazon-Cognito_16.svg' }, + { name: 'aws-kms', label: 'AWS Key Management Service', category: 'Security, Identity & Compliance', tier: 'reserve', file: 'Arch_Security-Identity-Compliance/16/Arch_AWS-Key-Management-Service_16.svg' }, + { name: 'aws-acm', label: 'AWS Certificate Manager', category: 'Security, Identity & Compliance', tier: 'reserve', file: 'Arch_Security-Identity-Compliance/16/Arch_AWS-Certificate-Manager_16.svg' }, + { name: 'aws-waf', label: 'AWS WAF', category: 'Security, Identity & Compliance', tier: 'reserve', file: 'Arch_Security-Identity-Compliance/16/Arch_AWS-WAF_16.svg' }, + { name: 'aws-systems-manager', label: 'AWS Systems Manager', category: 'Management & Governance', tier: 'reserve', file: 'Arch_Management-Governance/16/Arch_AWS-Systems-Manager_16.svg' }, + { name: 'aws-appconfig', label: 'AWS AppConfig', category: 'Management & Governance', tier: 'reserve', file: 'Arch_Management-Governance/16/Arch_AWS-AppConfig_16.svg' }, + { name: 'aws-cloudtrail', label: 'AWS CloudTrail', category: 'Management & Governance', tier: 'reserve', file: 'Arch_Management-Governance/16/Arch_AWS-CloudTrail_16.svg' }, + // AWS Config the compliance service — NOT application configuration. The + // `aws-` prefix is what keeps this from reading as a TreeUI functional icon. + { name: 'aws-config', label: 'AWS Config', category: 'Management & Governance', tier: 'reserve', file: 'Arch_Management-Governance/16/Arch_AWS-Config_16.svg' }, + { name: 'aws-x-ray', label: 'AWS X-Ray', category: 'Developer Tools', tier: 'reserve', file: 'Arch_Developer-Tools/16/Arch_AWS-X-Ray_16.svg' }, + { name: 'aws-cloudfront', label: 'Amazon CloudFront', category: 'Networking & Content Delivery', tier: 'reserve', file: 'Arch_Networking-Content-Delivery/16/Arch_Amazon-CloudFront_16.svg' }, + { name: 'aws-route-53', label: 'Amazon Route 53', category: 'Networking & Content Delivery', tier: 'reserve', file: 'Arch_Networking-Content-Delivery/16/Arch_Amazon-Route-53_16.svg' }, + { name: 'aws-vpc', label: 'Amazon Virtual Private Cloud', category: 'Networking & Content Delivery', tier: 'reserve', file: 'Arch_Networking-Content-Delivery/16/Arch_Amazon-Virtual-Private-Cloud_16.svg' }, + // `aws-elb` (Elastic Load Balancing) and `aws-ebs` (Elastic Block Store) are + // deliberately near-identical keys: both acronyms are the spoken name. A + // future ALB/NLB icon extends as `aws-alb`/`aws-nlb` — do not rename these. + { name: 'aws-elb', label: 'Elastic Load Balancing', category: 'Networking & Content Delivery', tier: 'reserve', file: 'Arch_Networking-Content-Delivery/16/Arch_Elastic-Load-Balancing_16.svg' }, + { name: 'aws-ecs', label: 'Amazon ECS', category: 'Containers', tier: 'reserve', file: 'Arch_Containers/16/Arch_Amazon-Elastic-Container-Service_16.svg' }, + { name: 'aws-ecr', label: 'Amazon ECR', category: 'Containers', tier: 'reserve', file: 'Arch_Containers/16/Arch_Amazon-Elastic-Container-Registry_16.svg' }, + { name: 'aws-eks', label: 'Amazon EKS', category: 'Containers', tier: 'reserve', file: 'Arch_Containers/16/Arch_Amazon-Elastic-Kubernetes-Service_16.svg' }, + { name: 'aws-fargate', label: 'AWS Fargate', category: 'Containers', tier: 'reserve', file: 'Arch_Containers/16/Arch_AWS-Fargate_16.svg' }, + { name: 'aws-ec2', label: 'Amazon EC2', category: 'Compute', tier: 'reserve', file: 'Arch_Compute/16/Arch_Amazon-EC2_16.svg' }, + { name: 'aws-batch', label: 'AWS Batch', category: 'Compute', tier: 'reserve', file: 'Arch_Compute/16/Arch_AWS-Batch_16.svg' }, + { name: 'aws-elastic-beanstalk', label: 'AWS Elastic Beanstalk', category: 'Compute', tier: 'reserve', file: 'Arch_Compute/16/Arch_AWS-Elastic-Beanstalk_16.svg' }, + { name: 'aws-app-runner', label: 'AWS App Runner', category: 'Compute', tier: 'reserve', file: 'Arch_Compute/16/Arch_AWS-App-Runner_16.svg' }, + { name: 'aws-rds', label: 'Amazon RDS', category: 'Database', tier: 'reserve', file: 'Arch_Database/16/Arch_Amazon-RDS_16.svg' }, + { name: 'aws-aurora', label: 'Amazon Aurora', category: 'Database', tier: 'reserve', file: 'Arch_Database/16/Arch_Amazon-Aurora_16.svg' }, + { name: 'aws-elasticache', label: 'Amazon ElastiCache', category: 'Database', tier: 'reserve', file: 'Arch_Database/16/Arch_Amazon-ElastiCache_16.svg' }, + { name: 'aws-neptune', label: 'Amazon Neptune', category: 'Database', tier: 'reserve', file: 'Arch_Database/16/Arch_Amazon-Neptune_16.svg' }, + { name: 'aws-documentdb', label: 'Amazon DocumentDB', category: 'Database', tier: 'reserve', file: 'Arch_Database/16/Arch_Amazon-DocumentDB_16.svg' }, + { name: 'aws-timestream', label: 'Amazon Timestream', category: 'Database', tier: 'reserve', file: 'Arch_Database/16/Arch_Amazon-Timestream_16.svg' }, + { name: 'aws-memorydb', label: 'Amazon MemoryDB', category: 'Database', tier: 'reserve', file: 'Arch_Database/16/Arch_Amazon-MemoryDB_16.svg' }, + { name: 'aws-efs', label: 'Amazon EFS', category: 'Storage', tier: 'reserve', file: 'Arch_Storage/16/Arch_Amazon-EFS_16.svg' }, + { name: 'aws-ebs', label: 'Amazon Elastic Block Store', category: 'Storage', tier: 'reserve', file: 'Arch_Storage/16/Arch_Amazon-Elastic-Block-Store_16.svg' }, + { name: 'aws-backup', label: 'AWS Backup', category: 'Storage', tier: 'reserve', file: 'Arch_Storage/16/Arch_AWS-Backup_16.svg' }, + { name: 'aws-ses', label: 'Amazon Simple Email Service', category: 'Business Applications', tier: 'reserve', file: 'Arch_Business-Applications/16/Arch_Amazon-Simple-Email-Service_16.svg' }, + { name: 'aws-amplify', label: 'AWS Amplify', category: 'Front-End Web & Mobile', tier: 'reserve', file: 'Arch_Front-End-Web-Mobile/16/Arch_AWS-Amplify_16.svg' }, + { name: 'aws-codebuild', label: 'AWS CodeBuild', category: 'Developer Tools', tier: 'reserve', file: 'Arch_Developer-Tools/16/Arch_AWS-CodeBuild_16.svg' }, + { name: 'aws-codepipeline', label: 'AWS CodePipeline', category: 'Developer Tools', tier: 'reserve', file: 'Arch_Developer-Tools/16/Arch_AWS-CodePipeline_16.svg' }, + { name: 'aws-cdk', label: 'AWS Cloud Development Kit', category: 'Developer Tools', tier: 'reserve', file: 'Arch_Developer-Tools/16/Arch_AWS-Cloud-Development-Kit_16.svg' }, + { name: 'aws-cli', label: 'AWS Command Line Interface', category: 'Developer Tools', tier: 'reserve', file: 'Arch_Developer-Tools/16/Arch_AWS-Command-Line-Interface_16.svg' }, + { name: 'aws-bedrock', label: 'Amazon Bedrock', category: 'Artificial Intelligence', tier: 'reserve', file: 'Arch_Artificial-Intelligence/16/Arch_Amazon-Bedrock_16.svg' }, + // The current brand. The legacy Analytics `Arch_Amazon-SageMaker_16.svg` is + // deliberately NOT vendored — it would be a near-duplicate key. + { name: 'aws-sagemaker-ai', label: 'Amazon SageMaker AI', category: 'Artificial Intelligence', tier: 'reserve', file: 'Arch_Artificial-Intelligence/16/Arch_Amazon-SageMaker-AI_16.svg' }, +]; + +// --------------------------------------------------------------------------- +// SVG parsing +// +// A 40-line parser instead of a dependency: the pack is a closed, uniform set +// of files (no entities, no CDATA, no namespaced elements) and this repo does +// not add dependencies for build-time chores. Anything the parser does not +// recognise makes it throw — see the ALLOWED/FORBIDDEN sets below. +// --------------------------------------------------------------------------- + +/** Shapes and containers the artwork is allowed to use. */ +const ALLOWED_TAGS = new Set(['svg', 'g', 'title', 'path', 'rect', 'circle', 'ellipse', 'line', 'polygon', 'polyline']); + +/** + * Tags that make an icon impossible to vendor as a plain node tree: they need + * a document-scoped id space (``/``/``/gradients), pull + * in external bytes (``, ``), or leak global styles (`