diff --git a/.env.example b/.env.example index 037f2c5..fc3abaa 100644 --- a/.env.example +++ b/.env.example @@ -3,3 +3,6 @@ DATABASE_URL="YOUR_NOT_SO_SECRET_DATABASE_URL_GOES_HERE" LEMON_SQUEEZY_API_KEY="" # Just get it from somewhere LEMON_SQUEEZY_STORE_ID="" # Just get it from somewhere LEMON_SQUEEZY_VARIANT_ID="" # Just get it from somewhere +LEMON_SQUEEZY_WEBHOOK_SECRET= +TEST_API_KEY= +REDIS_URL= diff --git a/AGENTS.md b/AGENTS.md index 010b1b2..9c74025 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,10 +2,7 @@ ## Commands -- **Test all**: `bun test` -- **Test single file**: `vitest src/__tests__/unit/path/to/test.test.ts` -- **Test with UI**: `bun run test:ui` -- **Dev server**: `bun run dev:backend` (auto-reload on port 8069) +- **Dev server**: `bun run dev:backend` (gRPC - 8069, HTTP - 8070) - **Generate protobuf**: `bun run gen` (from proto/ directory) - **DB migrations**: `bunx drizzle-kit push` @@ -20,3 +17,4 @@ - **Testing**: Use Vitest with mocks via `vi.fn()`; mock database transactions in beforeEach; test success, validation errors, and database errors - **Naming**: camelCase for variables/functions, PascalCase for classes/types/enums, SCREAMING_SNAKE_CASE for constants - **Database**: Use Drizzle ORM with transactions; validate all inputs before DB operations; handle unique constraint violations explicitly +- **Dates**: Only use the DateTime module, never bother using the built in default date object. Also ALWAYS use utc(), do not try to do any local time fuckery diff --git a/README.md b/README.md index a29f640..2797c68 100644 --- a/README.md +++ b/README.md @@ -74,12 +74,12 @@ bun run dev:backend bun start ``` -The server will start on `http://localhost:8069` +The server will start on `http://localhost:8070` ## Endpoints -- **Connect / gRPC-Web / gRPC (h2c / HTTP/2 cleartext)**: `http://localhost:8069` -- **Webhook**: `http://localhost:8069/webhooks/lemonsqueezy/createdCheckout` +- **Connect / gRPC-Web / gRPC (h2c / HTTP/2 cleartext)**: `http://localhost:8069` (raw gRPC) +- **Webhook**: `http://localhost:8070/webhooks/lemonsqueezy/createdCheckout` ## Documentation diff --git a/bun.lock b/bun.lock index ef08d9c..6852479 100644 --- a/bun.lock +++ b/bun.lock @@ -1,36 +1,39 @@ { "lockfileVersion": 1, - "configVersion": 0, + "configVersion": 1, "workspaces": { "": { "name": "backend", "dependencies": { - "@bufbuild/protobuf": "^2.9.0", - "@connectrpc/connect": "^2.1.0", - "@connectrpc/connect-node": "^2.1.0", + "@bufbuild/protobuf": "^2.12.0", + "@connectrpc/connect": "^2.1.1", + "@connectrpc/connect-fastify": "^2.1.1", + "@connectrpc/connect-node": "^2.1.1", + "@connectrpc/protoc-gen-connect-es": "^1.7.0", "@connectrpc/validate": "^0.2.0", "@lemonsqueezy/lemonsqueezy.js": "^4.0.0", - "@libsql/client": "^0.15.15", - "@types/expr-eval": "^1.1.2", + "@typescript/native-preview": "^7.0.0-dev.20260502.1", + "bullmq": "^5.75.2", "dotenv": "^17.2.3", "drizzle-orm": "^0.44.7", "expr-eval": "^2.0.2", + "fastify": "^5.8.5", + "fastify-raw-body": "^5.0.0", "luxon": "^3.7.2", - "mysql2": "^3.15.3", "pino": "^10.1.0", "pino-pretty": "^13.1.2", "postgres": "^3.4.7", - "skills": "^1.3.1", "zod": "^4.1.12", }, "devDependencies": { - "@bufbuild/protoc-gen-connect-es": "^0.13.0", - "@bufbuild/protoc-gen-es": "^2.9.0", + "@bufbuild/buf": "^1.66.1", + "@bufbuild/protoc-gen-es": "^2.11.0", "@types/bun": "latest", + "@types/expr-eval": "^1.1.2", "@types/luxon": "^3.7.1", "@vitest/ui": "^4.0.3", - "buf": "bufbuild/buf", "drizzle-kit": "^0.31.6", + "skills": "^1.3.1", "tsx": "^4.20.6", "vitest": "^4.0.3", }, @@ -40,169 +43,183 @@ }, }, "packages": { - "@bufbuild/cel": ["@bufbuild/cel@0.3.0", "", { "dependencies": { "@bufbuild/cel-spec": "0.3.0" }, "peerDependencies": { "@bufbuild/protobuf": "^2.6.2" } }, "sha512-vIdcn0Ot6XDKakcDqEQvvlCtMlYwLlxc++SrVjjCmYIiZRH+tlr1GRYpe5R9kguSiTS3BLh7C+I7ZoektVPICQ=="], + "@bufbuild/buf": ["@bufbuild/buf@1.69.0", "", { "optionalDependencies": { "@bufbuild/buf-darwin-arm64": "1.69.0", "@bufbuild/buf-darwin-x64": "1.69.0", "@bufbuild/buf-linux-aarch64": "1.69.0", "@bufbuild/buf-linux-armv7": "1.69.0", "@bufbuild/buf-linux-x64": "1.69.0", "@bufbuild/buf-win32-arm64": "1.69.0", "@bufbuild/buf-win32-x64": "1.69.0" }, "bin": { "buf": "bin/buf", "protoc-gen-buf-breaking": "bin/protoc-gen-buf-breaking", "protoc-gen-buf-lint": "bin/protoc-gen-buf-lint" } }, "sha512-hWk7cW6Z/7g6jpybePaf15QUUFd2+s4lJCeaAkBeo3tWPGoSgNJaJdMqIUy2y99uYy4yMjq9GYmjc5dSrfIn5A=="], + + "@bufbuild/buf-darwin-arm64": ["@bufbuild/buf-darwin-arm64@1.69.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-q7086l1PRS0fUn/IYef7WUAq5PEPIxCh3AVZZdObdOAA9C77ES7CYBSTWH3oEJHVElv1KPVVqvGmOC+G78HuXg=="], + + "@bufbuild/buf-darwin-x64": ["@bufbuild/buf-darwin-x64@1.69.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-ihM+lr0tahgLVbQvp5jhYS6T1cpydEX3TbJvAfePLJBCTrsXFMwKt1WIDjpSHIPHQABcqL9BuNnbs8r1+7E1MA=="], + + "@bufbuild/buf-linux-aarch64": ["@bufbuild/buf-linux-aarch64@1.69.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-4twJF1ehcPRBvgA2g2yIG/3ViZ3SrElqCqGjXHp+U4RfjHV249j8kzVj08mvI1t0kv8Rbm8JECYqkxcYnKyuRA=="], + + "@bufbuild/buf-linux-armv7": ["@bufbuild/buf-linux-armv7@1.69.0", "", { "os": "linux", "cpu": "arm" }, "sha512-zfbYrfPjOBp1Dxj+9avW05NWzGwLUTInfslhgWVbq61DYLegX6UW12hVk5xS/C5D0IlfIDfJUXEeTsHImigQTQ=="], - "@bufbuild/cel-spec": ["@bufbuild/cel-spec@0.3.0", "", { "peerDependencies": { "@bufbuild/protobuf": "^2.6.2" } }, "sha512-mN669LGlXkYNco6NzSTpFoW52UwGb0h5UJNct43nkOjk9YrgUtzcBn9PfjrwbyAe3OlUtasvXAFf1Tjs3NQLOg=="], + "@bufbuild/buf-linux-x64": ["@bufbuild/buf-linux-x64@1.69.0", "", { "os": "linux", "cpu": "x64" }, "sha512-mt/hJesHK62TlsSJPwBpRIC/OzWTlgaRmyjC8QF+T6+IbFwiwz1E3ZBCfNECEa2HW4ma8HbugpJyCBbUSA+z/Q=="], - "@bufbuild/protobuf": ["@bufbuild/protobuf@2.9.0", "", {}, "sha512-rnJenoStJ8nvmt9Gzye8nkYd6V22xUAnu4086ER7h1zJ508vStko4pMvDeQ446ilDTFpV5wnoc5YS7XvMwwMqA=="], + "@bufbuild/buf-win32-arm64": ["@bufbuild/buf-win32-arm64@1.69.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-IlMSIdCWvllwenbLlrWEH2YHQwCqmONKZYv4MXj56v6TvCWCTbYlaF5ZFP+xFAHToHp1OrFc+rwUqCt7ElBbHg=="], - "@bufbuild/protoc-gen-connect-es": ["@bufbuild/protoc-gen-connect-es@0.13.0", "", { "dependencies": { "@bufbuild/protobuf": "^1.2.1", "@bufbuild/protoplugin": "^1.2.1" }, "peerDependencies": { "@bufbuild/connect": "0.13.0", "@bufbuild/protoc-gen-es": "^1.2.1" }, "optionalPeers": ["@bufbuild/connect", "@bufbuild/protoc-gen-es"], "bin": { "protoc-gen-connect-es": "bin/protoc-gen-connect-es" } }, "sha512-4HbxWQ799ZLszJJIJsuVMFwkBx8DJ4VEhNDNtKpPJFsTdVUOp1LyFGY66Yjfj9vcuOeH44bS0ALE5pRP3rCxXA=="], + "@bufbuild/buf-win32-x64": ["@bufbuild/buf-win32-x64@1.69.0", "", { "os": "win32", "cpu": "x64" }, "sha512-wpKZLXUF/w85g4ZL9XqQqm33cfw2NRjiidSX5EVFMx4rDp7cnAUv3+PTwZvEPriqJEihnOJ5JCozsxjiWqSX7Q=="], - "@bufbuild/protoc-gen-es": ["@bufbuild/protoc-gen-es@2.9.0", "", { "dependencies": { "@bufbuild/protobuf": "2.9.0", "@bufbuild/protoplugin": "2.9.0" }, "bin": { "protoc-gen-es": "bin/protoc-gen-es" } }, "sha512-g54rrHLKc7fnxN25ikynstRxR19M5G5l/hyqut2JoypJ9iU9QgUE63zEm8PNvVfBd4r5PEzWPfbWy5MNOeuMKQ=="], + "@bufbuild/cel": ["@bufbuild/cel@0.4.0", "", { "dependencies": { "@bufbuild/cel-spec": "0.4.0" }, "peerDependencies": { "@bufbuild/protobuf": "^2.6.2" } }, "sha512-CdW/JgiTJCYXqnwuaJRo7NcoYhR37AaF58MMiog0/t8nudn86ZyLXYaA1f2yGhm2U17h8pKGZNksTHVSTcpmAw=="], - "@bufbuild/protoplugin": ["@bufbuild/protoplugin@1.10.1", "", { "dependencies": { "@bufbuild/protobuf": "1.10.1", "@typescript/vfs": "^1.4.0", "typescript": "4.5.2" } }, "sha512-LaSbfwabAFIvbVnbn8jWwElRoffCIxhVraO8arliVwWupWezHLXgqPHEYLXZY/SsAR+/YsFBQJa8tAGtNPJyaQ=="], + "@bufbuild/cel-spec": ["@bufbuild/cel-spec@0.4.0", "", { "peerDependencies": { "@bufbuild/protobuf": "^2.6.2" } }, "sha512-dUS6f2fNt6KEumsYGE7YFxERZE5ZuyME1hQmGjtO8tkZhR6ow6/ne3v4Gik9cfdb9lSLK3AJ+vDxCdGWmDbWvA=="], - "@bufbuild/protovalidate": ["@bufbuild/protovalidate@1.0.0", "", { "dependencies": { "@bufbuild/cel": "0.3.0" }, "peerDependencies": { "@bufbuild/protobuf": "^2.8.0" } }, "sha512-ICGANMQXaPKdR5BJ+6/L3nySHOZQQEZQvvivSZCFb799138obPLjNk32rSIKOMrA/YHc4Y2W738e+SL3CbZXSg=="], + "@bufbuild/protobuf": ["@bufbuild/protobuf@2.12.0", "", {}, "sha512-B/XlCaFIP8LOwzo+bz5uFzATYokcwCKQcghqnlfwSmM5eX/qTkvDBnDPs+gXtX/RyjxJ4DRikECcPJbyALA8FA=="], - "@connectrpc/connect": ["@connectrpc/connect@2.1.0", "", { "peerDependencies": { "@bufbuild/protobuf": "^2.7.0" } }, "sha512-xhiwnYlJNHzmFsRw+iSPIwXR/xweTvTw8x5HiwWp10sbVtd4OpOXbRgE7V58xs1EC17fzusF1f5uOAy24OkBuA=="], + "@bufbuild/protoc-gen-es": ["@bufbuild/protoc-gen-es@2.12.0", "", { "dependencies": { "@bufbuild/protobuf": "2.12.0", "@bufbuild/protoplugin": "2.12.0" }, "bin": { "protoc-gen-es": "bin/protoc-gen-es" } }, "sha512-d9htF6jEkSwPbp9d/vSmZOBF7eeG18AvTMKmVg4I23afnrQOxL2w3WOXa9TaufMCyu24QakEUb4vux8apI5e7A=="], - "@connectrpc/connect-node": ["@connectrpc/connect-node@2.1.0", "", { "peerDependencies": { "@bufbuild/protobuf": "^2.7.0", "@connectrpc/connect": "2.1.0" } }, "sha512-6akCXZSX5uWHLR654ne9Tnq7AnPUkLS65NvgsI5885xBkcuVy2APBd8sA4sLqaplUt84cVEr6LhjEFNx6W1KtQ=="], + "@bufbuild/protoplugin": ["@bufbuild/protoplugin@2.12.0", "", { "dependencies": { "@bufbuild/protobuf": "2.12.0", "@typescript/vfs": "^1.6.2", "typescript": "5.4.5" } }, "sha512-ORlDITp8AFUXzIhLRoMCG+ud+D3MPKWb5HQXBoskMMnjeyEjE1H1qLonVNPyOr8lkx3xSfYUo8a0dvOZJVAzow=="], + + "@bufbuild/protovalidate": ["@bufbuild/protovalidate@1.2.0", "", { "dependencies": { "@bufbuild/cel": "0.4.0" }, "peerDependencies": { "@bufbuild/protobuf": "^2.8.0" } }, "sha512-tD08DwGrHIV88khLz1Kdz9DYUwEo1TsoepaIg7/B/zd//AymaTx67kvCS1jlkcG/+vgQaSOl6f0HCE3sL8vI7w=="], + + "@connectrpc/connect": ["@connectrpc/connect@2.1.1", "", { "peerDependencies": { "@bufbuild/protobuf": "^2.7.0" } }, "sha512-JzhkaTvM73m2K1URT6tv53k2RwngSmCXLZJgK580qNQOXRzZRR/BCMfZw3h+90JpnG6XksP5bYT+cz0rpUzUWQ=="], + + "@connectrpc/connect-fastify": ["@connectrpc/connect-fastify@2.1.1", "", { "peerDependencies": { "@bufbuild/protobuf": "^2.7.0", "@connectrpc/connect": "2.1.1", "@connectrpc/connect-node": "2.1.1", "fastify": "^4.22.1 || ^5.1.0" } }, "sha512-UMkdus491H+iUTQE/wnZjaiX6oQ3+GH7gfE5kq2AtXZEZ4IV02bOmTYZS+jfu63+MMeyAkacgfruCYfvwqYzxA=="], + + "@connectrpc/connect-node": ["@connectrpc/connect-node@2.1.1", "", { "peerDependencies": { "@bufbuild/protobuf": "^2.7.0", "@connectrpc/connect": "2.1.1" } }, "sha512-s3TfsI1XF+n+1z6MBS9rTnFsxxR4Rw5wmdEnkQINli81ESGxcsfaEet8duzq8LVuuCupmhUsgpRo0Nv9pZkufg=="], + + "@connectrpc/protoc-gen-connect-es": ["@connectrpc/protoc-gen-connect-es@1.7.0", "", { "dependencies": { "@bufbuild/protobuf": "^1.10.0", "@bufbuild/protoplugin": "^1.10.0" }, "peerDependencies": { "@bufbuild/protoc-gen-es": "^1.10.0", "@connectrpc/connect": "1.7.0" }, "optionalPeers": ["@bufbuild/protoc-gen-es", "@connectrpc/connect"], "bin": { "protoc-gen-connect-es": "bin/protoc-gen-connect-es" } }, "sha512-g2rE799dxGgXtwSTBOJoSlzCy3HN0IX/Es8uKsCgXRmco8o277/bb5nz1X8TmvBooCBGNdtEdUDG50olcvS9jQ=="], "@connectrpc/validate": ["@connectrpc/validate@0.2.0", "", { "peerDependencies": { "@bufbuild/protobuf": "^2.9.0", "@bufbuild/protovalidate": "^1.0.0", "@connectrpc/connect": "^2.0.3" } }, "sha512-u1hdyt1WaFkKpuT/3J2wYlCjYLkYHMZamoatgxTIsV5Q8H9fO2px3zecmb0Q47YDjkZqnX6z0PAEstK+dNYiEQ=="], "@drizzle-team/brocli": ["@drizzle-team/brocli@0.10.2", "", {}, "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w=="], + "@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="], + + "@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="], + + "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="], + "@esbuild-kit/core-utils": ["@esbuild-kit/core-utils@3.3.2", "", { "dependencies": { "esbuild": "~0.18.20", "source-map-support": "^0.5.21" } }, "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ=="], "@esbuild-kit/esm-loader": ["@esbuild-kit/esm-loader@2.6.5", "", { "dependencies": { "@esbuild-kit/core-utils": "^3.3.2", "get-tsconfig": "^4.7.0" } }, "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA=="], - "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.11", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg=="], + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], - "@esbuild/android-arm": ["@esbuild/android-arm@0.25.11", "", { "os": "android", "cpu": "arm" }, "sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg=="], + "@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], - "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.11", "", { "os": "android", "cpu": "arm64" }, "sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ=="], + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], - "@esbuild/android-x64": ["@esbuild/android-x64@0.25.11", "", { "os": "android", "cpu": "x64" }, "sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g=="], + "@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], - "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.11", "", { "os": "darwin", "cpu": "arm64" }, "sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w=="], + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], - "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.11", "", { "os": "darwin", "cpu": "x64" }, "sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ=="], + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], - "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.11", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA=="], + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], - "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.11", "", { "os": "freebsd", "cpu": "x64" }, "sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw=="], + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], - "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.11", "", { "os": "linux", "cpu": "arm" }, "sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw=="], + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], - "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA=="], + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], - "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.11", "", { "os": "linux", "cpu": "ia32" }, "sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw=="], + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], - "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.11", "", { "os": "linux", "cpu": "none" }, "sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw=="], + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], - "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.11", "", { "os": "linux", "cpu": "none" }, "sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ=="], + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], - "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.11", "", { "os": "linux", "cpu": "ppc64" }, "sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw=="], + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], - "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.11", "", { "os": "linux", "cpu": "none" }, "sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww=="], + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], - "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.11", "", { "os": "linux", "cpu": "s390x" }, "sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw=="], + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], - "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.11", "", { "os": "linux", "cpu": "x64" }, "sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ=="], + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], - "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.11", "", { "os": "none", "cpu": "arm64" }, "sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg=="], + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="], - "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.11", "", { "os": "none", "cpu": "x64" }, "sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A=="], + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], - "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.11", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg=="], + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="], - "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.11", "", { "os": "openbsd", "cpu": "x64" }, "sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw=="], + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], - "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.11", "", { "os": "none", "cpu": "arm64" }, "sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ=="], + "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="], - "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.11", "", { "os": "sunos", "cpu": "x64" }, "sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA=="], + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], - "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.11", "", { "os": "win32", "cpu": "arm64" }, "sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q=="], + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], - "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.11", "", { "os": "win32", "cpu": "ia32" }, "sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA=="], + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], - "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.11", "", { "os": "win32", "cpu": "x64" }, "sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA=="], + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], - "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], + "@fastify/ajv-compiler": ["@fastify/ajv-compiler@4.0.5", "", { "dependencies": { "ajv": "^8.12.0", "ajv-formats": "^3.0.1", "fast-uri": "^3.0.0" } }, "sha512-KoWKW+MhvfTRWL4qrhUwAAZoaChluo0m0vbiJlGMt2GXvL4LVPQEjt8kSpHI3IBq5Rez8fg+XeH3cneztq+C7A=="], - "@lemonsqueezy/lemonsqueezy.js": ["@lemonsqueezy/lemonsqueezy.js@4.0.0", "", {}, "sha512-xcY1/lDrY7CpIF98WKiL1ElsfoVhddP7FT0fw7ssOzrFqQsr44HgolKrQZxd9SywsCPn12OTOUieqDIokI3mFg=="], + "@fastify/error": ["@fastify/error@4.2.0", "", {}, "sha512-RSo3sVDXfHskiBZKBPRgnQTtIqpi/7zhJOEmAxCiBcM7d0uwdGdxLlsCaLzGs8v8NnxIRlfG0N51p5yFaOentQ=="], - "@libsql/client": ["@libsql/client@0.15.15", "", { "dependencies": { "@libsql/core": "^0.15.14", "@libsql/hrana-client": "^0.7.0", "js-base64": "^3.7.5", "libsql": "^0.5.22", "promise-limit": "^2.7.0" } }, "sha512-twC0hQxPNHPKfeOv3sNT6u2pturQjLcI+CnpTM0SjRpocEGgfiZ7DWKXLNnsothjyJmDqEsBQJ5ztq9Wlu470w=="], + "@fastify/fast-json-stringify-compiler": ["@fastify/fast-json-stringify-compiler@5.0.3", "", { "dependencies": { "fast-json-stringify": "^6.0.0" } }, "sha512-uik7yYHkLr6fxd8hJSZ8c+xF4WafPK+XzneQDPU+D10r5X19GW8lJcom2YijX2+qtFF1ENJlHXKFM9ouXNJYgQ=="], - "@libsql/core": ["@libsql/core@0.15.15", "", { "dependencies": { "js-base64": "^3.7.5" } }, "sha512-C88Z6UKl+OyuKKPwz224riz02ih/zHYI3Ho/LAcVOgjsunIRZoBw7fjRfaH9oPMmSNeQfhGklSG2il1URoOIsA=="], + "@fastify/forwarded": ["@fastify/forwarded@3.0.1", "", {}, "sha512-JqDochHFqXs3C3Ml3gOY58zM7OqO9ENqPo0UqAjAjH8L01fRZqwX9iLeX34//kiJubF7r2ZQHtBRU36vONbLlw=="], - "@libsql/darwin-arm64": ["@libsql/darwin-arm64@0.5.22", "", { "os": "darwin", "cpu": "arm64" }, "sha512-4B8ZlX3nIDPndfct7GNe0nI3Yw6ibocEicWdC4fvQbSs/jdq/RC2oCsoJxJ4NzXkvktX70C1J4FcmmoBy069UA=="], + "@fastify/merge-json-schemas": ["@fastify/merge-json-schemas@0.2.1", "", { "dependencies": { "dequal": "^2.0.3" } }, "sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A=="], - "@libsql/darwin-x64": ["@libsql/darwin-x64@0.5.22", "", { "os": "darwin", "cpu": "x64" }, "sha512-ny2HYWt6lFSIdNFzUFIJ04uiW6finXfMNJ7wypkAD8Pqdm6nAByO+Fdqu8t7sD0sqJGeUCiOg480icjyQ2/8VA=="], + "@fastify/proxy-addr": ["@fastify/proxy-addr@5.1.0", "", { "dependencies": { "@fastify/forwarded": "^3.0.0", "ipaddr.js": "^2.1.0" } }, "sha512-INS+6gh91cLUjB+PVHfu1UqcB76Sqtpyp7bnL+FYojhjygvOPA9ctiD/JDKsyD9Xgu4hUhCSJBPig/w7duNajw=="], - "@libsql/hrana-client": ["@libsql/hrana-client@0.7.0", "", { "dependencies": { "@libsql/isomorphic-fetch": "^0.3.1", "@libsql/isomorphic-ws": "^0.1.5", "js-base64": "^3.7.5", "node-fetch": "^3.3.2" } }, "sha512-OF8fFQSkbL7vJY9rfuegK1R7sPgQ6kFMkDamiEccNUvieQ+3urzfDFI616oPl8V7T9zRmnTkSjMOImYCAVRVuw=="], + "@ioredis/commands": ["@ioredis/commands@1.5.1", "", {}, "sha512-JH8ZL/ywcJyR9MmJ5BNqZllXNZQqQbnVZOqpPQqE1vHiFgAw4NHbvE0FOduNU8IX9babitBT46571OnPTT0Zcw=="], - "@libsql/isomorphic-fetch": ["@libsql/isomorphic-fetch@0.3.1", "", {}, "sha512-6kK3SUK5Uu56zPq/Las620n5aS9xJq+jMBcNSOmjhNf/MUvdyji4vrMTqD7ptY7/4/CAVEAYDeotUz60LNQHtw=="], + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], - "@libsql/isomorphic-ws": ["@libsql/isomorphic-ws@0.1.5", "", { "dependencies": { "@types/ws": "^8.5.4", "ws": "^8.13.0" } }, "sha512-DtLWIH29onUYR00i0GlQ3UdcTRC6EP4u9w/h9LxpUZJWRMARk6dQwZ6Jkd+QdwVpuAOrdxt18v0K2uIYR3fwFg=="], + "@lemonsqueezy/lemonsqueezy.js": ["@lemonsqueezy/lemonsqueezy.js@4.0.0", "", {}, "sha512-xcY1/lDrY7CpIF98WKiL1ElsfoVhddP7FT0fw7ssOzrFqQsr44HgolKrQZxd9SywsCPn12OTOUieqDIokI3mFg=="], - "@libsql/linux-arm-gnueabihf": ["@libsql/linux-arm-gnueabihf@0.5.22", "", { "os": "linux", "cpu": "arm" }, "sha512-3Uo3SoDPJe/zBnyZKosziRGtszXaEtv57raWrZIahtQDsjxBVjuzYQinCm9LRCJCUT5t2r5Z5nLDPJi2CwZVoA=="], + "@msgpackr-extract/msgpackr-extract-darwin-arm64": ["@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw=="], - "@libsql/linux-arm-musleabihf": ["@libsql/linux-arm-musleabihf@0.5.22", "", { "os": "linux", "cpu": "arm" }, "sha512-LCsXh07jvSojTNJptT9CowOzwITznD+YFGGW+1XxUr7fS+7/ydUrpDfsMX7UqTqjm7xG17eq86VkWJgHJfvpNg=="], + "@msgpackr-extract/msgpackr-extract-darwin-x64": ["@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw=="], - "@libsql/linux-arm64-gnu": ["@libsql/linux-arm64-gnu@0.5.22", "", { "os": "linux", "cpu": "arm64" }, "sha512-KSdnOMy88c9mpOFKUEzPskSaF3VLflfSUCBwas/pn1/sV3pEhtMF6H8VUCd2rsedwoukeeCSEONqX7LLnQwRMA=="], + "@msgpackr-extract/msgpackr-extract-linux-arm": ["@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3", "", { "os": "linux", "cpu": "arm" }, "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw=="], - "@libsql/linux-arm64-musl": ["@libsql/linux-arm64-musl@0.5.22", "", { "os": "linux", "cpu": "arm64" }, "sha512-mCHSMAsDTLK5YH//lcV3eFEgiR23Ym0U9oEvgZA0667gqRZg/2px+7LshDvErEKv2XZ8ixzw3p1IrBzLQHGSsw=="], + "@msgpackr-extract/msgpackr-extract-linux-arm64": ["@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg=="], - "@libsql/linux-x64-gnu": ["@libsql/linux-x64-gnu@0.5.22", "", { "os": "linux", "cpu": "x64" }, "sha512-kNBHaIkSg78Y4BqAdgjcR2mBilZXs4HYkAmi58J+4GRwDQZh5fIUWbnQvB9f95DkWUIGVeenqLRFY2pcTmlsew=="], + "@msgpackr-extract/msgpackr-extract-linux-x64": ["@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3", "", { "os": "linux", "cpu": "x64" }, "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg=="], - "@libsql/linux-x64-musl": ["@libsql/linux-x64-musl@0.5.22", "", { "os": "linux", "cpu": "x64" }, "sha512-UZ4Xdxm4pu3pQXjvfJiyCzZop/9j/eA2JjmhMaAhe3EVLH2g11Fy4fwyUp9sT1QJYR1kpc2JLuybPM0kuXv/Tg=="], + "@msgpackr-extract/msgpackr-extract-win32-x64": ["@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3", "", { "os": "win32", "cpu": "x64" }, "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ=="], - "@libsql/win32-x64-msvc": ["@libsql/win32-x64-msvc@0.5.22", "", { "os": "win32", "cpu": "x64" }, "sha512-Fj0j8RnBpo43tVZUVoNK6BV/9AtDUM5S7DF3LB4qTYg1LMSZqi3yeCneUTLJD6XomQJlZzbI4mst89yspVSAnA=="], + "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.4", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow=="], - "@neon-rs/load": ["@neon-rs/load@0.0.4", "", {}, "sha512-kTPhdZyTQxB+2wpiRcFWrDcejc4JI6tkPuS7UZCG4l6Zvc5kU/gGQ/ozvHTh1XR5tS+UlfAfGuPajjzQjCiHCw=="], + "@oxc-project/types": ["@oxc-project/types@0.127.0", "", {}, "sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ=="], "@pinojs/redact": ["@pinojs/redact@0.4.0", "", {}, "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg=="], "@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="], - "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.52.5", "", { "os": "android", "cpu": "arm" }, "sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ=="], - - "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.52.5", "", { "os": "android", "cpu": "arm64" }, "sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA=="], - - "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.52.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA=="], + "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-rc.17", "", { "os": "android", "cpu": "arm64" }, "sha512-s70pVGhw4zqGeFnXWvAzJDlvxhlRollagdCCKRgOsgUOH3N1l0LIxf83AtGzmb5SiVM4Hjl5HyarMRfdfj3DaQ=="], - "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.52.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA=="], + "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-rc.17", "", { "os": "darwin", "cpu": "arm64" }, "sha512-4ksWc9n0mhlZpZ9PMZgTGjeOPRu8MB1Z3Tz0Mo02eWfWCHMW1zN82Qz/pL/rC+yQa+8ZnutMF0JjJe7PjwasYw=="], - "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.52.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA=="], + "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-rc.17", "", { "os": "darwin", "cpu": "x64" }, "sha512-SUSDOI6WwUVNcWxd02QEBjLdY1VPHvlEkw6T/8nYG322iYWCTxRb1vzk4E+mWWYehTp7ERibq54LSJGjmouOsw=="], - "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.52.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ=="], + "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-rc.17", "", { "os": "freebsd", "cpu": "x64" }, "sha512-hwnz3nw9dbJ05EDO/PvcjaaewqqDy7Y1rn1UO81l8iIK1GjenME75dl16ajbvSSMfv66WXSRCYKIqfgq2KCfxw=="], - "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.52.5", "", { "os": "linux", "cpu": "arm" }, "sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ=="], + "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.17", "", { "os": "linux", "cpu": "arm" }, "sha512-IS+W7epTcwANmFSQFrS1SivEXHtl1JtuQA9wlxrZTcNi6mx+FDOYrakGevvvTwgj2JvWiK8B29/qD9BELZPyXQ=="], - "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.52.5", "", { "os": "linux", "cpu": "arm" }, "sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ=="], + "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-rc.17", "", { "os": "linux", "cpu": "arm64" }, "sha512-e6usGaHKW5BMNZOymS1UcEYGowQMWcgZ71Z17Sl/h2+ZziNJ1a9n3Zvcz6LdRyIW5572wBCTH/Z+bKuZouGk9Q=="], - "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.52.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg=="], + "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-rc.17", "", { "os": "linux", "cpu": "arm64" }, "sha512-b/CgbwAJpmrRLp02RPfhbudf5tZnN9nsPWK82znefso832etkem8H7FSZwxrOI9djcdTP7U6YfNhbRnh7djErg=="], - "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.52.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q=="], + "@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.17", "", { "os": "linux", "cpu": "ppc64" }, "sha512-4EII1iNGRUN5WwGbF/kOh/EIkoDN9HsupgLQoXfY+D1oyJm7/F4t5PYU5n8SWZgG0FEwakyM8pGgwcBYruGTlA=="], - "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA=="], + "@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.0-rc.17", "", { "os": "linux", "cpu": "s390x" }, "sha512-AH8oq3XqQo4IibpVXvPeLDI5pzkpYn0WiZAfT05kFzoJ6tQNzwRdDYQ45M8I/gslbodRZwW8uxLhbSBbkv96rA=="], - "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.52.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw=="], + "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-rc.17", "", { "os": "linux", "cpu": "x64" }, "sha512-cLnjV3xfo7KslbU41Z7z8BH/E1y5mzUYzAqih1d1MDaIGZRCMqTijqLv76/P7fyHuvUcfGsIpqCdddbxLLK9rA=="], - "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw=="], + "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-rc.17", "", { "os": "linux", "cpu": "x64" }, "sha512-0phclDw1spsL7dUB37sIARuis2tAgomCJXAHZlpt8PXZ4Ba0dRP1e+66lsRqrfhISeN9bEGNjQs+T/Fbd7oYGw=="], - "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg=="], + "@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-rc.17", "", { "os": "none", "cpu": "arm64" }, "sha512-0ag/hEgXOwgw4t8QyQvUCxvEg+V0KBcA6YuOx9g0r02MprutRF5dyljgm3EmR02O292UX7UeS6HzWHAl6KgyhA=="], - "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.52.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ=="], + "@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-rc.17", "", { "dependencies": { "@emnapi/core": "1.10.0", "@emnapi/runtime": "1.10.0", "@napi-rs/wasm-runtime": "^1.1.4" }, "cpu": "none" }, "sha512-LEXei6vo0E5wTGwpkJ4KoT3OZJRnglwldt5ziLzOlc6qqb55z4tWNq2A+PFqCJuvWWdP53CVhG1Z9NtToDPJrA=="], - "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.52.5", "", { "os": "linux", "cpu": "x64" }, "sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q=="], + "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-rc.17", "", { "os": "win32", "cpu": "arm64" }, "sha512-gUmyzBl3SPMa6hrqFUth9sVfcLBlYsbMzBx5PlexMroZStgzGqlZ26pYG89rBb45Mnia+oil6YAIFeEWGWhoZA=="], - "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.52.5", "", { "os": "linux", "cpu": "x64" }, "sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg=="], + "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-rc.17", "", { "os": "win32", "cpu": "x64" }, "sha512-3hkiolcUAvPB9FLb3UZdfjVVNWherN1f/skkGWJP/fgSQhYUZpSIRr0/I8ZK9TkF3F7kxvJAk0+IcKvPHk9qQg=="], - "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.52.5", "", { "os": "none", "cpu": "arm64" }, "sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw=="], + "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.17", "", {}, "sha512-n8iosDOt6Ig1UhJ2AYqoIhHWh/isz0xpicHTzpKBeotdVsTEcxsSA/i3EVM7gQAj0rU27OLAxCjzlj15IWY7bg=="], - "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.52.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w=="], + "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], - "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.52.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg=="], + "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], - "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.52.5", "", { "os": "win32", "cpu": "x64" }, "sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ=="], - - "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.52.5", "", { "os": "win32", "cpu": "x64" }, "sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg=="], - - "@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="], - - "@types/bun": ["@types/bun@1.3.0", "", { "dependencies": { "bun-types": "1.3.0" } }, "sha512-+lAGCYjXjip2qY375xX/scJeVRmZ5cY0wyHYyCYxNcdEXrQ4AOe3gACgd4iQ8ksOslJtW4VNxBJ8llUwc3a6AA=="], + "@types/bun": ["@types/bun@1.3.13", "", { "dependencies": { "bun-types": "1.3.13" } }, "sha512-9fqXWk5YIHGGnUau9TEi+qdlTYDAnOj+xLCmSTwXfAIqXr2x4tytJb43E9uCvt09zJURKXwAtkoH4nLQfzeTXw=="], "@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="], @@ -214,49 +231,73 @@ "@types/luxon": ["@types/luxon@3.7.1", "", {}, "sha512-H3iskjFIAn5SlJU7OuxUmTEpebK6TKB8rxZShDslBMZJ5u9S//KM1sbdAisiSrqwLQncVjnpi2OK2J51h+4lsg=="], - "@types/node": ["@types/node@24.7.2", "", { "dependencies": { "undici-types": "~7.14.0" } }, "sha512-/NbVmcGTP+lj5oa4yiYxxeBjRivKQ5Ns1eSZeB99ExsEQ6rX5XYU1Zy/gGxY/ilqtD4Etx9mKyrPxZRetiahhA=="], + "@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], + + "@typescript/native-preview": ["@typescript/native-preview@7.0.0-dev.20260502.1", "", { "optionalDependencies": { "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20260502.1", "@typescript/native-preview-darwin-x64": "7.0.0-dev.20260502.1", "@typescript/native-preview-linux-arm": "7.0.0-dev.20260502.1", "@typescript/native-preview-linux-arm64": "7.0.0-dev.20260502.1", "@typescript/native-preview-linux-x64": "7.0.0-dev.20260502.1", "@typescript/native-preview-win32-arm64": "7.0.0-dev.20260502.1", "@typescript/native-preview-win32-x64": "7.0.0-dev.20260502.1" }, "bin": { "tsgo": "bin/tsgo.js" } }, "sha512-7G2S9N2HFA1L0Nug8shs3yHAq9yRrlJkc5wSeaCq5rPDdGbRU0hpb02Gti87Ulb3noqcJAkiStXm/H804dIu8Q=="], + + "@typescript/native-preview-darwin-arm64": ["@typescript/native-preview-darwin-arm64@7.0.0-dev.20260502.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-+usfUIAClShkS8U9YGeX4v3xq7082+Nm7V38llOHYM0YMoUgMvif8u3K44mMUund5LswKjMsFLp8m96mALf7cg=="], + + "@typescript/native-preview-darwin-x64": ["@typescript/native-preview-darwin-x64@7.0.0-dev.20260502.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-OqBaydzqoRYJRyQjf7mgT/txw4lDuft1ZCODg/BYMVan0npVvaYFCL4Bc6q34Gpl+jpXjanjKawZIZ34mT15UA=="], + + "@typescript/native-preview-linux-arm": ["@typescript/native-preview-linux-arm@7.0.0-dev.20260502.1", "", { "os": "linux", "cpu": "arm" }, "sha512-YJ/a1Iro3wq6DRRF9zkEAwFCZON2HMeNOlG51gAEX7BBSi0NuCeQrhF1u6YGeY8b846802u6LmV91pQenI3Jmw=="], - "@types/react": ["@types/react@19.2.2", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA=="], + "@typescript/native-preview-linux-arm64": ["@typescript/native-preview-linux-arm64@7.0.0-dev.20260502.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-RTmsZnsfACiJL/wDEaFkuYtFAlAH6i8sP/nK7OJMCoiXWD3KfGnvGkTKOIL8QiJ8MqyPP9bx2qxSUUdkXtp+Bw=="], - "@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="], + "@typescript/native-preview-linux-x64": ["@typescript/native-preview-linux-x64@7.0.0-dev.20260502.1", "", { "os": "linux", "cpu": "x64" }, "sha512-h+8GWkKtprzYm+W3J9ZGNHNmtFuxVu5sG0+d5mbfWacjOJl6z3DCb2U9/mAbx28fqbvIO/CwSYPoKkP5D03Ppg=="], - "@typescript/vfs": ["@typescript/vfs@1.6.1", "", { "dependencies": { "debug": "^4.1.1" }, "peerDependencies": { "typescript": "*" } }, "sha512-JwoxboBh7Oz1v38tPbkrZ62ZXNHAk9bJ7c9x0eI5zBfBnBYGhURdbnh7Z4smN/MV48Y5OCcZb58n972UtbazsA=="], + "@typescript/native-preview-win32-arm64": ["@typescript/native-preview-win32-arm64@7.0.0-dev.20260502.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-3FU/YiNyILvs7chIUUDYTT3i3jxL1gegSPB+pKEhpgw+rxa6B9ZSobbYZN4tetBrzgFpfeCRe0ZgGVdPzxVq2A=="], - "@vitest/expect": ["@vitest/expect@4.0.3", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.0.3", "@vitest/utils": "4.0.3", "chai": "^6.0.1", "tinyrainbow": "^3.0.3" } }, "sha512-v3eSDx/bF25pzar6aEJrrdTXJduEBU3uSGXHslIdGIpJVP8tQQHV6x1ZfzbFQ/bLIomLSbR/2ZCfnaEGkWkiVQ=="], + "@typescript/native-preview-win32-x64": ["@typescript/native-preview-win32-x64@7.0.0-dev.20260502.1", "", { "os": "win32", "cpu": "x64" }, "sha512-7+0ii6rRk1Tr/r6a3TPdo5xLfPDwyGTqGBlOGbIwVI8cJ32FFcBNXtNVy14EU0zoS/EyQybGLe09U53G2hMFsw=="], - "@vitest/mocker": ["@vitest/mocker@4.0.3", "", { "dependencies": { "@vitest/spy": "4.0.3", "estree-walker": "^3.0.3", "magic-string": "^0.30.19" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0-0" }, "optionalPeers": ["msw", "vite"] }, "sha512-evZcRspIPbbiJEe748zI2BRu94ThCBE+RkjCpVF8yoVYuTV7hMe+4wLF/7K86r8GwJHSmAPnPbZhpXWWrg1qbA=="], + "@typescript/vfs": ["@typescript/vfs@1.6.4", "", { "dependencies": { "debug": "^4.4.3" }, "peerDependencies": { "typescript": "*" } }, "sha512-PJFXFS4ZJKiJ9Qiuix6Dz/OwEIqHD7Dme1UwZhTK11vR+5dqW2ACbdndWQexBzCx+CPuMe5WBYQWCsFyGlQLlQ=="], - "@vitest/pretty-format": ["@vitest/pretty-format@4.0.3", "", { "dependencies": { "tinyrainbow": "^3.0.3" } }, "sha512-N7gly/DRXzxa9w9sbDXwD9QNFYP2hw90LLLGDobPNwiWgyW95GMxsCt29/COIKKh3P7XJICR38PSDePenMBtsw=="], + "@vitest/expect": ["@vitest/expect@4.1.5", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.1.5", "@vitest/utils": "4.1.5", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" } }, "sha512-PWBaRY5JoKuRnHlUHfpV/KohFylaDZTupcXN1H9vYryNLOnitSw60Mw9IAE2r67NbwwzBw/Cc/8q9BK3kIX8Kw=="], - "@vitest/runner": ["@vitest/runner@4.0.3", "", { "dependencies": { "@vitest/utils": "4.0.3", "pathe": "^2.0.3" } }, "sha512-1/aK6fPM0lYXWyGKwop2Gbvz1plyTps/HDbIIJXYtJtspHjpXIeB3If07eWpVH4HW7Rmd3Rl+IS/+zEAXrRtXA=="], + "@vitest/mocker": ["@vitest/mocker@4.1.5", "", { "dependencies": { "@vitest/spy": "4.1.5", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-/x2EmFC4mT4NNzqvC3fmesuV97w5FC903KPmey4gsnJiMQ3Be1IlDKVaDaG8iqaLFHqJ2FVEkxZk5VmeLjIItw=="], - "@vitest/snapshot": ["@vitest/snapshot@4.0.3", "", { "dependencies": { "@vitest/pretty-format": "4.0.3", "magic-string": "^0.30.19", "pathe": "^2.0.3" } }, "sha512-amnYmvZ5MTjNCP1HZmdeczAPLRD6iOm9+2nMRUGxbe/6sQ0Ymur0NnR9LIrWS8JA3wKE71X25D6ya/3LN9YytA=="], + "@vitest/pretty-format": ["@vitest/pretty-format@4.1.5", "", { "dependencies": { "tinyrainbow": "^3.1.0" } }, "sha512-7I3q6l5qr03dVfMX2wCo9FxwSJbPdwKjy2uu/YPpU3wfHvIL4QHwVRp57OfGrDFeUJ8/8QdfBKIV12FTtLn00g=="], - "@vitest/spy": ["@vitest/spy@4.0.3", "", {}, "sha512-82vVL8Cqz7rbXaNUl35V2G7xeNMAjBdNOVaHbrzznT9BmiCiPOzhf0FhU3eP41nP1bLDm/5wWKZqkG4nyU95DQ=="], + "@vitest/runner": ["@vitest/runner@4.1.5", "", { "dependencies": { "@vitest/utils": "4.1.5", "pathe": "^2.0.3" } }, "sha512-2D+o7Pr82IEO46YPpoA/YU0neeyr6FTerQb5Ro7BUnBuv6NQtT/kmVnczngiMEBhzgqz2UZYl5gArejsyERDSQ=="], - "@vitest/ui": ["@vitest/ui@4.0.7", "", { "dependencies": { "@vitest/utils": "4.0.7", "fflate": "^0.8.2", "flatted": "^3.3.3", "pathe": "^2.0.3", "sirv": "^3.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.0.3" }, "peerDependencies": { "vitest": "4.0.7" } }, "sha512-aIFPci9xoTmVkxpqsSKcRG/Hn0lTy421jsCehHydYeIMd+getn0Pue0JqY5cW8yZglZjMeX0YfIy5wDtQDHEcA=="], + "@vitest/snapshot": ["@vitest/snapshot@4.1.5", "", { "dependencies": { "@vitest/pretty-format": "4.1.5", "@vitest/utils": "4.1.5", "magic-string": "^0.30.21", "pathe": "^2.0.3" } }, "sha512-zypXEt4KH/XgKGPUz4eC2AvErYx0My5hfL8oDb1HzGFpEk1P62bxSohdyOmvz+d9UJwanI68MKwr2EquOaOgMQ=="], - "@vitest/utils": ["@vitest/utils@4.0.7", "", { "dependencies": { "@vitest/pretty-format": "4.0.7", "tinyrainbow": "^3.0.3" } }, "sha512-HNrg9CM/Z4ZWB6RuExhuC6FPmLipiShKVMnT9JlQvfhwR47JatWLChA6mtZqVHqypE6p/z6ofcjbyWpM7YLxPQ=="], + "@vitest/spy": ["@vitest/spy@4.1.5", "", {}, "sha512-2lNOsh6+R2Idnf1TCZqSwYlKN2E/iDlD8sgU59kYVl+OMDmvldO1VDk39smRfpUNwYpNRVn3w4YfuC7KfbBnkQ=="], + + "@vitest/ui": ["@vitest/ui@4.1.5", "", { "dependencies": { "@vitest/utils": "4.1.5", "fflate": "^0.8.2", "flatted": "^3.4.2", "pathe": "^2.0.3", "sirv": "^3.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.1.0" }, "peerDependencies": { "vitest": "4.1.5" } }, "sha512-3Z9HNFiV0IF1fk0JPiK+7kE1GcaIPefQQIBYur6PM5yFIq6agys3uqP/0t966e1wXfmjbRCHDe7qW236Xjwnag=="], + + "@vitest/utils": ["@vitest/utils@4.1.5", "", { "dependencies": { "@vitest/pretty-format": "4.1.5", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" } }, "sha512-76wdkrmfXfqGjueGgnb45ITPyUi1ycZ4IHgC2bhPDUfWHklY/q3MdLOAB+TF1e6xfl8NxNY0ZYaPCFNWSsw3Ug=="], + + "abstract-logging": ["abstract-logging@2.0.1", "", {}, "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA=="], + + "ajv": ["ajv@8.20.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA=="], + + "ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="], "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], "atomic-sleep": ["atomic-sleep@1.0.0", "", {}, "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ=="], - "aws-ssl-profiles": ["aws-ssl-profiles@1.1.2", "", {}, "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g=="], - - "buf": ["buf@github:bufbuild/buf#2e53c7d", {}, "bufbuild-buf-2e53c7d"], + "avvio": ["avvio@9.2.0", "", { "dependencies": { "@fastify/error": "^4.0.0", "fastq": "^1.17.1" } }, "sha512-2t/sy01ArdHHE0vRH5Hsay+RtCZt3dLPji7W7/MMOCEgze5b7SNDC4j5H6FnVgPkI1MTNFGzHdHrVXDDl7QSSQ=="], "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], - "bun-types": ["bun-types@1.3.0", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-u8X0thhx+yJ0KmkxuEo9HAtdfgCBaM/aI9K90VQcQioAmkVp3SG3FkwWGibUFz3WdXAdcsqOcbU40lK7tbHdkQ=="], + "bullmq": ["bullmq@5.76.4", "", { "dependencies": { "cron-parser": "4.9.0", "ioredis": "5.10.1", "msgpackr": "1.11.5", "node-abort-controller": "3.1.1", "semver": "7.7.4", "tslib": "2.8.1" } }, "sha512-hVAplia7zfN3BxSCgAoRInJnbemfLwJdQLqJy/txEX8UMSTAeg0saPFNGWIlzES/Ct5xQ20TUaik/XwS99DOMA=="], + + "bun-types": ["bun-types@1.3.13", "", { "dependencies": { "@types/node": "*" } }, "sha512-QXKeHLlOLqQX9LgYaHJfzdBaV21T63HhFJnvuRCcjZiaUDpbs5ED1MgxbMra71CsryN/1dAoXuJJJwIv/2drVA=="], + + "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], - "chai": ["chai@6.2.0", "", {}, "sha512-aUTnJc/JipRzJrNADXVvpVqi6CO0dn3nx4EVPxijri+fj3LUUDyZQOgVeW54Ob3Y1Xh9Iz8f+CgaCl8v0mn9bA=="], + "chai": ["chai@6.2.2", "", {}, "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg=="], + + "cluster-key-slot": ["cluster-key-slot@1.1.2", "", {}, "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA=="], "colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="], - "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], + "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], + + "cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="], - "data-uri-to-buffer": ["data-uri-to-buffer@4.0.1", "", {}, "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="], + "cron-parser": ["cron-parser@4.9.0", "", { "dependencies": { "luxon": "^3.2.1" } }, "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q=="], "dateformat": ["dateformat@4.6.3", "", {}, "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA=="], @@ -264,65 +305,111 @@ "denque": ["denque@2.1.0", "", {}, "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw=="], - "detect-libc": ["detect-libc@2.0.2", "", {}, "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw=="], + "depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="], + + "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="], + + "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], - "dotenv": ["dotenv@17.2.3", "", {}, "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w=="], + "dotenv": ["dotenv@17.4.2", "", {}, "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw=="], - "drizzle-kit": ["drizzle-kit@0.31.6", "", { "dependencies": { "@drizzle-team/brocli": "^0.10.2", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.25.4", "esbuild-register": "^3.5.0" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-/B4e/4pwnx25QwD5xXgdpo1S+077a2VZdosXbItE/oNmUgQwZydGDz9qJYmnQl/b+5IX0rLfwRhrPnroGtrg8Q=="], + "drizzle-kit": ["drizzle-kit@0.31.10", "", { "dependencies": { "@drizzle-team/brocli": "^0.10.2", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.25.4", "tsx": "^4.21.0" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-7OZcmQUrdGI+DUNNsKBn1aW8qSoKuTH7d0mYgSP8bAzdFzKoovxEFnoGQp2dVs82EOJeYycqRtciopszwUf8bw=="], "drizzle-orm": ["drizzle-orm@0.44.7", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-quIpnYznjU9lHshEOAYLoZ9s3jweleHlZIAWR/jX9gAWNg/JhQ1wj0KGRf7/Zm+obRrYd9GjPVJg790QY9N5AQ=="], "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="], - "es-module-lexer": ["es-module-lexer@1.7.0", "", {}, "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="], + "es-module-lexer": ["es-module-lexer@2.1.0", "", {}, "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ=="], - "esbuild": ["esbuild@0.25.11", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.11", "@esbuild/android-arm": "0.25.11", "@esbuild/android-arm64": "0.25.11", "@esbuild/android-x64": "0.25.11", "@esbuild/darwin-arm64": "0.25.11", "@esbuild/darwin-x64": "0.25.11", "@esbuild/freebsd-arm64": "0.25.11", "@esbuild/freebsd-x64": "0.25.11", "@esbuild/linux-arm": "0.25.11", "@esbuild/linux-arm64": "0.25.11", "@esbuild/linux-ia32": "0.25.11", "@esbuild/linux-loong64": "0.25.11", "@esbuild/linux-mips64el": "0.25.11", "@esbuild/linux-ppc64": "0.25.11", "@esbuild/linux-riscv64": "0.25.11", "@esbuild/linux-s390x": "0.25.11", "@esbuild/linux-x64": "0.25.11", "@esbuild/netbsd-arm64": "0.25.11", "@esbuild/netbsd-x64": "0.25.11", "@esbuild/openbsd-arm64": "0.25.11", "@esbuild/openbsd-x64": "0.25.11", "@esbuild/openharmony-arm64": "0.25.11", "@esbuild/sunos-x64": "0.25.11", "@esbuild/win32-arm64": "0.25.11", "@esbuild/win32-ia32": "0.25.11", "@esbuild/win32-x64": "0.25.11" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q=="], - - "esbuild-register": ["esbuild-register@3.6.0", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "esbuild": ">=0.12 <1" } }, "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg=="], + "esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], "estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], - "expect-type": ["expect-type@1.2.2", "", {}, "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA=="], + "expect-type": ["expect-type@1.3.0", "", {}, "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA=="], "expr-eval": ["expr-eval@2.0.2", "", {}, "sha512-4EMSHGOPSwAfBiibw3ndnP0AvjDWLsMvGOvWEZ2F96IGk0bIVdjQisOHxReSkE13mHcfbuCiXw+G4y0zv6N8Eg=="], - "fast-copy": ["fast-copy@3.0.2", "", {}, "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ=="], + "fast-copy": ["fast-copy@4.0.3", "", {}, "sha512-58apWr0GUiDFM8+3afrO6eYwJBn9ZAhDOzG3L+/9llab/haCARS2UIfffmOurYLwbgDRs8n0rfr6qAAPEAuAQw=="], + + "fast-decode-uri-component": ["fast-decode-uri-component@1.0.1", "", {}, "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg=="], + + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + + "fast-json-stringify": ["fast-json-stringify@6.3.0", "", { "dependencies": { "@fastify/merge-json-schemas": "^0.2.0", "ajv": "^8.12.0", "ajv-formats": "^3.0.1", "fast-uri": "^3.0.0", "json-schema-ref-resolver": "^3.0.0", "rfdc": "^1.2.0" } }, "sha512-oRCntNDY/329HJPlmdNLIdogNtt6Vyjb1WuT01Soss3slIdyUp8kAcDU3saQTOquEK8KFVfwIIF7FebxUAu+yA=="], + + "fast-querystring": ["fast-querystring@1.1.2", "", { "dependencies": { "fast-decode-uri-component": "^1.0.1" } }, "sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg=="], "fast-safe-stringify": ["fast-safe-stringify@2.1.1", "", {}, "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA=="], - "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], + "fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="], + + "fastify": ["fastify@5.8.5", "", { "dependencies": { "@fastify/ajv-compiler": "^4.0.5", "@fastify/error": "^4.0.0", "@fastify/fast-json-stringify-compiler": "^5.0.0", "@fastify/proxy-addr": "^5.0.0", "abstract-logging": "^2.0.1", "avvio": "^9.0.0", "fast-json-stringify": "^6.0.0", "find-my-way": "^9.0.0", "light-my-request": "^6.0.0", "pino": "^9.14.0 || ^10.1.0", "process-warning": "^5.0.0", "rfdc": "^1.3.1", "secure-json-parse": "^4.0.0", "semver": "^7.6.0", "toad-cache": "^3.7.0" } }, "sha512-Yqptv59pQzPgQUSIm87hMqHJmdkb1+GPxdE6vW6FRyVE9G86mt7rOghitiU4JHRaTyDUk9pfeKmDeu70lAwM4Q=="], + + "fastify-plugin": ["fastify-plugin@5.1.0", "", {}, "sha512-FAIDA8eovSt5qcDgcBvDuX/v0Cjz0ohGhENZ/wpc3y+oZCY2afZ9Baqql3g/lC+OHRnciQol4ww7tuthOb9idw=="], + + "fastify-raw-body": ["fastify-raw-body@5.0.0", "", { "dependencies": { "fastify-plugin": "^5.0.0", "raw-body": "^3.0.0", "secure-json-parse": "^2.4.0" } }, "sha512-2qfoaQ3BQDhZ1gtbkKZd6n0kKxJISJGM6u/skD9ljdWItAscjXrtZ1lnjr7PavmXX9j4EyCPmBDiIsLn07d5vA=="], + + "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], - "fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="], + "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], "fflate": ["fflate@0.8.2", "", {}, "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="], - "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="], + "find-my-way": ["find-my-way@9.5.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-querystring": "^1.0.0", "safe-regex2": "^5.0.0" } }, "sha512-VW2RfnmscZO5KgBY5XVyKREMW5nMZcxDy+buTOsL+zIPnBlbKm+00sgzoQzq1EVh4aALZLfKdwv6atBGcjvjrQ=="], - "formdata-polyfill": ["formdata-polyfill@4.0.10", "", { "dependencies": { "fetch-blob": "^3.1.2" } }, "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g=="], + "flatted": ["flatted@3.4.2", "", {}, "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA=="], "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], - "generate-function": ["generate-function@2.3.1", "", { "dependencies": { "is-property": "^1.0.2" } }, "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ=="], - - "get-tsconfig": ["get-tsconfig@4.13.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ=="], + "get-tsconfig": ["get-tsconfig@4.14.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA=="], "help-me": ["help-me@5.0.0", "", {}, "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg=="], - "iconv-lite": ["iconv-lite@0.7.0", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ=="], + "http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="], + + "iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="], + + "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], - "is-property": ["is-property@1.0.2", "", {}, "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g=="], + "ioredis": ["ioredis@5.10.1", "", { "dependencies": { "@ioredis/commands": "1.5.1", "cluster-key-slot": "^1.1.0", "debug": "^4.3.4", "denque": "^2.1.0", "lodash.defaults": "^4.2.0", "lodash.isarguments": "^3.1.0", "redis-errors": "^1.2.0", "redis-parser": "^3.0.0", "standard-as-callback": "^2.1.0" } }, "sha512-HuEDBTI70aYdx1v6U97SbNx9F1+svQKBDo30o0b9fw055LMepzpOOd0Ccg9Q6tbqmBSJaMuY0fB7yw9/vjBYCA=="], + + "ipaddr.js": ["ipaddr.js@2.3.0", "", {}, "sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg=="], "joycon": ["joycon@3.1.1", "", {}, "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw=="], - "js-base64": ["js-base64@3.7.8", "", {}, "sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow=="], + "json-schema-ref-resolver": ["json-schema-ref-resolver@3.0.0", "", { "dependencies": { "dequal": "^2.0.3" } }, "sha512-hOrZIVL5jyYFjzk7+y7n5JDzGlU8rfWDuYyHwGa2WA8/pcmMHezp2xsVwxrebD/Q9t8Nc5DboieySDpCp4WG4A=="], + + "json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], + + "light-my-request": ["light-my-request@6.6.0", "", { "dependencies": { "cookie": "^1.0.1", "process-warning": "^4.0.0", "set-cookie-parser": "^2.6.0" } }, "sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A=="], - "libsql": ["libsql@0.5.22", "", { "dependencies": { "@neon-rs/load": "^0.0.4", "detect-libc": "2.0.2" }, "optionalDependencies": { "@libsql/darwin-arm64": "0.5.22", "@libsql/darwin-x64": "0.5.22", "@libsql/linux-arm-gnueabihf": "0.5.22", "@libsql/linux-arm-musleabihf": "0.5.22", "@libsql/linux-arm64-gnu": "0.5.22", "@libsql/linux-arm64-musl": "0.5.22", "@libsql/linux-x64-gnu": "0.5.22", "@libsql/linux-x64-musl": "0.5.22", "@libsql/win32-x64-msvc": "0.5.22" }, "os": [ "linux", "win32", "darwin", ], "cpu": [ "arm", "x64", "arm64", ] }, "sha512-NscWthMQt7fpU8lqd7LXMvT9pi+KhhmTHAJWUB/Lj6MWa0MKFv0F2V4C6WKKpjCVZl0VwcDz4nOI3CyaT1DDiA=="], + "lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="], - "long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="], + "lightningcss-android-arm64": ["lightningcss-android-arm64@1.32.0", "", { "os": "android", "cpu": "arm64" }, "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg=="], - "lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="], + "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.32.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ=="], - "lru.min": ["lru.min@1.1.2", "", {}, "sha512-Nv9KddBcQSlQopmBHXSsZVY5xsdlZkdH/Iey0BlcBYggMd4two7cZnKOK9vmy3nY0O5RGH99z1PCeTpPqszUYg=="], + "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.32.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w=="], + + "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.32.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig=="], + + "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.32.0", "", { "os": "linux", "cpu": "arm" }, "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw=="], + + "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ=="], + + "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg=="], + + "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA=="], + + "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg=="], + + "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.32.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw=="], + + "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q=="], + + "lodash.defaults": ["lodash.defaults@4.2.0", "", {}, "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="], + + "lodash.isarguments": ["lodash.isarguments@3.1.0", "", {}, "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg=="], "luxon": ["luxon@3.7.2", "", {}, "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew=="], @@ -334,15 +421,17 @@ "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], - "mysql2": ["mysql2@3.15.3", "", { "dependencies": { "aws-ssl-profiles": "^1.1.1", "denque": "^2.1.0", "generate-function": "^2.3.1", "iconv-lite": "^0.7.0", "long": "^5.2.1", "lru.min": "^1.0.0", "named-placeholders": "^1.1.3", "seq-queue": "^0.0.5", "sqlstring": "^2.3.2" } }, "sha512-FBrGau0IXmuqg4haEZRBfHNWB5mUARw6hNwPDXXGg0XzVJ50mr/9hb267lvpVMnhZ1FON3qNd4Xfcez1rbFwSg=="], + "msgpackr": ["msgpackr@1.11.5", "", { "optionalDependencies": { "msgpackr-extract": "^3.0.2" } }, "sha512-UjkUHN0yqp9RWKy0Lplhh+wlpdt9oQBYgULZOiFhV3VclSF1JnSQWZ5r9gORQlNYaUKQoR8itv7g7z1xDDuACA=="], - "named-placeholders": ["named-placeholders@1.1.3", "", { "dependencies": { "lru-cache": "^7.14.1" } }, "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w=="], + "msgpackr-extract": ["msgpackr-extract@3.0.3", "", { "dependencies": { "node-gyp-build-optional-packages": "5.2.2" }, "optionalDependencies": { "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" }, "bin": { "download-msgpackr-prebuilds": "bin/download-prebuilds.js" } }, "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA=="], - "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], + "nanoid": ["nanoid@3.3.12", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ=="], - "node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="], + "node-abort-controller": ["node-abort-controller@3.1.1", "", {}, "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ=="], - "node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], + "node-gyp-build-optional-packages": ["node-gyp-build-optional-packages@5.2.2", "", { "dependencies": { "detect-libc": "^2.0.1" }, "bin": { "node-gyp-build-optional-packages": "bin.js", "node-gyp-build-optional-packages-optional": "optional.js", "node-gyp-build-optional-packages-test": "build-test.js" } }, "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw=="], + + "obug": ["obug@2.1.1", "", {}, "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ=="], "on-exit-leak-free": ["on-exit-leak-free@2.1.2", "", {}, "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA=="], @@ -352,33 +441,47 @@ "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], - "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], + "picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="], - "pino": ["pino@10.1.0", "", { "dependencies": { "@pinojs/redact": "^0.4.0", "atomic-sleep": "^1.0.0", "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^2.0.0", "pino-std-serializers": "^7.0.0", "process-warning": "^5.0.0", "quick-format-unescaped": "^4.0.3", "real-require": "^0.2.0", "safe-stable-stringify": "^2.3.1", "sonic-boom": "^4.0.1", "thread-stream": "^3.0.0" }, "bin": { "pino": "bin.js" } }, "sha512-0zZC2ygfdqvqK8zJIr1e+wT1T/L+LF6qvqvbzEQ6tiMAoTqEVK9a1K3YRu8HEUvGEvNqZyPJTtb2sNIoTkB83w=="], + "pino": ["pino@10.3.1", "", { "dependencies": { "@pinojs/redact": "^0.4.0", "atomic-sleep": "^1.0.0", "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^3.0.0", "pino-std-serializers": "^7.0.0", "process-warning": "^5.0.0", "quick-format-unescaped": "^4.0.3", "real-require": "^0.2.0", "safe-stable-stringify": "^2.3.1", "sonic-boom": "^4.0.1", "thread-stream": "^4.0.0" }, "bin": { "pino": "bin.js" } }, "sha512-r34yH/GlQpKZbU1BvFFqOjhISRo1MNx1tWYsYvmj6KIRHSPMT2+yHOEb1SG6NMvRoHRF0a07kCOox/9yakl1vg=="], - "pino-abstract-transport": ["pino-abstract-transport@2.0.0", "", { "dependencies": { "split2": "^4.0.0" } }, "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw=="], + "pino-abstract-transport": ["pino-abstract-transport@3.0.0", "", { "dependencies": { "split2": "^4.0.0" } }, "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg=="], - "pino-pretty": ["pino-pretty@13.1.2", "", { "dependencies": { "colorette": "^2.0.7", "dateformat": "^4.6.3", "fast-copy": "^3.0.2", "fast-safe-stringify": "^2.1.1", "help-me": "^5.0.0", "joycon": "^3.1.1", "minimist": "^1.2.6", "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^2.0.0", "pump": "^3.0.0", "secure-json-parse": "^4.0.0", "sonic-boom": "^4.0.1", "strip-json-comments": "^5.0.2" }, "bin": { "pino-pretty": "bin.js" } }, "sha512-3cN0tCakkT4f3zo9RXDIhy6GTvtYD6bK4CRBLN9j3E/ePqN1tugAXD5rGVfoChW6s0hiek+eyYlLNqc/BG7vBQ=="], + "pino-pretty": ["pino-pretty@13.1.3", "", { "dependencies": { "colorette": "^2.0.7", "dateformat": "^4.6.3", "fast-copy": "^4.0.0", "fast-safe-stringify": "^2.1.1", "help-me": "^5.0.0", "joycon": "^3.1.1", "minimist": "^1.2.6", "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^3.0.0", "pump": "^3.0.0", "secure-json-parse": "^4.0.0", "sonic-boom": "^4.0.1", "strip-json-comments": "^5.0.2" }, "bin": { "pino-pretty": "bin.js" } }, "sha512-ttXRkkOz6WWC95KeY9+xxWL6AtImwbyMHrL1mSwqwW9u+vLp/WIElvHvCSDg0xO/Dzrggz1zv3rN5ovTRVowKg=="], - "pino-std-serializers": ["pino-std-serializers@7.0.0", "", {}, "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA=="], + "pino-std-serializers": ["pino-std-serializers@7.1.0", "", {}, "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw=="], - "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], + "postcss": ["postcss@8.5.13", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-qif0+jGGZoLWdHey3UFHHWP0H7Gbmsk8T5VEqyYFbWqPr1XqvLGBbk/sl8V5exGmcYJklJOhOQq1pV9IcsiFag=="], - "postgres": ["postgres@3.4.7", "", {}, "sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw=="], + "postgres": ["postgres@3.4.9", "", {}, "sha512-GD3qdB0x1z9xgFI6cdRD6xu2Sp2WCOEoe3mtnyB5Ee0XrrL5Pe+e4CCnJrRMnL1zYtRDZmQQVbvOttLnKDLnaw=="], "process-warning": ["process-warning@5.0.0", "", {}, "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA=="], - "promise-limit": ["promise-limit@2.7.0", "", {}, "sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw=="], - - "pump": ["pump@3.0.3", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA=="], + "pump": ["pump@3.0.4", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA=="], "quick-format-unescaped": ["quick-format-unescaped@4.0.4", "", {}, "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg=="], + "raw-body": ["raw-body@3.0.2", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.7.0", "unpipe": "~1.0.0" } }, "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA=="], + "real-require": ["real-require@0.2.0", "", {}, "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg=="], + "redis-errors": ["redis-errors@1.2.0", "", {}, "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w=="], + + "redis-parser": ["redis-parser@3.0.0", "", { "dependencies": { "redis-errors": "^1.0.0" } }, "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A=="], + + "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], + "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="], - "rollup": ["rollup@4.52.5", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.52.5", "@rollup/rollup-android-arm64": "4.52.5", "@rollup/rollup-darwin-arm64": "4.52.5", "@rollup/rollup-darwin-x64": "4.52.5", "@rollup/rollup-freebsd-arm64": "4.52.5", "@rollup/rollup-freebsd-x64": "4.52.5", "@rollup/rollup-linux-arm-gnueabihf": "4.52.5", "@rollup/rollup-linux-arm-musleabihf": "4.52.5", "@rollup/rollup-linux-arm64-gnu": "4.52.5", "@rollup/rollup-linux-arm64-musl": "4.52.5", "@rollup/rollup-linux-loong64-gnu": "4.52.5", "@rollup/rollup-linux-ppc64-gnu": "4.52.5", "@rollup/rollup-linux-riscv64-gnu": "4.52.5", "@rollup/rollup-linux-riscv64-musl": "4.52.5", "@rollup/rollup-linux-s390x-gnu": "4.52.5", "@rollup/rollup-linux-x64-gnu": "4.52.5", "@rollup/rollup-linux-x64-musl": "4.52.5", "@rollup/rollup-openharmony-arm64": "4.52.5", "@rollup/rollup-win32-arm64-msvc": "4.52.5", "@rollup/rollup-win32-ia32-msvc": "4.52.5", "@rollup/rollup-win32-x64-gnu": "4.52.5", "@rollup/rollup-win32-x64-msvc": "4.52.5", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw=="], + "ret": ["ret@0.5.0", "", {}, "sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw=="], + + "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], + + "rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="], + + "rolldown": ["rolldown@1.0.0-rc.17", "", { "dependencies": { "@oxc-project/types": "=0.127.0", "@rolldown/pluginutils": "1.0.0-rc.17" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.17", "@rolldown/binding-darwin-arm64": "1.0.0-rc.17", "@rolldown/binding-darwin-x64": "1.0.0-rc.17", "@rolldown/binding-freebsd-x64": "1.0.0-rc.17", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.17", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.17", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.17", "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.17", "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.17", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.17", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.17", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.17", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.17", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.17", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.17" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-ZrT53oAKrtA4+YtBWPQbtPOxIbVDbxT0orcYERKd63VJTF13zPcgXTvD4843L8pcsI7M6MErt8QtON6lrB9tyA=="], + + "safe-regex2": ["safe-regex2@5.1.1", "", { "dependencies": { "ret": "~0.5.0" }, "bin": { "safe-regex2": "bin/safe-regex2.js" } }, "sha512-mOSBvHGDZMuIEZMdOz/aCEYDCv0E7nfcNsIhUF+/P+xC7Hyf3FkvymqgPbg9D1EdSGu+uKbJgy09K/RKKc7kJA=="], "safe-stable-stringify": ["safe-stable-stringify@2.5.0", "", {}, "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA=="], @@ -386,15 +489,19 @@ "secure-json-parse": ["secure-json-parse@4.1.0", "", {}, "sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA=="], - "seq-queue": ["seq-queue@0.0.5", "", {}, "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q=="], + "semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], + + "set-cookie-parser": ["set-cookie-parser@2.7.2", "", {}, "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw=="], + + "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="], "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="], "sirv": ["sirv@3.0.2", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g=="], - "skills": ["skills@1.3.1", "", { "bin": { "skills": "bin/cli.mjs", "add-skill": "bin/cli.mjs" } }, "sha512-Bi9R28oOVuUk6dB14QDcQYZjQ9t28fbZoQMIc+8vy+hkYVqBqS2HwVYfUWWMYWt5IhvvLn2QUfXLjK1GTDaaSQ=="], + "skills": ["skills@1.5.3", "", { "dependencies": { "yaml": "^2.8.3" }, "bin": { "skills": "bin/cli.mjs", "add-skill": "bin/cli.mjs" } }, "sha512-lgZa7NvOGJA1WcwyqsOysO3ojMabq4R/NdQGNbry05y5ccDb/8CFed0HoSU9fvKfjuGbXSCVoV++4gcLMKAykQ=="], - "sonic-boom": ["sonic-boom@4.2.0", "", { "dependencies": { "atomic-sleep": "^1.0.0" } }, "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww=="], + "sonic-boom": ["sonic-boom@4.2.1", "", { "dependencies": { "atomic-sleep": "^1.0.0" } }, "sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q=="], "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], @@ -404,65 +511,67 @@ "split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="], - "sqlstring": ["sqlstring@2.3.3", "", {}, "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg=="], - "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="], - "std-env": ["std-env@3.10.0", "", {}, "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg=="], + "standard-as-callback": ["standard-as-callback@2.1.0", "", {}, "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A=="], + + "statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="], + + "std-env": ["std-env@4.1.0", "", {}, "sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ=="], "strip-json-comments": ["strip-json-comments@5.0.3", "", {}, "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw=="], - "thread-stream": ["thread-stream@3.1.0", "", { "dependencies": { "real-require": "^0.2.0" } }, "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A=="], + "thread-stream": ["thread-stream@4.0.0", "", { "dependencies": { "real-require": "^0.2.0" } }, "sha512-4iMVL6HAINXWf1ZKZjIPcz5wYaOdPhtO8ATvZ+Xqp3BTdaqtAwQkNmKORqcIo5YkQqGXq5cwfswDwMqqQNrpJA=="], "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="], - "tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], + "tinyexec": ["tinyexec@1.1.2", "", {}, "sha512-dAqSqE/RabpBKI8+h26GfLq6Vb3JVXs30XYQjdMjaj/c2tS8IYYMbIzP599KtRj7c57/wYApb3QjgRgXmrCukA=="], + + "tinyglobby": ["tinyglobby@0.2.16", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg=="], - "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], + "tinyrainbow": ["tinyrainbow@3.1.0", "", {}, "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw=="], - "tinyrainbow": ["tinyrainbow@3.0.3", "", {}, "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q=="], + "toad-cache": ["toad-cache@3.7.0", "", {}, "sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw=="], + + "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="], "totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="], - "tsx": ["tsx@4.20.6", "", { "dependencies": { "esbuild": "~0.25.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg=="], + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "tsx": ["tsx@4.21.0", "", { "dependencies": { "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw=="], - "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], + "typescript": ["typescript@5.4.5", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ=="], - "undici-types": ["undici-types@7.14.0", "", {}, "sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA=="], + "undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], - "vite": ["vite@7.1.12", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-ZWyE8YXEXqJrrSLvYgrRP7p62OziLW7xI5HYGWFzOvupfAlrLvURSzv/FyGyy0eidogEM3ujU+kUG1zuHgb6Ug=="], + "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="], - "vitest": ["vitest@4.0.3", "", { "dependencies": { "@vitest/expect": "4.0.3", "@vitest/mocker": "4.0.3", "@vitest/pretty-format": "4.0.3", "@vitest/runner": "4.0.3", "@vitest/snapshot": "4.0.3", "@vitest/spy": "4.0.3", "@vitest/utils": "4.0.3", "debug": "^4.4.3", "es-module-lexer": "^1.7.0", "expect-type": "^1.2.2", "magic-string": "^0.30.19", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.0.3", "vite": "^6.0.0 || ^7.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.0.3", "@vitest/browser-preview": "4.0.3", "@vitest/browser-webdriverio": "4.0.3", "@vitest/ui": "4.0.3", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-IUSop8jgaT7w0g1yOM/35qVtKjr/8Va4PrjzH1OUb0YH4c3OXB2lCZDkMAB6glA8T5w8S164oJGsbcmAecr4sA=="], + "vite": ["vite@8.0.10", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.10", "rolldown": "1.0.0-rc.17", "tinyglobby": "^0.2.16" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-rZuUu9j6J5uotLDs+cAA4O5H4K1SfPliUlQwqa6YEwSrWDZzP4rhm00oJR5snMewjxF5V/K3D4kctsUTsIU9Mw=="], - "web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="], + "vitest": ["vitest@4.1.5", "", { "dependencies": { "@vitest/expect": "4.1.5", "@vitest/mocker": "4.1.5", "@vitest/pretty-format": "4.1.5", "@vitest/runner": "4.1.5", "@vitest/snapshot": "4.1.5", "@vitest/spy": "4.1.5", "@vitest/utils": "4.1.5", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.1.0", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.1.5", "@vitest/browser-preview": "4.1.5", "@vitest/browser-webdriverio": "4.1.5", "@vitest/coverage-istanbul": "4.1.5", "@vitest/coverage-v8": "4.1.5", "@vitest/ui": "4.1.5", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/coverage-istanbul", "@vitest/coverage-v8", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-9Xx1v3/ih3m9hN+SbfkUyy0JAs72ap3r7joc87XL6jwF0jGg6mFBvQ1SrwaX+h8BlkX6Hz9shdd1uo6AF+ZGpg=="], "why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="], "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], - "ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="], - - "zod": ["zod@4.1.12", "", {}, "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ=="], + "yaml": ["yaml@2.8.4", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-ml/JPOj9fOQK8RNnWojA67GbZ0ApXAUlN2UQclwv2eVgTgn7O9gg9o7paZWKMp4g0H3nTLtS9LVzhkpOFIKzog=="], - "@bufbuild/protoc-gen-connect-es/@bufbuild/protobuf": ["@bufbuild/protobuf@1.10.1", "", {}, "sha512-wJ8ReQbHxsAfXhrf9ixl0aYbZorRuOWpBNzm8pL8ftmSxQx/wnJD5Eg861NwJU/czy2VXFIebCeZnZrI9rktIQ=="], + "zod": ["zod@4.4.2", "", {}, "sha512-IynmDyxsEsb9RKzO3J9+4SxXnl2FTFSzNBaKKaMV6tsSk0rw9gYw9gs+JFCq/qk2LCZ78KDwyj+Z289TijSkUw=="], - "@bufbuild/protoc-gen-es/@bufbuild/protoplugin": ["@bufbuild/protoplugin@2.9.0", "", { "dependencies": { "@bufbuild/protobuf": "2.9.0", "@typescript/vfs": "^1.5.2", "typescript": "5.4.5" } }, "sha512-uoiwNVYoTq+AyqaV1L6pBazGx5fXOO89L0NSR9/7hEfo0Y8n9T1jsKGu4mkitLmP3z+8gJREaule1mMuKBPyYw=="], + "@connectrpc/protoc-gen-connect-es/@bufbuild/protobuf": ["@bufbuild/protobuf@1.10.1", "", {}, "sha512-wJ8ReQbHxsAfXhrf9ixl0aYbZorRuOWpBNzm8pL8ftmSxQx/wnJD5Eg861NwJU/czy2VXFIebCeZnZrI9rktIQ=="], - "@bufbuild/protoplugin/@bufbuild/protobuf": ["@bufbuild/protobuf@1.10.1", "", {}, "sha512-wJ8ReQbHxsAfXhrf9ixl0aYbZorRuOWpBNzm8pL8ftmSxQx/wnJD5Eg861NwJU/czy2VXFIebCeZnZrI9rktIQ=="], - - "@bufbuild/protoplugin/typescript": ["typescript@4.5.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw=="], + "@connectrpc/protoc-gen-connect-es/@bufbuild/protoplugin": ["@bufbuild/protoplugin@1.10.1", "", { "dependencies": { "@bufbuild/protobuf": "1.10.1", "@typescript/vfs": "^1.4.0", "typescript": "4.5.2" } }, "sha512-LaSbfwabAFIvbVnbn8jWwElRoffCIxhVraO8arliVwWupWezHLXgqPHEYLXZY/SsAR+/YsFBQJa8tAGtNPJyaQ=="], "@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="], - "@vitest/expect/@vitest/utils": ["@vitest/utils@4.0.3", "", { "dependencies": { "@vitest/pretty-format": "4.0.3", "tinyrainbow": "^3.0.3" } }, "sha512-qV6KJkq8W3piW6MDIbGOmn1xhvcW4DuA07alqaQ+vdx7YA49J85pnwnxigZVQFQw3tWnQNRKWwhz5wbP6iv/GQ=="], - - "@vitest/runner/@vitest/utils": ["@vitest/utils@4.0.3", "", { "dependencies": { "@vitest/pretty-format": "4.0.3", "tinyrainbow": "^3.0.3" } }, "sha512-qV6KJkq8W3piW6MDIbGOmn1xhvcW4DuA07alqaQ+vdx7YA49J85pnwnxigZVQFQw3tWnQNRKWwhz5wbP6iv/GQ=="], + "fastify-raw-body/secure-json-parse": ["secure-json-parse@2.7.0", "", {}, "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw=="], - "@vitest/utils/@vitest/pretty-format": ["@vitest/pretty-format@4.0.7", "", { "dependencies": { "tinyrainbow": "^3.0.3" } }, "sha512-YY//yxqTmk29+/pK+Wi1UB4DUH3lSVgIm+M10rAJ74pOSMgT7rydMSc+vFuq9LjZLhFvVEXir8EcqMke3SVM6Q=="], + "light-my-request/process-warning": ["process-warning@4.0.1", "", {}, "sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q=="], - "vitest/@vitest/utils": ["@vitest/utils@4.0.3", "", { "dependencies": { "@vitest/pretty-format": "4.0.3", "tinyrainbow": "^3.0.3" } }, "sha512-qV6KJkq8W3piW6MDIbGOmn1xhvcW4DuA07alqaQ+vdx7YA49J85pnwnxigZVQFQw3tWnQNRKWwhz5wbP6iv/GQ=="], + "tsx/esbuild": ["esbuild@0.27.7", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.7", "@esbuild/android-arm": "0.27.7", "@esbuild/android-arm64": "0.27.7", "@esbuild/android-x64": "0.27.7", "@esbuild/darwin-arm64": "0.27.7", "@esbuild/darwin-x64": "0.27.7", "@esbuild/freebsd-arm64": "0.27.7", "@esbuild/freebsd-x64": "0.27.7", "@esbuild/linux-arm": "0.27.7", "@esbuild/linux-arm64": "0.27.7", "@esbuild/linux-ia32": "0.27.7", "@esbuild/linux-loong64": "0.27.7", "@esbuild/linux-mips64el": "0.27.7", "@esbuild/linux-ppc64": "0.27.7", "@esbuild/linux-riscv64": "0.27.7", "@esbuild/linux-s390x": "0.27.7", "@esbuild/linux-x64": "0.27.7", "@esbuild/netbsd-arm64": "0.27.7", "@esbuild/netbsd-x64": "0.27.7", "@esbuild/openbsd-arm64": "0.27.7", "@esbuild/openbsd-x64": "0.27.7", "@esbuild/openharmony-arm64": "0.27.7", "@esbuild/sunos-x64": "0.27.7", "@esbuild/win32-arm64": "0.27.7", "@esbuild/win32-ia32": "0.27.7", "@esbuild/win32-x64": "0.27.7" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w=="], - "@bufbuild/protoc-gen-es/@bufbuild/protoplugin/typescript": ["typescript@5.4.5", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ=="], + "@connectrpc/protoc-gen-connect-es/@bufbuild/protoplugin/typescript": ["typescript@4.5.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw=="], "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="], @@ -507,5 +616,57 @@ "@esbuild-kit/core-utils/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.18.20", "", { "os": "win32", "cpu": "ia32" }, "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g=="], "@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="], + + "tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.7", "", { "os": "aix", "cpu": "ppc64" }, "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg=="], + + "tsx/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.7", "", { "os": "android", "cpu": "arm" }, "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ=="], + + "tsx/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.7", "", { "os": "android", "cpu": "arm64" }, "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ=="], + + "tsx/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.27.7", "", { "os": "android", "cpu": "x64" }, "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg=="], + + "tsx/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw=="], + + "tsx/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ=="], + + "tsx/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.7", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w=="], + + "tsx/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.7", "", { "os": "freebsd", "cpu": "x64" }, "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ=="], + + "tsx/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.7", "", { "os": "linux", "cpu": "arm" }, "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA=="], + + "tsx/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A=="], + + "tsx/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.7", "", { "os": "linux", "cpu": "ia32" }, "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg=="], + + "tsx/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.7", "", { "os": "linux", "cpu": "none" }, "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q=="], + + "tsx/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.7", "", { "os": "linux", "cpu": "none" }, "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw=="], + + "tsx/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.7", "", { "os": "linux", "cpu": "ppc64" }, "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ=="], + + "tsx/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.7", "", { "os": "linux", "cpu": "none" }, "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ=="], + + "tsx/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.7", "", { "os": "linux", "cpu": "s390x" }, "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw=="], + + "tsx/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.7", "", { "os": "linux", "cpu": "x64" }, "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA=="], + + "tsx/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.7", "", { "os": "none", "cpu": "arm64" }, "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w=="], + + "tsx/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.7", "", { "os": "none", "cpu": "x64" }, "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw=="], + + "tsx/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.7", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A=="], + + "tsx/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.7", "", { "os": "openbsd", "cpu": "x64" }, "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg=="], + + "tsx/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.7", "", { "os": "none", "cpu": "arm64" }, "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw=="], + + "tsx/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.7", "", { "os": "sunos", "cpu": "x64" }, "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA=="], + + "tsx/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.7", "", { "os": "win32", "cpu": "arm64" }, "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA=="], + + "tsx/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.7", "", { "os": "win32", "cpu": "ia32" }, "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw=="], + + "tsx/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.7", "", { "os": "win32", "cpu": "x64" }, "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg=="], } } diff --git a/package.json b/package.json index 1e48882..027800b 100644 --- a/package.json +++ b/package.json @@ -15,36 +15,39 @@ "proto:push": "cd proto && git add . && git commit -s -m \"$1\" && git push && cd .." }, "devDependencies": { - "@bufbuild/protoc-gen-connect-es": "^0.13.0", - "@bufbuild/protoc-gen-es": "^2.9.0", + "@bufbuild/protoc-gen-es": "^2.11.0", "@types/bun": "latest", + "@types/expr-eval": "^1.1.2", "@types/luxon": "^3.7.1", "@vitest/ui": "^4.0.3", - "buf": "bufbuild/buf", + "@bufbuild/buf": "^1.66.1", "drizzle-kit": "^0.31.6", "tsx": "^4.20.6", + "skills": "^1.3.1", "vitest": "^4.0.3" }, "peerDependencies": { "typescript": "^5" }, "dependencies": { - "@bufbuild/protobuf": "^2.9.0", - "@connectrpc/connect": "^2.1.0", - "@connectrpc/connect-node": "^2.1.0", + "@bufbuild/protobuf": "^2.12.0", + "@connectrpc/connect": "^2.1.1", + "@connectrpc/connect-fastify": "^2.1.1", + "@connectrpc/connect-node": "^2.1.1", + "@connectrpc/protoc-gen-connect-es": "^1.7.0", "@connectrpc/validate": "^0.2.0", "@lemonsqueezy/lemonsqueezy.js": "^4.0.0", - "@libsql/client": "^0.15.15", - "@types/expr-eval": "^1.1.2", + "@typescript/native-preview": "^7.0.0-dev.20260502.1", + "bullmq": "^5.75.2", "dotenv": "^17.2.3", "drizzle-orm": "^0.44.7", "expr-eval": "^2.0.2", + "fastify": "^5.8.5", + "fastify-raw-body": "^5.0.0", "luxon": "^3.7.2", - "mysql2": "^3.15.3", "pino": "^10.1.0", "pino-pretty": "^13.1.2", "postgres": "^3.4.7", - "skills": "^1.3.1", "zod": "^4.1.12" } } diff --git a/proto b/proto index 83447d5..8818b4b 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 83447d560777e189b47ee6c7736b6a013450664c +Subproject commit 8818b4bb59c05b772fe10b95976ce80e99507105 diff --git a/src/errors/internals.ts b/src/errors/internals.ts new file mode 100644 index 0000000..22037bd --- /dev/null +++ b/src/errors/internals.ts @@ -0,0 +1,73 @@ +import { Code, ConnectError } from "@connectrpc/connect"; + +export enum InternalsErrorType { + INVALID_CRON = "INVALID_CRON", + QUEUE_CREATION_FAILED = "QUEUE_CREATION_FAILED", + VALIDATION_FAILED = "VALIDATION_FAILED", + UNKNOWN = "UNKNOWN", +} + +export interface InternalsErrorContext { + type: InternalsErrorType; + message: string; + originalError?: Error; + code: Code; +} + +export class InternalsError extends ConnectError { + readonly type: InternalsErrorType; + readonly originalError?: Error; + + constructor(context: InternalsErrorContext) { + super(context.message, context.code); + this.name = "InternalsError"; + this.type = context.type; + this.originalError = context.originalError; + + Object.setPrototypeOf(this, InternalsError.prototype); + } + + static invalidCron(details?: string, originalError?: Error): InternalsError { + return new InternalsError({ + type: InternalsErrorType.INVALID_CRON, + message: details + ? `Invalid cron expression: ${details}` + : "Invalid cron expression", + code: Code.InvalidArgument, + originalError, + }); + } + + static queueCreationFailed( + details?: string, + originalError?: Error + ): InternalsError { + return new InternalsError({ + type: InternalsErrorType.QUEUE_CREATION_FAILED, + message: details + ? `Failed to create queue: ${details}` + : "Failed to create queue", + code: Code.Internal, + originalError, + }); + } + + static validationFailed(details: string, originalError?: Error): InternalsError { + return new InternalsError({ + type: InternalsErrorType.VALIDATION_FAILED, + message: `Internals validation failed: ${details}`, + code: Code.InvalidArgument, + originalError, + }); + } + + static unknown(originalError?: Error): InternalsError { + const details = originalError?.message || "No details available"; + return new InternalsError({ + type: InternalsErrorType.UNKNOWN, + message: `Unexpected internals error: ${details}`, + code: Code.Internal, + originalError, + }); + } +} \ No newline at end of file diff --git a/src/events/AIEvents/AITokenUsage.ts b/src/events/AIEvents/AITokenUsage.ts index 14fcea9..5acb864 100644 --- a/src/events/AIEvents/AITokenUsage.ts +++ b/src/events/AIEvents/AITokenUsage.ts @@ -6,14 +6,15 @@ import { DateTime } from "luxon"; import type { UserId } from "../../config/identifiers"; export class AITokenUsage implements AITokenUsageEvent { - public reported_timestamp: DateTime; + public ingested_timestamp: DateTime; public readonly type = "AI_TOKEN_USAGE" as const; constructor( public userId: UserId, + public reportedTimestamp: DateTime, public data: AITokenUsageEventData ) { - this.reported_timestamp = DateTime.utc(); + this.ingested_timestamp = DateTime.utc(); } serialize() { @@ -21,7 +22,7 @@ export class AITokenUsage implements AITokenUsageEvent { SQL: { type: this.type, userId: this.userId, - reported_timestamp: this.reported_timestamp, + reported_timestamp: this.reportedTimestamp, data: this.data, }, }; diff --git a/src/events/RawEvents/AddKey.ts b/src/events/RawEvents/AddKey.ts index d6a01c3..1489aec 100644 --- a/src/events/RawEvents/AddKey.ts +++ b/src/events/RawEvents/AddKey.ts @@ -2,18 +2,18 @@ import type { AddKeyEvent, AddKeyEventData } from "../../interface/event/Event"; import { DateTime } from "luxon"; export class AddKey implements AddKeyEvent { - public reported_timestamp: DateTime; + public ingested_timestamp: DateTime; public readonly type = "ADD_KEY" as const; constructor(public data: AddKeyEventData) { - this.reported_timestamp = DateTime.utc(); + this.ingested_timestamp = DateTime.utc(); } serialize() { return { SQL: { type: this.type, - reported_timestamp: this.reported_timestamp, + reported_timestamp: this.ingested_timestamp, data: this.data, }, }; diff --git a/src/events/RawEvents/Metadata.ts b/src/events/RawEvents/Metadata.ts new file mode 100644 index 0000000..7372fc8 --- /dev/null +++ b/src/events/RawEvents/Metadata.ts @@ -0,0 +1,24 @@ +import type { + MetadataEvent, + MetadataEventData, +} from "../../interface/event/Event"; +import { DateTime } from "luxon"; + +export class Metadata implements MetadataEvent { + public ingested_timestamp: DateTime; + public readonly type = "METADATA" as const; + + constructor(public data: MetadataEventData) { + this.ingested_timestamp = DateTime.utc(); + } + + serialize() { + return { + SQL: { + type: this.type, + reported_timestamp: this.ingested_timestamp, + data: this.data, + }, + }; + } +} diff --git a/src/events/RawEvents/Payment.ts b/src/events/RawEvents/Payment.ts index e8247f7..add3436 100644 --- a/src/events/RawEvents/Payment.ts +++ b/src/events/RawEvents/Payment.ts @@ -6,14 +6,14 @@ import { DateTime } from "luxon"; import type { UserId } from "../../config/identifiers"; export class Payment implements PaymentEvent { - public reported_timestamp: DateTime; + public ingested_timestamp: DateTime; public readonly type = "PAYMENT" as const; constructor( public userId: UserId, public data: PaymentEventData ) { - this.reported_timestamp = DateTime.utc(); + this.ingested_timestamp = DateTime.utc(); } serialize() { @@ -21,7 +21,7 @@ export class Payment implements PaymentEvent { SQL: { type: this.type, userId: this.userId, - reported_timestamp: this.reported_timestamp, + reported_timestamp: this.ingested_timestamp, data: this.data, }, }; diff --git a/src/events/RawEvents/SDKCall.ts b/src/events/RawEvents/SDKCall.ts index 82d3f28..cf83ecb 100644 --- a/src/events/RawEvents/SDKCall.ts +++ b/src/events/RawEvents/SDKCall.ts @@ -6,14 +6,15 @@ import { DateTime } from "luxon"; import type { UserId } from "../../config/identifiers"; export class SDKCall implements SDKCallEvent { - public reported_timestamp: DateTime; + public ingested_timestamp: DateTime; public readonly type = "SDK_CALL" as const; constructor( public userId: UserId, + public reportedTimestamp: DateTime, public data: SDKCallEventData ) { - this.reported_timestamp = DateTime.utc(); + this.ingested_timestamp = DateTime.utc(); } serialize() { @@ -21,7 +22,7 @@ export class SDKCall implements SDKCallEvent { SQL: { type: this.type, userId: this.userId, - reported_timestamp: this.reported_timestamp, + reported_timestamp: this.reportedTimestamp, data: this.data, }, }; diff --git a/src/factory/EventStorageAdapterFactory.ts b/src/factory/EventStorageAdapterFactory.ts index 66471c8..690fdff 100644 --- a/src/factory/EventStorageAdapterFactory.ts +++ b/src/factory/EventStorageAdapterFactory.ts @@ -1,12 +1,6 @@ import type { EventKind } from "../interface/event/Event.ts"; import { PostgresAdapter } from "../storage/adapter/postgres/postgres.ts"; -/** - * StorageAdapterFactory - Facade for the new SQL adapter factory - * - * Maintains backward compatibility while delegating to the new - * dependency-injected SQL adapter factory - */ export class StorageAdapterFactory { /** * Get the appropriate storage adapter for a given event @@ -29,6 +23,9 @@ export class StorageAdapterFactory { case "ADD_KEY": { return new PostgresAdapter(); } + case "METADATA": { + return new PostgresAdapter(); + } default: { throw new Error(`Unknown event type: ${RequestType}`); } diff --git a/src/gen/auth/v1/auth_connect.ts b/src/gen/auth/v1/auth_connect.ts index 10c60b5..798e784 100644 --- a/src/gen/auth/v1/auth_connect.ts +++ b/src/gen/auth/v1/auth_connect.ts @@ -1,4 +1,4 @@ -// @generated by protoc-gen-connect-es v0.13.0 with parameter "target=ts" +// @generated by protoc-gen-connect-es v1.7.0 with parameter "target=ts" // @generated from file auth/v1/auth.proto (package auth.v1, syntax proto3) /* eslint-disable */ // @ts-nocheck @@ -23,5 +23,6 @@ export const AuthService = { O: CreateAPIKeyResponse, kind: MethodKind.Unary, }, - }, + } } as const; + diff --git a/src/gen/auth/v1/auth_pb.ts b/src/gen/auth/v1/auth_pb.ts index 8840a7a..4cff83e 100644 --- a/src/gen/auth/v1/auth_pb.ts +++ b/src/gen/auth/v1/auth_pb.ts @@ -1,27 +1,16 @@ -// @generated by protoc-gen-es v2.9.0 with parameter "target=ts" +// @generated by protoc-gen-es v2.12.0 with parameter "target=ts" // @generated from file auth/v1/auth.proto (package auth.v1, syntax proto3) /* eslint-disable */ -import type { - GenFile, - GenMessage, - GenService, -} from "@bufbuild/protobuf/codegenv2"; -import { - fileDesc, - messageDesc, - serviceDesc, -} from "@bufbuild/protobuf/codegenv2"; +import type { GenFile, GenMessage, GenService } from "@bufbuild/protobuf/codegenv2"; +import { fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv2"; import type { Message } from "@bufbuild/protobuf"; /** * Describes the file auth/v1/auth.proto. */ -export const file_auth_v1_auth: GenFile = - /*@__PURE__*/ - fileDesc( - "ChJhdXRoL3YxL2F1dGgucHJvdG8SB2F1dGgudjEiNgoTQ3JlYXRlQVBJS2V5UmVxdWVzdBIMCgRuYW1lGAEgASgJEhEKCWV4cGlyZXNJbhgCIAEoAyJsChRDcmVhdGVBUElLZXlSZXNwb25zZRIQCghhcGlLZXlJZBgBIAEoCRIOCgZhcGlLZXkYAiABKAkSDAoEbmFtZRgDIAEoCRIRCgljcmVhdGVkQXQYBCABKAkSEQoJZXhwaXJlc0F0GAUgASgJMlwKC0F1dGhTZXJ2aWNlEk0KDENyZWF0ZUFQSUtleRIcLmF1dGgudjEuQ3JlYXRlQVBJS2V5UmVxdWVzdBodLmF1dGgudjEuQ3JlYXRlQVBJS2V5UmVzcG9uc2UiAGIGcHJvdG8z" - ); +export const file_auth_v1_auth: GenFile = /*@__PURE__*/ + fileDesc("ChJhdXRoL3YxL2F1dGgucHJvdG8SB2F1dGgudjEiNgoTQ3JlYXRlQVBJS2V5UmVxdWVzdBIMCgRuYW1lGAEgASgJEhEKCWV4cGlyZXNJbhgCIAEoAyJsChRDcmVhdGVBUElLZXlSZXNwb25zZRIQCghhcGlLZXlJZBgBIAEoCRIOCgZhcGlLZXkYAiABKAkSDAoEbmFtZRgDIAEoCRIRCgljcmVhdGVkQXQYBCABKAkSEQoJZXhwaXJlc0F0GAUgASgJMlwKC0F1dGhTZXJ2aWNlEk0KDENyZWF0ZUFQSUtleRIcLmF1dGgudjEuQ3JlYXRlQVBJS2V5UmVxdWVzdBodLmF1dGgudjEuQ3JlYXRlQVBJS2V5UmVzcG9uc2UiAGIGcHJvdG8z"); /** * @generated from message auth.v1.CreateAPIKeyRequest @@ -44,8 +33,7 @@ export type CreateAPIKeyRequest = Message<"auth.v1.CreateAPIKeyRequest"> & { * Describes the message auth.v1.CreateAPIKeyRequest. * Use `create(CreateAPIKeyRequestSchema)` to create a new message. */ -export const CreateAPIKeyRequestSchema: GenMessage = - /*@__PURE__*/ +export const CreateAPIKeyRequestSchema: GenMessage = /*@__PURE__*/ messageDesc(file_auth_v1_auth, 0); /** @@ -82,8 +70,7 @@ export type CreateAPIKeyResponse = Message<"auth.v1.CreateAPIKeyResponse"> & { * Describes the message auth.v1.CreateAPIKeyResponse. * Use `create(CreateAPIKeyResponseSchema)` to create a new message. */ -export const CreateAPIKeyResponseSchema: GenMessage = - /*@__PURE__*/ +export const CreateAPIKeyResponseSchema: GenMessage = /*@__PURE__*/ messageDesc(file_auth_v1_auth, 1); /** @@ -99,5 +86,7 @@ export const AuthService: GenService<{ methodKind: "unary"; input: typeof CreateAPIKeyRequestSchema; output: typeof CreateAPIKeyResponseSchema; - }; -}> = /*@__PURE__*/ serviceDesc(file_auth_v1_auth, 0); + }, +}> = /*@__PURE__*/ + serviceDesc(file_auth_v1_auth, 0); + diff --git a/src/gen/event/v1/event_connect.ts b/src/gen/event/v1/event_connect.ts index 00fd773..ebb510a 100644 --- a/src/gen/event/v1/event_connect.ts +++ b/src/gen/event/v1/event_connect.ts @@ -1,14 +1,9 @@ -// @generated by protoc-gen-connect-es v0.13.0 with parameter "target=ts" +// @generated by protoc-gen-connect-es v1.7.0 with parameter "target=ts" // @generated from file event/v1/event.proto (package event.v1, syntax proto3) /* eslint-disable */ // @ts-nocheck -import { - RegisterEventRequest, - RegisterEventResponse, - StreamEventRequest, - StreamEventResponse, -} from "./event_pb.js"; +import { RegisterEventRequest, RegisterEventResponse, StreamEventRequest, StreamEventResponse } from "./event_pb.js"; import { MethodKind } from "@bufbuild/protobuf"; /** @@ -39,5 +34,6 @@ export const EventService = { O: StreamEventResponse, kind: MethodKind.ClientStreaming, }, - }, + } } as const; + diff --git a/src/gen/event/v1/event_pb.ts b/src/gen/event/v1/event_pb.ts index 4f15c6d..dbef54c 100644 --- a/src/gen/event/v1/event_pb.ts +++ b/src/gen/event/v1/event_pb.ts @@ -1,29 +1,16 @@ -// @generated by protoc-gen-es v2.9.0 with parameter "target=ts" +// @generated by protoc-gen-es v2.12.0 with parameter "target=ts" // @generated from file event/v1/event.proto (package event.v1, syntax proto3) /* eslint-disable */ -import type { - GenEnum, - GenFile, - GenMessage, - GenService, -} from "@bufbuild/protobuf/codegenv2"; -import { - enumDesc, - fileDesc, - messageDesc, - serviceDesc, -} from "@bufbuild/protobuf/codegenv2"; +import type { GenEnum, GenFile, GenMessage, GenService } from "@bufbuild/protobuf/codegenv2"; +import { enumDesc, fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv2"; import type { Message } from "@bufbuild/protobuf"; /** * Describes the file event/v1/event.proto. */ -export const file_event_v1_event: GenFile = - /*@__PURE__*/ - fileDesc( - "ChRldmVudC92MS9ldmVudC5wcm90bxIIZXZlbnQudjEidwoUUmVnaXN0ZXJFdmVudFJlcXVlc3QSIQoEdHlwZRgBIAEoDjITLmV2ZW50LnYxLkV2ZW50VHlwZRIOCgZ1c2VySWQYAiABKAkSJAoHc2RrQ2FsbBgDIAEoCzIRLmV2ZW50LnYxLlNES0NhbGxIAEIGCgRkYXRhIm8KB1NES0NhbGwSKgoLc2RrQ2FsbFR5cGUYASABKA4yFS5ldmVudC52MS5TREtDYWxsVHlwZRIQCgZhbW91bnQYAiABKAJIABINCgN0YWcYAyABKAlIABIOCgRleHByGAQgASgJSABCBwoFZGViaXQiJwoVUmVnaXN0ZXJFdmVudFJlc3BvbnNlEg4KBnJhbmRvbRgBIAEoCSKlAQoSU3RyZWFtRXZlbnRSZXF1ZXN0EiEKBHR5cGUYASABKA4yEy5ldmVudC52MS5FdmVudFR5cGUSDgoGdXNlcklkGAIgASgJEiQKB3Nka0NhbGwYAyABKAsyES5ldmVudC52MS5TREtDYWxsSAASLgoMYWlUb2tlblVzYWdlGAQgASgLMhYuZXZlbnQudjEuQUlUb2tlblVzYWdlSABCBgoEZGF0YSLoAQoMQUlUb2tlblVzYWdlEg0KBW1vZGVsGAEgASgJEhMKC2lucHV0VG9rZW5zGAIgASgFEhQKDG91dHB1dFRva2VucxgDIAEoBRIVCgtpbnB1dEFtb3VudBgEIAEoAkgAEhIKCGlucHV0VGFnGAUgASgJSAASEwoJaW5wdXRFeHByGAggASgJSAASFgoMb3V0cHV0QW1vdW50GAYgASgCSAESEwoJb3V0cHV0VGFnGAcgASgJSAESFAoKb3V0cHV0RXhwchgJIAEoCUgBQgwKCmlucHV0RGViaXRCDQoLb3V0cHV0RGViaXQiPwoTU3RyZWFtRXZlbnRSZXNwb25zZRIXCg9ldmVudHNQcm9jZXNzZWQYASABKAUSDwoHbWVzc2FnZRgCIAEoCSpJCglFdmVudFR5cGUSGgoWRVZFTlRfVFlQRV9VTlNQRUNJRklFRBAAEgwKCFNES19DQUxMEAESEgoOQUlfVE9LRU5fVVNBR0UQAipICgtTREtDYWxsVHlwZRIbChdTREtDYWxsVHlwZV9VTlNQRUNJRklFRBAAEgcKA1JBVxABEhMKD01JRERMRVdBUkVfQ0FMTBACMrMBCgxFdmVudFNlcnZpY2USUgoNUmVnaXN0ZXJFdmVudBIeLmV2ZW50LnYxLlJlZ2lzdGVyRXZlbnRSZXF1ZXN0Gh8uZXZlbnQudjEuUmVnaXN0ZXJFdmVudFJlc3BvbnNlIgASTwoMU3RyZWFtRXZlbnRzEhwuZXZlbnQudjEuU3RyZWFtRXZlbnRSZXF1ZXN0Gh0uZXZlbnQudjEuU3RyZWFtRXZlbnRSZXNwb25zZSIAKAFiBnByb3RvMw" - ); +export const file_event_v1_event: GenFile = /*@__PURE__*/ + fileDesc("ChRldmVudC92MS9ldmVudC5wcm90bxIIZXZlbnQudjEikgEKFFJlZ2lzdGVyRXZlbnRSZXF1ZXN0EiEKBHR5cGUYASABKA4yEy5ldmVudC52MS5FdmVudFR5cGUSDgoGdXNlcklkGAIgASgJEhkKEXJlcG9ydGVkVGltZXN0YW1wGAMgASgFEiQKB3Nka0NhbGwYBCABKAsyES5ldmVudC52MS5TREtDYWxsSABCBgoEZGF0YSJvCgdTREtDYWxsEioKC3Nka0NhbGxUeXBlGAEgASgOMhUuZXZlbnQudjEuU0RLQ2FsbFR5cGUSEAoGYW1vdW50GAIgASgCSAASDQoDdGFnGAMgASgJSAASDgoEZXhwchgEIAEoCUgAQgcKBWRlYml0IicKFVJlZ2lzdGVyRXZlbnRSZXNwb25zZRIOCgZyYW5kb20YASABKAkiwAEKElN0cmVhbUV2ZW50UmVxdWVzdBIhCgR0eXBlGAEgASgOMhMuZXZlbnQudjEuRXZlbnRUeXBlEg4KBnVzZXJJZBgCIAEoCRIZChFyZXBvcnRlZFRpbWVzdGFtcBgDIAEoBRIkCgdzZGtDYWxsGAQgASgLMhEuZXZlbnQudjEuU0RLQ2FsbEgAEi4KDGFpVG9rZW5Vc2FnZRgFIAEoCzIWLmV2ZW50LnYxLkFJVG9rZW5Vc2FnZUgAQgYKBGRhdGEi6AEKDEFJVG9rZW5Vc2FnZRINCgVtb2RlbBgBIAEoCRITCgtpbnB1dFRva2VucxgCIAEoBRIUCgxvdXRwdXRUb2tlbnMYAyABKAUSFQoLaW5wdXRBbW91bnQYBCABKAJIABISCghpbnB1dFRhZxgFIAEoCUgAEhMKCWlucHV0RXhwchgIIAEoCUgAEhYKDG91dHB1dEFtb3VudBgGIAEoAkgBEhMKCW91dHB1dFRhZxgHIAEoCUgBEhQKCm91dHB1dEV4cHIYCSABKAlIAUIMCgppbnB1dERlYml0Qg0KC291dHB1dERlYml0Ij8KE1N0cmVhbUV2ZW50UmVzcG9uc2USFwoPZXZlbnRzUHJvY2Vzc2VkGAEgASgFEg8KB21lc3NhZ2UYAiABKAkqSQoJRXZlbnRUeXBlEhoKFkVWRU5UX1RZUEVfVU5TUEVDSUZJRUQQABIMCghTREtfQ0FMTBABEhIKDkFJX1RPS0VOX1VTQUdFEAIqSAoLU0RLQ2FsbFR5cGUSGwoXU0RLQ2FsbFR5cGVfVU5TUEVDSUZJRUQQABIHCgNSQVcQARITCg9NSURETEVXQVJFX0NBTEwQAjKzAQoMRXZlbnRTZXJ2aWNlElIKDVJlZ2lzdGVyRXZlbnQSHi5ldmVudC52MS5SZWdpc3RlckV2ZW50UmVxdWVzdBofLmV2ZW50LnYxLlJlZ2lzdGVyRXZlbnRSZXNwb25zZSIAEk8KDFN0cmVhbUV2ZW50cxIcLmV2ZW50LnYxLlN0cmVhbUV2ZW50UmVxdWVzdBodLmV2ZW50LnYxLlN0cmVhbUV2ZW50UmVzcG9uc2UiACgBYgZwcm90bzM"); /** * @generated from message event.v1.RegisterEventRequest @@ -39,26 +26,28 @@ export type RegisterEventRequest = Message<"event.v1.RegisterEventRequest"> & { */ userId: string; + /** + * @generated from field: int32 reportedTimestamp = 3; + */ + reportedTimestamp: number; + /** * @generated from oneof event.v1.RegisterEventRequest.data */ - data: - | { - /** - * @generated from field: event.v1.SDKCall sdkCall = 3; - */ - value: SDKCall; - case: "sdkCall"; - } - | { case: undefined; value?: undefined }; + data: { + /** + * @generated from field: event.v1.SDKCall sdkCall = 4; + */ + value: SDKCall; + case: "sdkCall"; + } | { case: undefined; value?: undefined }; }; /** * Describes the message event.v1.RegisterEventRequest. * Use `create(RegisterEventRequestSchema)` to create a new message. */ -export const RegisterEventRequestSchema: GenMessage = - /*@__PURE__*/ +export const RegisterEventRequestSchema: GenMessage = /*@__PURE__*/ messageDesc(file_event_v1_event, 0); /** @@ -73,58 +62,51 @@ export type SDKCall = Message<"event.v1.SDKCall"> & { /** * @generated from oneof event.v1.SDKCall.debit */ - debit: - | { - /** - * @generated from field: float amount = 2; - */ - value: number; - case: "amount"; - } - | { - /** - * @generated from field: string tag = 3; - */ - value: string; - case: "tag"; - } - | { - /** - * Pricing expression (e.g., "add(mul(tag('PREMIUM'),3),250)") - * - * @generated from field: string expr = 4; - */ - value: string; - case: "expr"; - } - | { case: undefined; value?: undefined }; + debit: { + /** + * @generated from field: float amount = 2; + */ + value: number; + case: "amount"; + } | { + /** + * @generated from field: string tag = 3; + */ + value: string; + case: "tag"; + } | { + /** + * Pricing expression (e.g., "add(mul(tag('PREMIUM'),3),250)") + * + * @generated from field: string expr = 4; + */ + value: string; + case: "expr"; + } | { case: undefined; value?: undefined }; }; /** * Describes the message event.v1.SDKCall. * Use `create(SDKCallSchema)` to create a new message. */ -export const SDKCallSchema: GenMessage = - /*@__PURE__*/ +export const SDKCallSchema: GenMessage = /*@__PURE__*/ messageDesc(file_event_v1_event, 1); /** * @generated from message event.v1.RegisterEventResponse */ -export type RegisterEventResponse = - Message<"event.v1.RegisterEventResponse"> & { - /** - * @generated from field: string random = 1; - */ - random: string; - }; +export type RegisterEventResponse = Message<"event.v1.RegisterEventResponse"> & { + /** + * @generated from field: string random = 1; + */ + random: string; +}; /** * Describes the message event.v1.RegisterEventResponse. * Use `create(RegisterEventResponseSchema)` to create a new message. */ -export const RegisterEventResponseSchema: GenMessage = - /*@__PURE__*/ +export const RegisterEventResponseSchema: GenMessage = /*@__PURE__*/ messageDesc(file_event_v1_event, 2); /** @@ -141,33 +123,34 @@ export type StreamEventRequest = Message<"event.v1.StreamEventRequest"> & { */ userId: string; + /** + * @generated from field: int32 reportedTimestamp = 3; + */ + reportedTimestamp: number; + /** * @generated from oneof event.v1.StreamEventRequest.data */ - data: - | { - /** - * @generated from field: event.v1.SDKCall sdkCall = 3; - */ - value: SDKCall; - case: "sdkCall"; - } - | { - /** - * @generated from field: event.v1.AITokenUsage aiTokenUsage = 4; - */ - value: AITokenUsage; - case: "aiTokenUsage"; - } - | { case: undefined; value?: undefined }; + data: { + /** + * @generated from field: event.v1.SDKCall sdkCall = 4; + */ + value: SDKCall; + case: "sdkCall"; + } | { + /** + * @generated from field: event.v1.AITokenUsage aiTokenUsage = 5; + */ + value: AITokenUsage; + case: "aiTokenUsage"; + } | { case: undefined; value?: undefined }; }; /** * Describes the message event.v1.StreamEventRequest. * Use `create(StreamEventRequestSchema)` to create a new message. */ -export const StreamEventRequestSchema: GenMessage = - /*@__PURE__*/ +export const StreamEventRequestSchema: GenMessage = /*@__PURE__*/ messageDesc(file_event_v1_event, 3); /** @@ -192,68 +175,59 @@ export type AITokenUsage = Message<"event.v1.AITokenUsage"> & { /** * @generated from oneof event.v1.AITokenUsage.inputDebit */ - inputDebit: - | { - /** - * @generated from field: float inputAmount = 4; - */ - value: number; - case: "inputAmount"; - } - | { - /** - * @generated from field: string inputTag = 5; - */ - value: string; - case: "inputTag"; - } - | { - /** - * Pricing expression for input tokens - * - * @generated from field: string inputExpr = 8; - */ - value: string; - case: "inputExpr"; - } - | { case: undefined; value?: undefined }; + inputDebit: { + /** + * @generated from field: float inputAmount = 4; + */ + value: number; + case: "inputAmount"; + } | { + /** + * @generated from field: string inputTag = 5; + */ + value: string; + case: "inputTag"; + } | { + /** + * Pricing expression for input tokens + * + * @generated from field: string inputExpr = 8; + */ + value: string; + case: "inputExpr"; + } | { case: undefined; value?: undefined }; /** * @generated from oneof event.v1.AITokenUsage.outputDebit */ - outputDebit: - | { - /** - * @generated from field: float outputAmount = 6; - */ - value: number; - case: "outputAmount"; - } - | { - /** - * @generated from field: string outputTag = 7; - */ - value: string; - case: "outputTag"; - } - | { - /** - * Pricing expression for output tokens - * - * @generated from field: string outputExpr = 9; - */ - value: string; - case: "outputExpr"; - } - | { case: undefined; value?: undefined }; + outputDebit: { + /** + * @generated from field: float outputAmount = 6; + */ + value: number; + case: "outputAmount"; + } | { + /** + * @generated from field: string outputTag = 7; + */ + value: string; + case: "outputTag"; + } | { + /** + * Pricing expression for output tokens + * + * @generated from field: string outputExpr = 9; + */ + value: string; + case: "outputExpr"; + } | { case: undefined; value?: undefined }; }; /** * Describes the message event.v1.AITokenUsage. * Use `create(AITokenUsageSchema)` to create a new message. */ -export const AITokenUsageSchema: GenMessage = - /*@__PURE__*/ +export const AITokenUsageSchema: GenMessage = /*@__PURE__*/ messageDesc(file_event_v1_event, 4); /** @@ -275,8 +249,7 @@ export type StreamEventResponse = Message<"event.v1.StreamEventResponse"> & { * Describes the message event.v1.StreamEventResponse. * Use `create(StreamEventResponseSchema)` to create a new message. */ -export const StreamEventResponseSchema: GenMessage = - /*@__PURE__*/ +export const StreamEventResponseSchema: GenMessage = /*@__PURE__*/ messageDesc(file_event_v1_event, 5); /** @@ -302,8 +275,7 @@ export enum EventType { /** * Describes the enum event.v1.EventType. */ -export const EventTypeSchema: GenEnum = - /*@__PURE__*/ +export const EventTypeSchema: GenEnum = /*@__PURE__*/ enumDesc(file_event_v1_event, 0); /** @@ -329,8 +301,7 @@ export enum SDKCallType { /** * Describes the enum event.v1.SDKCallType. */ -export const SDKCallTypeSchema: GenEnum = - /*@__PURE__*/ +export const SDKCallTypeSchema: GenEnum = /*@__PURE__*/ enumDesc(file_event_v1_event, 1); /** @@ -346,7 +317,7 @@ export const EventService: GenService<{ methodKind: "unary"; input: typeof RegisterEventRequestSchema; output: typeof RegisterEventResponseSchema; - }; + }, /** * StreamEvents streams events from client to server (e.g., AI token usage) * @@ -356,5 +327,7 @@ export const EventService: GenService<{ methodKind: "client_streaming"; input: typeof StreamEventRequestSchema; output: typeof StreamEventResponseSchema; - }; -}> = /*@__PURE__*/ serviceDesc(file_event_v1_event, 0); + }, +}> = /*@__PURE__*/ + serviceDesc(file_event_v1_event, 0); + diff --git a/src/gen/payment/v1/payment_connect.ts b/src/gen/payment/v1/payment_connect.ts index 2380330..ad9ebba 100644 --- a/src/gen/payment/v1/payment_connect.ts +++ b/src/gen/payment/v1/payment_connect.ts @@ -1,12 +1,9 @@ -// @generated by protoc-gen-connect-es v0.13.0 with parameter "target=ts" +// @generated by protoc-gen-connect-es v1.7.0 with parameter "target=ts" // @generated from file payment/v1/payment.proto (package payment.v1, syntax proto3) /* eslint-disable */ // @ts-nocheck -import { - CreateCheckoutLinkRequest, - CreateCheckoutLinkResponse, -} from "./payment_pb.js"; +import { CreateCheckoutLinkRequest, CreateCheckoutLinkResponse } from "./payment_pb.js"; import { MethodKind } from "@bufbuild/protobuf"; /** @@ -26,5 +23,6 @@ export const PaymentService = { O: CreateCheckoutLinkResponse, kind: MethodKind.Unary, }, - }, + } } as const; + diff --git a/src/gen/payment/v1/payment_pb.ts b/src/gen/payment/v1/payment_pb.ts index 3ccf520..f9020c9 100644 --- a/src/gen/payment/v1/payment_pb.ts +++ b/src/gen/payment/v1/payment_pb.ts @@ -1,64 +1,49 @@ -// @generated by protoc-gen-es v2.9.0 with parameter "target=ts" +// @generated by protoc-gen-es v2.12.0 with parameter "target=ts" // @generated from file payment/v1/payment.proto (package payment.v1, syntax proto3) /* eslint-disable */ -import type { - GenFile, - GenMessage, - GenService, -} from "@bufbuild/protobuf/codegenv2"; -import { - fileDesc, - messageDesc, - serviceDesc, -} from "@bufbuild/protobuf/codegenv2"; +import type { GenFile, GenMessage, GenService } from "@bufbuild/protobuf/codegenv2"; +import { fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv2"; import type { Message } from "@bufbuild/protobuf"; /** * Describes the file payment/v1/payment.proto. */ -export const file_payment_v1_payment: GenFile = - /*@__PURE__*/ - fileDesc( - "ChhwYXltZW50L3YxL3BheW1lbnQucHJvdG8SCnBheW1lbnQudjEiKwoZQ3JlYXRlQ2hlY2tvdXRMaW5rUmVxdWVzdBIOCgZ1c2VySWQYASABKAkiMgoaQ3JlYXRlQ2hlY2tvdXRMaW5rUmVzcG9uc2USFAoMY2hlY2tvdXRMaW5rGAEgASgJMncKDlBheW1lbnRTZXJ2aWNlEmUKEkNyZWF0ZUNoZWNrb3V0TGluaxIlLnBheW1lbnQudjEuQ3JlYXRlQ2hlY2tvdXRMaW5rUmVxdWVzdBomLnBheW1lbnQudjEuQ3JlYXRlQ2hlY2tvdXRMaW5rUmVzcG9uc2UiAGIGcHJvdG8z" - ); +export const file_payment_v1_payment: GenFile = /*@__PURE__*/ + fileDesc("ChhwYXltZW50L3YxL3BheW1lbnQucHJvdG8SCnBheW1lbnQudjEiKwoZQ3JlYXRlQ2hlY2tvdXRMaW5rUmVxdWVzdBIOCgZ1c2VySWQYASABKAkiMgoaQ3JlYXRlQ2hlY2tvdXRMaW5rUmVzcG9uc2USFAoMY2hlY2tvdXRMaW5rGAEgASgJMncKDlBheW1lbnRTZXJ2aWNlEmUKEkNyZWF0ZUNoZWNrb3V0TGluaxIlLnBheW1lbnQudjEuQ3JlYXRlQ2hlY2tvdXRMaW5rUmVxdWVzdBomLnBheW1lbnQudjEuQ3JlYXRlQ2hlY2tvdXRMaW5rUmVzcG9uc2UiAGIGcHJvdG8z"); /** * @generated from message payment.v1.CreateCheckoutLinkRequest */ -export type CreateCheckoutLinkRequest = - Message<"payment.v1.CreateCheckoutLinkRequest"> & { - /** - * @generated from field: string userId = 1; - */ - userId: string; - }; +export type CreateCheckoutLinkRequest = Message<"payment.v1.CreateCheckoutLinkRequest"> & { + /** + * @generated from field: string userId = 1; + */ + userId: string; +}; /** * Describes the message payment.v1.CreateCheckoutLinkRequest. * Use `create(CreateCheckoutLinkRequestSchema)` to create a new message. */ -export const CreateCheckoutLinkRequestSchema: GenMessage = - /*@__PURE__*/ +export const CreateCheckoutLinkRequestSchema: GenMessage = /*@__PURE__*/ messageDesc(file_payment_v1_payment, 0); /** * @generated from message payment.v1.CreateCheckoutLinkResponse */ -export type CreateCheckoutLinkResponse = - Message<"payment.v1.CreateCheckoutLinkResponse"> & { - /** - * @generated from field: string checkoutLink = 1; - */ - checkoutLink: string; - }; +export type CreateCheckoutLinkResponse = Message<"payment.v1.CreateCheckoutLinkResponse"> & { + /** + * @generated from field: string checkoutLink = 1; + */ + checkoutLink: string; +}; /** * Describes the message payment.v1.CreateCheckoutLinkResponse. * Use `create(CreateCheckoutLinkResponseSchema)` to create a new message. */ -export const CreateCheckoutLinkResponseSchema: GenMessage = - /*@__PURE__*/ +export const CreateCheckoutLinkResponseSchema: GenMessage = /*@__PURE__*/ messageDesc(file_payment_v1_payment, 1); /** @@ -74,5 +59,7 @@ export const PaymentService: GenService<{ methodKind: "unary"; input: typeof CreateCheckoutLinkRequestSchema; output: typeof CreateCheckoutLinkResponseSchema; - }; -}> = /*@__PURE__*/ serviceDesc(file_payment_v1_payment, 0); + }, +}> = /*@__PURE__*/ + serviceDesc(file_payment_v1_payment, 0); + diff --git a/src/interceptors/connectInterceptors.ts b/src/interceptors/connectInterceptors.ts new file mode 100644 index 0000000..ad142a4 --- /dev/null +++ b/src/interceptors/connectInterceptors.ts @@ -0,0 +1,7 @@ +import type { Interceptor } from "@connectrpc/connect"; +import { loggingInterceptor } from "./logging.ts"; +import { authInterceptor } from "./auth.ts"; + +export function createConnectInterceptors(): Interceptor[] { + return [loggingInterceptor(), authInterceptor()]; +} diff --git a/src/interceptors/logging.ts b/src/interceptors/logging.ts index b032643..140e3a0 100644 --- a/src/interceptors/logging.ts +++ b/src/interceptors/logging.ts @@ -129,7 +129,7 @@ function extractErrorDetails(error: unknown): ErrorDetails { export function loggingInterceptor(): Interceptor { return (next) => async (req) => { const requestId = generateRequestId(); - const method = req.method.kind; // "unary", "server_streaming", "client_streaming", "bidi_streaming" + const method = String(req.method.kind); // "unary", "server_streaming", "client_streaming", "bidi_streaming" const url = req.url; const builder = createWideEventBuilder(requestId, method, url); diff --git a/src/interface/event/Event.ts b/src/interface/event/Event.ts index 1f3f435..19bfffb 100644 --- a/src/interface/event/Event.ts +++ b/src/interface/event/Event.ts @@ -27,6 +27,11 @@ export type PaymentEventData = { creditAmount: number; }; +export type MetadataEventData = { + payment_cron: string; + payment_webhook: string | null; +}; + /** * Event kind discriminator */ @@ -35,6 +40,7 @@ export type EventKind = | "AI_TOKEN_USAGE" | "ADD_KEY" | "PAYMENT" + | "METADATA"; /** * Mapping of event kinds to their data structures @@ -44,6 +50,7 @@ export type EventDataMap = { AI_TOKEN_USAGE: AITokenUsageEventData; ADD_KEY: AddKeyEventData; PAYMENT: PaymentEventData; + METADATA: MetadataEventData; }; /** @@ -75,6 +82,7 @@ type SqlRecordMap = { SDK_CALL: SqlRecordWithUserId<"SDK_CALL">; AI_TOKEN_USAGE: SqlRecordWithUserId<"AI_TOKEN_USAGE">; PAYMENT: SqlRecordWithUserId<"PAYMENT">; + METADATA: BaseSqlRecord<"METADATA">; }; /** @@ -94,7 +102,7 @@ export type SerializedEvent = { */ export interface Event { readonly type: K; - readonly reported_timestamp: DateTime; + readonly ingested_timestamp: DateTime; readonly data: EventData; serialize(): SerializedEvent; @@ -105,6 +113,7 @@ export interface Event { */ export interface SDKCallEvent extends Event<"SDK_CALL"> { readonly userId: UserId; + readonly reportedTimestamp: DateTime; } /** @@ -112,6 +121,7 @@ export interface SDKCallEvent extends Event<"SDK_CALL"> { */ export interface AITokenUsageEvent extends Event<"AI_TOKEN_USAGE"> { readonly userId: UserId; + readonly reportedTimestamp: DateTime; } /** @@ -125,3 +135,8 @@ export interface AddKeyEvent extends Event<"ADD_KEY"> {} export interface PaymentEvent extends Event<"PAYMENT"> { readonly userId: UserId; } + +/** + * Metadata Event + */ +export interface MetadataEvent extends Event<"METADATA"> {} diff --git a/src/interface/storage/Storage.ts b/src/interface/storage/Storage.ts index 68100a4..6cf1e24 100644 --- a/src/interface/storage/Storage.ts +++ b/src/interface/storage/Storage.ts @@ -9,7 +9,7 @@ export interface StorageAdapter { add( serialized: SerializedEvent, - apiKeyId: string + apiKeyId?: string ): Promise<{ id: string } | void>; price(userID: UserId, event_type: EventKind): Promise; } diff --git a/src/queues/onboarding.ts b/src/queues/onboarding.ts new file mode 100644 index 0000000..72ad6bc --- /dev/null +++ b/src/queues/onboarding.ts @@ -0,0 +1,48 @@ +import { Queue, type RepeatOptions } from "bullmq"; +import { DateTime } from "luxon"; +import { getRedisConnection } from "../storage/db/redis.ts"; + +export interface OnboardingJobData { + cronExpression: string; + createdAt: string; +} + +let onboardingQueue: Queue | null = null; + +export function getOnboardingQueue(): Queue { + if (!onboardingQueue) { + onboardingQueue = new Queue("onboarding", { + connection: getRedisConnection(), + }); + } + return onboardingQueue; +} + +export async function addOnboardingCronJob( + cronExpression: string +): Promise { + const queue = getOnboardingQueue(); + + const existingJobs = await queue.getRepeatableJobs(); + const jobName = `onboarding-${cronExpression}`; + const alreadyExists = existingJobs.some((job) => job.name === jobName); + + if (alreadyExists) { + return; + } + + const repeatOptions: RepeatOptions = { + pattern: cronExpression, + }; + + await queue.add( + jobName, + { + cronExpression, + createdAt: DateTime.utc().toISO(), + }, + { + repeat: repeatOptions, + } + ); +} \ No newline at end of file diff --git a/src/routes/gRPC/auth/createAPIKey.ts b/src/routes/gRPC/auth/createAPIKey.ts index 5349067..634c9a7 100644 --- a/src/routes/gRPC/auth/createAPIKey.ts +++ b/src/routes/gRPC/auth/createAPIKey.ts @@ -1,9 +1,5 @@ -import type { - CreateAPIKeyRequest, - CreateAPIKeyResponse, -} from "../../../gen/auth/v1/auth_pb"; -import { CreateAPIKeyResponseSchema } from "../../../gen/auth/v1/auth_pb"; -import { create } from "@bufbuild/protobuf"; +import type { CreateAPIKeyRequest, CreateAPIKeyResponse } from "../../../gen/auth/v1/auth_pb"; +import { CreateAPIKeyResponseSchema, CreateAPIKeyRequestSchema } from "../../../gen/auth/v1/auth_pb"; import { createAPIKeySchema } from "../../../zod/apikey"; import { APIKeyError } from "../../../errors/apikey"; import { AuthError } from "../../../errors/auth"; @@ -15,6 +11,8 @@ import type { HandlerContext } from "@connectrpc/connect"; import { apiKeyContextKey } from "../../../context/auth"; import { wideEventContextKey } from "../../../context/requestContext"; import { hashAPIKey } from "../../../utils/hashAPIKey"; +import { create } from "@bufbuild/protobuf"; +import { toJson } from "@bufbuild/protobuf"; export async function createAPIKey( req: CreateAPIKeyRequest, @@ -75,7 +73,8 @@ export async function createAPIKey( function validateRequest(req: CreateAPIKeyRequest) { try { - return createAPIKeySchema.parse(req); + const json = toJson(CreateAPIKeyRequestSchema, req); + return createAPIKeySchema.parse(json); } catch (error) { if (error instanceof ZodError) { const issues = error.issues @@ -87,4 +86,4 @@ function validateRequest(req: CreateAPIKeyRequest) { error instanceof Error ? error.message : String(error) ); } -} +} \ No newline at end of file diff --git a/src/routes/gRPC/events/registerEvent.ts b/src/routes/gRPC/events/registerEvent.ts index 83c3688..ad0fccc 100644 --- a/src/routes/gRPC/events/registerEvent.ts +++ b/src/routes/gRPC/events/registerEvent.ts @@ -1,10 +1,7 @@ -import type { - RegisterEventRequest, - RegisterEventResponse, -} from "../../../gen/event/v1/event_pb"; +import type { RegisterEventRequest, RegisterEventResponse } from "../../../gen/event/v1/event_pb"; import { RegisterEventResponseSchema } from "../../../gen/event/v1/event_pb"; -import { create } from "@bufbuild/protobuf"; import type { HandlerContext } from "@connectrpc/connect"; +import { create } from "@bufbuild/protobuf"; import { wideEventContextKey } from "../../../context/requestContext"; import { extractApiKeyFromContext, @@ -38,4 +35,4 @@ export async function registerEvent( return create(RegisterEventResponseSchema, { random: "Event stored successfully", }); -} +} \ No newline at end of file diff --git a/src/routes/gRPC/events/streamEvents.ts b/src/routes/gRPC/events/streamEvents.ts index ade4c4a..ef7f406 100644 --- a/src/routes/gRPC/events/streamEvents.ts +++ b/src/routes/gRPC/events/streamEvents.ts @@ -1,13 +1,9 @@ -import type { - StreamEventRequest, - StreamEventResponse, -} from "../../../gen/event/v1/event_pb"; - +import type { StreamEventRequest, StreamEventResponse } from "../../../gen/event/v1/event_pb"; import { StreamEventResponseSchema } from "../../../gen/event/v1/event_pb"; -import { create } from "@bufbuild/protobuf"; import { EventError } from "../../../errors/event"; import type { HandlerContext } from "@connectrpc/connect"; import { wideEventContextKey } from "../../../context/requestContext"; +import { create } from "@bufbuild/protobuf"; import { extractApiKeyFromContext, validateAndParseStreamEvent, @@ -56,4 +52,4 @@ export async function streamEvents( // Always update the count, even on error wideEventBuilder?.setEventContext({ eventCount: eventsProcessed }); } -} +} \ No newline at end of file diff --git a/src/routes/gRPC/payment/createCheckoutLink.ts b/src/routes/gRPC/payment/createCheckoutLink.ts index e561042..c132aa4 100644 --- a/src/routes/gRPC/payment/createCheckoutLink.ts +++ b/src/routes/gRPC/payment/createCheckoutLink.ts @@ -1,9 +1,5 @@ -import type { - CreateCheckoutLinkRequest, - CreateCheckoutLinkResponse, -} from "../../../gen/payment/v1/payment_pb"; -import { CreateCheckoutLinkResponseSchema } from "../../../gen/payment/v1/payment_pb"; -import { create } from "@bufbuild/protobuf"; +import type { CreateCheckoutLinkRequest, CreateCheckoutLinkResponse } from "../../../gen/payment/v1/payment_pb"; +import { CreateCheckoutLinkResponseSchema, CreateCheckoutLinkRequestSchema } from "../../../gen/payment/v1/payment_pb"; import { createCheckoutLinkSchema, type CreateCheckoutLinkSchemaType, @@ -19,6 +15,8 @@ import { import { StorageAdapterFactory } from "../../../factory"; import { apiKeyContextKey } from "../../../context/auth"; import { wideEventContextKey } from "../../../context/requestContext"; +import { create } from "@bufbuild/protobuf"; +import { toJson } from "@bufbuild/protobuf"; import type { UserId } from "../../../config/identifiers"; export async function createCheckoutLink( @@ -81,7 +79,8 @@ function validateRequest( req: CreateCheckoutLinkRequest ): CreateCheckoutLinkSchemaType { try { - return createCheckoutLinkSchema.parse(req); + const json = toJson(CreateCheckoutLinkRequestSchema, req); + return createCheckoutLinkSchema.parse(json); } catch (error) { if (error instanceof ZodError) { const issues = error.issues diff --git a/src/routes/gRPC/registerRoutes.ts b/src/routes/gRPC/registerRoutes.ts new file mode 100644 index 0000000..94d3c05 --- /dev/null +++ b/src/routes/gRPC/registerRoutes.ts @@ -0,0 +1,23 @@ +import type { ConnectRouter } from "@connectrpc/connect"; +import { EventService } from "../../gen/event/v1/event_pb"; +import { AuthService } from "../../gen/auth/v1/auth_pb"; +import { PaymentService } from "../../gen/payment/v1/payment_pb"; +import { registerEvent } from "./events/registerEvent.ts"; +import { streamEvents } from "./events/streamEvents.ts"; +import { createAPIKey } from "./auth/createAPIKey.ts"; +import { createCheckoutLink } from "./payment/createCheckoutLink.ts"; + +export function registerGrpcRoutes(router: ConnectRouter): void { + router.service(AuthService, { + createAPIKey, + }); + + router.service(EventService, { + registerEvent, + streamEvents, + }); + + router.service(PaymentService, { + createCheckoutLink, + }); +} diff --git a/src/routes/http/api/onboarding.ts b/src/routes/http/api/onboarding.ts new file mode 100644 index 0000000..7b10b57 --- /dev/null +++ b/src/routes/http/api/onboarding.ts @@ -0,0 +1,81 @@ +import type { FastifyRequest, FastifyReply } from "fastify"; +import { ZodError } from "zod"; +import { + onboardingCronSchema, + type OnboardingCronSchemaType, +} from "../../../zod/internals.ts"; +import { addOnboardingCronJob } from "../../../queues/onboarding.ts"; +import { + createWideEventBuilder, + generateRequestId, +} from "../../../context/requestContext.ts"; +import { logger } from "../../../errors/logger.ts"; +import { StorageAdapterFactory } from "../../../factory/index.ts"; +import { Metadata } from "../../../events/RawEvents/Metadata.ts"; + +export async function handleOnboarding( + request: FastifyRequest, + reply: FastifyReply +): Promise<{ crons: string[] }> { + const builder = createWideEventBuilder( + generateRequestId(), + request.method, + request.url + ); + + try { + const body = await request.body; + const validated = onboardingCronSchema.parse(body); + + const crons: string[] = []; + + for (const cronExpression of validated.crons) { + await addOnboardingCronJob(cronExpression); + crons.push(cronExpression); + } + + const webhookUrl = + validated.webhookUrl && validated.webhookUrl !== "" + ? validated.webhookUrl + : null; + + const metadataEvent = new Metadata({ + payment_cron: crons.join(","), + payment_webhook: webhookUrl, + }); + + const adapter = await StorageAdapterFactory.getEventStorageAdapter( + metadataEvent.type + ); + await adapter.add(metadataEvent.serialize(), ""); + + builder.setSuccess(200).addContext({ + cronCount: crons.length, + }); + + reply.code(201); + return { crons }; + } catch (error) { + if (error instanceof ZodError) { + const issues = error.issues + .map((issue) => `${issue.path.join(".")}: ${issue.message}`) + .join("; "); + builder.setError(400, { + type: "ValidationError", + message: issues, + }); + reply.code(400); + return { crons: [] }; + } + + const err = error instanceof Error ? error : new Error(String(error)); + builder.setError(500, { + type: "InternalError", + message: err.message, + }); + reply.code(500); + return { crons: [] }; + } finally { + logger.emit(builder.build()); + } +} diff --git a/src/routes/http/api/registerApiRoutes.ts b/src/routes/http/api/registerApiRoutes.ts new file mode 100644 index 0000000..4775d02 --- /dev/null +++ b/src/routes/http/api/registerApiRoutes.ts @@ -0,0 +1,16 @@ +import type { FastifyInstance, FastifyRequest, FastifyReply } from "fastify"; +import { handleOnboarding } from "./onboarding.ts"; + +export async function registerApiRoutes( + server: ReturnType +): Promise { + server.post( + "/api/v1/internals/onboarding", + async ( + request: FastifyRequest, + reply: FastifyReply + ) => { + return handleOnboarding(request, reply); + } + ); +} \ No newline at end of file diff --git a/src/routes/http/createdCheckout.ts b/src/routes/http/createdCheckout.ts index a2b9f6d..ef6dd1b 100644 --- a/src/routes/http/createdCheckout.ts +++ b/src/routes/http/createdCheckout.ts @@ -1,5 +1,4 @@ import crypto from "node:crypto"; -import type { IncomingMessage, ServerResponse } from "node:http"; import { lemonSqueezySetup } from "@lemonsqueezy/lemonsqueezy.js"; import { Payment } from "../../events/RawEvents/Payment.ts"; import { StorageAdapterFactory } from "../../factory/EventStorageAdapterFactory.ts"; @@ -40,6 +39,11 @@ interface LemonSqueezyWebhookPayload { }; } +interface WebhookResponse { + statusCode: number; + body: { message?: string; error?: string }; +} + /** * Verifies the webhook signature from Lemon Squeezy */ @@ -63,41 +67,17 @@ function verifyWebhookSignature( } } -/** - * Reads the request body as a string - */ -function readBody(req: IncomingMessage): Promise { - return new Promise((resolve, reject) => { - let body = ""; - req.on("data", (chunk: Buffer) => { - body += chunk.toString(); - }); - req.on("end", () => { - resolve(body); - }); - req.on("error", (error: Error) => { - reject(error); - }); - }); -} - /** * Handles the Lemon Squeezy order-created webhook. * This handler is designed to work with the HTTP logging middleware, * which provides a WideEventBuilder for adding business context. */ export async function handleLemonSqueezyWebhook( - req: IncomingMessage, - res: ServerResponse, + rawBody: string, + signature: string | undefined, builder: WideEventBuilder -): Promise { +): Promise { try { - // Read the raw body - const rawBody = await readBody(req); - - // Verify webhook signature - const signature = req.headers["x-signature"] as string | undefined; - // Read webhook secret at runtime for testability const LEMON_SQUEEZY_WEBHOOK_SECRET = process.env.LEMON_SQUEEZY_WEBHOOK_SECRET; @@ -107,9 +87,10 @@ export async function handleLemonSqueezyWebhook( type: "ConfigurationError", message: "Webhook secret not configured", }); - res.writeHead(500, { "Content-Type": "application/json" }); - res.end(JSON.stringify({ error: "Webhook secret not configured" })); - return; + return { + statusCode: 500, + body: { error: "Webhook secret not configured" }, + }; } const isValid = verifyWebhookSignature( @@ -123,52 +104,57 @@ export async function handleLemonSqueezyWebhook( type: "AuthenticationError", message: "Invalid signature", }); - res.writeHead(401, { "Content-Type": "application/json" }); - res.end(JSON.stringify({ error: "Invalid signature" })); - return; + return { statusCode: 401, body: { error: "Invalid signature" } }; } - // Parse the payload - let payload: LemonSqueezyWebhookPayload; + let webhookPayload: LemonSqueezyWebhookPayload; try { - payload = JSON.parse(rawBody); + webhookPayload = JSON.parse(rawBody) as LemonSqueezyWebhookPayload; } catch { builder.setError(400, { type: "ParseError", message: "Invalid JSON payload", }); - res.writeHead(400, { "Content-Type": "application/json" }); - res.end(JSON.stringify({ error: "Invalid JSON payload" })); - return; + return { statusCode: 400, body: { error: "Invalid JSON payload" } }; + } + + if (!webhookPayload.meta || !webhookPayload.data?.attributes) { + builder.setError(400, { + type: "ParseError", + message: "Invalid webhook payload shape", + }); + return { + statusCode: 400, + body: { error: "Invalid webhook payload shape" }, + }; } // Add webhook event context builder.setWebhookContext({ - webhookEvent: payload.meta.event_name, - orderId: payload.data.id, + webhookEvent: webhookPayload.meta.event_name, + orderId: webhookPayload.data.id, }); // Handle only order-created events - if (payload.meta.event_name !== "order_created") { + if (webhookPayload.meta.event_name !== "order_created") { builder.setSuccess(200); builder.addContext({ ignored: true }); - res.writeHead(200, { "Content-Type": "application/json" }); - res.end(JSON.stringify({ message: "Event ignored" })); - return; + return { statusCode: 200, body: { message: "Event ignored" } }; } // Extract user ID from custom data - const userId = payload.meta.custom_data?.user_id; - const apiKeyId = payload.meta.custom_data?.api_key_id; + const userId = webhookPayload.meta.custom_data?.user_id; + const apiKeyId = webhookPayload.meta.custom_data?.api_key_id; if (!userId) { builder.setError(400, { type: "ValidationError", message: "Missing user_id in webhook payload", }); - res.writeHead(400, { "Content-Type": "application/json" }); - res.end(JSON.stringify({ error: "Missing user_id in webhook payload" })); - return; + return { + statusCode: 400, + body: { error: "Missing user_id in webhook payload" }, + }; } if (!apiKeyId) { @@ -176,16 +162,17 @@ export async function handleLemonSqueezyWebhook( type: "ValidationError", message: "Missing apiKeyId in webhook payload", }); - res.writeHead(400, { "Content-Type": "application/json" }); - res.end(JSON.stringify({ error: "Missing apiKeyId in webhook payload" })); - return; + return { + statusCode: 400, + body: { error: "Missing apiKeyId in webhook payload" }, + }; } // Add user and payment context to wide event builder.setUser(userId); // Extract payment amount (convert from cents to the integer format used in DB) - const creditAmount = Math.round(payload.data.attributes.total); + const creditAmount = Math.round(webhookPayload.data.attributes.total); builder.setPaymentContext({ creditAmount }); // Create and store the payment event @@ -197,10 +184,10 @@ export async function handleLemonSqueezyWebhook( await adapter.add(paymentEvent.serialize(), apiKeyId); builder.setSuccess(200); - res.writeHead(200, { "Content-Type": "application/json" }); - res.end( - JSON.stringify({ message: "Webhook processed successfuladdEvent " }) - ); + return { + statusCode: 200, + body: { message: "Webhook processed successfully" }, + }; } catch (dbError) { const errorMessage = dbError instanceof Error ? dbError.message : String(dbError); @@ -210,8 +197,7 @@ export async function handleLemonSqueezyWebhook( cause: dbError instanceof Error ? dbError.message : undefined, stack: isDev && dbError instanceof Error ? dbError.stack : undefined, }); - res.writeHead(500, { "Content-Type": "application/json" }); - res.end(JSON.stringify({ error: "Database error" })); + return { statusCode: 500, body: { error: "Database error" } }; } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); @@ -221,7 +207,6 @@ export async function handleLemonSqueezyWebhook( cause: error instanceof Error ? error.message : undefined, stack: isDev && error instanceof Error ? error.stack : undefined, }); - res.writeHead(500, { "Content-Type": "application/json" }); - res.end(JSON.stringify({ error: "Internal server error" })); + return { statusCode: 500, body: { error: "Internal server error" } }; } } diff --git a/src/routes/http/registerWebhookRoutes.ts b/src/routes/http/registerWebhookRoutes.ts new file mode 100644 index 0000000..8844e4c --- /dev/null +++ b/src/routes/http/registerWebhookRoutes.ts @@ -0,0 +1,62 @@ +import type { FastifyInstance, FastifyRequest, FastifyReply } from "fastify"; +import { createWideEventBuilder, generateRequestId } from "../../context/requestContext.ts"; +import { logger } from "../../errors/logger.ts"; +import { handleLemonSqueezyWebhook } from "./createdCheckout.ts"; + +export async function registerWebhookRoutes( + server: ReturnType +): Promise { + server.post( + "/webhooks/lemonsqueezy/createdCheckout", + { config: { rawBody: true } }, + async ( + request: FastifyRequest, + reply: FastifyReply + ) => { + const builder = createWideEventBuilder( + generateRequestId(), + request.method, + request.url + ); + + try { + const signatureHeader = request.headers["x-signature"]; + const signature = + typeof signatureHeader === "string" + ? signatureHeader + : Array.isArray(signatureHeader) + ? signatureHeader[0] + : undefined; + + const requestWithRawBody = request as typeof request & { + rawBody?: string; + }; + const rawBody = requestWithRawBody.rawBody; + + if (!rawBody) { + builder.setError(400, { + type: "ParseError", + message: "Missing raw webhook payload", + }); + reply.code(400); + return { error: "Missing raw webhook payload" }; + } + + const result = await handleLemonSqueezyWebhook(rawBody, signature, builder); + + reply.code(result.statusCode); + return result.body; + } catch (error) { + const err = error instanceof Error ? error : new Error(String(error)); + builder.setError(500, { + type: "InternalError", + message: err.message, + }); + reply.code(500); + return { error: "Internal server error" }; + } finally { + logger.emit(builder.build()); + } + } + ); +} diff --git a/src/server.ts b/src/server.ts index b4e6608..44720ff 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,24 +1,13 @@ -import * as http from "node:http"; -import * as http2 from "node:http2"; -import type { ConnectRouter } from "@connectrpc/connect"; -import { connectNodeAdapter } from "@connectrpc/connect-node"; -import { createValidateInterceptor } from "@connectrpc/validate"; -import { EventService } from "./gen/event/v1/event_pb.ts"; -import { AuthService } from "./gen/auth/v1/auth_pb.ts"; -import { PaymentService } from "./gen/payment/v1/payment_pb.ts"; -import { loggingInterceptor } from "./interceptors/logging.ts"; -import { authInterceptor } from "./interceptors/auth.ts"; -import { registerEvent } from "./routes/gRPC/events/registerEvent.ts"; -import { streamEvents } from "./routes/gRPC/events/streamEvents.ts"; -import { createAPIKey } from "./routes/gRPC/auth/createAPIKey.ts"; -import { createCheckoutLink } from "./routes/gRPC/payment/createCheckoutLink.ts"; import { getPostgresDB } from "./storage/db/postgres/db.ts"; -import { handleLemonSqueezyWebhook } from "./routes/http/createdCheckout.ts"; -import { withHttpLogging } from "./middleware/httpLogging.ts"; import { logger } from "./errors/logger.ts"; +import { startRawGrpcServer } from "./servers/rawGrpcServer.ts"; +import { startFastifyServer } from "./servers/fastifyServer.ts"; +import { OnboardingWorker } from "./workers/onboarding.ts"; +import { getRedisConnection } from "./storage/db/redis.ts"; const DATABASE_URL = process.env.DATABASE_URL; const HMAC_SECRET = process.env.HMAC_SECRET; +const REDIS_URL = process.env.REDIS_URL; if (!DATABASE_URL) { logger.fatal("DATABASE_URL is not defined in environment variables"); @@ -30,68 +19,31 @@ if (!HMAC_SECRET) { throw new Error("HMAC_SECRET environment variable is not set"); } +if (!REDIS_URL) { + logger.fatal("REDIS_URL environmentvariable is not set"); + throw new Error("REDIS_URL environmentvariable is not set"); +} + getPostgresDB(DATABASE_URL); +getRedisConnection(REDIS_URL); -const grpcHandler = connectNodeAdapter({ - interceptors: [ - loggingInterceptor(), // First - captures all requests including auth failures - createValidateInterceptor(), - authInterceptor(), - ], - routes: (router: ConnectRouter) => { - // EventService implementation - router.service(EventService, { - registerEvent, - streamEvents, - }); +const PORT = Number(process.env.PORT ?? 8070); +const GRPC_PORT = Number(process.env.GRPC_PORT ?? 8069); - // AuthService implementation - router.service(AuthService, { - createAPIKey, - }); +let onboardingWorker: OnboardingWorker | undefined; - // PaymentService implementation - router.service(PaymentService, { - createCheckoutLink, - }); - }, -}); +async function main(): Promise { + startRawGrpcServer(GRPC_PORT); + await startFastifyServer(PORT, GRPC_PORT); -// Wrap webhook handler with HTTP logging middleware -const webhookHandler = withHttpLogging(handleLemonSqueezyWebhook); + onboardingWorker = new OnboardingWorker(); + logger.lifecycle("Onboarding worker started"); +} -// Create a combined handler for both gRPC and HTTP webhooks -const requestHandler = ( - req: http.IncomingMessage | http2.Http2ServerRequest, - res: http.ServerResponse | http2.Http2ServerResponse -) => { - // Handle webhook endpoint - if ( - req.url === "/webhooks/lemonsqueezy/createdCheckout" && - req.method === "POST" - ) { - webhookHandler( - req as unknown as http.IncomingMessage, - res as unknown as http.ServerResponse - ); - return; +process.on("beforeExit", async () => { + if (onboardingWorker) { + await onboardingWorker.close(); } - - // Handle all other requests as gRPC - grpcHandler(req, res); -}; - -const PORT = Number(process.env.PORT ?? 8069); - -http2.createServer(requestHandler).listen(PORT); - -logger.lifecycle("Server started", { - grpcH2Port: PORT, - env: process.env.NODE_ENV || "development", -}); -logger.lifecycle("Webhook endpoint available", { - url: `http://localhost:${PORT}/webhooks/lemonsqueezy/createdCheckout`, -}); -logger.lifecycle("gRPC h2c endpoint available", { - url: `http://localhost:${PORT}`, }); + +void main(); diff --git a/src/servers/fastifyServer.ts b/src/servers/fastifyServer.ts new file mode 100644 index 0000000..5803f4b --- /dev/null +++ b/src/servers/fastifyServer.ts @@ -0,0 +1,38 @@ +import { fastify } from "fastify"; +import fastifyRawBody from "fastify-raw-body"; +import { registerWebhookRoutes } from "../routes/http/registerWebhookRoutes.ts"; +import { registerApiRoutes } from "../routes/http/api/registerApiRoutes.ts"; +import { logger } from "../errors/logger.ts"; + +export async function startFastifyServer(port: number, grpcPort: number): Promise { + const server = fastify(); + + await server.register(fastifyRawBody, { + field: "rawBody", + global: false, + encoding: "utf8", + runFirst: true, + }); + + server.get("/", async (_request, reply) => { + reply.type("text/plain"); + return "Hello World!"; + }); + + await registerWebhookRoutes(server); + await registerApiRoutes(server); + + await server.listen({ host: "localhost", port }); + + logger.lifecycle("Server started", { + httpPort: port, + grpcH2Port: grpcPort, + env: process.env.NODE_ENV || "development", + }); + logger.lifecycle("Webhook endpoint available", { + url: `http://localhost:${port}/webhooks/lemonsqueezy/createdCheckout`, + }); + logger.lifecycle("API endpoint available", { + url: `http://localhost:${port}/api/v1/internals/onboarding`, + }); +} diff --git a/src/servers/rawGrpcServer.ts b/src/servers/rawGrpcServer.ts new file mode 100644 index 0000000..1f5c718 --- /dev/null +++ b/src/servers/rawGrpcServer.ts @@ -0,0 +1,18 @@ +import * as http2 from "node:http2"; +import { connectNodeAdapter } from "@connectrpc/connect-node"; +import { registerGrpcRoutes } from "../routes/gRPC/registerRoutes.ts"; +import { createConnectInterceptors } from "../interceptors/connectInterceptors.ts"; +import { logger } from "../errors/logger.ts"; + +export function startRawGrpcServer(grpcPort: number): void { + const grpcHandler = connectNodeAdapter({ + interceptors: createConnectInterceptors(), + routes: registerGrpcRoutes, + }); + + http2.createServer(grpcHandler).listen(grpcPort); + + logger.lifecycle("Raw gRPC h2c endpoint available", { + url: `http://localhost:${grpcPort}`, + }); +} diff --git a/src/storage/adapter/postgres/handlers/addAiTokenUsage.ts b/src/storage/adapter/postgres/handlers/addAiTokenUsage.ts index 1f8f8af..8559623 100644 --- a/src/storage/adapter/postgres/handlers/addAiTokenUsage.ts +++ b/src/storage/adapter/postgres/handlers/addAiTokenUsage.ts @@ -7,6 +7,7 @@ import { import { StorageError } from "../../../../errors/storage"; import { type SqlRecord } from "../../../../interface/event/Event"; import type { UserId } from "../../../../config/identifiers"; +import { DateTime } from "luxon"; type AggregatedEvent = { userId: UserId; @@ -148,6 +149,7 @@ export async function handleAddAiTokenUsage( // Prepare event values for batch insert const eventValues = aggregatedEvents.map((aggEvent) => ({ reported_timestamp: aggEvent.reported_timestamp, + ingested_timestamp: DateTime.utc().toString(), userId: aggEvent.userId, api_keyId: apiKeyId, })); diff --git a/src/storage/adapter/postgres/handlers/addMetadata.ts b/src/storage/adapter/postgres/handlers/addMetadata.ts new file mode 100644 index 0000000..75e94ce --- /dev/null +++ b/src/storage/adapter/postgres/handlers/addMetadata.ts @@ -0,0 +1,52 @@ +import { getPostgresDB } from "../../../db/postgres/db"; +import { metadataTable } from "../../../db/postgres/schema"; +import { StorageError } from "../../../../errors/storage"; +import { type SqlRecord } from "../../../../interface/event/Event"; +import { eq } from "drizzle-orm"; + +export async function handleAddMetadata( + event_data: SqlRecord<"METADATA"> +): Promise { + const connectionObject = getPostgresDB(); + + const paymentCron = event_data.data.payment_cron; + const paymentWebhook = event_data.data.payment_webhook; + + if (!paymentCron || paymentCron.trim().length === 0) { + throw StorageError.invalidData("Invalid payment_cron: value is required"); + } + + if (paymentWebhook !== null && typeof paymentWebhook !== "string") { + throw StorageError.invalidData( + "Invalid payment_webhook: must be a string or null" + ); + } + + try { + const [existingMetadata] = await connectionObject + .select({ id: metadataTable.id }) + .from(metadataTable) + .limit(1); + + if (existingMetadata) { + await connectionObject + .update(metadataTable) + .set({ + payment_cron: paymentCron, + payment_webhook: paymentWebhook, + }) + .where(eq(metadataTable.id, existingMetadata.id)); + return; + } + + await connectionObject.insert(metadataTable).values({ + payment_cron: paymentCron, + payment_webhook: paymentWebhook, + }); + } catch (e) { + throw StorageError.insertFailed( + "Failed to upsert metadata record", + e instanceof Error ? e : new Error(String(e)) + ); + } +} diff --git a/src/storage/adapter/postgres/handlers/addPayment.ts b/src/storage/adapter/postgres/handlers/addPayment.ts index b4e6175..52cce0b 100644 --- a/src/storage/adapter/postgres/handlers/addPayment.ts +++ b/src/storage/adapter/postgres/handlers/addPayment.ts @@ -6,6 +6,7 @@ import { } from "../../../db/postgres/schema"; import { StorageError } from "../../../../errors/storage"; import { type SqlRecord } from "../../../../interface/event/Event"; +import { DateTime } from "luxon"; export async function handleAddPayment( event_data: SqlRecord<"PAYMENT">, @@ -78,6 +79,7 @@ export async function handleAddPayment( .insert(eventsTable) .values({ reported_timestamp, + ingested_timestamp: DateTime.utc().toString(), userId: event_data.userId, api_keyId: apiKeyId, }) diff --git a/src/storage/adapter/postgres/handlers/addSdkCall.ts b/src/storage/adapter/postgres/handlers/addSdkCall.ts index 50d8f17..3714ef0 100644 --- a/src/storage/adapter/postgres/handlers/addSdkCall.ts +++ b/src/storage/adapter/postgres/handlers/addSdkCall.ts @@ -6,6 +6,7 @@ import { } from "../../../db/postgres/schema"; import { StorageError } from "../../../../errors/storage"; import { type SqlRecord } from "../../../../interface/event/Event"; +import { DateTime } from "luxon"; export async function handleAddSdkCall( event_data: SqlRecord<"SDK_CALL">, @@ -70,6 +71,7 @@ export async function handleAddSdkCall( .insert(eventsTable) .values({ reported_timestamp, + ingested_timestamp: DateTime.utc().toString(), userId: event_data.userId, api_keyId: apiKeyId, }) diff --git a/src/storage/adapter/postgres/handlers/index.ts b/src/storage/adapter/postgres/handlers/index.ts index 72639cb..e4e13b1 100644 --- a/src/storage/adapter/postgres/handlers/index.ts +++ b/src/storage/adapter/postgres/handlers/index.ts @@ -5,3 +5,4 @@ export { handlePriceRequestPayment } from "./priceRequestPayment"; export { handlePriceRequestSdkCall } from "./priceRequestSdkCall"; export { handleAddAiTokenUsage } from "./addAiTokenUsage"; export { handlePriceRequestAiTokenUsage } from "./priceRequestAiTokenUsage"; +export { handleAddMetadata } from "./addMetadata"; diff --git a/src/storage/adapter/postgres/handlers/priceRequestAiTokenUsage.ts b/src/storage/adapter/postgres/handlers/priceRequestAiTokenUsage.ts index acd96cd..d8ea9fc 100644 --- a/src/storage/adapter/postgres/handlers/priceRequestAiTokenUsage.ts +++ b/src/storage/adapter/postgres/handlers/priceRequestAiTokenUsage.ts @@ -2,6 +2,7 @@ import { getPostgresDB } from "../../../db/postgres/db"; import { aiTokenUsageEventsTable, eventsTable, + usersTable, } from "../../../db/postgres/schema"; import { StorageError } from "../../../../errors/storage"; import { eq, sum, sql } from "drizzle-orm"; @@ -33,8 +34,14 @@ export async function handlePriceRequestAiTokenUsage( ), }) .from(aiTokenUsageEventsTable) - .leftJoin(eventsTable, eq(aiTokenUsageEventsTable.id, eventsTable.id)) - .where(eq(eventsTable.userId, userId)) + .innerJoin(eventsTable, eq(aiTokenUsageEventsTable.id, eventsTable.id)) + .innerJoin( + usersTable, + eq(eventsTable.userId, usersTable.id) + ) + .where( + sql`${eventsTable.reported_timestamp} > ${usersTable.last_billed_timestamp} AND ${eventsTable.userId} = ${userId}` + ) .groupBy(eventsTable.userId); } catch (e) { throw StorageError.queryFailed( diff --git a/src/storage/adapter/postgres/handlers/priceRequestSdkCall.ts b/src/storage/adapter/postgres/handlers/priceRequestSdkCall.ts index 69c69b3..020aa5b 100644 --- a/src/storage/adapter/postgres/handlers/priceRequestSdkCall.ts +++ b/src/storage/adapter/postgres/handlers/priceRequestSdkCall.ts @@ -1,7 +1,7 @@ import { getPostgresDB } from "../../../db/postgres/db"; -import { sdkCallEventsTable, eventsTable } from "../../../db/postgres/schema"; +import { sdkCallEventsTable, eventsTable, usersTable } from "../../../db/postgres/schema"; import { StorageError } from "../../../../errors/storage"; -import { eq, sum } from "drizzle-orm"; +import { eq, sum, gt, sql } from "drizzle-orm"; import { type UserId } from "../../../../config/identifiers"; export async function handlePriceRequestSdkCall( @@ -27,8 +27,14 @@ export async function handlePriceRequestSdkCall( price: sum(sdkCallEventsTable.debitAmount), }) .from(sdkCallEventsTable) - .leftJoin(eventsTable, eq(sdkCallEventsTable.id, eventsTable.id)) - .where(eq(eventsTable.userId, userId)) + .innerJoin(eventsTable, eq(sdkCallEventsTable.id, eventsTable.id)) + .innerJoin( + usersTable, + eq(eventsTable.userId, usersTable.id) + ) + .where( + sql`${eventsTable.reported_timestamp} > ${usersTable.last_billed_timestamp} AND ${eventsTable.userId} = ${userId}` + ) .groupBy(eventsTable.userId); } catch (e) { throw StorageError.queryFailed( diff --git a/src/storage/adapter/postgres/postgres.ts b/src/storage/adapter/postgres/postgres.ts index 94c8c15..a0c0284 100644 --- a/src/storage/adapter/postgres/postgres.ts +++ b/src/storage/adapter/postgres/postgres.ts @@ -10,6 +10,7 @@ import { handlePriceRequestSdkCall, handleAddAiTokenUsage, handlePriceRequestAiTokenUsage, + handleAddMetadata, } from "./handlers"; import type { SerializedEvent, @@ -72,6 +73,10 @@ export class PostgresAdapter implements StorageAdapter { return await handleAddPayment(event_data, apiKeyId); } + case "METADATA": { + return await handleAddMetadata(event_data); + } + default: { //@ts-ignore throw StorageError.unknownEventType(event_data.type); diff --git a/src/storage/db/postgres/schema.ts b/src/storage/db/postgres/schema.ts index 6d3aaba..91fbf13 100644 --- a/src/storage/db/postgres/schema.ts +++ b/src/storage/db/postgres/schema.ts @@ -9,9 +9,16 @@ import { uniqueIndex, } from "drizzle-orm/pg-core"; import { USER_ID_CONFIG } from "../../../config/identifiers"; +import { DateTime } from "luxon"; export const usersTable = pgTable("users", { id: USER_ID_CONFIG.dbType("id").primaryKey(), + last_billed_timestamp: timestamp("last_billed_timestamp", { + withTimezone: true, + mode: "string", + }) + .default(DateTime.utc(1).toString()) + .notNull(), }); export const usersRelation = relations(usersTable, ({ many }) => ({ @@ -57,6 +64,12 @@ export const eventsTable = pgTable("events", { withTimezone: true, mode: "string", }).notNull(), + ingested_timestamp: timestamp("ingested_timestamp", { + withTimezone: true, + mode: "string", + }) + .defaultNow() + .notNull(), userId: USER_ID_CONFIG.dbType("user_id") .references(() => usersTable.id) .notNull(), @@ -123,7 +136,7 @@ export const paymentEventsRelation = relations( export const tagsTable = pgTable("tags", { id: uuid("id").primaryKey().defaultRandom(), - tag: text("key").notNull(), + key: text("key").notNull(), amount: integer("amount").notNull(), }); @@ -147,3 +160,9 @@ export const aiTokenUsageEventsRelation = relations( }), }) ); + +export const metadataTable = pgTable("metadata", { + id: uuid("id").primaryKey().defaultRandom(), + payment_cron: text("payment_cron").notNull(), + payment_webhook: text("payment_webhook"), +}); diff --git a/src/storage/db/redis.ts b/src/storage/db/redis.ts new file mode 100644 index 0000000..a0c1cda --- /dev/null +++ b/src/storage/db/redis.ts @@ -0,0 +1,18 @@ +import IORedis from "ioredis"; + +let redisConnection: IORedis | null = null; + +export function getRedisConnection(REDIS_URL?: string): IORedis { + if (redisConnection) return redisConnection; + + if (!REDIS_URL) { + throw new Error("REDIS_URL is not defined"); + } + + redisConnection = new IORedis(REDIS_URL, { + maxRetriesPerRequest: null, + lazyConnect: true, + }); + + return redisConnection; +} \ No newline at end of file diff --git a/src/utils/eventHelpers.ts b/src/utils/eventHelpers.ts index a37794d..3c8b04f 100644 --- a/src/utils/eventHelpers.ts +++ b/src/utils/eventHelpers.ts @@ -17,6 +17,8 @@ import type { RegisterEventRequest, StreamEventRequest, } from "../gen/event/v1/event_pb"; +import { toJson } from "@bufbuild/protobuf"; +import { RegisterEventRequestSchema, StreamEventRequestSchema } from "../gen/event/v1/event_pb"; /** * Extract API key ID from the request context @@ -37,7 +39,8 @@ export async function validateAndParseRegisterEvent( req: RegisterEventRequest ): Promise { try { - return await registerEventSchema.parseAsync(req); + const json = toJson(RegisterEventRequestSchema, req); + return await registerEventSchema.parseAsync(json); } catch (error) { throw convertValidationError(error); } @@ -50,7 +53,8 @@ export async function validateAndParseStreamEvent( req: StreamEventRequest ): Promise { try { - return await streamEventSchema.parseAsync(req); + const json = toJson(StreamEventRequestSchema, req); + return await streamEventSchema.parseAsync(json); } catch (error) { throw convertValidationError(error); } @@ -96,9 +100,17 @@ export function createEventInstance( ): Event { switch (eventSkeleton.type) { case "SDK_CALL": - return new SDKCall(eventSkeleton.userId, eventSkeleton.data); + return new SDKCall( + eventSkeleton.userId, + eventSkeleton.reportedTimestamp, + eventSkeleton.data + ); case "AI_TOKEN_USAGE": - return new AITokenUsage(eventSkeleton.userId, eventSkeleton.data); + return new AITokenUsage( + eventSkeleton.userId, + eventSkeleton.reportedTimestamp, + eventSkeleton.data + ); default: throw EventError.unsupportedEventType("Unknown event type"); } diff --git a/src/utils/fetchTagAmount.ts b/src/utils/fetchTagAmount.ts index 6da969f..e92eef6 100644 --- a/src/utils/fetchTagAmount.ts +++ b/src/utils/fetchTagAmount.ts @@ -17,7 +17,7 @@ export async function fetchTagAmount( const [tagRow] = await db .select() .from(tagsTable) - .where(eq(tagsTable.tag, tag)) + .where(eq(tagsTable.key, tag)) .limit(1); if (!tagRow) { diff --git a/src/workers/onboarding.ts b/src/workers/onboarding.ts new file mode 100644 index 0000000..a90b7f1 --- /dev/null +++ b/src/workers/onboarding.ts @@ -0,0 +1,71 @@ +import { Worker, Job } from "bullmq"; +import { DateTime } from "luxon"; +import { getRedisConnection } from "../storage/db/redis.ts"; +import { getPostgresDB } from "../storage/db/postgres/db.ts"; +import { metadataTable } from "../storage/db/postgres/schema.ts"; +import { logger } from "../errors/logger.ts"; + +export class OnboardingWorker { + private worker: Worker; + + constructor() { + this.worker = new Worker( + "onboarding", + async (job: Job) => { + await this.processJob(job); + }, + { + connection: getRedisConnection(), + concurrency: 1, + limiter: { + max: 1, + duration: 1800000, + }, + maxStalledCount: 2, + } + ); + } + + private async processJob(job: Job): Promise { + const db = getPostgresDB(); + const [metadata] = await db.select().from(metadataTable).limit(1); + + if (!metadata) { + logger.lifecycle("[onboarding] No metadata found, skipping"); + return; + } + + if (!metadata.payment_webhook) { + logger.lifecycle("[onboarding] No webhook configured, skipping"); + return; + } + + const timestamp = DateTime.utc().toISO(); + + try { + const response = await fetch(metadata.payment_webhook, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ timestamp }), + }); + + if (!response.ok) { + logger.fatal( + `[onboarding] Webhook failed: ${response.status} ${response.statusText}` + ); + return; + } + + logger.lifecycle(`[onboarding] Webhook triggered at ${timestamp}`); + } catch (e) { + const err = e instanceof Error ? e : new Error(String(e)); + logger.fatal(`[onboarding] Webhook error: ${err.message}`, err); + } + } + + async close(): Promise { + await this.worker.close(); + } +} diff --git a/src/zod/event.ts b/src/zod/event.ts index ca2979f..bc1d5b7 100644 --- a/src/zod/event.ts +++ b/src/zod/event.ts @@ -1,4 +1,5 @@ import { z } from "zod"; +import { DateTime } from "luxon"; import { USER_ID_CONFIG } from "../config/identifiers"; import { fetchTagAmount } from "../utils/fetchTagAmount"; import { parseAndEvaluateExpr } from "../utils/parseExpr"; @@ -8,6 +9,10 @@ export { parseAndEvaluateExpr } from "../utils/parseExpr"; const BaseEvent = z.object({ type: z.number(), // overwritten later by discriminators userId: USER_ID_CONFIG.validator, + reportedTimestamp: z + .number() + .int() + .transform((ts) => DateTime.fromSeconds(ts)), }); const SDKCallEvent = BaseEvent.extend({ diff --git a/src/zod/internals.ts b/src/zod/internals.ts new file mode 100644 index 0000000..2c4aa6b --- /dev/null +++ b/src/zod/internals.ts @@ -0,0 +1,21 @@ +import { z } from "zod"; + +const cronField = z + .string() + .min(9, "Cron expression must be at least 9 characters") + .max(100, "Cron expression must be less than 100 characters") + .refine((val) => { + const parts = val.trim().split(/\s+/); + if (parts.length < 5 || parts.length > 6) return false; + return true; + }, "Cron expression must have 5 or 6 fields (minute hour day month weekday or with seconds)"); + +export const onboardingCronSchema = z.object({ + crons: z + .array(cronField) + .min(1, "At least one cron expression is required") + .max(100, "Maximum 100 cron expressions allowed"), + webhookUrl: z.url("Invalid webhook URL").or(z.literal("")), +}); + +export type OnboardingCronSchemaType = z.infer; \ No newline at end of file