├── .github
└── workflows
│ ├── cd.yaml
│ └── ci.yaml
├── .gitignore
├── LICENSE
├── README.md
├── biome.json
├── examples
├── using-decorators
│ ├── .editorconfig
│ ├── .gitignore
│ ├── .prettierrc
│ ├── README.md
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── src
│ │ └── index.ts
│ ├── tsconfig.json
│ ├── worker-configuration.d.ts
│ └── wrangler.toml
└── using-state
│ ├── .editorconfig
│ ├── .gitignore
│ ├── .prettierrc
│ ├── README.md
│ ├── package.json
│ ├── src
│ └── index.ts
│ ├── tsconfig.json
│ ├── worker-configuration.d.ts
│ └── wrangler.toml
├── package.json
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
├── src
├── decorator.ts
├── index.ts
├── observable.ts
├── sqlite.ts
├── tracker.ts
└── util.ts
├── tests
├── decorator.test.ts
├── global.d.ts
├── helper.ts
├── index.test.ts
├── observable.test.ts
├── sqlite.test.ts
└── worker.ts
├── tsconfig.build.json
├── tsconfig.json
└── vitest.config.ts
/.github/workflows/cd.yaml:
--------------------------------------------------------------------------------
1 | name: Publish to NPM
2 | on:
3 | release:
4 | types: [published]
5 | jobs:
6 | build:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/checkout@v3
10 | - uses: pnpm/action-setup@v3
11 | with:
12 | version: 8
13 | - uses: actions/setup-node@v3
14 | with:
15 | node-version: "20.x"
16 | registry-url: "https://registry.npmjs.org"
17 | - run: pnpm install
18 | - run: pnpm build
19 | - run: pnpm publish --no-git-checks
20 | env:
21 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
22 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yaml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request:
8 | branches:
9 | - main
10 |
11 | jobs:
12 | build:
13 | runs-on: ubuntu-latest
14 | strategy:
15 | matrix:
16 | node-version: [22]
17 | steps:
18 | - uses: actions/checkout@v3
19 | - uses: pnpm/action-setup@v3
20 | with:
21 | version: 9
22 |
23 | - name: Use Node.js
24 | uses: actions/setup-node@v3
25 | with:
26 | node-version: ${{ matrix.node-version }}
27 | cache: "pnpm"
28 |
29 | - name: Install dependencies
30 | run: pnpm install --frozen-lockfile
31 |
32 | - name: Biome format check
33 | run: pnpm check:format
34 |
35 | - name: Biome lint
36 | run: pnpm check:lint
37 |
38 | - name: Run tests
39 | run: pnpm test
40 |
41 | - name: Build
42 | run: pnpm build
43 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | dist/
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Zebulon Piasecki
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
diffable-objects
2 |
3 |
4 | A package for dynamic state tracking for Cloudflare's Durable Objects using SQLite.
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | ## Installation
20 |
21 | ```
22 | # NPM
23 | $ npm install --save diffable-objects
24 | # Yarn
25 | $ yarn add diffable-objects
26 | # PNPM
27 | $ pnpm add diffable-objects
28 | # Bun
29 | $ bun add diffable-objects
30 | ```
31 |
32 | ## Example
33 |
34 | > For complete examples see the [examples](./examples/) directory.
35 |
36 | Basic example of `diffable-objects`.
37 |
38 | ```typescript
39 | import { DurableObject } from "cloudflare:workers";
40 | export { diffable, state } from "diffable-objects";
41 |
42 | export class SampleObject extends DurableObject {
43 | // Within a durale object we can register a property to
44 | // have its values automatically tracked and persisted.
45 | #state = state(this.ctx, "state", { count: 0 });
46 |
47 | increment() {
48 | this.#state.count++;
49 | }
50 | }
51 |
52 | // Currently requires wrangler@next
53 | export class DecoratorObject extends DurableObject {
54 | // You can also use decorators if you'd prefer a simpler
55 | // (but more magic) syntax.
56 | @diffable
57 | #state = { count: 0 };
58 |
59 | // Snapshot policies are configrable via an options object.
60 | @diffable({ snapshotPolicy: "every-change" })
61 | #stateWithOptions = { count: 0 };
62 |
63 | increment() {
64 | this.#state.count++;
65 | this.#stateWithOptions.count++;
66 | }
67 | }
68 | ```
69 |
70 | ## License
71 |
72 | Distributed under the MIT License. See [LICENSE](LICENSE) for more information.
73 |
--------------------------------------------------------------------------------
/biome.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
3 | "vcs": {
4 | "enabled": false,
5 | "clientKind": "git",
6 | "useIgnoreFile": false
7 | },
8 | "files": {
9 | "ignoreUnknown": false,
10 | "ignore": ["dist/**/*", "node_modules/**/*", "examples/**/*"]
11 | },
12 | "formatter": {
13 | "enabled": true,
14 | "indentStyle": "space",
15 | "indentWidth": 2
16 | },
17 | "organizeImports": {
18 | "enabled": true
19 | },
20 | "linter": {
21 | "enabled": true,
22 | "rules": {
23 | "recommended": true,
24 | "suspicious": {
25 | "noExplicitAny": "off"
26 | }
27 | }
28 | },
29 | "javascript": {
30 | "formatter": {
31 | "quoteStyle": "double"
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/examples/using-decorators/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = tab
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
11 | [*.yml]
12 | indent_style = space
13 |
--------------------------------------------------------------------------------
/examples/using-decorators/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 |
3 | logs
4 | _.log
5 | npm-debug.log_
6 | yarn-debug.log*
7 | yarn-error.log*
8 | lerna-debug.log*
9 | .pnpm-debug.log*
10 |
11 | # Diagnostic reports (https://nodejs.org/api/report.html)
12 |
13 | report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
14 |
15 | # Runtime data
16 |
17 | pids
18 | _.pid
19 | _.seed
20 | \*.pid.lock
21 |
22 | # Directory for instrumented libs generated by jscoverage/JSCover
23 |
24 | lib-cov
25 |
26 | # Coverage directory used by tools like istanbul
27 |
28 | coverage
29 | \*.lcov
30 |
31 | # nyc test coverage
32 |
33 | .nyc_output
34 |
35 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
36 |
37 | .grunt
38 |
39 | # Bower dependency directory (https://bower.io/)
40 |
41 | bower_components
42 |
43 | # node-waf configuration
44 |
45 | .lock-wscript
46 |
47 | # Compiled binary addons (https://nodejs.org/api/addons.html)
48 |
49 | build/Release
50 |
51 | # Dependency directories
52 |
53 | node_modules/
54 | jspm_packages/
55 |
56 | # Snowpack dependency directory (https://snowpack.dev/)
57 |
58 | web_modules/
59 |
60 | # TypeScript cache
61 |
62 | \*.tsbuildinfo
63 |
64 | # Optional npm cache directory
65 |
66 | .npm
67 |
68 | # Optional eslint cache
69 |
70 | .eslintcache
71 |
72 | # Optional stylelint cache
73 |
74 | .stylelintcache
75 |
76 | # Microbundle cache
77 |
78 | .rpt2_cache/
79 | .rts2_cache_cjs/
80 | .rts2_cache_es/
81 | .rts2_cache_umd/
82 |
83 | # Optional REPL history
84 |
85 | .node_repl_history
86 |
87 | # Output of 'npm pack'
88 |
89 | \*.tgz
90 |
91 | # Yarn Integrity file
92 |
93 | .yarn-integrity
94 |
95 | # dotenv environment variable files
96 |
97 | .env
98 | .env.development.local
99 | .env.test.local
100 | .env.production.local
101 | .env.local
102 |
103 | # parcel-bundler cache (https://parceljs.org/)
104 |
105 | .cache
106 | .parcel-cache
107 |
108 | # Next.js build output
109 |
110 | .next
111 | out
112 |
113 | # Nuxt.js build / generate output
114 |
115 | .nuxt
116 | dist
117 |
118 | # Gatsby files
119 |
120 | .cache/
121 |
122 | # Comment in the public line in if your project uses Gatsby and not Next.js
123 |
124 | # https://nextjs.org/blog/next-9-1#public-directory-support
125 |
126 | # public
127 |
128 | # vuepress build output
129 |
130 | .vuepress/dist
131 |
132 | # vuepress v2.x temp and cache directory
133 |
134 | .temp
135 | .cache
136 |
137 | # Docusaurus cache and generated files
138 |
139 | .docusaurus
140 |
141 | # Serverless directories
142 |
143 | .serverless/
144 |
145 | # FuseBox cache
146 |
147 | .fusebox/
148 |
149 | # DynamoDB Local files
150 |
151 | .dynamodb/
152 |
153 | # TernJS port file
154 |
155 | .tern-port
156 |
157 | # Stores VSCode versions used for testing VSCode extensions
158 |
159 | .vscode-test
160 |
161 | # yarn v2
162 |
163 | .yarn/cache
164 | .yarn/unplugged
165 | .yarn/build-state.yml
166 | .yarn/install-state.gz
167 | .pnp.\*
168 |
169 | # wrangler project
170 |
171 | .dev.vars
172 | .wrangler/
173 |
--------------------------------------------------------------------------------
/examples/using-decorators/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 140,
3 | "singleQuote": true,
4 | "semi": true,
5 | "useTabs": true
6 | }
7 |
--------------------------------------------------------------------------------
/examples/using-decorators/README.md:
--------------------------------------------------------------------------------
1 | # using-decorators
2 |
3 | This sample updates the [Hello World Durable Object](https://github.com/cloudflare/workers-sdk/tree/main/packages/create-cloudflare/templates/hello-world-durable-object/ts) template from Cloudflare to use `diffable-objects` using decorators.
4 |
5 | ## Note
6 |
7 | Because `wrangler`, Cloudflare's Workers CLI, uses an older version of `esbuild` you must use `wrangler@next` in your Worker until the next major release.
8 |
9 | ## Try it out
10 |
11 | ```
12 | pnpm dev
13 | ```
--------------------------------------------------------------------------------
/examples/using-decorators/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "using-decorators",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "deploy": "wrangler deploy",
7 | "dev": "wrangler dev",
8 | "start": "wrangler dev",
9 | "cf-typegen": "wrangler types"
10 | },
11 | "devDependencies": {
12 | "@cloudflare/workers-types": "^4.20241224.0",
13 | "typescript": "^5.5.2",
14 | "wrangler": "0.0.0-dc669c404"
15 | },
16 | "dependencies": {
17 | "diffable-objects": "^0.1.1"
18 | }
19 | }
--------------------------------------------------------------------------------
/examples/using-decorators/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: '9.0'
2 |
3 | settings:
4 | autoInstallPeers: true
5 | excludeLinksFromLockfile: false
6 |
7 | importers:
8 |
9 | .:
10 | devDependencies:
11 | '@cloudflare/workers-types':
12 | specifier: ^4.20241224.0
13 | version: 4.20241224.0
14 | typescript:
15 | specifier: ^5.5.2
16 | version: 5.7.2
17 | wrangler:
18 | specifier: ^3.60.3
19 | version: 3.99.0(@cloudflare/workers-types@4.20241224.0)
20 |
21 | packages:
22 |
23 | '@cloudflare/kv-asset-handler@0.3.4':
24 | resolution: {integrity: sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q==}
25 | engines: {node: '>=16.13'}
26 |
27 | '@cloudflare/workerd-darwin-64@1.20241218.0':
28 | resolution: {integrity: sha512-8rveQoxtUvlmORKqTWgjv2ycM8uqWox0u9evn3zd2iWKdou5sncFwH517ZRLI3rq9P31ZLmCQBZ0gloFsTeY6w==}
29 | engines: {node: '>=16'}
30 | cpu: [x64]
31 | os: [darwin]
32 |
33 | '@cloudflare/workerd-darwin-arm64@1.20241218.0':
34 | resolution: {integrity: sha512-be59Ad9nmM9lCkhHqmTs/uZ3JVZt8NJ9Z0PY+B0xnc5z6WwmV2lj0RVLtq7xJhQsQJA189zt5rXqDP6J+2mu7Q==}
35 | engines: {node: '>=16'}
36 | cpu: [arm64]
37 | os: [darwin]
38 |
39 | '@cloudflare/workerd-linux-64@1.20241218.0':
40 | resolution: {integrity: sha512-MzpSBcfZXRxrYWxQ4pVDYDrUbkQuM62ssl4ZtHH8J35OAeGsWFAYji6MkS2SpVwVcvacPwJXIF4JSzp4xKImKw==}
41 | engines: {node: '>=16'}
42 | cpu: [x64]
43 | os: [linux]
44 |
45 | '@cloudflare/workerd-linux-arm64@1.20241218.0':
46 | resolution: {integrity: sha512-RIuJjPxpNqvwIs52vQsXeRMttvhIjgg9NLjjFa3jK8Ijnj8c3ZDru9Wqi48lJP07yDFIRr4uDMMqh/y29YQi2A==}
47 | engines: {node: '>=16'}
48 | cpu: [arm64]
49 | os: [linux]
50 |
51 | '@cloudflare/workerd-windows-64@1.20241218.0':
52 | resolution: {integrity: sha512-tO1VjlvK3F6Yb2d1jgEy/QBYl//9Pyv3K0j+lq8Eu7qdfm0IgKwSRgDWLept84/qmNsQfausZ4JdNGxTf9xsxQ==}
53 | engines: {node: '>=16'}
54 | cpu: [x64]
55 | os: [win32]
56 |
57 | '@cloudflare/workers-types@4.20241224.0':
58 | resolution: {integrity: sha512-1ZmFc8qqM7S/HUGmLplc4P8n8DoMqiJmc47r9Lr7VbuaotoqCXVljz09w1V1mc4K3pbFPgvqSy4XYStZ08HrlQ==}
59 |
60 | '@cspotcode/source-map-support@0.8.1':
61 | resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
62 | engines: {node: '>=12'}
63 |
64 | '@esbuild-plugins/node-globals-polyfill@0.2.3':
65 | resolution: {integrity: sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw==}
66 | peerDependencies:
67 | esbuild: '*'
68 |
69 | '@esbuild-plugins/node-modules-polyfill@0.2.2':
70 | resolution: {integrity: sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA==}
71 | peerDependencies:
72 | esbuild: '*'
73 |
74 | '@esbuild/android-arm64@0.17.19':
75 | resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==}
76 | engines: {node: '>=12'}
77 | cpu: [arm64]
78 | os: [android]
79 |
80 | '@esbuild/android-arm@0.17.19':
81 | resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==}
82 | engines: {node: '>=12'}
83 | cpu: [arm]
84 | os: [android]
85 |
86 | '@esbuild/android-x64@0.17.19':
87 | resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==}
88 | engines: {node: '>=12'}
89 | cpu: [x64]
90 | os: [android]
91 |
92 | '@esbuild/darwin-arm64@0.17.19':
93 | resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==}
94 | engines: {node: '>=12'}
95 | cpu: [arm64]
96 | os: [darwin]
97 |
98 | '@esbuild/darwin-x64@0.17.19':
99 | resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==}
100 | engines: {node: '>=12'}
101 | cpu: [x64]
102 | os: [darwin]
103 |
104 | '@esbuild/freebsd-arm64@0.17.19':
105 | resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==}
106 | engines: {node: '>=12'}
107 | cpu: [arm64]
108 | os: [freebsd]
109 |
110 | '@esbuild/freebsd-x64@0.17.19':
111 | resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==}
112 | engines: {node: '>=12'}
113 | cpu: [x64]
114 | os: [freebsd]
115 |
116 | '@esbuild/linux-arm64@0.17.19':
117 | resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==}
118 | engines: {node: '>=12'}
119 | cpu: [arm64]
120 | os: [linux]
121 |
122 | '@esbuild/linux-arm@0.17.19':
123 | resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==}
124 | engines: {node: '>=12'}
125 | cpu: [arm]
126 | os: [linux]
127 |
128 | '@esbuild/linux-ia32@0.17.19':
129 | resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==}
130 | engines: {node: '>=12'}
131 | cpu: [ia32]
132 | os: [linux]
133 |
134 | '@esbuild/linux-loong64@0.17.19':
135 | resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==}
136 | engines: {node: '>=12'}
137 | cpu: [loong64]
138 | os: [linux]
139 |
140 | '@esbuild/linux-mips64el@0.17.19':
141 | resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==}
142 | engines: {node: '>=12'}
143 | cpu: [mips64el]
144 | os: [linux]
145 |
146 | '@esbuild/linux-ppc64@0.17.19':
147 | resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==}
148 | engines: {node: '>=12'}
149 | cpu: [ppc64]
150 | os: [linux]
151 |
152 | '@esbuild/linux-riscv64@0.17.19':
153 | resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==}
154 | engines: {node: '>=12'}
155 | cpu: [riscv64]
156 | os: [linux]
157 |
158 | '@esbuild/linux-s390x@0.17.19':
159 | resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==}
160 | engines: {node: '>=12'}
161 | cpu: [s390x]
162 | os: [linux]
163 |
164 | '@esbuild/linux-x64@0.17.19':
165 | resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==}
166 | engines: {node: '>=12'}
167 | cpu: [x64]
168 | os: [linux]
169 |
170 | '@esbuild/netbsd-x64@0.17.19':
171 | resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==}
172 | engines: {node: '>=12'}
173 | cpu: [x64]
174 | os: [netbsd]
175 |
176 | '@esbuild/openbsd-x64@0.17.19':
177 | resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==}
178 | engines: {node: '>=12'}
179 | cpu: [x64]
180 | os: [openbsd]
181 |
182 | '@esbuild/sunos-x64@0.17.19':
183 | resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==}
184 | engines: {node: '>=12'}
185 | cpu: [x64]
186 | os: [sunos]
187 |
188 | '@esbuild/win32-arm64@0.17.19':
189 | resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==}
190 | engines: {node: '>=12'}
191 | cpu: [arm64]
192 | os: [win32]
193 |
194 | '@esbuild/win32-ia32@0.17.19':
195 | resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==}
196 | engines: {node: '>=12'}
197 | cpu: [ia32]
198 | os: [win32]
199 |
200 | '@esbuild/win32-x64@0.17.19':
201 | resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==}
202 | engines: {node: '>=12'}
203 | cpu: [x64]
204 | os: [win32]
205 |
206 | '@fastify/busboy@2.1.1':
207 | resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==}
208 | engines: {node: '>=14'}
209 |
210 | '@jridgewell/resolve-uri@3.1.2':
211 | resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
212 | engines: {node: '>=6.0.0'}
213 |
214 | '@jridgewell/sourcemap-codec@1.5.0':
215 | resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
216 |
217 | '@jridgewell/trace-mapping@0.3.9':
218 | resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
219 |
220 | '@types/node-forge@1.3.11':
221 | resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==}
222 |
223 | '@types/node@22.10.2':
224 | resolution: {integrity: sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==}
225 |
226 | acorn-walk@8.3.4:
227 | resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==}
228 | engines: {node: '>=0.4.0'}
229 |
230 | acorn@8.14.0:
231 | resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==}
232 | engines: {node: '>=0.4.0'}
233 | hasBin: true
234 |
235 | as-table@1.0.55:
236 | resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==}
237 |
238 | blake3-wasm@2.1.5:
239 | resolution: {integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==}
240 |
241 | capnp-ts@0.7.0:
242 | resolution: {integrity: sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g==}
243 |
244 | chokidar@4.0.3:
245 | resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
246 | engines: {node: '>= 14.16.0'}
247 |
248 | cookie@0.7.2:
249 | resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==}
250 | engines: {node: '>= 0.6'}
251 |
252 | data-uri-to-buffer@2.0.2:
253 | resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==}
254 |
255 | date-fns@4.1.0:
256 | resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==}
257 |
258 | debug@4.4.0:
259 | resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
260 | engines: {node: '>=6.0'}
261 | peerDependencies:
262 | supports-color: '*'
263 | peerDependenciesMeta:
264 | supports-color:
265 | optional: true
266 |
267 | defu@6.1.4:
268 | resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
269 |
270 | esbuild@0.17.19:
271 | resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==}
272 | engines: {node: '>=12'}
273 | hasBin: true
274 |
275 | escape-string-regexp@4.0.0:
276 | resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
277 | engines: {node: '>=10'}
278 |
279 | estree-walker@0.6.1:
280 | resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==}
281 |
282 | exit-hook@2.2.1:
283 | resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==}
284 | engines: {node: '>=6'}
285 |
286 | fsevents@2.3.3:
287 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
288 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
289 | os: [darwin]
290 |
291 | function-bind@1.1.2:
292 | resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
293 |
294 | get-source@2.0.12:
295 | resolution: {integrity: sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==}
296 |
297 | glob-to-regexp@0.4.1:
298 | resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==}
299 |
300 | hasown@2.0.2:
301 | resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
302 | engines: {node: '>= 0.4'}
303 |
304 | is-core-module@2.16.1:
305 | resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==}
306 | engines: {node: '>= 0.4'}
307 |
308 | itty-time@1.0.6:
309 | resolution: {integrity: sha512-+P8IZaLLBtFv8hCkIjcymZOp4UJ+xW6bSlQsXGqrkmJh7vSiMFSlNne0mCYagEE0N7HDNR5jJBRxwN0oYv61Rw==}
310 |
311 | magic-string@0.25.9:
312 | resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
313 |
314 | mime@3.0.0:
315 | resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==}
316 | engines: {node: '>=10.0.0'}
317 | hasBin: true
318 |
319 | miniflare@3.20241218.0:
320 | resolution: {integrity: sha512-spYFDArH0wd+wJSTrzBrWrXJrbyJhRMJa35mat947y1jYhVV8I5V8vnD3LwjfpLr0SaEilojz1OIW7ekmnRe+w==}
321 | engines: {node: '>=16.13'}
322 | hasBin: true
323 |
324 | ms@2.1.3:
325 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
326 |
327 | mustache@4.2.0:
328 | resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==}
329 | hasBin: true
330 |
331 | nanoid@3.3.8:
332 | resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==}
333 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
334 | hasBin: true
335 |
336 | node-forge@1.3.1:
337 | resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==}
338 | engines: {node: '>= 6.13.0'}
339 |
340 | ohash@1.1.4:
341 | resolution: {integrity: sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g==}
342 |
343 | path-parse@1.0.7:
344 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
345 |
346 | path-to-regexp@6.3.0:
347 | resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==}
348 |
349 | pathe@1.1.2:
350 | resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
351 |
352 | printable-characters@1.0.42:
353 | resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==}
354 |
355 | readdirp@4.0.2:
356 | resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==}
357 | engines: {node: '>= 14.16.0'}
358 |
359 | resolve@1.22.10:
360 | resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==}
361 | engines: {node: '>= 0.4'}
362 | hasBin: true
363 |
364 | rollup-plugin-inject@3.0.2:
365 | resolution: {integrity: sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==}
366 | deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject.
367 |
368 | rollup-plugin-node-polyfills@0.2.1:
369 | resolution: {integrity: sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==}
370 |
371 | rollup-pluginutils@2.8.2:
372 | resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==}
373 |
374 | selfsigned@2.4.1:
375 | resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==}
376 | engines: {node: '>=10'}
377 |
378 | source-map@0.6.1:
379 | resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
380 | engines: {node: '>=0.10.0'}
381 |
382 | sourcemap-codec@1.4.8:
383 | resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==}
384 | deprecated: Please use @jridgewell/sourcemap-codec instead
385 |
386 | stacktracey@2.1.8:
387 | resolution: {integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==}
388 |
389 | stoppable@1.1.0:
390 | resolution: {integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==}
391 | engines: {node: '>=4', npm: '>=6'}
392 |
393 | supports-preserve-symlinks-flag@1.0.0:
394 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
395 | engines: {node: '>= 0.4'}
396 |
397 | tslib@2.8.1:
398 | resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
399 |
400 | typescript@5.7.2:
401 | resolution: {integrity: sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==}
402 | engines: {node: '>=14.17'}
403 | hasBin: true
404 |
405 | ufo@1.5.4:
406 | resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==}
407 |
408 | undici-types@6.20.0:
409 | resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==}
410 |
411 | undici@5.28.4:
412 | resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==}
413 | engines: {node: '>=14.0'}
414 |
415 | unenv-nightly@2.0.0-20241204-140205-a5d5190:
416 | resolution: {integrity: sha512-jpmAytLeiiW01pl5bhVn9wYJ4vtiLdhGe10oXlJBuQEX8mxjxO8BlEXGHU4vr4yEikjFP1wsomTHt/CLU8kUwg==}
417 |
418 | workerd@1.20241218.0:
419 | resolution: {integrity: sha512-7Z3D4vOVChMz9mWDffE299oQxUWm/pbkeAWx1btVamPcAK/2IuoNBhwflWo3jyuKuxvYuFAdIucgYxc8ICqXiA==}
420 | engines: {node: '>=16'}
421 | hasBin: true
422 |
423 | wrangler@3.99.0:
424 | resolution: {integrity: sha512-k0x4rT3G/QCbxcoZY7CHRVlAIS8WMmKdga6lf4d2c3gXFqssh44vwlTDuARA9QANBxKJTcA7JPTJRfUDhd9QBA==}
425 | engines: {node: '>=16.17.0'}
426 | hasBin: true
427 | peerDependencies:
428 | '@cloudflare/workers-types': ^4.20241218.0
429 | peerDependenciesMeta:
430 | '@cloudflare/workers-types':
431 | optional: true
432 |
433 | ws@8.18.0:
434 | resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==}
435 | engines: {node: '>=10.0.0'}
436 | peerDependencies:
437 | bufferutil: ^4.0.1
438 | utf-8-validate: '>=5.0.2'
439 | peerDependenciesMeta:
440 | bufferutil:
441 | optional: true
442 | utf-8-validate:
443 | optional: true
444 |
445 | xxhash-wasm@1.1.0:
446 | resolution: {integrity: sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==}
447 |
448 | youch@3.3.4:
449 | resolution: {integrity: sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg==}
450 |
451 | zod@3.24.1:
452 | resolution: {integrity: sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==}
453 |
454 | snapshots:
455 |
456 | '@cloudflare/kv-asset-handler@0.3.4':
457 | dependencies:
458 | mime: 3.0.0
459 |
460 | '@cloudflare/workerd-darwin-64@1.20241218.0':
461 | optional: true
462 |
463 | '@cloudflare/workerd-darwin-arm64@1.20241218.0':
464 | optional: true
465 |
466 | '@cloudflare/workerd-linux-64@1.20241218.0':
467 | optional: true
468 |
469 | '@cloudflare/workerd-linux-arm64@1.20241218.0':
470 | optional: true
471 |
472 | '@cloudflare/workerd-windows-64@1.20241218.0':
473 | optional: true
474 |
475 | '@cloudflare/workers-types@4.20241224.0': {}
476 |
477 | '@cspotcode/source-map-support@0.8.1':
478 | dependencies:
479 | '@jridgewell/trace-mapping': 0.3.9
480 |
481 | '@esbuild-plugins/node-globals-polyfill@0.2.3(esbuild@0.17.19)':
482 | dependencies:
483 | esbuild: 0.17.19
484 |
485 | '@esbuild-plugins/node-modules-polyfill@0.2.2(esbuild@0.17.19)':
486 | dependencies:
487 | esbuild: 0.17.19
488 | escape-string-regexp: 4.0.0
489 | rollup-plugin-node-polyfills: 0.2.1
490 |
491 | '@esbuild/android-arm64@0.17.19':
492 | optional: true
493 |
494 | '@esbuild/android-arm@0.17.19':
495 | optional: true
496 |
497 | '@esbuild/android-x64@0.17.19':
498 | optional: true
499 |
500 | '@esbuild/darwin-arm64@0.17.19':
501 | optional: true
502 |
503 | '@esbuild/darwin-x64@0.17.19':
504 | optional: true
505 |
506 | '@esbuild/freebsd-arm64@0.17.19':
507 | optional: true
508 |
509 | '@esbuild/freebsd-x64@0.17.19':
510 | optional: true
511 |
512 | '@esbuild/linux-arm64@0.17.19':
513 | optional: true
514 |
515 | '@esbuild/linux-arm@0.17.19':
516 | optional: true
517 |
518 | '@esbuild/linux-ia32@0.17.19':
519 | optional: true
520 |
521 | '@esbuild/linux-loong64@0.17.19':
522 | optional: true
523 |
524 | '@esbuild/linux-mips64el@0.17.19':
525 | optional: true
526 |
527 | '@esbuild/linux-ppc64@0.17.19':
528 | optional: true
529 |
530 | '@esbuild/linux-riscv64@0.17.19':
531 | optional: true
532 |
533 | '@esbuild/linux-s390x@0.17.19':
534 | optional: true
535 |
536 | '@esbuild/linux-x64@0.17.19':
537 | optional: true
538 |
539 | '@esbuild/netbsd-x64@0.17.19':
540 | optional: true
541 |
542 | '@esbuild/openbsd-x64@0.17.19':
543 | optional: true
544 |
545 | '@esbuild/sunos-x64@0.17.19':
546 | optional: true
547 |
548 | '@esbuild/win32-arm64@0.17.19':
549 | optional: true
550 |
551 | '@esbuild/win32-ia32@0.17.19':
552 | optional: true
553 |
554 | '@esbuild/win32-x64@0.17.19':
555 | optional: true
556 |
557 | '@fastify/busboy@2.1.1': {}
558 |
559 | '@jridgewell/resolve-uri@3.1.2': {}
560 |
561 | '@jridgewell/sourcemap-codec@1.5.0': {}
562 |
563 | '@jridgewell/trace-mapping@0.3.9':
564 | dependencies:
565 | '@jridgewell/resolve-uri': 3.1.2
566 | '@jridgewell/sourcemap-codec': 1.5.0
567 |
568 | '@types/node-forge@1.3.11':
569 | dependencies:
570 | '@types/node': 22.10.2
571 |
572 | '@types/node@22.10.2':
573 | dependencies:
574 | undici-types: 6.20.0
575 |
576 | acorn-walk@8.3.4:
577 | dependencies:
578 | acorn: 8.14.0
579 |
580 | acorn@8.14.0: {}
581 |
582 | as-table@1.0.55:
583 | dependencies:
584 | printable-characters: 1.0.42
585 |
586 | blake3-wasm@2.1.5: {}
587 |
588 | capnp-ts@0.7.0:
589 | dependencies:
590 | debug: 4.4.0
591 | tslib: 2.8.1
592 | transitivePeerDependencies:
593 | - supports-color
594 |
595 | chokidar@4.0.3:
596 | dependencies:
597 | readdirp: 4.0.2
598 |
599 | cookie@0.7.2: {}
600 |
601 | data-uri-to-buffer@2.0.2: {}
602 |
603 | date-fns@4.1.0: {}
604 |
605 | debug@4.4.0:
606 | dependencies:
607 | ms: 2.1.3
608 |
609 | defu@6.1.4: {}
610 |
611 | esbuild@0.17.19:
612 | optionalDependencies:
613 | '@esbuild/android-arm': 0.17.19
614 | '@esbuild/android-arm64': 0.17.19
615 | '@esbuild/android-x64': 0.17.19
616 | '@esbuild/darwin-arm64': 0.17.19
617 | '@esbuild/darwin-x64': 0.17.19
618 | '@esbuild/freebsd-arm64': 0.17.19
619 | '@esbuild/freebsd-x64': 0.17.19
620 | '@esbuild/linux-arm': 0.17.19
621 | '@esbuild/linux-arm64': 0.17.19
622 | '@esbuild/linux-ia32': 0.17.19
623 | '@esbuild/linux-loong64': 0.17.19
624 | '@esbuild/linux-mips64el': 0.17.19
625 | '@esbuild/linux-ppc64': 0.17.19
626 | '@esbuild/linux-riscv64': 0.17.19
627 | '@esbuild/linux-s390x': 0.17.19
628 | '@esbuild/linux-x64': 0.17.19
629 | '@esbuild/netbsd-x64': 0.17.19
630 | '@esbuild/openbsd-x64': 0.17.19
631 | '@esbuild/sunos-x64': 0.17.19
632 | '@esbuild/win32-arm64': 0.17.19
633 | '@esbuild/win32-ia32': 0.17.19
634 | '@esbuild/win32-x64': 0.17.19
635 |
636 | escape-string-regexp@4.0.0: {}
637 |
638 | estree-walker@0.6.1: {}
639 |
640 | exit-hook@2.2.1: {}
641 |
642 | fsevents@2.3.3:
643 | optional: true
644 |
645 | function-bind@1.1.2: {}
646 |
647 | get-source@2.0.12:
648 | dependencies:
649 | data-uri-to-buffer: 2.0.2
650 | source-map: 0.6.1
651 |
652 | glob-to-regexp@0.4.1: {}
653 |
654 | hasown@2.0.2:
655 | dependencies:
656 | function-bind: 1.1.2
657 |
658 | is-core-module@2.16.1:
659 | dependencies:
660 | hasown: 2.0.2
661 |
662 | itty-time@1.0.6: {}
663 |
664 | magic-string@0.25.9:
665 | dependencies:
666 | sourcemap-codec: 1.4.8
667 |
668 | mime@3.0.0: {}
669 |
670 | miniflare@3.20241218.0:
671 | dependencies:
672 | '@cspotcode/source-map-support': 0.8.1
673 | acorn: 8.14.0
674 | acorn-walk: 8.3.4
675 | capnp-ts: 0.7.0
676 | exit-hook: 2.2.1
677 | glob-to-regexp: 0.4.1
678 | stoppable: 1.1.0
679 | undici: 5.28.4
680 | workerd: 1.20241218.0
681 | ws: 8.18.0
682 | youch: 3.3.4
683 | zod: 3.24.1
684 | transitivePeerDependencies:
685 | - bufferutil
686 | - supports-color
687 | - utf-8-validate
688 |
689 | ms@2.1.3: {}
690 |
691 | mustache@4.2.0: {}
692 |
693 | nanoid@3.3.8: {}
694 |
695 | node-forge@1.3.1: {}
696 |
697 | ohash@1.1.4: {}
698 |
699 | path-parse@1.0.7: {}
700 |
701 | path-to-regexp@6.3.0: {}
702 |
703 | pathe@1.1.2: {}
704 |
705 | printable-characters@1.0.42: {}
706 |
707 | readdirp@4.0.2: {}
708 |
709 | resolve@1.22.10:
710 | dependencies:
711 | is-core-module: 2.16.1
712 | path-parse: 1.0.7
713 | supports-preserve-symlinks-flag: 1.0.0
714 |
715 | rollup-plugin-inject@3.0.2:
716 | dependencies:
717 | estree-walker: 0.6.1
718 | magic-string: 0.25.9
719 | rollup-pluginutils: 2.8.2
720 |
721 | rollup-plugin-node-polyfills@0.2.1:
722 | dependencies:
723 | rollup-plugin-inject: 3.0.2
724 |
725 | rollup-pluginutils@2.8.2:
726 | dependencies:
727 | estree-walker: 0.6.1
728 |
729 | selfsigned@2.4.1:
730 | dependencies:
731 | '@types/node-forge': 1.3.11
732 | node-forge: 1.3.1
733 |
734 | source-map@0.6.1: {}
735 |
736 | sourcemap-codec@1.4.8: {}
737 |
738 | stacktracey@2.1.8:
739 | dependencies:
740 | as-table: 1.0.55
741 | get-source: 2.0.12
742 |
743 | stoppable@1.1.0: {}
744 |
745 | supports-preserve-symlinks-flag@1.0.0: {}
746 |
747 | tslib@2.8.1: {}
748 |
749 | typescript@5.7.2: {}
750 |
751 | ufo@1.5.4: {}
752 |
753 | undici-types@6.20.0: {}
754 |
755 | undici@5.28.4:
756 | dependencies:
757 | '@fastify/busboy': 2.1.1
758 |
759 | unenv-nightly@2.0.0-20241204-140205-a5d5190:
760 | dependencies:
761 | defu: 6.1.4
762 | ohash: 1.1.4
763 | pathe: 1.1.2
764 | ufo: 1.5.4
765 |
766 | workerd@1.20241218.0:
767 | optionalDependencies:
768 | '@cloudflare/workerd-darwin-64': 1.20241218.0
769 | '@cloudflare/workerd-darwin-arm64': 1.20241218.0
770 | '@cloudflare/workerd-linux-64': 1.20241218.0
771 | '@cloudflare/workerd-linux-arm64': 1.20241218.0
772 | '@cloudflare/workerd-windows-64': 1.20241218.0
773 |
774 | wrangler@3.99.0(@cloudflare/workers-types@4.20241224.0):
775 | dependencies:
776 | '@cloudflare/kv-asset-handler': 0.3.4
777 | '@esbuild-plugins/node-globals-polyfill': 0.2.3(esbuild@0.17.19)
778 | '@esbuild-plugins/node-modules-polyfill': 0.2.2(esbuild@0.17.19)
779 | blake3-wasm: 2.1.5
780 | chokidar: 4.0.3
781 | date-fns: 4.1.0
782 | esbuild: 0.17.19
783 | itty-time: 1.0.6
784 | miniflare: 3.20241218.0
785 | nanoid: 3.3.8
786 | path-to-regexp: 6.3.0
787 | resolve: 1.22.10
788 | selfsigned: 2.4.1
789 | source-map: 0.6.1
790 | unenv: unenv-nightly@2.0.0-20241204-140205-a5d5190
791 | workerd: 1.20241218.0
792 | xxhash-wasm: 1.1.0
793 | optionalDependencies:
794 | '@cloudflare/workers-types': 4.20241224.0
795 | fsevents: 2.3.3
796 | transitivePeerDependencies:
797 | - bufferutil
798 | - supports-color
799 | - utf-8-validate
800 |
801 | ws@8.18.0: {}
802 |
803 | xxhash-wasm@1.1.0: {}
804 |
805 | youch@3.3.4:
806 | dependencies:
807 | cookie: 0.7.2
808 | mustache: 4.2.0
809 | stacktracey: 2.1.8
810 |
811 | zod@3.24.1: {}
812 |
--------------------------------------------------------------------------------
/examples/using-decorators/src/index.ts:
--------------------------------------------------------------------------------
1 | import { DurableObject } from "cloudflare:workers";
2 | import { diffable } from "diffable-objects";
3 |
4 | /**
5 | * Welcome to Cloudflare Workers! This is your first Durable Objects application.
6 | *
7 | * - Run `npm run dev` in your terminal to start a development server
8 | * - Open a browser tab at http://localhost:8787/ to see your Durable Object in action
9 | * - Run `npm run deploy` to publish your application
10 | *
11 | * Bind resources to your worker in `wrangler.toml`. After adding bindings, a type definition for the
12 | * `Env` object can be regenerated with `npm run cf-typegen`.
13 | *
14 | * Learn more at https://developers.cloudflare.com/durable-objects
15 | */
16 |
17 | /** A Durable Object's behavior is defined in an exported Javascript class */
18 | export class MyDurableObject extends DurableObject {
19 | /**
20 | * The state of a Durable Object is defined using the `diffable` decorator
21 | */
22 | @diffable
23 | #state = { count: 0 };
24 |
25 | /**
26 | * The constructor is invoked once upon creation of the Durable Object, i.e. the first call to
27 | * `DurableObjectStub::get` for a given identifier (no-op constructors can be omitted)
28 | *
29 | * @param ctx - The interface for interacting with Durable Object state
30 | * @param env - The interface to reference bindings declared in wrangler.toml
31 | */
32 | constructor(ctx: DurableObjectState, env: Env) {
33 | super(ctx, env);
34 | }
35 |
36 | /**
37 | * The Durable Object exposes an RPC method increment which will be invoked when when a Durable
38 | * Object instance receives a request from a Worker via the same method invocation on the stub
39 | *
40 | * @returns The number of times the method has been called on this Durable Object instance
41 | */
42 | async increment(): Promise {
43 | this.#state.count++;
44 | return this.#state.count;
45 | }
46 | }
47 |
48 | export default {
49 | /**
50 | * This is the standard fetch handler for a Cloudflare Worker
51 | *
52 | * @param request - The request submitted to the Worker from the client
53 | * @param env - The interface to reference bindings declared in wrangler.toml
54 | * @param ctx - The execution context of the Worker
55 | * @returns The response to be sent back to the client
56 | */
57 | async fetch(request, env, ctx): Promise {
58 | // We will create a `DurableObjectId` using the pathname from the Worker request
59 | // This id refers to a unique instance of our 'MyDurableObject' class above
60 | const id: DurableObjectId = env.MY_DURABLE_OBJECT.idFromName(new URL(request.url).pathname);
61 |
62 | // This stub creates a communication channel with the Durable Object instance
63 | // The Durable Object constructor will be invoked upon the first call for a given id
64 | const stub = env.MY_DURABLE_OBJECT.get(id);
65 |
66 | // We call the `increment()` RPC method on the stub to invoke the method on the remote
67 | // Durable Object instance
68 | const count = await stub.increment();
69 |
70 | return Response.json({ count });
71 | },
72 | } satisfies ExportedHandler;
73 |
--------------------------------------------------------------------------------
/examples/using-decorators/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */
4 |
5 | /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
6 | "target": "es2021",
7 | /* Specify a set of bundled library declaration files that describe the target runtime environment. */
8 | "lib": ["es2021"],
9 | /* Specify what JSX code is generated. */
10 | "jsx": "react-jsx",
11 |
12 | /* Specify what module code is generated. */
13 | "module": "es2022",
14 | /* Specify how TypeScript looks up a file from a given module specifier. */
15 | "moduleResolution": "node",
16 | /* Specify type package names to be included without being referenced in a source file. */
17 | "types": [
18 | "@cloudflare/workers-types/2023-07-01"
19 | ],
20 | /* Enable importing .json files */
21 | "resolveJsonModule": true,
22 |
23 | /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
24 | "allowJs": true,
25 | /* Enable error reporting in type-checked JavaScript files. */
26 | "checkJs": false,
27 |
28 | /* Disable emitting files from a compilation. */
29 | "noEmit": true,
30 |
31 | /* Ensure that each file can be safely transpiled without relying on other imports. */
32 | "isolatedModules": true,
33 | /* Allow 'import x from y' when a module doesn't have a default export. */
34 | "allowSyntheticDefaultImports": true,
35 | /* Ensure that casing is correct in imports. */
36 | "forceConsistentCasingInFileNames": true,
37 |
38 | /* Enable all strict type-checking options. */
39 | "strict": true,
40 |
41 | /* Skip type checking all .d.ts files. */
42 | "skipLibCheck": true
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/examples/using-decorators/worker-configuration.d.ts:
--------------------------------------------------------------------------------
1 | // Generated by Wrangler by running `wrangler types`
2 |
3 | interface Env {
4 | MY_DURABLE_OBJECT: DurableObjectNamespace;
5 | }
6 |
--------------------------------------------------------------------------------
/examples/using-decorators/wrangler.toml:
--------------------------------------------------------------------------------
1 | #:schema node_modules/wrangler/config-schema.json
2 | name = "using-decorators"
3 | main = "src/index.ts"
4 | compatibility_date = "2024-12-24"
5 |
6 | # Workers Logs
7 | # Docs: https://developers.cloudflare.com/workers/observability/logs/workers-logs/
8 | # Configuration: https://developers.cloudflare.com/workers/observability/logs/workers-logs/#enable-workers-logs
9 | [observability]
10 | enabled = true
11 |
12 | # Bind a Durable Object. Durable objects are a scale-to-zero compute primitive based on the actor model.
13 | # Durable Objects can live for as long as needed. Use these when you need a long-running "server", such as in realtime apps.
14 | # Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects
15 | [[durable_objects.bindings]]
16 | name = "MY_DURABLE_OBJECT"
17 | class_name = "MyDurableObject"
18 |
19 | # Durable Object migrations.
20 | # Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#migrations
21 | [[migrations]]
22 | tag = "v1"
23 | new_sqlite_classes = ["MyDurableObject"] # diffable-objects requires a class to use sqlite
24 |
--------------------------------------------------------------------------------
/examples/using-state/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = tab
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
11 | [*.yml]
12 | indent_style = space
13 |
--------------------------------------------------------------------------------
/examples/using-state/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 |
3 | logs
4 | _.log
5 | npm-debug.log_
6 | yarn-debug.log*
7 | yarn-error.log*
8 | lerna-debug.log*
9 | .pnpm-debug.log*
10 |
11 | # Diagnostic reports (https://nodejs.org/api/report.html)
12 |
13 | report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
14 |
15 | # Runtime data
16 |
17 | pids
18 | _.pid
19 | _.seed
20 | \*.pid.lock
21 |
22 | # Directory for instrumented libs generated by jscoverage/JSCover
23 |
24 | lib-cov
25 |
26 | # Coverage directory used by tools like istanbul
27 |
28 | coverage
29 | \*.lcov
30 |
31 | # nyc test coverage
32 |
33 | .nyc_output
34 |
35 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
36 |
37 | .grunt
38 |
39 | # Bower dependency directory (https://bower.io/)
40 |
41 | bower_components
42 |
43 | # node-waf configuration
44 |
45 | .lock-wscript
46 |
47 | # Compiled binary addons (https://nodejs.org/api/addons.html)
48 |
49 | build/Release
50 |
51 | # Dependency directories
52 |
53 | node_modules/
54 | jspm_packages/
55 |
56 | # Snowpack dependency directory (https://snowpack.dev/)
57 |
58 | web_modules/
59 |
60 | # TypeScript cache
61 |
62 | \*.tsbuildinfo
63 |
64 | # Optional npm cache directory
65 |
66 | .npm
67 |
68 | # Optional eslint cache
69 |
70 | .eslintcache
71 |
72 | # Optional stylelint cache
73 |
74 | .stylelintcache
75 |
76 | # Microbundle cache
77 |
78 | .rpt2_cache/
79 | .rts2_cache_cjs/
80 | .rts2_cache_es/
81 | .rts2_cache_umd/
82 |
83 | # Optional REPL history
84 |
85 | .node_repl_history
86 |
87 | # Output of 'npm pack'
88 |
89 | \*.tgz
90 |
91 | # Yarn Integrity file
92 |
93 | .yarn-integrity
94 |
95 | # dotenv environment variable files
96 |
97 | .env
98 | .env.development.local
99 | .env.test.local
100 | .env.production.local
101 | .env.local
102 |
103 | # parcel-bundler cache (https://parceljs.org/)
104 |
105 | .cache
106 | .parcel-cache
107 |
108 | # Next.js build output
109 |
110 | .next
111 | out
112 |
113 | # Nuxt.js build / generate output
114 |
115 | .nuxt
116 | dist
117 |
118 | # Gatsby files
119 |
120 | .cache/
121 |
122 | # Comment in the public line in if your project uses Gatsby and not Next.js
123 |
124 | # https://nextjs.org/blog/next-9-1#public-directory-support
125 |
126 | # public
127 |
128 | # vuepress build output
129 |
130 | .vuepress/dist
131 |
132 | # vuepress v2.x temp and cache directory
133 |
134 | .temp
135 | .cache
136 |
137 | # Docusaurus cache and generated files
138 |
139 | .docusaurus
140 |
141 | # Serverless directories
142 |
143 | .serverless/
144 |
145 | # FuseBox cache
146 |
147 | .fusebox/
148 |
149 | # DynamoDB Local files
150 |
151 | .dynamodb/
152 |
153 | # TernJS port file
154 |
155 | .tern-port
156 |
157 | # Stores VSCode versions used for testing VSCode extensions
158 |
159 | .vscode-test
160 |
161 | # yarn v2
162 |
163 | .yarn/cache
164 | .yarn/unplugged
165 | .yarn/build-state.yml
166 | .yarn/install-state.gz
167 | .pnp.\*
168 |
169 | # wrangler project
170 |
171 | .dev.vars
172 | .wrangler/
173 |
--------------------------------------------------------------------------------
/examples/using-state/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 140,
3 | "singleQuote": true,
4 | "semi": true,
5 | "useTabs": true
6 | }
7 |
--------------------------------------------------------------------------------
/examples/using-state/README.md:
--------------------------------------------------------------------------------
1 | # using-decorators
2 |
3 | This sample updates the [Hello World Durable Object](https://github.com/cloudflare/workers-sdk/tree/main/packages/create-cloudflare/templates/hello-world-durable-object/ts) template from Cloudflare to use `diffable-objects` using the `state` function.
4 |
5 | ## Try it out
6 |
7 | ```
8 | pnpm dev
9 | ```
--------------------------------------------------------------------------------
/examples/using-state/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "using-state",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "deploy": "wrangler deploy",
7 | "dev": "wrangler dev",
8 | "start": "wrangler dev",
9 | "cf-typegen": "wrangler types"
10 | },
11 | "devDependencies": {
12 | "@cloudflare/workers-types": "^4.20241224.0",
13 | "typescript": "^5.5.2",
14 | "wrangler": "^3.60.3"
15 | },
16 | "dependencies": {
17 | "diffable-objects": "0.1.1"
18 | }
19 | }
--------------------------------------------------------------------------------
/examples/using-state/src/index.ts:
--------------------------------------------------------------------------------
1 | import { DurableObject } from "cloudflare:workers";
2 | import { state } from "diffable-objects";
3 |
4 | /**
5 | * Welcome to Cloudflare Workers! This is your first Durable Objects application.
6 | *
7 | * - Run `npm run dev` in your terminal to start a development server
8 | * - Open a browser tab at http://localhost:8787/ to see your Durable Object in action
9 | * - Run `npm run deploy` to publish your application
10 | *
11 | * Bind resources to your worker in `wrangler.toml`. After adding bindings, a type definition for the
12 | * `Env` object can be regenerated with `npm run cf-typegen`.
13 | *
14 | * Learn more at https://developers.cloudflare.com/durable-objects
15 | */
16 |
17 | /** A Durable Object's behavior is defined in an exported Javascript class */
18 | export class MyDurableObject extends DurableObject {
19 | #state = state(this.ctx, "state", { count: 0 });
20 |
21 | /**
22 | * The constructor is invoked once upon creation of the Durable Object, i.e. the first call to
23 | * `DurableObjectStub::get` for a given identifier (no-op constructors can be omitted)
24 | *
25 | * @param ctx - The interface for interacting with Durable Object state
26 | * @param env - The interface to reference bindings declared in wrangler.toml
27 | */
28 | constructor(ctx: DurableObjectState, env: Env) {
29 | super(ctx, env);
30 | }
31 |
32 | /**
33 | * The Durable Object exposes an RPC method increment which will be invoked when when a Durable
34 | * Object instance receives a request from a Worker via the same method invocation on the stub
35 | *
36 | * @returns The number of times the method has been called on this Durable Object instance
37 | */
38 | async increment(): Promise {
39 | this.#state.count++;
40 | return this.#state.count;
41 | }
42 | }
43 |
44 | export default {
45 | /**
46 | * This is the standard fetch handler for a Cloudflare Worker
47 | *
48 | * @param request - The request submitted to the Worker from the client
49 | * @param env - The interface to reference bindings declared in wrangler.toml
50 | * @param ctx - The execution context of the Worker
51 | * @returns The response to be sent back to the client
52 | */
53 | async fetch(request, env, ctx): Promise {
54 | // We will create a `DurableObjectId` using the pathname from the Worker request
55 | // This id refers to a unique instance of our 'MyDurableObject' class above
56 | const id: DurableObjectId = env.MY_DURABLE_OBJECT.idFromName(new URL(request.url).pathname);
57 |
58 | // This stub creates a communication channel with the Durable Object instance
59 | // The Durable Object constructor will be invoked upon the first call for a given id
60 | const stub = env.MY_DURABLE_OBJECT.get(id);
61 |
62 | // We call the `increment()` RPC method on the stub to invoke the method on the remote
63 | // Durable Object instance
64 | const count = await stub.increment();
65 |
66 | return Response.json({ count });
67 | },
68 | } satisfies ExportedHandler;
69 |
--------------------------------------------------------------------------------
/examples/using-state/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */
4 |
5 | /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
6 | "target": "es2021",
7 | /* Specify a set of bundled library declaration files that describe the target runtime environment. */
8 | "lib": ["es2021"],
9 | /* Specify what JSX code is generated. */
10 | "jsx": "react-jsx",
11 |
12 | /* Specify what module code is generated. */
13 | "module": "es2022",
14 | /* Specify how TypeScript looks up a file from a given module specifier. */
15 | "moduleResolution": "node",
16 | /* Specify type package names to be included without being referenced in a source file. */
17 | "types": [
18 | "@cloudflare/workers-types/2023-07-01"
19 | ],
20 | /* Enable importing .json files */
21 | "resolveJsonModule": true,
22 |
23 | /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
24 | "allowJs": true,
25 | /* Enable error reporting in type-checked JavaScript files. */
26 | "checkJs": false,
27 |
28 | /* Disable emitting files from a compilation. */
29 | "noEmit": true,
30 |
31 | /* Ensure that each file can be safely transpiled without relying on other imports. */
32 | "isolatedModules": true,
33 | /* Allow 'import x from y' when a module doesn't have a default export. */
34 | "allowSyntheticDefaultImports": true,
35 | /* Ensure that casing is correct in imports. */
36 | "forceConsistentCasingInFileNames": true,
37 |
38 | /* Enable all strict type-checking options. */
39 | "strict": true,
40 |
41 | /* Skip type checking all .d.ts files. */
42 | "skipLibCheck": true
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/examples/using-state/worker-configuration.d.ts:
--------------------------------------------------------------------------------
1 | // Generated by Wrangler by running `wrangler types`
2 |
3 | interface Env {
4 | MY_DURABLE_OBJECT: DurableObjectNamespace;
5 | }
6 |
--------------------------------------------------------------------------------
/examples/using-state/wrangler.toml:
--------------------------------------------------------------------------------
1 | #:schema node_modules/wrangler/config-schema.json
2 | name = "using-state"
3 | main = "src/index.ts"
4 | compatibility_date = "2024-12-24"
5 |
6 | # Workers Logs
7 | # Docs: https://developers.cloudflare.com/workers/observability/logs/workers-logs/
8 | # Configuration: https://developers.cloudflare.com/workers/observability/logs/workers-logs/#enable-workers-logs
9 | [observability]
10 | enabled = true
11 |
12 | # Bind a Durable Object. Durable objects are a scale-to-zero compute primitive based on the actor model.
13 | # Durable Objects can live for as long as needed. Use these when you need a long-running "server", such as in realtime apps.
14 | # Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects
15 | [[durable_objects.bindings]]
16 | name = "MY_DURABLE_OBJECT"
17 | class_name = "MyDurableObject"
18 |
19 | # Durable Object migrations.
20 | # Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#migrations
21 | [[migrations]]
22 | tag = "v1"
23 | new_sqlite_classes = ["MyDurableObject"] # diffable-objects requires a class to use sqlite
24 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "diffable-objects",
3 | "version": "0.1.1",
4 | "description": "A package for dynamic state tracking for Cloudflare's Durable Objects using SQLite",
5 | "author": "Zeb Piasecki ",
6 | "repository": "https://github.com/zebp/diffable-objects",
7 | "license": "MIT",
8 | "keywords": ["cloudflare", "workers", "durable-objects", "sqlite"],
9 | "type": "module",
10 | "main": "dist/index.js",
11 | "types": "dist/index.d.ts",
12 | "exports": {
13 | ".": {
14 | "import": "./dist/index.js",
15 | "types": "./dist/index.d.ts"
16 | }
17 | },
18 | "scripts": {
19 | "build": "tsc -p tsconfig.build.json",
20 | "build:watch": "tsc -p tsconfig.build.json -w",
21 | "format": "biome format ./**/*.ts --write",
22 | "check:lint": "biome lint ./**/*.ts",
23 | "check:format": "biome format ./**/*.ts",
24 | "test": "vitest run"
25 | },
26 | "devDependencies": {
27 | "@biomejs/biome": "1.9.4",
28 | "@cloudflare/vitest-pool-workers": "^0.5.40",
29 | "@cloudflare/workers-types": "^4.20241224.0",
30 | "typescript": "^5.7.2",
31 | "vitest": "2.1.8"
32 | },
33 | "dependencies": {
34 | "json-diff-ts": "^4.1.0"
35 | },
36 | "pnpm": {
37 | "overrides": {
38 | "lodash": "npm:@technically/lodash"
39 | }
40 | },
41 | "files": [
42 | "dist",
43 | "LICENSE"
44 | ]
45 | }
46 |
--------------------------------------------------------------------------------
/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: '9.0'
2 |
3 | settings:
4 | autoInstallPeers: true
5 | excludeLinksFromLockfile: false
6 |
7 | overrides:
8 | lodash: npm:@technically/lodash
9 |
10 | importers:
11 |
12 | .:
13 | dependencies:
14 | json-diff-ts:
15 | specifier: ^4.1.0
16 | version: 4.1.0
17 | devDependencies:
18 | '@biomejs/biome':
19 | specifier: 1.9.4
20 | version: 1.9.4
21 | '@cloudflare/vitest-pool-workers':
22 | specifier: ^0.5.40
23 | version: 0.5.40(@cloudflare/workers-types@4.20241224.0)(@vitest/runner@2.1.8)(@vitest/snapshot@2.1.8)(vitest@2.1.8(@types/node@22.10.2))
24 | '@cloudflare/workers-types':
25 | specifier: ^4.20241224.0
26 | version: 4.20241224.0
27 | typescript:
28 | specifier: ^5.7.2
29 | version: 5.7.2
30 | vitest:
31 | specifier: 2.1.8
32 | version: 2.1.8(@types/node@22.10.2)
33 |
34 | examples/using-decorators:
35 | dependencies:
36 | diffable-objects:
37 | specifier: ^0.1.1
38 | version: 0.1.1
39 | devDependencies:
40 | '@cloudflare/workers-types':
41 | specifier: ^4.20241224.0
42 | version: 4.20241224.0
43 | typescript:
44 | specifier: ^5.5.2
45 | version: 5.7.2
46 | wrangler:
47 | specifier: 0.0.0-dc669c404
48 | version: 0.0.0-dc669c404(@cloudflare/workers-types@4.20241224.0)
49 |
50 | examples/using-state:
51 | dependencies:
52 | diffable-objects:
53 | specifier: 0.1.1
54 | version: 0.1.1
55 | devDependencies:
56 | '@cloudflare/workers-types':
57 | specifier: ^4.20241224.0
58 | version: 4.20241224.0
59 | typescript:
60 | specifier: ^5.5.2
61 | version: 5.7.2
62 | wrangler:
63 | specifier: ^3.60.3
64 | version: 3.99.0(@cloudflare/workers-types@4.20241224.0)
65 |
66 | packages:
67 |
68 | '@biomejs/biome@1.9.4':
69 | resolution: {integrity: sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==}
70 | engines: {node: '>=14.21.3'}
71 | hasBin: true
72 |
73 | '@biomejs/cli-darwin-arm64@1.9.4':
74 | resolution: {integrity: sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw==}
75 | engines: {node: '>=14.21.3'}
76 | cpu: [arm64]
77 | os: [darwin]
78 |
79 | '@biomejs/cli-darwin-x64@1.9.4':
80 | resolution: {integrity: sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg==}
81 | engines: {node: '>=14.21.3'}
82 | cpu: [x64]
83 | os: [darwin]
84 |
85 | '@biomejs/cli-linux-arm64-musl@1.9.4':
86 | resolution: {integrity: sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA==}
87 | engines: {node: '>=14.21.3'}
88 | cpu: [arm64]
89 | os: [linux]
90 |
91 | '@biomejs/cli-linux-arm64@1.9.4':
92 | resolution: {integrity: sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==}
93 | engines: {node: '>=14.21.3'}
94 | cpu: [arm64]
95 | os: [linux]
96 |
97 | '@biomejs/cli-linux-x64-musl@1.9.4':
98 | resolution: {integrity: sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==}
99 | engines: {node: '>=14.21.3'}
100 | cpu: [x64]
101 | os: [linux]
102 |
103 | '@biomejs/cli-linux-x64@1.9.4':
104 | resolution: {integrity: sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==}
105 | engines: {node: '>=14.21.3'}
106 | cpu: [x64]
107 | os: [linux]
108 |
109 | '@biomejs/cli-win32-arm64@1.9.4':
110 | resolution: {integrity: sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==}
111 | engines: {node: '>=14.21.3'}
112 | cpu: [arm64]
113 | os: [win32]
114 |
115 | '@biomejs/cli-win32-x64@1.9.4':
116 | resolution: {integrity: sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA==}
117 | engines: {node: '>=14.21.3'}
118 | cpu: [x64]
119 | os: [win32]
120 |
121 | '@cloudflare/kv-asset-handler@0.3.4':
122 | resolution: {integrity: sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q==}
123 | engines: {node: '>=16.13'}
124 |
125 | '@cloudflare/vitest-pool-workers@0.5.40':
126 | resolution: {integrity: sha512-aBHNj55l6G07+ZJuhJsuElDYOEKcGJ4nEdE+X7XmyCRxiw7eRjc1iPQOfEFqprzKQ/2tPEOO8hL0mgRIgt8K3g==}
127 | peerDependencies:
128 | '@vitest/runner': 2.0.x - 2.1.x
129 | '@vitest/snapshot': 2.0.x - 2.1.x
130 | vitest: 2.0.x - 2.1.x
131 |
132 | '@cloudflare/workerd-darwin-64@1.20241106.1':
133 | resolution: {integrity: sha512-zxvaToi1m0qzAScrxFt7UvFVqU8DxrCO2CinM1yQkv5no7pA1HolpIrwZ0xOhR3ny64Is2s/J6BrRjpO5dM9Zw==}
134 | engines: {node: '>=16'}
135 | cpu: [x64]
136 | os: [darwin]
137 |
138 | '@cloudflare/workerd-darwin-64@1.20241218.0':
139 | resolution: {integrity: sha512-8rveQoxtUvlmORKqTWgjv2ycM8uqWox0u9evn3zd2iWKdou5sncFwH517ZRLI3rq9P31ZLmCQBZ0gloFsTeY6w==}
140 | engines: {node: '>=16'}
141 | cpu: [x64]
142 | os: [darwin]
143 |
144 | '@cloudflare/workerd-darwin-arm64@1.20241106.1':
145 | resolution: {integrity: sha512-j3dg/42D/bPgfNP3cRUBxF+4waCKO/5YKwXNj+lnVOwHxDu+ne5pFw9TIkKYcWTcwn0ZUkbNZNM5rhJqRn4xbg==}
146 | engines: {node: '>=16'}
147 | cpu: [arm64]
148 | os: [darwin]
149 |
150 | '@cloudflare/workerd-darwin-arm64@1.20241218.0':
151 | resolution: {integrity: sha512-be59Ad9nmM9lCkhHqmTs/uZ3JVZt8NJ9Z0PY+B0xnc5z6WwmV2lj0RVLtq7xJhQsQJA189zt5rXqDP6J+2mu7Q==}
152 | engines: {node: '>=16'}
153 | cpu: [arm64]
154 | os: [darwin]
155 |
156 | '@cloudflare/workerd-linux-64@1.20241106.1':
157 | resolution: {integrity: sha512-Ih+Ye8E1DMBXcKrJktGfGztFqHKaX1CeByqshmTbODnWKHt6O65ax3oTecUwyC0+abuyraOpAtdhHNpFMhUkmw==}
158 | engines: {node: '>=16'}
159 | cpu: [x64]
160 | os: [linux]
161 |
162 | '@cloudflare/workerd-linux-64@1.20241218.0':
163 | resolution: {integrity: sha512-MzpSBcfZXRxrYWxQ4pVDYDrUbkQuM62ssl4ZtHH8J35OAeGsWFAYji6MkS2SpVwVcvacPwJXIF4JSzp4xKImKw==}
164 | engines: {node: '>=16'}
165 | cpu: [x64]
166 | os: [linux]
167 |
168 | '@cloudflare/workerd-linux-arm64@1.20241106.1':
169 | resolution: {integrity: sha512-mdQFPk4+14Yywn7n1xIzI+6olWM8Ybz10R7H3h+rk0XulMumCWUCy1CzIDauOx6GyIcSgKIibYMssVHZR30ObA==}
170 | engines: {node: '>=16'}
171 | cpu: [arm64]
172 | os: [linux]
173 |
174 | '@cloudflare/workerd-linux-arm64@1.20241218.0':
175 | resolution: {integrity: sha512-RIuJjPxpNqvwIs52vQsXeRMttvhIjgg9NLjjFa3jK8Ijnj8c3ZDru9Wqi48lJP07yDFIRr4uDMMqh/y29YQi2A==}
176 | engines: {node: '>=16'}
177 | cpu: [arm64]
178 | os: [linux]
179 |
180 | '@cloudflare/workerd-windows-64@1.20241106.1':
181 | resolution: {integrity: sha512-4rtcss31E/Rb/PeFocZfr+B9i1MdrkhsTBWizh8siNR4KMmkslU2xs2wPaH1z8+ErxkOsHrKRa5EPLh5rIiFeg==}
182 | engines: {node: '>=16'}
183 | cpu: [x64]
184 | os: [win32]
185 |
186 | '@cloudflare/workerd-windows-64@1.20241218.0':
187 | resolution: {integrity: sha512-tO1VjlvK3F6Yb2d1jgEy/QBYl//9Pyv3K0j+lq8Eu7qdfm0IgKwSRgDWLept84/qmNsQfausZ4JdNGxTf9xsxQ==}
188 | engines: {node: '>=16'}
189 | cpu: [x64]
190 | os: [win32]
191 |
192 | '@cloudflare/workers-shared@0.8.0':
193 | resolution: {integrity: sha512-1OvFkNtslaMZAJsaocTmbACApgmWv55uLpNj50Pn2MGcxdAjpqykXJFQw5tKc+lGV9TDZh9oO3Rsk17IEQDzIg==}
194 | engines: {node: '>=16.7.0'}
195 |
196 | '@cloudflare/workers-types@4.20241224.0':
197 | resolution: {integrity: sha512-1ZmFc8qqM7S/HUGmLplc4P8n8DoMqiJmc47r9Lr7VbuaotoqCXVljz09w1V1mc4K3pbFPgvqSy4XYStZ08HrlQ==}
198 |
199 | '@cspotcode/source-map-support@0.8.1':
200 | resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
201 | engines: {node: '>=12'}
202 |
203 | '@esbuild-plugins/node-globals-polyfill@0.2.3':
204 | resolution: {integrity: sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw==}
205 | peerDependencies:
206 | esbuild: '*'
207 |
208 | '@esbuild-plugins/node-modules-polyfill@0.2.2':
209 | resolution: {integrity: sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA==}
210 | peerDependencies:
211 | esbuild: '*'
212 |
213 | '@esbuild/aix-ppc64@0.21.5':
214 | resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
215 | engines: {node: '>=12'}
216 | cpu: [ppc64]
217 | os: [aix]
218 |
219 | '@esbuild/aix-ppc64@0.24.0':
220 | resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==}
221 | engines: {node: '>=18'}
222 | cpu: [ppc64]
223 | os: [aix]
224 |
225 | '@esbuild/android-arm64@0.17.19':
226 | resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==}
227 | engines: {node: '>=12'}
228 | cpu: [arm64]
229 | os: [android]
230 |
231 | '@esbuild/android-arm64@0.21.5':
232 | resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
233 | engines: {node: '>=12'}
234 | cpu: [arm64]
235 | os: [android]
236 |
237 | '@esbuild/android-arm64@0.24.0':
238 | resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==}
239 | engines: {node: '>=18'}
240 | cpu: [arm64]
241 | os: [android]
242 |
243 | '@esbuild/android-arm@0.17.19':
244 | resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==}
245 | engines: {node: '>=12'}
246 | cpu: [arm]
247 | os: [android]
248 |
249 | '@esbuild/android-arm@0.21.5':
250 | resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
251 | engines: {node: '>=12'}
252 | cpu: [arm]
253 | os: [android]
254 |
255 | '@esbuild/android-arm@0.24.0':
256 | resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==}
257 | engines: {node: '>=18'}
258 | cpu: [arm]
259 | os: [android]
260 |
261 | '@esbuild/android-x64@0.17.19':
262 | resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==}
263 | engines: {node: '>=12'}
264 | cpu: [x64]
265 | os: [android]
266 |
267 | '@esbuild/android-x64@0.21.5':
268 | resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
269 | engines: {node: '>=12'}
270 | cpu: [x64]
271 | os: [android]
272 |
273 | '@esbuild/android-x64@0.24.0':
274 | resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==}
275 | engines: {node: '>=18'}
276 | cpu: [x64]
277 | os: [android]
278 |
279 | '@esbuild/darwin-arm64@0.17.19':
280 | resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==}
281 | engines: {node: '>=12'}
282 | cpu: [arm64]
283 | os: [darwin]
284 |
285 | '@esbuild/darwin-arm64@0.21.5':
286 | resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
287 | engines: {node: '>=12'}
288 | cpu: [arm64]
289 | os: [darwin]
290 |
291 | '@esbuild/darwin-arm64@0.24.0':
292 | resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==}
293 | engines: {node: '>=18'}
294 | cpu: [arm64]
295 | os: [darwin]
296 |
297 | '@esbuild/darwin-x64@0.17.19':
298 | resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==}
299 | engines: {node: '>=12'}
300 | cpu: [x64]
301 | os: [darwin]
302 |
303 | '@esbuild/darwin-x64@0.21.5':
304 | resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
305 | engines: {node: '>=12'}
306 | cpu: [x64]
307 | os: [darwin]
308 |
309 | '@esbuild/darwin-x64@0.24.0':
310 | resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==}
311 | engines: {node: '>=18'}
312 | cpu: [x64]
313 | os: [darwin]
314 |
315 | '@esbuild/freebsd-arm64@0.17.19':
316 | resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==}
317 | engines: {node: '>=12'}
318 | cpu: [arm64]
319 | os: [freebsd]
320 |
321 | '@esbuild/freebsd-arm64@0.21.5':
322 | resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
323 | engines: {node: '>=12'}
324 | cpu: [arm64]
325 | os: [freebsd]
326 |
327 | '@esbuild/freebsd-arm64@0.24.0':
328 | resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==}
329 | engines: {node: '>=18'}
330 | cpu: [arm64]
331 | os: [freebsd]
332 |
333 | '@esbuild/freebsd-x64@0.17.19':
334 | resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==}
335 | engines: {node: '>=12'}
336 | cpu: [x64]
337 | os: [freebsd]
338 |
339 | '@esbuild/freebsd-x64@0.21.5':
340 | resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
341 | engines: {node: '>=12'}
342 | cpu: [x64]
343 | os: [freebsd]
344 |
345 | '@esbuild/freebsd-x64@0.24.0':
346 | resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==}
347 | engines: {node: '>=18'}
348 | cpu: [x64]
349 | os: [freebsd]
350 |
351 | '@esbuild/linux-arm64@0.17.19':
352 | resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==}
353 | engines: {node: '>=12'}
354 | cpu: [arm64]
355 | os: [linux]
356 |
357 | '@esbuild/linux-arm64@0.21.5':
358 | resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
359 | engines: {node: '>=12'}
360 | cpu: [arm64]
361 | os: [linux]
362 |
363 | '@esbuild/linux-arm64@0.24.0':
364 | resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==}
365 | engines: {node: '>=18'}
366 | cpu: [arm64]
367 | os: [linux]
368 |
369 | '@esbuild/linux-arm@0.17.19':
370 | resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==}
371 | engines: {node: '>=12'}
372 | cpu: [arm]
373 | os: [linux]
374 |
375 | '@esbuild/linux-arm@0.21.5':
376 | resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
377 | engines: {node: '>=12'}
378 | cpu: [arm]
379 | os: [linux]
380 |
381 | '@esbuild/linux-arm@0.24.0':
382 | resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==}
383 | engines: {node: '>=18'}
384 | cpu: [arm]
385 | os: [linux]
386 |
387 | '@esbuild/linux-ia32@0.17.19':
388 | resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==}
389 | engines: {node: '>=12'}
390 | cpu: [ia32]
391 | os: [linux]
392 |
393 | '@esbuild/linux-ia32@0.21.5':
394 | resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
395 | engines: {node: '>=12'}
396 | cpu: [ia32]
397 | os: [linux]
398 |
399 | '@esbuild/linux-ia32@0.24.0':
400 | resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==}
401 | engines: {node: '>=18'}
402 | cpu: [ia32]
403 | os: [linux]
404 |
405 | '@esbuild/linux-loong64@0.17.19':
406 | resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==}
407 | engines: {node: '>=12'}
408 | cpu: [loong64]
409 | os: [linux]
410 |
411 | '@esbuild/linux-loong64@0.21.5':
412 | resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
413 | engines: {node: '>=12'}
414 | cpu: [loong64]
415 | os: [linux]
416 |
417 | '@esbuild/linux-loong64@0.24.0':
418 | resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==}
419 | engines: {node: '>=18'}
420 | cpu: [loong64]
421 | os: [linux]
422 |
423 | '@esbuild/linux-mips64el@0.17.19':
424 | resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==}
425 | engines: {node: '>=12'}
426 | cpu: [mips64el]
427 | os: [linux]
428 |
429 | '@esbuild/linux-mips64el@0.21.5':
430 | resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
431 | engines: {node: '>=12'}
432 | cpu: [mips64el]
433 | os: [linux]
434 |
435 | '@esbuild/linux-mips64el@0.24.0':
436 | resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==}
437 | engines: {node: '>=18'}
438 | cpu: [mips64el]
439 | os: [linux]
440 |
441 | '@esbuild/linux-ppc64@0.17.19':
442 | resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==}
443 | engines: {node: '>=12'}
444 | cpu: [ppc64]
445 | os: [linux]
446 |
447 | '@esbuild/linux-ppc64@0.21.5':
448 | resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
449 | engines: {node: '>=12'}
450 | cpu: [ppc64]
451 | os: [linux]
452 |
453 | '@esbuild/linux-ppc64@0.24.0':
454 | resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==}
455 | engines: {node: '>=18'}
456 | cpu: [ppc64]
457 | os: [linux]
458 |
459 | '@esbuild/linux-riscv64@0.17.19':
460 | resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==}
461 | engines: {node: '>=12'}
462 | cpu: [riscv64]
463 | os: [linux]
464 |
465 | '@esbuild/linux-riscv64@0.21.5':
466 | resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
467 | engines: {node: '>=12'}
468 | cpu: [riscv64]
469 | os: [linux]
470 |
471 | '@esbuild/linux-riscv64@0.24.0':
472 | resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==}
473 | engines: {node: '>=18'}
474 | cpu: [riscv64]
475 | os: [linux]
476 |
477 | '@esbuild/linux-s390x@0.17.19':
478 | resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==}
479 | engines: {node: '>=12'}
480 | cpu: [s390x]
481 | os: [linux]
482 |
483 | '@esbuild/linux-s390x@0.21.5':
484 | resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
485 | engines: {node: '>=12'}
486 | cpu: [s390x]
487 | os: [linux]
488 |
489 | '@esbuild/linux-s390x@0.24.0':
490 | resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==}
491 | engines: {node: '>=18'}
492 | cpu: [s390x]
493 | os: [linux]
494 |
495 | '@esbuild/linux-x64@0.17.19':
496 | resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==}
497 | engines: {node: '>=12'}
498 | cpu: [x64]
499 | os: [linux]
500 |
501 | '@esbuild/linux-x64@0.21.5':
502 | resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
503 | engines: {node: '>=12'}
504 | cpu: [x64]
505 | os: [linux]
506 |
507 | '@esbuild/linux-x64@0.24.0':
508 | resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==}
509 | engines: {node: '>=18'}
510 | cpu: [x64]
511 | os: [linux]
512 |
513 | '@esbuild/netbsd-x64@0.17.19':
514 | resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==}
515 | engines: {node: '>=12'}
516 | cpu: [x64]
517 | os: [netbsd]
518 |
519 | '@esbuild/netbsd-x64@0.21.5':
520 | resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
521 | engines: {node: '>=12'}
522 | cpu: [x64]
523 | os: [netbsd]
524 |
525 | '@esbuild/netbsd-x64@0.24.0':
526 | resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==}
527 | engines: {node: '>=18'}
528 | cpu: [x64]
529 | os: [netbsd]
530 |
531 | '@esbuild/openbsd-arm64@0.24.0':
532 | resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==}
533 | engines: {node: '>=18'}
534 | cpu: [arm64]
535 | os: [openbsd]
536 |
537 | '@esbuild/openbsd-x64@0.17.19':
538 | resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==}
539 | engines: {node: '>=12'}
540 | cpu: [x64]
541 | os: [openbsd]
542 |
543 | '@esbuild/openbsd-x64@0.21.5':
544 | resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
545 | engines: {node: '>=12'}
546 | cpu: [x64]
547 | os: [openbsd]
548 |
549 | '@esbuild/openbsd-x64@0.24.0':
550 | resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==}
551 | engines: {node: '>=18'}
552 | cpu: [x64]
553 | os: [openbsd]
554 |
555 | '@esbuild/sunos-x64@0.17.19':
556 | resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==}
557 | engines: {node: '>=12'}
558 | cpu: [x64]
559 | os: [sunos]
560 |
561 | '@esbuild/sunos-x64@0.21.5':
562 | resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
563 | engines: {node: '>=12'}
564 | cpu: [x64]
565 | os: [sunos]
566 |
567 | '@esbuild/sunos-x64@0.24.0':
568 | resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==}
569 | engines: {node: '>=18'}
570 | cpu: [x64]
571 | os: [sunos]
572 |
573 | '@esbuild/win32-arm64@0.17.19':
574 | resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==}
575 | engines: {node: '>=12'}
576 | cpu: [arm64]
577 | os: [win32]
578 |
579 | '@esbuild/win32-arm64@0.21.5':
580 | resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
581 | engines: {node: '>=12'}
582 | cpu: [arm64]
583 | os: [win32]
584 |
585 | '@esbuild/win32-arm64@0.24.0':
586 | resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==}
587 | engines: {node: '>=18'}
588 | cpu: [arm64]
589 | os: [win32]
590 |
591 | '@esbuild/win32-ia32@0.17.19':
592 | resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==}
593 | engines: {node: '>=12'}
594 | cpu: [ia32]
595 | os: [win32]
596 |
597 | '@esbuild/win32-ia32@0.21.5':
598 | resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
599 | engines: {node: '>=12'}
600 | cpu: [ia32]
601 | os: [win32]
602 |
603 | '@esbuild/win32-ia32@0.24.0':
604 | resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==}
605 | engines: {node: '>=18'}
606 | cpu: [ia32]
607 | os: [win32]
608 |
609 | '@esbuild/win32-x64@0.17.19':
610 | resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==}
611 | engines: {node: '>=12'}
612 | cpu: [x64]
613 | os: [win32]
614 |
615 | '@esbuild/win32-x64@0.21.5':
616 | resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
617 | engines: {node: '>=12'}
618 | cpu: [x64]
619 | os: [win32]
620 |
621 | '@esbuild/win32-x64@0.24.0':
622 | resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==}
623 | engines: {node: '>=18'}
624 | cpu: [x64]
625 | os: [win32]
626 |
627 | '@fastify/busboy@2.1.1':
628 | resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==}
629 | engines: {node: '>=14'}
630 |
631 | '@jridgewell/resolve-uri@3.1.2':
632 | resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
633 | engines: {node: '>=6.0.0'}
634 |
635 | '@jridgewell/sourcemap-codec@1.5.0':
636 | resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
637 |
638 | '@jridgewell/trace-mapping@0.3.9':
639 | resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
640 |
641 | '@rollup/rollup-android-arm-eabi@4.29.1':
642 | resolution: {integrity: sha512-ssKhA8RNltTZLpG6/QNkCSge+7mBQGUqJRisZ2MDQcEGaK93QESEgWK2iOpIDZ7k9zPVkG5AS3ksvD5ZWxmItw==}
643 | cpu: [arm]
644 | os: [android]
645 |
646 | '@rollup/rollup-android-arm64@4.29.1':
647 | resolution: {integrity: sha512-CaRfrV0cd+NIIcVVN/jx+hVLN+VRqnuzLRmfmlzpOzB87ajixsN/+9L5xNmkaUUvEbI5BmIKS+XTwXsHEb65Ew==}
648 | cpu: [arm64]
649 | os: [android]
650 |
651 | '@rollup/rollup-darwin-arm64@4.29.1':
652 | resolution: {integrity: sha512-2ORr7T31Y0Mnk6qNuwtyNmy14MunTAMx06VAPI6/Ju52W10zk1i7i5U3vlDRWjhOI5quBcrvhkCHyF76bI7kEw==}
653 | cpu: [arm64]
654 | os: [darwin]
655 |
656 | '@rollup/rollup-darwin-x64@4.29.1':
657 | resolution: {integrity: sha512-j/Ej1oanzPjmN0tirRd5K2/nncAhS9W6ICzgxV+9Y5ZsP0hiGhHJXZ2JQ53iSSjj8m6cRY6oB1GMzNn2EUt6Ng==}
658 | cpu: [x64]
659 | os: [darwin]
660 |
661 | '@rollup/rollup-freebsd-arm64@4.29.1':
662 | resolution: {integrity: sha512-91C//G6Dm/cv724tpt7nTyP+JdN12iqeXGFM1SqnljCmi5yTXriH7B1r8AD9dAZByHpKAumqP1Qy2vVNIdLZqw==}
663 | cpu: [arm64]
664 | os: [freebsd]
665 |
666 | '@rollup/rollup-freebsd-x64@4.29.1':
667 | resolution: {integrity: sha512-hEioiEQ9Dec2nIRoeHUP6hr1PSkXzQaCUyqBDQ9I9ik4gCXQZjJMIVzoNLBRGet+hIUb3CISMh9KXuCcWVW/8w==}
668 | cpu: [x64]
669 | os: [freebsd]
670 |
671 | '@rollup/rollup-linux-arm-gnueabihf@4.29.1':
672 | resolution: {integrity: sha512-Py5vFd5HWYN9zxBv3WMrLAXY3yYJ6Q/aVERoeUFwiDGiMOWsMs7FokXihSOaT/PMWUty/Pj60XDQndK3eAfE6A==}
673 | cpu: [arm]
674 | os: [linux]
675 |
676 | '@rollup/rollup-linux-arm-musleabihf@4.29.1':
677 | resolution: {integrity: sha512-RiWpGgbayf7LUcuSNIbahr0ys2YnEERD4gYdISA06wa0i8RALrnzflh9Wxii7zQJEB2/Eh74dX4y/sHKLWp5uQ==}
678 | cpu: [arm]
679 | os: [linux]
680 |
681 | '@rollup/rollup-linux-arm64-gnu@4.29.1':
682 | resolution: {integrity: sha512-Z80O+taYxTQITWMjm/YqNoe9d10OX6kDh8X5/rFCMuPqsKsSyDilvfg+vd3iXIqtfmp+cnfL1UrYirkaF8SBZA==}
683 | cpu: [arm64]
684 | os: [linux]
685 |
686 | '@rollup/rollup-linux-arm64-musl@4.29.1':
687 | resolution: {integrity: sha512-fOHRtF9gahwJk3QVp01a/GqS4hBEZCV1oKglVVq13kcK3NeVlS4BwIFzOHDbmKzt3i0OuHG4zfRP0YoG5OF/rA==}
688 | cpu: [arm64]
689 | os: [linux]
690 |
691 | '@rollup/rollup-linux-loongarch64-gnu@4.29.1':
692 | resolution: {integrity: sha512-5a7q3tnlbcg0OodyxcAdrrCxFi0DgXJSoOuidFUzHZ2GixZXQs6Tc3CHmlvqKAmOs5eRde+JJxeIf9DonkmYkw==}
693 | cpu: [loong64]
694 | os: [linux]
695 |
696 | '@rollup/rollup-linux-powerpc64le-gnu@4.29.1':
697 | resolution: {integrity: sha512-9b4Mg5Yfz6mRnlSPIdROcfw1BU22FQxmfjlp/CShWwO3LilKQuMISMTtAu/bxmmrE6A902W2cZJuzx8+gJ8e9w==}
698 | cpu: [ppc64]
699 | os: [linux]
700 |
701 | '@rollup/rollup-linux-riscv64-gnu@4.29.1':
702 | resolution: {integrity: sha512-G5pn0NChlbRM8OJWpJFMX4/i8OEU538uiSv0P6roZcbpe/WfhEO+AT8SHVKfp8qhDQzaz7Q+1/ixMy7hBRidnQ==}
703 | cpu: [riscv64]
704 | os: [linux]
705 |
706 | '@rollup/rollup-linux-s390x-gnu@4.29.1':
707 | resolution: {integrity: sha512-WM9lIkNdkhVwiArmLxFXpWndFGuOka4oJOZh8EP3Vb8q5lzdSCBuhjavJsw68Q9AKDGeOOIHYzYm4ZFvmWez5g==}
708 | cpu: [s390x]
709 | os: [linux]
710 |
711 | '@rollup/rollup-linux-x64-gnu@4.29.1':
712 | resolution: {integrity: sha512-87xYCwb0cPGZFoGiErT1eDcssByaLX4fc0z2nRM6eMtV9njAfEE6OW3UniAoDhX4Iq5xQVpE6qO9aJbCFumKYQ==}
713 | cpu: [x64]
714 | os: [linux]
715 |
716 | '@rollup/rollup-linux-x64-musl@4.29.1':
717 | resolution: {integrity: sha512-xufkSNppNOdVRCEC4WKvlR1FBDyqCSCpQeMMgv9ZyXqqtKBfkw1yfGMTUTs9Qsl6WQbJnsGboWCp7pJGkeMhKA==}
718 | cpu: [x64]
719 | os: [linux]
720 |
721 | '@rollup/rollup-win32-arm64-msvc@4.29.1':
722 | resolution: {integrity: sha512-F2OiJ42m77lSkizZQLuC+jiZ2cgueWQL5YC9tjo3AgaEw+KJmVxHGSyQfDUoYR9cci0lAywv2Clmckzulcq6ig==}
723 | cpu: [arm64]
724 | os: [win32]
725 |
726 | '@rollup/rollup-win32-ia32-msvc@4.29.1':
727 | resolution: {integrity: sha512-rYRe5S0FcjlOBZQHgbTKNrqxCBUmgDJem/VQTCcTnA2KCabYSWQDrytOzX7avb79cAAweNmMUb/Zw18RNd4mng==}
728 | cpu: [ia32]
729 | os: [win32]
730 |
731 | '@rollup/rollup-win32-x64-msvc@4.29.1':
732 | resolution: {integrity: sha512-+10CMg9vt1MoHj6x1pxyjPSMjHTIlqs8/tBztXvPAx24SKs9jwVnKqHJumlH/IzhaPUaj3T6T6wfZr8okdXaIg==}
733 | cpu: [x64]
734 | os: [win32]
735 |
736 | '@technically/lodash@4.17.0':
737 | resolution: {integrity: sha512-x0dRMAZbdv7HOyaayrW0Tua9V0k8Sdr+NDgsNRRfPada2+MlCE6esmYoSL7KJeCh13O3up5dlq8VbcQBTW+wqg==}
738 |
739 | '@types/estree@1.0.6':
740 | resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
741 |
742 | '@types/lodash-es@4.17.12':
743 | resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==}
744 |
745 | '@types/lodash@4.17.13':
746 | resolution: {integrity: sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg==}
747 |
748 | '@types/node-forge@1.3.11':
749 | resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==}
750 |
751 | '@types/node@22.10.2':
752 | resolution: {integrity: sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==}
753 |
754 | '@vitest/expect@2.1.8':
755 | resolution: {integrity: sha512-8ytZ/fFHq2g4PJVAtDX57mayemKgDR6X3Oa2Foro+EygiOJHUXhCqBAAKQYYajZpFoIfvBCF1j6R6IYRSIUFuw==}
756 |
757 | '@vitest/mocker@2.1.8':
758 | resolution: {integrity: sha512-7guJ/47I6uqfttp33mgo6ga5Gr1VnL58rcqYKyShoRK9ebu8T5Rs6HN3s1NABiBeVTdWNrwUMcHH54uXZBN4zA==}
759 | peerDependencies:
760 | msw: ^2.4.9
761 | vite: ^5.0.0
762 | peerDependenciesMeta:
763 | msw:
764 | optional: true
765 | vite:
766 | optional: true
767 |
768 | '@vitest/pretty-format@2.1.8':
769 | resolution: {integrity: sha512-9HiSZ9zpqNLKlbIDRWOnAWqgcA7xu+8YxXSekhr0Ykab7PAYFkhkwoqVArPOtJhPmYeE2YHgKZlj3CP36z2AJQ==}
770 |
771 | '@vitest/runner@2.1.8':
772 | resolution: {integrity: sha512-17ub8vQstRnRlIU5k50bG+QOMLHRhYPAna5tw8tYbj+jzjcspnwnwtPtiOlkuKC4+ixDPTuLZiqiWWQ2PSXHVg==}
773 |
774 | '@vitest/snapshot@2.1.8':
775 | resolution: {integrity: sha512-20T7xRFbmnkfcmgVEz+z3AU/3b0cEzZOt/zmnvZEctg64/QZbSDJEVm9fLnnlSi74KibmRsO9/Qabi+t0vCRPg==}
776 |
777 | '@vitest/spy@2.1.8':
778 | resolution: {integrity: sha512-5swjf2q95gXeYPevtW0BLk6H8+bPlMb4Vw/9Em4hFxDcaOxS+e0LOX4yqNxoHzMR2akEB2xfpnWUzkZokmgWDg==}
779 |
780 | '@vitest/utils@2.1.8':
781 | resolution: {integrity: sha512-dwSoui6djdwbfFmIgbIjX2ZhIoG7Ex/+xpxyiEgIGzjliY8xGkcpITKTlp6B4MgtGkF2ilvm97cPM96XZaAgcA==}
782 |
783 | acorn-walk@8.3.4:
784 | resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==}
785 | engines: {node: '>=0.4.0'}
786 |
787 | acorn@8.14.0:
788 | resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==}
789 | engines: {node: '>=0.4.0'}
790 | hasBin: true
791 |
792 | as-table@1.0.55:
793 | resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==}
794 |
795 | assertion-error@2.0.1:
796 | resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
797 | engines: {node: '>=12'}
798 |
799 | birpc@0.2.14:
800 | resolution: {integrity: sha512-37FHE8rqsYM5JEKCnXFyHpBCzvgHEExwVVTq+nUmloInU7l8ezD1TpOhKpS8oe1DTYFqEK27rFZVKG43oTqXRA==}
801 |
802 | blake3-wasm@2.1.5:
803 | resolution: {integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==}
804 |
805 | cac@6.7.14:
806 | resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
807 | engines: {node: '>=8'}
808 |
809 | capnp-ts@0.7.0:
810 | resolution: {integrity: sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g==}
811 |
812 | chai@5.1.2:
813 | resolution: {integrity: sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==}
814 | engines: {node: '>=12'}
815 |
816 | check-error@2.1.1:
817 | resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==}
818 | engines: {node: '>= 16'}
819 |
820 | chokidar@4.0.3:
821 | resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
822 | engines: {node: '>= 14.16.0'}
823 |
824 | cjs-module-lexer@1.4.1:
825 | resolution: {integrity: sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==}
826 |
827 | cookie@0.7.2:
828 | resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==}
829 | engines: {node: '>= 0.6'}
830 |
831 | data-uri-to-buffer@2.0.2:
832 | resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==}
833 |
834 | date-fns@4.1.0:
835 | resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==}
836 |
837 | debug@4.4.0:
838 | resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
839 | engines: {node: '>=6.0'}
840 | peerDependencies:
841 | supports-color: '*'
842 | peerDependenciesMeta:
843 | supports-color:
844 | optional: true
845 |
846 | deep-eql@5.0.2:
847 | resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==}
848 | engines: {node: '>=6'}
849 |
850 | defu@6.1.4:
851 | resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
852 |
853 | devalue@4.3.3:
854 | resolution: {integrity: sha512-UH8EL6H2ifcY8TbD2QsxwCC/pr5xSwPvv85LrLXVihmHVC3T3YqTCIwnR5ak0yO1KYqlxrPVOA/JVZJYPy2ATg==}
855 |
856 | diffable-objects@0.1.1:
857 | resolution: {integrity: sha512-vk6VMf4Jjt49ls4FdwYNU1BesPxIqsk6jSihFuU/qr17nMcZ+hGguC5aE+EKsI/M5qaj0+A9O53zTh5gN3MSpQ==}
858 |
859 | es-module-lexer@1.5.4:
860 | resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==}
861 |
862 | esbuild@0.17.19:
863 | resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==}
864 | engines: {node: '>=12'}
865 | hasBin: true
866 |
867 | esbuild@0.21.5:
868 | resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
869 | engines: {node: '>=12'}
870 | hasBin: true
871 |
872 | esbuild@0.24.0:
873 | resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==}
874 | engines: {node: '>=18'}
875 | hasBin: true
876 |
877 | escape-string-regexp@4.0.0:
878 | resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
879 | engines: {node: '>=10'}
880 |
881 | estree-walker@0.6.1:
882 | resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==}
883 |
884 | estree-walker@3.0.3:
885 | resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
886 |
887 | exit-hook@2.2.1:
888 | resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==}
889 | engines: {node: '>=6'}
890 |
891 | expect-type@1.1.0:
892 | resolution: {integrity: sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==}
893 | engines: {node: '>=12.0.0'}
894 |
895 | fsevents@2.3.3:
896 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
897 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
898 | os: [darwin]
899 |
900 | function-bind@1.1.2:
901 | resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
902 |
903 | get-source@2.0.12:
904 | resolution: {integrity: sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==}
905 |
906 | glob-to-regexp@0.4.1:
907 | resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==}
908 |
909 | hasown@2.0.2:
910 | resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
911 | engines: {node: '>= 0.4'}
912 |
913 | is-core-module@2.16.1:
914 | resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==}
915 | engines: {node: '>= 0.4'}
916 |
917 | itty-time@1.0.6:
918 | resolution: {integrity: sha512-+P8IZaLLBtFv8hCkIjcymZOp4UJ+xW6bSlQsXGqrkmJh7vSiMFSlNne0mCYagEE0N7HDNR5jJBRxwN0oYv61Rw==}
919 |
920 | json-diff-ts@4.1.0:
921 | resolution: {integrity: sha512-WriM1FhU8xnvlvDsmoB5YgwkL2uOy/p4rKPmJz0Bo221nHHEQbh6WspTowEl2qxy9yP5gGYv0pUQ7kNnjrn/TQ==}
922 |
923 | lodash-es@4.17.21:
924 | resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
925 |
926 | loupe@3.1.2:
927 | resolution: {integrity: sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==}
928 |
929 | magic-string@0.25.9:
930 | resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
931 |
932 | magic-string@0.30.17:
933 | resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
934 |
935 | mime@3.0.0:
936 | resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==}
937 | engines: {node: '>=10.0.0'}
938 | hasBin: true
939 |
940 | miniflare@0.0.0-dc669c404:
941 | resolution: {integrity: sha512-Qu6XmE81AQdAnki9b9bOBs8kwltgAnuobiwiz+X+oNNzN9n+LrpGELudwDJPerfDq3cNLnH5P5FiKMmwLNBLYg==}
942 | engines: {node: '>=18.0.0'}
943 | hasBin: true
944 |
945 | miniflare@3.20241218.0:
946 | resolution: {integrity: sha512-spYFDArH0wd+wJSTrzBrWrXJrbyJhRMJa35mat947y1jYhVV8I5V8vnD3LwjfpLr0SaEilojz1OIW7ekmnRe+w==}
947 | engines: {node: '>=16.13'}
948 | hasBin: true
949 |
950 | ms@2.1.3:
951 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
952 |
953 | mustache@4.2.0:
954 | resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==}
955 | hasBin: true
956 |
957 | nanoid@3.3.8:
958 | resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==}
959 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
960 | hasBin: true
961 |
962 | node-forge@1.3.1:
963 | resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==}
964 | engines: {node: '>= 6.13.0'}
965 |
966 | ohash@1.1.4:
967 | resolution: {integrity: sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g==}
968 |
969 | path-parse@1.0.7:
970 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
971 |
972 | path-to-regexp@6.3.0:
973 | resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==}
974 |
975 | pathe@1.1.2:
976 | resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
977 |
978 | pathval@2.0.0:
979 | resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==}
980 | engines: {node: '>= 14.16'}
981 |
982 | picocolors@1.1.1:
983 | resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
984 |
985 | postcss@8.4.49:
986 | resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==}
987 | engines: {node: ^10 || ^12 || >=14}
988 |
989 | printable-characters@1.0.42:
990 | resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==}
991 |
992 | readdirp@4.0.2:
993 | resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==}
994 | engines: {node: '>= 14.16.0'}
995 |
996 | resolve.exports@2.0.3:
997 | resolution: {integrity: sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==}
998 | engines: {node: '>=10'}
999 |
1000 | resolve@1.22.10:
1001 | resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==}
1002 | engines: {node: '>= 0.4'}
1003 | hasBin: true
1004 |
1005 | rollup-plugin-inject@3.0.2:
1006 | resolution: {integrity: sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==}
1007 | deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject.
1008 |
1009 | rollup-plugin-node-polyfills@0.2.1:
1010 | resolution: {integrity: sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==}
1011 |
1012 | rollup-pluginutils@2.8.2:
1013 | resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==}
1014 |
1015 | rollup@4.29.1:
1016 | resolution: {integrity: sha512-RaJ45M/kmJUzSWDs1Nnd5DdV4eerC98idtUOVr6FfKcgxqvjwHmxc5upLF9qZU9EpsVzzhleFahrT3shLuJzIw==}
1017 | engines: {node: '>=18.0.0', npm: '>=8.0.0'}
1018 | hasBin: true
1019 |
1020 | selfsigned@2.4.1:
1021 | resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==}
1022 | engines: {node: '>=10'}
1023 |
1024 | semver@7.6.3:
1025 | resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==}
1026 | engines: {node: '>=10'}
1027 | hasBin: true
1028 |
1029 | siginfo@2.0.0:
1030 | resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
1031 |
1032 | source-map-js@1.2.1:
1033 | resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
1034 | engines: {node: '>=0.10.0'}
1035 |
1036 | source-map@0.6.1:
1037 | resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
1038 | engines: {node: '>=0.10.0'}
1039 |
1040 | sourcemap-codec@1.4.8:
1041 | resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==}
1042 | deprecated: Please use @jridgewell/sourcemap-codec instead
1043 |
1044 | stackback@0.0.2:
1045 | resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
1046 |
1047 | stacktracey@2.1.8:
1048 | resolution: {integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==}
1049 |
1050 | std-env@3.8.0:
1051 | resolution: {integrity: sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==}
1052 |
1053 | stoppable@1.1.0:
1054 | resolution: {integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==}
1055 | engines: {node: '>=4', npm: '>=6'}
1056 |
1057 | supports-preserve-symlinks-flag@1.0.0:
1058 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
1059 | engines: {node: '>= 0.4'}
1060 |
1061 | tinybench@2.9.0:
1062 | resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
1063 |
1064 | tinyexec@0.3.1:
1065 | resolution: {integrity: sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==}
1066 |
1067 | tinypool@1.0.2:
1068 | resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==}
1069 | engines: {node: ^18.0.0 || >=20.0.0}
1070 |
1071 | tinyrainbow@1.2.0:
1072 | resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==}
1073 | engines: {node: '>=14.0.0'}
1074 |
1075 | tinyspy@3.0.2:
1076 | resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==}
1077 | engines: {node: '>=14.0.0'}
1078 |
1079 | tslib@2.8.1:
1080 | resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
1081 |
1082 | typescript@5.7.2:
1083 | resolution: {integrity: sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==}
1084 | engines: {node: '>=14.17'}
1085 | hasBin: true
1086 |
1087 | ufo@1.5.4:
1088 | resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==}
1089 |
1090 | undici-types@6.20.0:
1091 | resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==}
1092 |
1093 | undici@5.28.4:
1094 | resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==}
1095 | engines: {node: '>=14.0'}
1096 |
1097 | unenv-nightly@2.0.0-20241121-161142-806b5c0:
1098 | resolution: {integrity: sha512-RnFOasE/O0Q55gBkNB1b84OgKttgLEijGO0JCWpbn+O4XxpyCQg89NmcqQ5RGUiy4y+rMIrKzePTquQcLQF5pQ==}
1099 |
1100 | unenv-nightly@2.0.0-20241204-140205-a5d5190:
1101 | resolution: {integrity: sha512-jpmAytLeiiW01pl5bhVn9wYJ4vtiLdhGe10oXlJBuQEX8mxjxO8BlEXGHU4vr4yEikjFP1wsomTHt/CLU8kUwg==}
1102 |
1103 | vite-node@2.1.8:
1104 | resolution: {integrity: sha512-uPAwSr57kYjAUux+8E2j0q0Fxpn8M9VoyfGiRI8Kfktz9NcYMCenwY5RnZxnF1WTu3TGiYipirIzacLL3VVGFg==}
1105 | engines: {node: ^18.0.0 || >=20.0.0}
1106 | hasBin: true
1107 |
1108 | vite@5.4.11:
1109 | resolution: {integrity: sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==}
1110 | engines: {node: ^18.0.0 || >=20.0.0}
1111 | hasBin: true
1112 | peerDependencies:
1113 | '@types/node': ^18.0.0 || >=20.0.0
1114 | less: '*'
1115 | lightningcss: ^1.21.0
1116 | sass: '*'
1117 | sass-embedded: '*'
1118 | stylus: '*'
1119 | sugarss: '*'
1120 | terser: ^5.4.0
1121 | peerDependenciesMeta:
1122 | '@types/node':
1123 | optional: true
1124 | less:
1125 | optional: true
1126 | lightningcss:
1127 | optional: true
1128 | sass:
1129 | optional: true
1130 | sass-embedded:
1131 | optional: true
1132 | stylus:
1133 | optional: true
1134 | sugarss:
1135 | optional: true
1136 | terser:
1137 | optional: true
1138 |
1139 | vitest@2.1.8:
1140 | resolution: {integrity: sha512-1vBKTZskHw/aosXqQUlVWWlGUxSJR8YtiyZDJAFeW2kPAeX6S3Sool0mjspO+kXLuxVWlEDDowBAeqeAQefqLQ==}
1141 | engines: {node: ^18.0.0 || >=20.0.0}
1142 | hasBin: true
1143 | peerDependencies:
1144 | '@edge-runtime/vm': '*'
1145 | '@types/node': ^18.0.0 || >=20.0.0
1146 | '@vitest/browser': 2.1.8
1147 | '@vitest/ui': 2.1.8
1148 | happy-dom: '*'
1149 | jsdom: '*'
1150 | peerDependenciesMeta:
1151 | '@edge-runtime/vm':
1152 | optional: true
1153 | '@types/node':
1154 | optional: true
1155 | '@vitest/browser':
1156 | optional: true
1157 | '@vitest/ui':
1158 | optional: true
1159 | happy-dom:
1160 | optional: true
1161 | jsdom:
1162 | optional: true
1163 |
1164 | why-is-node-running@2.3.0:
1165 | resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==}
1166 | engines: {node: '>=8'}
1167 | hasBin: true
1168 |
1169 | workerd@1.20241106.1:
1170 | resolution: {integrity: sha512-1GdKl0kDw8rrirr/ThcK66Kbl4/jd4h8uHx5g7YHBrnenY5SX1UPuop2cnCzYUxlg55kPjzIqqYslz1muRFgFw==}
1171 | engines: {node: '>=16'}
1172 | hasBin: true
1173 |
1174 | workerd@1.20241218.0:
1175 | resolution: {integrity: sha512-7Z3D4vOVChMz9mWDffE299oQxUWm/pbkeAWx1btVamPcAK/2IuoNBhwflWo3jyuKuxvYuFAdIucgYxc8ICqXiA==}
1176 | engines: {node: '>=16'}
1177 | hasBin: true
1178 |
1179 | wrangler@0.0.0-dc669c404:
1180 | resolution: {integrity: sha512-NXu1FQBaRBSkSG73ze4o6+lHaQcu+DNZCNLeBHXUVGjU17IW2+uL76Rq9Nopj9VIw4YFwgEsJJN2dD7tBPji0w==}
1181 | engines: {node: '>=18.0.0'}
1182 | hasBin: true
1183 | peerDependencies:
1184 | '@cloudflare/workers-types': ^4.20241106.0
1185 | peerDependenciesMeta:
1186 | '@cloudflare/workers-types':
1187 | optional: true
1188 |
1189 | wrangler@3.99.0:
1190 | resolution: {integrity: sha512-k0x4rT3G/QCbxcoZY7CHRVlAIS8WMmKdga6lf4d2c3gXFqssh44vwlTDuARA9QANBxKJTcA7JPTJRfUDhd9QBA==}
1191 | engines: {node: '>=16.17.0'}
1192 | hasBin: true
1193 | peerDependencies:
1194 | '@cloudflare/workers-types': ^4.20241218.0
1195 | peerDependenciesMeta:
1196 | '@cloudflare/workers-types':
1197 | optional: true
1198 |
1199 | ws@8.18.0:
1200 | resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==}
1201 | engines: {node: '>=10.0.0'}
1202 | peerDependencies:
1203 | bufferutil: ^4.0.1
1204 | utf-8-validate: '>=5.0.2'
1205 | peerDependenciesMeta:
1206 | bufferutil:
1207 | optional: true
1208 | utf-8-validate:
1209 | optional: true
1210 |
1211 | xxhash-wasm@1.1.0:
1212 | resolution: {integrity: sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==}
1213 |
1214 | youch@3.3.4:
1215 | resolution: {integrity: sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg==}
1216 |
1217 | zod@3.24.1:
1218 | resolution: {integrity: sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==}
1219 |
1220 | snapshots:
1221 |
1222 | '@biomejs/biome@1.9.4':
1223 | optionalDependencies:
1224 | '@biomejs/cli-darwin-arm64': 1.9.4
1225 | '@biomejs/cli-darwin-x64': 1.9.4
1226 | '@biomejs/cli-linux-arm64': 1.9.4
1227 | '@biomejs/cli-linux-arm64-musl': 1.9.4
1228 | '@biomejs/cli-linux-x64': 1.9.4
1229 | '@biomejs/cli-linux-x64-musl': 1.9.4
1230 | '@biomejs/cli-win32-arm64': 1.9.4
1231 | '@biomejs/cli-win32-x64': 1.9.4
1232 |
1233 | '@biomejs/cli-darwin-arm64@1.9.4':
1234 | optional: true
1235 |
1236 | '@biomejs/cli-darwin-x64@1.9.4':
1237 | optional: true
1238 |
1239 | '@biomejs/cli-linux-arm64-musl@1.9.4':
1240 | optional: true
1241 |
1242 | '@biomejs/cli-linux-arm64@1.9.4':
1243 | optional: true
1244 |
1245 | '@biomejs/cli-linux-x64-musl@1.9.4':
1246 | optional: true
1247 |
1248 | '@biomejs/cli-linux-x64@1.9.4':
1249 | optional: true
1250 |
1251 | '@biomejs/cli-win32-arm64@1.9.4':
1252 | optional: true
1253 |
1254 | '@biomejs/cli-win32-x64@1.9.4':
1255 | optional: true
1256 |
1257 | '@cloudflare/kv-asset-handler@0.3.4':
1258 | dependencies:
1259 | mime: 3.0.0
1260 |
1261 | '@cloudflare/vitest-pool-workers@0.5.40(@cloudflare/workers-types@4.20241224.0)(@vitest/runner@2.1.8)(@vitest/snapshot@2.1.8)(vitest@2.1.8(@types/node@22.10.2))':
1262 | dependencies:
1263 | '@vitest/runner': 2.1.8
1264 | '@vitest/snapshot': 2.1.8
1265 | birpc: 0.2.14
1266 | cjs-module-lexer: 1.4.1
1267 | devalue: 4.3.3
1268 | esbuild: 0.17.19
1269 | miniflare: 3.20241218.0
1270 | semver: 7.6.3
1271 | vitest: 2.1.8(@types/node@22.10.2)
1272 | wrangler: 3.99.0(@cloudflare/workers-types@4.20241224.0)
1273 | zod: 3.24.1
1274 | transitivePeerDependencies:
1275 | - '@cloudflare/workers-types'
1276 | - bufferutil
1277 | - supports-color
1278 | - utf-8-validate
1279 |
1280 | '@cloudflare/workerd-darwin-64@1.20241106.1':
1281 | optional: true
1282 |
1283 | '@cloudflare/workerd-darwin-64@1.20241218.0':
1284 | optional: true
1285 |
1286 | '@cloudflare/workerd-darwin-arm64@1.20241106.1':
1287 | optional: true
1288 |
1289 | '@cloudflare/workerd-darwin-arm64@1.20241218.0':
1290 | optional: true
1291 |
1292 | '@cloudflare/workerd-linux-64@1.20241106.1':
1293 | optional: true
1294 |
1295 | '@cloudflare/workerd-linux-64@1.20241218.0':
1296 | optional: true
1297 |
1298 | '@cloudflare/workerd-linux-arm64@1.20241106.1':
1299 | optional: true
1300 |
1301 | '@cloudflare/workerd-linux-arm64@1.20241218.0':
1302 | optional: true
1303 |
1304 | '@cloudflare/workerd-windows-64@1.20241106.1':
1305 | optional: true
1306 |
1307 | '@cloudflare/workerd-windows-64@1.20241218.0':
1308 | optional: true
1309 |
1310 | '@cloudflare/workers-shared@0.8.0':
1311 | dependencies:
1312 | mime: 3.0.0
1313 | zod: 3.24.1
1314 |
1315 | '@cloudflare/workers-types@4.20241224.0': {}
1316 |
1317 | '@cspotcode/source-map-support@0.8.1':
1318 | dependencies:
1319 | '@jridgewell/trace-mapping': 0.3.9
1320 |
1321 | '@esbuild-plugins/node-globals-polyfill@0.2.3(esbuild@0.17.19)':
1322 | dependencies:
1323 | esbuild: 0.17.19
1324 |
1325 | '@esbuild-plugins/node-modules-polyfill@0.2.2(esbuild@0.17.19)':
1326 | dependencies:
1327 | esbuild: 0.17.19
1328 | escape-string-regexp: 4.0.0
1329 | rollup-plugin-node-polyfills: 0.2.1
1330 |
1331 | '@esbuild/aix-ppc64@0.21.5':
1332 | optional: true
1333 |
1334 | '@esbuild/aix-ppc64@0.24.0':
1335 | optional: true
1336 |
1337 | '@esbuild/android-arm64@0.17.19':
1338 | optional: true
1339 |
1340 | '@esbuild/android-arm64@0.21.5':
1341 | optional: true
1342 |
1343 | '@esbuild/android-arm64@0.24.0':
1344 | optional: true
1345 |
1346 | '@esbuild/android-arm@0.17.19':
1347 | optional: true
1348 |
1349 | '@esbuild/android-arm@0.21.5':
1350 | optional: true
1351 |
1352 | '@esbuild/android-arm@0.24.0':
1353 | optional: true
1354 |
1355 | '@esbuild/android-x64@0.17.19':
1356 | optional: true
1357 |
1358 | '@esbuild/android-x64@0.21.5':
1359 | optional: true
1360 |
1361 | '@esbuild/android-x64@0.24.0':
1362 | optional: true
1363 |
1364 | '@esbuild/darwin-arm64@0.17.19':
1365 | optional: true
1366 |
1367 | '@esbuild/darwin-arm64@0.21.5':
1368 | optional: true
1369 |
1370 | '@esbuild/darwin-arm64@0.24.0':
1371 | optional: true
1372 |
1373 | '@esbuild/darwin-x64@0.17.19':
1374 | optional: true
1375 |
1376 | '@esbuild/darwin-x64@0.21.5':
1377 | optional: true
1378 |
1379 | '@esbuild/darwin-x64@0.24.0':
1380 | optional: true
1381 |
1382 | '@esbuild/freebsd-arm64@0.17.19':
1383 | optional: true
1384 |
1385 | '@esbuild/freebsd-arm64@0.21.5':
1386 | optional: true
1387 |
1388 | '@esbuild/freebsd-arm64@0.24.0':
1389 | optional: true
1390 |
1391 | '@esbuild/freebsd-x64@0.17.19':
1392 | optional: true
1393 |
1394 | '@esbuild/freebsd-x64@0.21.5':
1395 | optional: true
1396 |
1397 | '@esbuild/freebsd-x64@0.24.0':
1398 | optional: true
1399 |
1400 | '@esbuild/linux-arm64@0.17.19':
1401 | optional: true
1402 |
1403 | '@esbuild/linux-arm64@0.21.5':
1404 | optional: true
1405 |
1406 | '@esbuild/linux-arm64@0.24.0':
1407 | optional: true
1408 |
1409 | '@esbuild/linux-arm@0.17.19':
1410 | optional: true
1411 |
1412 | '@esbuild/linux-arm@0.21.5':
1413 | optional: true
1414 |
1415 | '@esbuild/linux-arm@0.24.0':
1416 | optional: true
1417 |
1418 | '@esbuild/linux-ia32@0.17.19':
1419 | optional: true
1420 |
1421 | '@esbuild/linux-ia32@0.21.5':
1422 | optional: true
1423 |
1424 | '@esbuild/linux-ia32@0.24.0':
1425 | optional: true
1426 |
1427 | '@esbuild/linux-loong64@0.17.19':
1428 | optional: true
1429 |
1430 | '@esbuild/linux-loong64@0.21.5':
1431 | optional: true
1432 |
1433 | '@esbuild/linux-loong64@0.24.0':
1434 | optional: true
1435 |
1436 | '@esbuild/linux-mips64el@0.17.19':
1437 | optional: true
1438 |
1439 | '@esbuild/linux-mips64el@0.21.5':
1440 | optional: true
1441 |
1442 | '@esbuild/linux-mips64el@0.24.0':
1443 | optional: true
1444 |
1445 | '@esbuild/linux-ppc64@0.17.19':
1446 | optional: true
1447 |
1448 | '@esbuild/linux-ppc64@0.21.5':
1449 | optional: true
1450 |
1451 | '@esbuild/linux-ppc64@0.24.0':
1452 | optional: true
1453 |
1454 | '@esbuild/linux-riscv64@0.17.19':
1455 | optional: true
1456 |
1457 | '@esbuild/linux-riscv64@0.21.5':
1458 | optional: true
1459 |
1460 | '@esbuild/linux-riscv64@0.24.0':
1461 | optional: true
1462 |
1463 | '@esbuild/linux-s390x@0.17.19':
1464 | optional: true
1465 |
1466 | '@esbuild/linux-s390x@0.21.5':
1467 | optional: true
1468 |
1469 | '@esbuild/linux-s390x@0.24.0':
1470 | optional: true
1471 |
1472 | '@esbuild/linux-x64@0.17.19':
1473 | optional: true
1474 |
1475 | '@esbuild/linux-x64@0.21.5':
1476 | optional: true
1477 |
1478 | '@esbuild/linux-x64@0.24.0':
1479 | optional: true
1480 |
1481 | '@esbuild/netbsd-x64@0.17.19':
1482 | optional: true
1483 |
1484 | '@esbuild/netbsd-x64@0.21.5':
1485 | optional: true
1486 |
1487 | '@esbuild/netbsd-x64@0.24.0':
1488 | optional: true
1489 |
1490 | '@esbuild/openbsd-arm64@0.24.0':
1491 | optional: true
1492 |
1493 | '@esbuild/openbsd-x64@0.17.19':
1494 | optional: true
1495 |
1496 | '@esbuild/openbsd-x64@0.21.5':
1497 | optional: true
1498 |
1499 | '@esbuild/openbsd-x64@0.24.0':
1500 | optional: true
1501 |
1502 | '@esbuild/sunos-x64@0.17.19':
1503 | optional: true
1504 |
1505 | '@esbuild/sunos-x64@0.21.5':
1506 | optional: true
1507 |
1508 | '@esbuild/sunos-x64@0.24.0':
1509 | optional: true
1510 |
1511 | '@esbuild/win32-arm64@0.17.19':
1512 | optional: true
1513 |
1514 | '@esbuild/win32-arm64@0.21.5':
1515 | optional: true
1516 |
1517 | '@esbuild/win32-arm64@0.24.0':
1518 | optional: true
1519 |
1520 | '@esbuild/win32-ia32@0.17.19':
1521 | optional: true
1522 |
1523 | '@esbuild/win32-ia32@0.21.5':
1524 | optional: true
1525 |
1526 | '@esbuild/win32-ia32@0.24.0':
1527 | optional: true
1528 |
1529 | '@esbuild/win32-x64@0.17.19':
1530 | optional: true
1531 |
1532 | '@esbuild/win32-x64@0.21.5':
1533 | optional: true
1534 |
1535 | '@esbuild/win32-x64@0.24.0':
1536 | optional: true
1537 |
1538 | '@fastify/busboy@2.1.1': {}
1539 |
1540 | '@jridgewell/resolve-uri@3.1.2': {}
1541 |
1542 | '@jridgewell/sourcemap-codec@1.5.0': {}
1543 |
1544 | '@jridgewell/trace-mapping@0.3.9':
1545 | dependencies:
1546 | '@jridgewell/resolve-uri': 3.1.2
1547 | '@jridgewell/sourcemap-codec': 1.5.0
1548 |
1549 | '@rollup/rollup-android-arm-eabi@4.29.1':
1550 | optional: true
1551 |
1552 | '@rollup/rollup-android-arm64@4.29.1':
1553 | optional: true
1554 |
1555 | '@rollup/rollup-darwin-arm64@4.29.1':
1556 | optional: true
1557 |
1558 | '@rollup/rollup-darwin-x64@4.29.1':
1559 | optional: true
1560 |
1561 | '@rollup/rollup-freebsd-arm64@4.29.1':
1562 | optional: true
1563 |
1564 | '@rollup/rollup-freebsd-x64@4.29.1':
1565 | optional: true
1566 |
1567 | '@rollup/rollup-linux-arm-gnueabihf@4.29.1':
1568 | optional: true
1569 |
1570 | '@rollup/rollup-linux-arm-musleabihf@4.29.1':
1571 | optional: true
1572 |
1573 | '@rollup/rollup-linux-arm64-gnu@4.29.1':
1574 | optional: true
1575 |
1576 | '@rollup/rollup-linux-arm64-musl@4.29.1':
1577 | optional: true
1578 |
1579 | '@rollup/rollup-linux-loongarch64-gnu@4.29.1':
1580 | optional: true
1581 |
1582 | '@rollup/rollup-linux-powerpc64le-gnu@4.29.1':
1583 | optional: true
1584 |
1585 | '@rollup/rollup-linux-riscv64-gnu@4.29.1':
1586 | optional: true
1587 |
1588 | '@rollup/rollup-linux-s390x-gnu@4.29.1':
1589 | optional: true
1590 |
1591 | '@rollup/rollup-linux-x64-gnu@4.29.1':
1592 | optional: true
1593 |
1594 | '@rollup/rollup-linux-x64-musl@4.29.1':
1595 | optional: true
1596 |
1597 | '@rollup/rollup-win32-arm64-msvc@4.29.1':
1598 | optional: true
1599 |
1600 | '@rollup/rollup-win32-ia32-msvc@4.29.1':
1601 | optional: true
1602 |
1603 | '@rollup/rollup-win32-x64-msvc@4.29.1':
1604 | optional: true
1605 |
1606 | '@technically/lodash@4.17.0':
1607 | dependencies:
1608 | '@types/lodash-es': 4.17.12
1609 | lodash-es: 4.17.21
1610 |
1611 | '@types/estree@1.0.6': {}
1612 |
1613 | '@types/lodash-es@4.17.12':
1614 | dependencies:
1615 | '@types/lodash': 4.17.13
1616 |
1617 | '@types/lodash@4.17.13': {}
1618 |
1619 | '@types/node-forge@1.3.11':
1620 | dependencies:
1621 | '@types/node': 22.10.2
1622 |
1623 | '@types/node@22.10.2':
1624 | dependencies:
1625 | undici-types: 6.20.0
1626 |
1627 | '@vitest/expect@2.1.8':
1628 | dependencies:
1629 | '@vitest/spy': 2.1.8
1630 | '@vitest/utils': 2.1.8
1631 | chai: 5.1.2
1632 | tinyrainbow: 1.2.0
1633 |
1634 | '@vitest/mocker@2.1.8(vite@5.4.11(@types/node@22.10.2))':
1635 | dependencies:
1636 | '@vitest/spy': 2.1.8
1637 | estree-walker: 3.0.3
1638 | magic-string: 0.30.17
1639 | optionalDependencies:
1640 | vite: 5.4.11(@types/node@22.10.2)
1641 |
1642 | '@vitest/pretty-format@2.1.8':
1643 | dependencies:
1644 | tinyrainbow: 1.2.0
1645 |
1646 | '@vitest/runner@2.1.8':
1647 | dependencies:
1648 | '@vitest/utils': 2.1.8
1649 | pathe: 1.1.2
1650 |
1651 | '@vitest/snapshot@2.1.8':
1652 | dependencies:
1653 | '@vitest/pretty-format': 2.1.8
1654 | magic-string: 0.30.17
1655 | pathe: 1.1.2
1656 |
1657 | '@vitest/spy@2.1.8':
1658 | dependencies:
1659 | tinyspy: 3.0.2
1660 |
1661 | '@vitest/utils@2.1.8':
1662 | dependencies:
1663 | '@vitest/pretty-format': 2.1.8
1664 | loupe: 3.1.2
1665 | tinyrainbow: 1.2.0
1666 |
1667 | acorn-walk@8.3.4:
1668 | dependencies:
1669 | acorn: 8.14.0
1670 |
1671 | acorn@8.14.0: {}
1672 |
1673 | as-table@1.0.55:
1674 | dependencies:
1675 | printable-characters: 1.0.42
1676 |
1677 | assertion-error@2.0.1: {}
1678 |
1679 | birpc@0.2.14: {}
1680 |
1681 | blake3-wasm@2.1.5: {}
1682 |
1683 | cac@6.7.14: {}
1684 |
1685 | capnp-ts@0.7.0:
1686 | dependencies:
1687 | debug: 4.4.0
1688 | tslib: 2.8.1
1689 | transitivePeerDependencies:
1690 | - supports-color
1691 |
1692 | chai@5.1.2:
1693 | dependencies:
1694 | assertion-error: 2.0.1
1695 | check-error: 2.1.1
1696 | deep-eql: 5.0.2
1697 | loupe: 3.1.2
1698 | pathval: 2.0.0
1699 |
1700 | check-error@2.1.1: {}
1701 |
1702 | chokidar@4.0.3:
1703 | dependencies:
1704 | readdirp: 4.0.2
1705 |
1706 | cjs-module-lexer@1.4.1: {}
1707 |
1708 | cookie@0.7.2: {}
1709 |
1710 | data-uri-to-buffer@2.0.2: {}
1711 |
1712 | date-fns@4.1.0: {}
1713 |
1714 | debug@4.4.0:
1715 | dependencies:
1716 | ms: 2.1.3
1717 |
1718 | deep-eql@5.0.2: {}
1719 |
1720 | defu@6.1.4: {}
1721 |
1722 | devalue@4.3.3: {}
1723 |
1724 | diffable-objects@0.1.1:
1725 | dependencies:
1726 | json-diff-ts: 4.1.0
1727 |
1728 | es-module-lexer@1.5.4: {}
1729 |
1730 | esbuild@0.17.19:
1731 | optionalDependencies:
1732 | '@esbuild/android-arm': 0.17.19
1733 | '@esbuild/android-arm64': 0.17.19
1734 | '@esbuild/android-x64': 0.17.19
1735 | '@esbuild/darwin-arm64': 0.17.19
1736 | '@esbuild/darwin-x64': 0.17.19
1737 | '@esbuild/freebsd-arm64': 0.17.19
1738 | '@esbuild/freebsd-x64': 0.17.19
1739 | '@esbuild/linux-arm': 0.17.19
1740 | '@esbuild/linux-arm64': 0.17.19
1741 | '@esbuild/linux-ia32': 0.17.19
1742 | '@esbuild/linux-loong64': 0.17.19
1743 | '@esbuild/linux-mips64el': 0.17.19
1744 | '@esbuild/linux-ppc64': 0.17.19
1745 | '@esbuild/linux-riscv64': 0.17.19
1746 | '@esbuild/linux-s390x': 0.17.19
1747 | '@esbuild/linux-x64': 0.17.19
1748 | '@esbuild/netbsd-x64': 0.17.19
1749 | '@esbuild/openbsd-x64': 0.17.19
1750 | '@esbuild/sunos-x64': 0.17.19
1751 | '@esbuild/win32-arm64': 0.17.19
1752 | '@esbuild/win32-ia32': 0.17.19
1753 | '@esbuild/win32-x64': 0.17.19
1754 |
1755 | esbuild@0.21.5:
1756 | optionalDependencies:
1757 | '@esbuild/aix-ppc64': 0.21.5
1758 | '@esbuild/android-arm': 0.21.5
1759 | '@esbuild/android-arm64': 0.21.5
1760 | '@esbuild/android-x64': 0.21.5
1761 | '@esbuild/darwin-arm64': 0.21.5
1762 | '@esbuild/darwin-x64': 0.21.5
1763 | '@esbuild/freebsd-arm64': 0.21.5
1764 | '@esbuild/freebsd-x64': 0.21.5
1765 | '@esbuild/linux-arm': 0.21.5
1766 | '@esbuild/linux-arm64': 0.21.5
1767 | '@esbuild/linux-ia32': 0.21.5
1768 | '@esbuild/linux-loong64': 0.21.5
1769 | '@esbuild/linux-mips64el': 0.21.5
1770 | '@esbuild/linux-ppc64': 0.21.5
1771 | '@esbuild/linux-riscv64': 0.21.5
1772 | '@esbuild/linux-s390x': 0.21.5
1773 | '@esbuild/linux-x64': 0.21.5
1774 | '@esbuild/netbsd-x64': 0.21.5
1775 | '@esbuild/openbsd-x64': 0.21.5
1776 | '@esbuild/sunos-x64': 0.21.5
1777 | '@esbuild/win32-arm64': 0.21.5
1778 | '@esbuild/win32-ia32': 0.21.5
1779 | '@esbuild/win32-x64': 0.21.5
1780 |
1781 | esbuild@0.24.0:
1782 | optionalDependencies:
1783 | '@esbuild/aix-ppc64': 0.24.0
1784 | '@esbuild/android-arm': 0.24.0
1785 | '@esbuild/android-arm64': 0.24.0
1786 | '@esbuild/android-x64': 0.24.0
1787 | '@esbuild/darwin-arm64': 0.24.0
1788 | '@esbuild/darwin-x64': 0.24.0
1789 | '@esbuild/freebsd-arm64': 0.24.0
1790 | '@esbuild/freebsd-x64': 0.24.0
1791 | '@esbuild/linux-arm': 0.24.0
1792 | '@esbuild/linux-arm64': 0.24.0
1793 | '@esbuild/linux-ia32': 0.24.0
1794 | '@esbuild/linux-loong64': 0.24.0
1795 | '@esbuild/linux-mips64el': 0.24.0
1796 | '@esbuild/linux-ppc64': 0.24.0
1797 | '@esbuild/linux-riscv64': 0.24.0
1798 | '@esbuild/linux-s390x': 0.24.0
1799 | '@esbuild/linux-x64': 0.24.0
1800 | '@esbuild/netbsd-x64': 0.24.0
1801 | '@esbuild/openbsd-arm64': 0.24.0
1802 | '@esbuild/openbsd-x64': 0.24.0
1803 | '@esbuild/sunos-x64': 0.24.0
1804 | '@esbuild/win32-arm64': 0.24.0
1805 | '@esbuild/win32-ia32': 0.24.0
1806 | '@esbuild/win32-x64': 0.24.0
1807 |
1808 | escape-string-regexp@4.0.0: {}
1809 |
1810 | estree-walker@0.6.1: {}
1811 |
1812 | estree-walker@3.0.3:
1813 | dependencies:
1814 | '@types/estree': 1.0.6
1815 |
1816 | exit-hook@2.2.1: {}
1817 |
1818 | expect-type@1.1.0: {}
1819 |
1820 | fsevents@2.3.3:
1821 | optional: true
1822 |
1823 | function-bind@1.1.2: {}
1824 |
1825 | get-source@2.0.12:
1826 | dependencies:
1827 | data-uri-to-buffer: 2.0.2
1828 | source-map: 0.6.1
1829 |
1830 | glob-to-regexp@0.4.1: {}
1831 |
1832 | hasown@2.0.2:
1833 | dependencies:
1834 | function-bind: 1.1.2
1835 |
1836 | is-core-module@2.16.1:
1837 | dependencies:
1838 | hasown: 2.0.2
1839 |
1840 | itty-time@1.0.6: {}
1841 |
1842 | json-diff-ts@4.1.0:
1843 | dependencies:
1844 | lodash: '@technically/lodash@4.17.0'
1845 |
1846 | lodash-es@4.17.21: {}
1847 |
1848 | loupe@3.1.2: {}
1849 |
1850 | magic-string@0.25.9:
1851 | dependencies:
1852 | sourcemap-codec: 1.4.8
1853 |
1854 | magic-string@0.30.17:
1855 | dependencies:
1856 | '@jridgewell/sourcemap-codec': 1.5.0
1857 |
1858 | mime@3.0.0: {}
1859 |
1860 | miniflare@0.0.0-dc669c404:
1861 | dependencies:
1862 | '@cspotcode/source-map-support': 0.8.1
1863 | acorn: 8.14.0
1864 | acorn-walk: 8.3.4
1865 | capnp-ts: 0.7.0
1866 | exit-hook: 2.2.1
1867 | glob-to-regexp: 0.4.1
1868 | stoppable: 1.1.0
1869 | undici: 5.28.4
1870 | workerd: 1.20241106.1
1871 | ws: 8.18.0
1872 | youch: 3.3.4
1873 | zod: 3.24.1
1874 | transitivePeerDependencies:
1875 | - bufferutil
1876 | - supports-color
1877 | - utf-8-validate
1878 |
1879 | miniflare@3.20241218.0:
1880 | dependencies:
1881 | '@cspotcode/source-map-support': 0.8.1
1882 | acorn: 8.14.0
1883 | acorn-walk: 8.3.4
1884 | capnp-ts: 0.7.0
1885 | exit-hook: 2.2.1
1886 | glob-to-regexp: 0.4.1
1887 | stoppable: 1.1.0
1888 | undici: 5.28.4
1889 | workerd: 1.20241218.0
1890 | ws: 8.18.0
1891 | youch: 3.3.4
1892 | zod: 3.24.1
1893 | transitivePeerDependencies:
1894 | - bufferutil
1895 | - supports-color
1896 | - utf-8-validate
1897 |
1898 | ms@2.1.3: {}
1899 |
1900 | mustache@4.2.0: {}
1901 |
1902 | nanoid@3.3.8: {}
1903 |
1904 | node-forge@1.3.1: {}
1905 |
1906 | ohash@1.1.4: {}
1907 |
1908 | path-parse@1.0.7: {}
1909 |
1910 | path-to-regexp@6.3.0: {}
1911 |
1912 | pathe@1.1.2: {}
1913 |
1914 | pathval@2.0.0: {}
1915 |
1916 | picocolors@1.1.1: {}
1917 |
1918 | postcss@8.4.49:
1919 | dependencies:
1920 | nanoid: 3.3.8
1921 | picocolors: 1.1.1
1922 | source-map-js: 1.2.1
1923 |
1924 | printable-characters@1.0.42: {}
1925 |
1926 | readdirp@4.0.2: {}
1927 |
1928 | resolve.exports@2.0.3: {}
1929 |
1930 | resolve@1.22.10:
1931 | dependencies:
1932 | is-core-module: 2.16.1
1933 | path-parse: 1.0.7
1934 | supports-preserve-symlinks-flag: 1.0.0
1935 |
1936 | rollup-plugin-inject@3.0.2:
1937 | dependencies:
1938 | estree-walker: 0.6.1
1939 | magic-string: 0.25.9
1940 | rollup-pluginutils: 2.8.2
1941 |
1942 | rollup-plugin-node-polyfills@0.2.1:
1943 | dependencies:
1944 | rollup-plugin-inject: 3.0.2
1945 |
1946 | rollup-pluginutils@2.8.2:
1947 | dependencies:
1948 | estree-walker: 0.6.1
1949 |
1950 | rollup@4.29.1:
1951 | dependencies:
1952 | '@types/estree': 1.0.6
1953 | optionalDependencies:
1954 | '@rollup/rollup-android-arm-eabi': 4.29.1
1955 | '@rollup/rollup-android-arm64': 4.29.1
1956 | '@rollup/rollup-darwin-arm64': 4.29.1
1957 | '@rollup/rollup-darwin-x64': 4.29.1
1958 | '@rollup/rollup-freebsd-arm64': 4.29.1
1959 | '@rollup/rollup-freebsd-x64': 4.29.1
1960 | '@rollup/rollup-linux-arm-gnueabihf': 4.29.1
1961 | '@rollup/rollup-linux-arm-musleabihf': 4.29.1
1962 | '@rollup/rollup-linux-arm64-gnu': 4.29.1
1963 | '@rollup/rollup-linux-arm64-musl': 4.29.1
1964 | '@rollup/rollup-linux-loongarch64-gnu': 4.29.1
1965 | '@rollup/rollup-linux-powerpc64le-gnu': 4.29.1
1966 | '@rollup/rollup-linux-riscv64-gnu': 4.29.1
1967 | '@rollup/rollup-linux-s390x-gnu': 4.29.1
1968 | '@rollup/rollup-linux-x64-gnu': 4.29.1
1969 | '@rollup/rollup-linux-x64-musl': 4.29.1
1970 | '@rollup/rollup-win32-arm64-msvc': 4.29.1
1971 | '@rollup/rollup-win32-ia32-msvc': 4.29.1
1972 | '@rollup/rollup-win32-x64-msvc': 4.29.1
1973 | fsevents: 2.3.3
1974 |
1975 | selfsigned@2.4.1:
1976 | dependencies:
1977 | '@types/node-forge': 1.3.11
1978 | node-forge: 1.3.1
1979 |
1980 | semver@7.6.3: {}
1981 |
1982 | siginfo@2.0.0: {}
1983 |
1984 | source-map-js@1.2.1: {}
1985 |
1986 | source-map@0.6.1: {}
1987 |
1988 | sourcemap-codec@1.4.8: {}
1989 |
1990 | stackback@0.0.2: {}
1991 |
1992 | stacktracey@2.1.8:
1993 | dependencies:
1994 | as-table: 1.0.55
1995 | get-source: 2.0.12
1996 |
1997 | std-env@3.8.0: {}
1998 |
1999 | stoppable@1.1.0: {}
2000 |
2001 | supports-preserve-symlinks-flag@1.0.0: {}
2002 |
2003 | tinybench@2.9.0: {}
2004 |
2005 | tinyexec@0.3.1: {}
2006 |
2007 | tinypool@1.0.2: {}
2008 |
2009 | tinyrainbow@1.2.0: {}
2010 |
2011 | tinyspy@3.0.2: {}
2012 |
2013 | tslib@2.8.1: {}
2014 |
2015 | typescript@5.7.2: {}
2016 |
2017 | ufo@1.5.4: {}
2018 |
2019 | undici-types@6.20.0: {}
2020 |
2021 | undici@5.28.4:
2022 | dependencies:
2023 | '@fastify/busboy': 2.1.1
2024 |
2025 | unenv-nightly@2.0.0-20241121-161142-806b5c0:
2026 | dependencies:
2027 | defu: 6.1.4
2028 | ohash: 1.1.4
2029 | pathe: 1.1.2
2030 | ufo: 1.5.4
2031 |
2032 | unenv-nightly@2.0.0-20241204-140205-a5d5190:
2033 | dependencies:
2034 | defu: 6.1.4
2035 | ohash: 1.1.4
2036 | pathe: 1.1.2
2037 | ufo: 1.5.4
2038 |
2039 | vite-node@2.1.8(@types/node@22.10.2):
2040 | dependencies:
2041 | cac: 6.7.14
2042 | debug: 4.4.0
2043 | es-module-lexer: 1.5.4
2044 | pathe: 1.1.2
2045 | vite: 5.4.11(@types/node@22.10.2)
2046 | transitivePeerDependencies:
2047 | - '@types/node'
2048 | - less
2049 | - lightningcss
2050 | - sass
2051 | - sass-embedded
2052 | - stylus
2053 | - sugarss
2054 | - supports-color
2055 | - terser
2056 |
2057 | vite@5.4.11(@types/node@22.10.2):
2058 | dependencies:
2059 | esbuild: 0.21.5
2060 | postcss: 8.4.49
2061 | rollup: 4.29.1
2062 | optionalDependencies:
2063 | '@types/node': 22.10.2
2064 | fsevents: 2.3.3
2065 |
2066 | vitest@2.1.8(@types/node@22.10.2):
2067 | dependencies:
2068 | '@vitest/expect': 2.1.8
2069 | '@vitest/mocker': 2.1.8(vite@5.4.11(@types/node@22.10.2))
2070 | '@vitest/pretty-format': 2.1.8
2071 | '@vitest/runner': 2.1.8
2072 | '@vitest/snapshot': 2.1.8
2073 | '@vitest/spy': 2.1.8
2074 | '@vitest/utils': 2.1.8
2075 | chai: 5.1.2
2076 | debug: 4.4.0
2077 | expect-type: 1.1.0
2078 | magic-string: 0.30.17
2079 | pathe: 1.1.2
2080 | std-env: 3.8.0
2081 | tinybench: 2.9.0
2082 | tinyexec: 0.3.1
2083 | tinypool: 1.0.2
2084 | tinyrainbow: 1.2.0
2085 | vite: 5.4.11(@types/node@22.10.2)
2086 | vite-node: 2.1.8(@types/node@22.10.2)
2087 | why-is-node-running: 2.3.0
2088 | optionalDependencies:
2089 | '@types/node': 22.10.2
2090 | transitivePeerDependencies:
2091 | - less
2092 | - lightningcss
2093 | - msw
2094 | - sass
2095 | - sass-embedded
2096 | - stylus
2097 | - sugarss
2098 | - supports-color
2099 | - terser
2100 |
2101 | why-is-node-running@2.3.0:
2102 | dependencies:
2103 | siginfo: 2.0.0
2104 | stackback: 0.0.2
2105 |
2106 | workerd@1.20241106.1:
2107 | optionalDependencies:
2108 | '@cloudflare/workerd-darwin-64': 1.20241106.1
2109 | '@cloudflare/workerd-darwin-arm64': 1.20241106.1
2110 | '@cloudflare/workerd-linux-64': 1.20241106.1
2111 | '@cloudflare/workerd-linux-arm64': 1.20241106.1
2112 | '@cloudflare/workerd-windows-64': 1.20241106.1
2113 |
2114 | workerd@1.20241218.0:
2115 | optionalDependencies:
2116 | '@cloudflare/workerd-darwin-64': 1.20241218.0
2117 | '@cloudflare/workerd-darwin-arm64': 1.20241218.0
2118 | '@cloudflare/workerd-linux-64': 1.20241218.0
2119 | '@cloudflare/workerd-linux-arm64': 1.20241218.0
2120 | '@cloudflare/workerd-windows-64': 1.20241218.0
2121 |
2122 | wrangler@0.0.0-dc669c404(@cloudflare/workers-types@4.20241224.0):
2123 | dependencies:
2124 | '@cloudflare/kv-asset-handler': 0.3.4
2125 | '@cloudflare/workers-shared': 0.8.0
2126 | blake3-wasm: 2.1.5
2127 | chokidar: 4.0.3
2128 | date-fns: 4.1.0
2129 | esbuild: 0.24.0
2130 | itty-time: 1.0.6
2131 | miniflare: 0.0.0-dc669c404
2132 | nanoid: 3.3.8
2133 | path-to-regexp: 6.3.0
2134 | resolve: 1.22.10
2135 | resolve.exports: 2.0.3
2136 | selfsigned: 2.4.1
2137 | source-map: 0.6.1
2138 | unenv: unenv-nightly@2.0.0-20241121-161142-806b5c0
2139 | workerd: 1.20241106.1
2140 | xxhash-wasm: 1.1.0
2141 | optionalDependencies:
2142 | '@cloudflare/workers-types': 4.20241224.0
2143 | fsevents: 2.3.3
2144 | transitivePeerDependencies:
2145 | - bufferutil
2146 | - supports-color
2147 | - utf-8-validate
2148 |
2149 | wrangler@3.99.0(@cloudflare/workers-types@4.20241224.0):
2150 | dependencies:
2151 | '@cloudflare/kv-asset-handler': 0.3.4
2152 | '@esbuild-plugins/node-globals-polyfill': 0.2.3(esbuild@0.17.19)
2153 | '@esbuild-plugins/node-modules-polyfill': 0.2.2(esbuild@0.17.19)
2154 | blake3-wasm: 2.1.5
2155 | chokidar: 4.0.3
2156 | date-fns: 4.1.0
2157 | esbuild: 0.17.19
2158 | itty-time: 1.0.6
2159 | miniflare: 3.20241218.0
2160 | nanoid: 3.3.8
2161 | path-to-regexp: 6.3.0
2162 | resolve: 1.22.10
2163 | selfsigned: 2.4.1
2164 | source-map: 0.6.1
2165 | unenv: unenv-nightly@2.0.0-20241204-140205-a5d5190
2166 | workerd: 1.20241218.0
2167 | xxhash-wasm: 1.1.0
2168 | optionalDependencies:
2169 | '@cloudflare/workers-types': 4.20241224.0
2170 | fsevents: 2.3.3
2171 | transitivePeerDependencies:
2172 | - bufferutil
2173 | - supports-color
2174 | - utf-8-validate
2175 |
2176 | ws@8.18.0: {}
2177 |
2178 | xxhash-wasm@1.1.0: {}
2179 |
2180 | youch@3.3.4:
2181 | dependencies:
2182 | cookie: 0.7.2
2183 | mustache: 4.2.0
2184 | stacktracey: 2.1.8
2185 |
2186 | zod@3.24.1: {}
2187 |
--------------------------------------------------------------------------------
/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | - examples/*
--------------------------------------------------------------------------------
/src/decorator.ts:
--------------------------------------------------------------------------------
1 | import type { DurableObject } from "cloudflare:workers";
2 | import { type SnapshotPolicy, state } from "./index.js";
3 | import { unreachable } from "./util.js";
4 |
5 | type FieldDecoratorFactoryReturn = (
6 | value: T,
7 | metadata: { kind: string; name: string },
8 | ) => FieldDecoratorReturn;
9 |
10 | type FieldDecoratorReturn = (this: DurableObject, initialValue: T) => T;
11 |
12 | type DiffableArgs =
13 | | []
14 | | [DiffableOpts]
15 | | [name?: string]
16 | | [_: any, { kind: string; name: string }];
17 |
18 | type DiffableOpts = {
19 | /**
20 | * The name of the state, typically the name of the field.
21 | */
22 | name?: string;
23 | /**
24 | * Diffable-objects will automatically snapshot the state perodically based on this policy to minimize
25 | * the number of diffs that must be applied to restore the state when the Durable Object is restarted.
26 | */
27 | snapshotPolicy?: SnapshotPolicy;
28 | };
29 |
30 | /**
31 | * Dynamically create a state object that persists changes to durable storage using Proxy and SQLite.
32 | *
33 | * ```
34 | * import { DurableObject } from "cloudflare:workers";
35 | * import { diffable } from "diffable-objects";
36 | *
37 | * class Counter extends DurableObject {
38 | * @diffable
39 | * #state = { count: 0 };
40 | *
41 | * async fetch(request) {
42 | * this.#state.count += 1;
43 | * return new Response(`Count: ${this.#state.count}`);
44 | * }
45 | * }
46 | * ```
47 | */
48 | export function diffable(
49 | _: any,
50 | { kind, name }: { kind: string; name: string },
51 | ): FieldDecoratorReturn;
52 | /**
53 | * Dynamically create a state object that persists changes to durable storage using Proxy and SQLite.
54 | *
55 | * ```
56 | * import { DurableObject } from "cloudflare:workers";
57 | * import { diffable } from "diffable-objects";
58 | *
59 | * class Counter extends DurableObject {
60 | * @diffable("counter")
61 | * #state = { count: 0 };
62 | *
63 | * async fetch(request) {
64 | * this.#state.count += 1;
65 | * return new Response(`Count: ${this.#state.count}`);
66 | * }
67 | * }
68 | * ```
69 | */
70 | export function diffable(name?: string): FieldDecoratorFactoryReturn;
71 | /**
72 | * Dynamically create a state object that persists changes to durable storage using Proxy and SQLite.
73 | *
74 | * ```
75 | * import { DurableObject } from "cloudflare:workers";
76 | * import { diffable } from "diffable-objects";
77 | *
78 | * class Counter extends DurableObject {
79 | * @diffable({ name: "counter", snapshotPolicy: "never" })
80 | * #state = { count: 0 };
81 | *
82 | * async fetch(request) {
83 | * this.#state.count += 1;
84 | * return new Response(`Count: ${this.#state.count}`);
85 | * }
86 | * }
87 | * ```
88 | */
89 | export function diffable(
90 | options: DiffableOpts,
91 | ): FieldDecoratorFactoryReturn;
92 | export function diffable():
93 | | FieldDecoratorReturn
94 | | FieldDecoratorFactoryReturn {
95 | // biome-ignore lint/style/noArguments:
96 | const args = arguments as unknown as DiffableArgs;
97 | const fn =
98 | (opts: DiffableOpts = {}) =>
99 | (_: any, { kind, name: fieldName }: { kind: string; name: string }) => {
100 | if (kind === "field") {
101 | return function (this: DurableObject, initialValue: any) {
102 | const fieldNameNonPrivate = fieldName.replace(/^#/, "");
103 | return state(
104 | this.ctx,
105 | opts.name ?? fieldNameNonPrivate,
106 | initialValue,
107 | {
108 | snapshotPolicy: opts.snapshotPolicy ?? { changes: 10 },
109 | },
110 | );
111 | };
112 | }
113 |
114 | throw new Error("Only fields can be persistable");
115 | };
116 |
117 | if (args.length === 0) {
118 | return fn();
119 | }
120 |
121 | if (args.length === 1) {
122 | const [optsOrName] = args;
123 |
124 | if (typeof optsOrName === "object") {
125 | return fn(optsOrName);
126 | }
127 |
128 | return fn(optsOrName ? { name: optsOrName } : {});
129 | }
130 |
131 | const [value, metadata] = args;
132 | return fn()(value, metadata ?? unreachable());
133 | }
134 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import { recursivelyObservable } from "./observable.js";
2 | import { SqliteState } from "./sqlite.js";
3 | import { unreachable } from "./util.js";
4 |
5 | export * from "./decorator.js";
6 |
7 | export type SnapshotPolicy = "never" | "every-change" | { changes: number };
8 |
9 | export type StateOptions = {
10 | /**
11 | * Diffable-objects will automatically snapshot the state perodically based on this policy to minimize the
12 | * number of diffs that must be applied to restore the state when the Durable Object is restarted.
13 | */
14 | snapshotPolicy?: SnapshotPolicy;
15 | };
16 |
17 | /**
18 | * Dynamically create a state object that persists changes to durable storage using Proxy and SQLite.
19 | *
20 | * @example
21 | * ```
22 | * import { DurableObject } from "cloudflare:workers";
23 | * import { state } from "diffable-objects";
24 | *
25 | * class Counter extends DurableObject {
26 | * #state = state(this, "counter", { count: 0 });
27 | *
28 | * async fetch(request) {
29 | * this.#state.count += 1;
30 | * return new Response(`Count: ${this.#state.count}`);
31 | * }
32 | * }
33 | * ```
34 | *
35 | * @param ctx the DurableObject state.
36 | * @param name the name of the state, typically the name of the field.
37 | * @param initialState the initial state of this object, this must be the same every time the DO is created.
38 | * @param options options for configuring how the state is persisted.
39 | * @returns a copy of state that will persist changes.
40 | */
41 | export function state(
42 | ctx: DurableObjectState,
43 | name: string,
44 | initialState: T,
45 | options: StateOptions = {
46 | snapshotPolicy: { changes: 10 },
47 | },
48 | ): T {
49 | const state = new SqliteState(name, ctx.storage);
50 | const data = state.resume(initialState);
51 | return recursivelyObservable(data, {
52 | onUpdate(changes, data) {
53 | state.appendChanges(changes);
54 | maybeSnapshot(data, state, options.snapshotPolicy ?? { changes: 10 });
55 | },
56 | });
57 | }
58 |
59 | function maybeSnapshot(
60 | data: T,
61 | state: SqliteState,
62 | snapshotPolicy: SnapshotPolicy,
63 | ) {
64 | if (snapshotPolicy === "every-change") {
65 | state.snapshot(data);
66 | } else if (
67 | typeof snapshotPolicy === "object" &&
68 | "changes" in snapshotPolicy
69 | ) {
70 | const latest = state.latestChange() ?? unreachable();
71 | if (latest.id % snapshotPolicy.changes === 0) {
72 | state.snapshot(data);
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/observable.ts:
--------------------------------------------------------------------------------
1 | import { atomizeChangeset, diff, type IAtomicChange } from "json-diff-ts";
2 |
3 | type ProcessUpdateFn = (applyChanges: () => void) => void;
4 |
5 | type RecursivelyObservableOptions = {
6 | processUpdate?: ProcessUpdateFn;
7 | onUpdate: (changes: IAtomicChange[], data: T) => void;
8 | };
9 |
10 | export function recursivelyObservable(
11 | data: T,
12 | opts: RecursivelyObservableOptions,
13 | ): T {
14 | const processUpdate =
15 | opts.processUpdate ??
16 | ((applyChanges) => {
17 | const old = structuredClone(data);
18 | applyChanges();
19 | const diffs = diff(old, data);
20 | const atomicChanges = atomizeChangeset(diffs);
21 | if (atomicChanges.length > 0) {
22 | opts.onUpdate(atomicChanges, data);
23 | }
24 | });
25 |
26 | const proxyOpts: ProxyHandler = {
27 | get(target, p) {
28 | const property = target[p as keyof T];
29 | if (property !== null && typeof property === "object") {
30 | // @ts-ignore TODO
31 | return recursivelyObservable(property, {
32 | ...opts,
33 | processUpdate,
34 | });
35 | }
36 | return target[p as keyof T];
37 | },
38 | set(target, p, newValue) {
39 | processUpdate(() => {
40 | target[p as keyof T] = newValue;
41 | });
42 | return true;
43 | },
44 | };
45 |
46 | return new Proxy(data, proxyOpts) as T;
47 | }
48 |
--------------------------------------------------------------------------------
/src/sqlite.ts:
--------------------------------------------------------------------------------
1 | import type { IAtomicChange, Operation } from "json-diff-ts";
2 | import { replay, type TrackerActions } from "./tracker.js";
3 |
4 | const INITIAL_QUERY = `
5 | CREATE TABLE IF NOT EXISTS changes (
6 | id INTEGER PRIMARY KEY AUTOINCREMENT,
7 | state TEXT NOT NULL,
8 | type TEXT NOT NULL,
9 | key TEXT NOT NULL,
10 | path TEXT NOT NULL,
11 | valueType TEXT,
12 | value TEXT,
13 | oldValue TEXT
14 | );
15 |
16 | CREATE TABLE IF NOT EXISTS snapshots (
17 | id INTEGER PRIMARY KEY AUTOINCREMENT,
18 | state TEXT NOT NULL,
19 | value TEXT NOT NULL,
20 | changes_id INTEGER NOT NULL,
21 | created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
22 | );
23 | `;
24 |
25 | type Change = {
26 | type: string;
27 | key: string;
28 | path: string;
29 | valueType: string | null;
30 | value: string | null;
31 | oldValue: string | null;
32 | };
33 |
34 | export class SqliteState {
35 | #name: string;
36 | #storage: DurableObjectStorage;
37 | #db: SqlStorage;
38 |
39 | constructor(name: string, storage: DurableObjectStorage) {
40 | this.#name = name;
41 | this.#storage = storage;
42 | this.#db = storage.sql;
43 | this.#db.exec(INITIAL_QUERY);
44 | }
45 |
46 | resume(initialValue: T): T {
47 | const results = this.#db.exec<{ value: string; changes_id: number }>(
48 | "SELECT value, changes_id FROM snapshots WHERE state = ? ORDER BY created_at DESC LIMIT 1",
49 | this.#name,
50 | );
51 | const result = results.next();
52 |
53 | const mapChanges = (changes: Change[]) =>
54 | changes.map(
55 | (change) =>
56 | ({
57 | type: "change",
58 | atomicChange: {
59 | type: change.type as Operation,
60 | key: change.key,
61 | path: change.path,
62 | valueType: change.valueType,
63 | value: change.value ? JSON.parse(change.value) : undefined,
64 | oldValue: change.oldValue
65 | ? JSON.parse(change.oldValue)
66 | : undefined,
67 | },
68 | }) as const,
69 | );
70 |
71 | if (!result.done) {
72 | const { value, changes_id } = result.value;
73 | const changes = this.#db
74 | .exec(
75 | "SELECT * FROM changes WHERE id > ? AND state = ?",
76 | changes_id,
77 | this.#name,
78 | )
79 | .toArray();
80 |
81 | const actions: TrackerActions = [
82 | {
83 | type: "snapshot",
84 | value: JSON.parse(value),
85 | },
86 | ...mapChanges(changes),
87 | ];
88 | return replay(actions, initialValue);
89 | }
90 |
91 | const changes = this.#db
92 | .exec("SELECT * FROM changes WHERE state = ?", this.#name)
93 | .toArray();
94 | return replay(mapChanges(changes), initialValue);
95 | }
96 |
97 | appendChanges(changes: IAtomicChange[]): void {
98 | if (changes.length === 0) {
99 | return;
100 | }
101 |
102 | this.#storage.transactionSync(() => {
103 | for (const { type, key, path, valueType, value, oldValue } of changes) {
104 | this.#db.exec(
105 | "INSERT INTO changes (state, type, key, path, valueType, value, oldValue) VALUES (?, ?, ?, ?, ?, ?, ?)",
106 | this.#name,
107 | type,
108 | key,
109 | path,
110 | valueType,
111 | value ? JSON.stringify(value) : null,
112 | oldValue ? JSON.stringify(oldValue) : null,
113 | );
114 | }
115 | });
116 | }
117 |
118 | latestChange(): { id: number } | null {
119 | const result = this.#db
120 | .exec<{ id: number }>(
121 | "SELECT id FROM changes WHERE state = ? ORDER BY id DESC LIMIT 1",
122 | this.#name,
123 | )
124 | .next();
125 |
126 | if (result.done) {
127 | return null;
128 | }
129 |
130 | return { id: result.value.id };
131 | }
132 |
133 | latestSnapshot(): Date | null {
134 | const result = this.#db
135 | .exec<{ created_at: string }>(
136 | "SELECT created_at FROM snapshots WHERE state = ? ORDER BY created_at DESC LIMIT 1",
137 | this.#name,
138 | )
139 | .next();
140 |
141 | if (result.done) {
142 | return null;
143 | }
144 |
145 | return new Date(result.value.created_at);
146 | }
147 |
148 | snapshot(snapshot: T): void {
149 | const { id } = this.#db
150 | .exec<{ id: number }>(
151 | "SELECT id FROM changes WHERE state = ? ORDER BY id DESC LIMIT 1",
152 | this.#name,
153 | )
154 | .one();
155 |
156 | // TODO: assert there are changes in the DB before we can snapshot.
157 |
158 | this.#db.exec(
159 | "INSERT INTO snapshots (state, value, changes_id) VALUES (?, ?, ?)",
160 | this.#name,
161 | JSON.stringify(snapshot),
162 | id,
163 | );
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/src/tracker.ts:
--------------------------------------------------------------------------------
1 | import {
2 | applyChangeset,
3 | unatomizeChangeset,
4 | type IAtomicChange,
5 | } from "json-diff-ts";
6 |
7 | type Snapshot = {
8 | type: "snapshot";
9 | value: unknown;
10 | };
11 |
12 | type Change = {
13 | type: "change";
14 | atomicChange: IAtomicChange;
15 | };
16 |
17 | export type TrackerActions = [Snapshot, ...Change[]] | Change[];
18 |
19 | export function replay(
20 | actions: TrackerActions,
21 | initialValue: T,
22 | ): T {
23 | if (actions.length === 0) {
24 | return initialValue;
25 | }
26 |
27 | let data =
28 | actions[0].type === "snapshot" ? (actions[0].value as T) : initialValue;
29 | assertChanges(actions);
30 |
31 | const atomicChanges = actions.map((it) => it.atomicChange);
32 | const changeSet = unatomizeChangeset(atomicChanges);
33 | data = applyChangeset(data, changeSet);
34 |
35 | return data;
36 | }
37 |
38 | function assertChanges(actions: TrackerActions): asserts actions is Change[] {
39 | if (actions.length === 0) {
40 | throw new Error("No changes to assert");
41 | }
42 |
43 | if (actions[0].type === "snapshot") {
44 | actions.shift();
45 | }
46 |
47 | actions.forEach((it, i) => {
48 | if (it.type !== "change") {
49 | throw new Error(`Expected changes, but got snapshot at index ${i}`);
50 | }
51 | });
52 | }
53 |
--------------------------------------------------------------------------------
/src/util.ts:
--------------------------------------------------------------------------------
1 | export function unreachable(): never {
2 | throw new Error("unreachable");
3 | }
4 |
--------------------------------------------------------------------------------
/tests/decorator.test.ts:
--------------------------------------------------------------------------------
1 | import { diffable } from "../src/index.js";
2 | import { describe, expect } from "vitest";
3 | import { durableIt, snapshots } from "./helper.js";
4 | import { DurableObject } from "cloudflare:workers";
5 | import { env } from "cloudflare:test";
6 |
7 | describe("state tracking with decorators", () => {
8 | durableIt("should track with no args", (objectState) => {
9 | class TestObject extends DurableObject {
10 | @diffable
11 | state = { count: 0 };
12 | }
13 |
14 | const obj = new TestObject(objectState, env);
15 | for (let i = 0; i < 20; i++) {
16 | obj.state.count++;
17 | }
18 |
19 | const snapshowRows = snapshots(objectState.storage.sql);
20 | expect(snapshowRows).toMatchInlineSnapshot(`
21 | [
22 | {
23 | "changes_id": 10,
24 | "id": 1,
25 | "state": "state",
26 | "value": {
27 | "count": 10,
28 | },
29 | },
30 | {
31 | "changes_id": 20,
32 | "id": 2,
33 | "state": "state",
34 | "value": {
35 | "count": 20,
36 | },
37 | },
38 | ]
39 | `);
40 | });
41 |
42 | durableIt("should track with empty args", (objectState) => {
43 | class TestObject extends DurableObject {
44 | @diffable()
45 | state = { count: 0 };
46 | }
47 |
48 | const obj = new TestObject(objectState, env);
49 | for (let i = 0; i < 20; i++) {
50 | obj.state.count++;
51 | }
52 |
53 | const snapshowRows = snapshots(objectState.storage.sql);
54 | expect(snapshowRows).toMatchInlineSnapshot(`
55 | [
56 | {
57 | "changes_id": 10,
58 | "id": 1,
59 | "state": "state",
60 | "value": {
61 | "count": 10,
62 | },
63 | },
64 | {
65 | "changes_id": 20,
66 | "id": 2,
67 | "state": "state",
68 | "value": {
69 | "count": 20,
70 | },
71 | },
72 | ]
73 | `);
74 | });
75 |
76 | durableIt("should track with named args", (objectState) => {
77 | class TestObject extends DurableObject {
78 | @diffable("foo")
79 | state = { count: 0 };
80 | }
81 |
82 | const obj = new TestObject(objectState, env);
83 | for (let i = 0; i < 20; i++) {
84 | obj.state.count++;
85 | }
86 |
87 | const snapshowRows = snapshots(objectState.storage.sql);
88 | expect(snapshowRows).toMatchInlineSnapshot(`
89 | [
90 | {
91 | "changes_id": 10,
92 | "id": 1,
93 | "state": "foo",
94 | "value": {
95 | "count": 10,
96 | },
97 | },
98 | {
99 | "changes_id": 20,
100 | "id": 2,
101 | "state": "foo",
102 | "value": {
103 | "count": 20,
104 | },
105 | },
106 | ]
107 | `);
108 | });
109 |
110 | durableIt("should track with options", (objectState) => {
111 | class TestObject extends DurableObject {
112 | @diffable({ name: "foo", snapshotPolicy: "every-change" })
113 | state = { count: 0 };
114 | }
115 |
116 | const obj = new TestObject(objectState, env);
117 | obj.state.count++;
118 | obj.state.count++;
119 |
120 | const snapshowRows = snapshots(objectState.storage.sql);
121 | expect(snapshowRows).toMatchInlineSnapshot(`
122 | [
123 | {
124 | "changes_id": 1,
125 | "id": 1,
126 | "state": "foo",
127 | "value": {
128 | "count": 1,
129 | },
130 | },
131 | {
132 | "changes_id": 2,
133 | "id": 2,
134 | "state": "foo",
135 | "value": {
136 | "count": 2,
137 | },
138 | },
139 | ]
140 | `);
141 | });
142 | });
143 |
--------------------------------------------------------------------------------
/tests/global.d.ts:
--------------------------------------------------------------------------------
1 | declare module "cloudflare:test" {
2 | interface ProvidedEnv {
3 | test: DurableObjectNamespace;
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/tests/helper.ts:
--------------------------------------------------------------------------------
1 | import { env, runInDurableObject } from "cloudflare:test";
2 | import { it } from "vitest";
3 |
4 | export async function runInTestDurableObject(
5 | fn: (objectState: DurableObjectState) => void,
6 | ) {
7 | const id = env.test.idFromName("test");
8 | const stub = env.test.get(id);
9 | await runInDurableObject(stub, async (_, objectState) => {
10 | fn(objectState);
11 | });
12 | }
13 |
14 | export function durableIt(
15 | name: string,
16 | fn: (objectState: DurableObjectState) => void,
17 | ) {
18 | it(name, async () => {
19 | await runInTestDurableObject(fn);
20 | });
21 | }
22 |
23 | type SnapshotRow = {
24 | id: number;
25 | state: string;
26 | value: string;
27 | changes_id: number;
28 | created_at?: string;
29 | };
30 |
31 | export function snapshots(sql: SqlStorage) {
32 | return sql
33 | .exec("SELECT * FROM snapshots")
34 | .toArray()
35 | .map((row) => {
36 | // biome-ignore lint/performance/noDelete:
37 | delete row.created_at;
38 | return {
39 | ...row,
40 | value: JSON.parse(row.value),
41 | };
42 | });
43 | }
44 |
--------------------------------------------------------------------------------
/tests/index.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect } from "vitest";
2 | import { durableIt, snapshots } from "./helper.js";
3 | import * as diffable from "../src/index.js";
4 |
5 | describe("state tracking", () => {
6 | durableIt("should be able to track changes in root object", (objectState) => {
7 | const state = diffable.state(objectState, "test", { a: 1, b: 2 });
8 | state.a = 3;
9 | expect(state).toEqual({ a: 3, b: 2 });
10 |
11 | const newCopyOfState = diffable.state(objectState, "test", { a: 1, b: 2 });
12 | expect(newCopyOfState).toEqual({ a: 3, b: 2 });
13 | });
14 |
15 | durableIt("should never snapshot", (objectState) => {
16 | const state = diffable.state(
17 | objectState,
18 | "test",
19 | { count: 0 },
20 | {
21 | snapshotPolicy: "never",
22 | },
23 | );
24 |
25 | for (let i = 0; i < 500; i++) {
26 | state.count++;
27 | }
28 |
29 | const snapshotRows = snapshots(objectState.storage.sql);
30 | expect(snapshotRows).toEqual([]);
31 | });
32 |
33 | durableIt(
34 | "should automatically snapshot after every change",
35 | (objectState) => {
36 | const state = diffable.state(
37 | objectState,
38 | "test",
39 | { count: 0 },
40 | {
41 | snapshotPolicy: "every-change",
42 | },
43 | );
44 |
45 | state.count++;
46 | state.count++;
47 | state.count++;
48 |
49 | const snapshotRows = snapshots(objectState.storage.sql);
50 | expect(snapshotRows).toMatchInlineSnapshot(`
51 | [
52 | {
53 | "changes_id": 1,
54 | "id": 1,
55 | "state": "test",
56 | "value": {
57 | "count": 1,
58 | },
59 | },
60 | {
61 | "changes_id": 2,
62 | "id": 2,
63 | "state": "test",
64 | "value": {
65 | "count": 2,
66 | },
67 | },
68 | {
69 | "changes_id": 3,
70 | "id": 3,
71 | "state": "test",
72 | "value": {
73 | "count": 3,
74 | },
75 | },
76 | ]
77 | `);
78 | },
79 | );
80 |
81 | durableIt("should automatically snapshot after 2 changes", (objectState) => {
82 | const state = diffable.state(
83 | objectState,
84 | "test",
85 | { count: 0 },
86 | {
87 | snapshotPolicy: { changes: 2 },
88 | },
89 | );
90 |
91 | for (let i = 0; i < 5; i++) {
92 | state.count++;
93 | }
94 |
95 | const snapshotRows = snapshots(objectState.storage.sql);
96 | expect(snapshotRows).toMatchInlineSnapshot(`
97 | [
98 | {
99 | "changes_id": 2,
100 | "id": 1,
101 | "state": "test",
102 | "value": {
103 | "count": 2,
104 | },
105 | },
106 | {
107 | "changes_id": 4,
108 | "id": 2,
109 | "state": "test",
110 | "value": {
111 | "count": 4,
112 | },
113 | },
114 | ]
115 | `);
116 | });
117 | });
118 |
--------------------------------------------------------------------------------
/tests/observable.test.ts:
--------------------------------------------------------------------------------
1 | import { vitest, describe, expect, it } from "vitest";
2 | import { recursivelyObservable } from "../src/observable.js";
3 |
4 | describe("recursively observable", () => {
5 | it("should be able to observe changes in root object", () => {
6 | const data = { a: 1, b: 2 };
7 | const onUpdate = vitest.fn();
8 | const observable = recursivelyObservable(data, { onUpdate });
9 | observable.a = 3;
10 |
11 | expect(onUpdate).toHaveBeenCalledWith(
12 | [
13 | {
14 | key: "a",
15 | value: 3,
16 | oldValue: 1,
17 | valueType: "Number",
18 | type: "UPDATE",
19 | path: "$.a",
20 | },
21 | ],
22 | { a: 3, b: 2 },
23 | );
24 | });
25 |
26 | it("should be able to observe changes in nested object", () => {
27 | const data = { a: { b: 1 } };
28 | const onUpdate = vitest.fn();
29 | const observable = recursivelyObservable(data, { onUpdate });
30 | observable.a.b = 2;
31 |
32 | expect(onUpdate).toHaveBeenCalledWith(
33 | [
34 | {
35 | key: "b",
36 | path: "$.a.b",
37 | value: 2,
38 | oldValue: 1,
39 | valueType: "Number",
40 | type: "UPDATE",
41 | },
42 | ],
43 | { a: { b: 2 } },
44 | );
45 | });
46 | });
47 |
--------------------------------------------------------------------------------
/tests/sqlite.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect } from "vitest";
2 | import { SqliteState } from "../src/sqlite.js";
3 | import { type IAtomicChange, Operation } from "json-diff-ts";
4 | import { durableIt } from "./helper.js";
5 |
6 | const saveChange = (sql: SqlStorage, change: IAtomicChange) =>
7 | sql.exec(
8 | `INSERT INTO changes (state, key, value, oldValue, valueType, type, path) VALUES (
9 | ?, ?, ?, ?, ?, ?, ?)`,
10 | "test",
11 | change.key,
12 | change.value ? JSON.stringify(change.value) : null,
13 | change.oldValue ? JSON.stringify(change.oldValue) : null,
14 | change.valueType,
15 | change.type,
16 | change.path,
17 | );
18 |
19 | describe("sqlite state", () => {
20 | durableIt("doesn't throw", (objectState) => {
21 | void new SqliteState("test", objectState.storage);
22 | });
23 |
24 | durableIt("can resume unnested objects", (objectState) => {
25 | const { sql } = objectState.storage;
26 | const state = new SqliteState<{ a: number }>("test", objectState.storage);
27 |
28 | saveChange(sql, {
29 | key: "a",
30 | value: 3,
31 | oldValue: 1,
32 | valueType: "Number",
33 | type: Operation.UPDATE,
34 | path: "$.a",
35 | });
36 |
37 | const data = state.resume({ a: 1 });
38 | expect(data).toEqual({ a: 3 });
39 | });
40 |
41 | durableIt("can resume nested objects", (objectState) => {
42 | const { sql } = objectState.storage;
43 | const state = new SqliteState<{ a: { b: number } }>(
44 | "test",
45 | objectState.storage,
46 | );
47 |
48 | saveChange(sql, {
49 | key: "b",
50 | path: "$.a.b",
51 | value: 2,
52 | oldValue: 1,
53 | valueType: "Number",
54 | type: Operation.UPDATE,
55 | });
56 |
57 | const data = state.resume({ a: { b: 1 } });
58 | expect(data).toEqual({ a: { b: 2 } });
59 | });
60 |
61 | durableIt("can resume with snapshot", (objectState) => {
62 | const { sql } = objectState.storage;
63 | const state = new SqliteState<{ a: number }>("test", objectState.storage);
64 |
65 | saveChange(sql, {
66 | key: "a",
67 | value: 3,
68 | oldValue: 1,
69 | valueType: "Number",
70 | type: Operation.UPDATE,
71 | path: "$.a",
72 | });
73 |
74 | sql.exec(
75 | `INSERT INTO snapshots (state, value, changes_id)
76 | VALUES ('test', ?, (SELECT MAX(id) FROM changes WHERE state = 'test'))`,
77 | JSON.stringify({ a: 3 }),
78 | );
79 |
80 | const data = state.resume({ a: 1 });
81 | expect(data).toEqual({ a: 3 });
82 | });
83 |
84 | durableIt("can append changes", (objectState) => {
85 | const { sql } = objectState.storage;
86 | const state = new SqliteState<{ a: number }>("test", objectState.storage);
87 |
88 | state.appendChanges([
89 | {
90 | key: "a",
91 | value: 3,
92 | oldValue: 1,
93 | valueType: "Number",
94 | type: Operation.UPDATE,
95 | path: "$.a",
96 | },
97 | {
98 | type: Operation.ADD,
99 | key: "b",
100 | value: 2,
101 | valueType: "Number",
102 | path: "$.b",
103 | },
104 | ]);
105 |
106 | const changes = sql.exec("SELECT * FROM changes").toArray();
107 | expect(changes).toEqual([
108 | {
109 | id: 1,
110 | key: "a",
111 | path: "$.a",
112 | value: "3",
113 | oldValue: "1",
114 | valueType: "Number",
115 | type: Operation.UPDATE,
116 | state: "test",
117 | },
118 | {
119 | id: 2,
120 | key: "b",
121 | oldValue: null,
122 | path: "$.b",
123 | type: Operation.ADD,
124 | value: "2",
125 | valueType: "Number",
126 | state: "test",
127 | },
128 | ]);
129 | });
130 |
131 | durableIt("can snapshot", (objectState) => {
132 | const { sql } = objectState.storage;
133 | const state = new SqliteState<{ a: number }>("test", objectState.storage);
134 |
135 | saveChange(sql, {
136 | key: "a",
137 | value: 3,
138 | oldValue: 1,
139 | valueType: "Number",
140 | type: Operation.UPDATE,
141 | path: "$.a",
142 | });
143 |
144 | state.snapshot({ a: 3 });
145 |
146 | const { value } = sql
147 | .exec<{ value: string }>("SELECT * FROM snapshots")
148 | .one();
149 | expect(value).toEqual('{"a":3}');
150 | });
151 | });
152 |
--------------------------------------------------------------------------------
/tests/worker.ts:
--------------------------------------------------------------------------------
1 | import { DurableObject, WorkerEntrypoint } from "cloudflare:workers";
2 |
3 | export class TestDurableObject extends DurableObject {}
4 |
5 | export default class Main extends WorkerEntrypoint {}
6 |
--------------------------------------------------------------------------------
/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "include": ["src/**/*.ts"],
4 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | /* Visit https://aka.ms/tsconfig to read more about this file */
4 |
5 | /* Projects */
6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
12 |
13 | /* Language and Environment */
14 | "target": "ES2022" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
16 | // "jsx": "preserve", /* Specify what JSX code is generated. */
17 | // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
26 |
27 | /* Modules */
28 | "module": "NodeNext" /* Specify what module code is generated. */,
29 | // "rootDir": "./", /* Specify the root folder within your source files. */
30 | "moduleResolution": "nodenext" /* Specify how TypeScript looks up a file from a given module specifier. */,
31 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
35 | "types": [
36 | "@cloudflare/workers-types",
37 | "@cloudflare/vitest-pool-workers"
38 | ] /* Specify type package names to be included without being referenced in a source file. */,
39 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
40 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
41 | // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
42 | // "rewriteRelativeImportExtensions": true, /* Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files. */
43 | // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
44 | // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
45 | // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
46 | // "noUncheckedSideEffectImports": true, /* Check side effect imports. */
47 | // "resolveJsonModule": true, /* Enable importing .json files. */
48 | // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
49 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
50 |
51 | /* JavaScript Support */
52 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
53 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
54 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
55 |
56 | /* Emit */
57 | "declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */,
58 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */
59 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
60 | // "sourceMap": true /* Create source map files for emitted JavaScript files. */,
61 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
62 | // "noEmit": true, /* Disable emitting files from a compilation. */
63 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
64 | "outDir": "./dist" /* Specify an output folder for all emitted files. */,
65 | // "removeComments": true, /* Disable emitting comments. */
66 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
67 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
68 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
69 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
70 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
71 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
72 | // "newLine": "crlf", /* Set the newline character for emitting files. */
73 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
74 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
75 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
76 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
77 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */
78 |
79 | /* Interop Constraints */
80 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
81 | // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
82 | // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */
83 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
84 | "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
85 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
86 | "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
87 |
88 | /* Type Checking */
89 | "strict": true /* Enable all strict type-checking options. */,
90 | "noImplicitAny": true /* Enable error reporting for expressions and declarations with an implied 'any' type. */,
91 | "strictNullChecks": true /* When type checking, take into account 'null' and 'undefined'. */,
92 | "strictFunctionTypes": true /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */,
93 | "strictBindCallApply": true /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */,
94 | "strictPropertyInitialization": true /* Check for class properties that are declared but not set in the constructor. */,
95 | "strictBuiltinIteratorReturn": true /* Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'. */,
96 | "noImplicitThis": true /* Enable error reporting when 'this' is given the type 'any'. */,
97 | "useUnknownInCatchVariables": true /* Default catch clause variables as 'unknown' instead of 'any'. */,
98 | "alwaysStrict": true /* Ensure 'use strict' is always emitted. */,
99 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
100 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
101 | "exactOptionalPropertyTypes": true /* Interpret optional property types as written, rather than adding 'undefined'. */,
102 | "noImplicitReturns": true /* Enable error reporting for codepaths that do not explicitly return in a function. */,
103 | "noFallthroughCasesInSwitch": true /* Enable error reporting for fallthrough cases in switch statements. */,
104 | "noUncheckedIndexedAccess": true /* Add 'undefined' to a type when accessed using an index. */,
105 | "noImplicitOverride": true /* Ensure overriding members in derived classes are marked with an override modifier. */,
106 | "noPropertyAccessFromIndexSignature": true /* Enforces using indexed accessors for keys declared using an indexed type. */,
107 | "allowUnusedLabels": true /* Disable error reporting for unused labels. */,
108 | "allowUnreachableCode": true /* Disable error reporting for unreachable code. */,
109 |
110 | /* Completeness */
111 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
112 | "skipLibCheck": true /* Skip type checking all .d.ts files. */
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { defineWorkersConfig } from "@cloudflare/vitest-pool-workers/config";
2 |
3 | export default defineWorkersConfig({
4 | test: {
5 | poolOptions: {
6 | workers: {
7 | main: "./tests/worker.ts",
8 | miniflare: {
9 | compatibilityDate: "2024-12-18",
10 | compatibilityFlags: ["nodejs_compat", "nodejs_compat_v2"],
11 | durableObjects: {
12 | test: {
13 | className: "TestDurableObject",
14 | useSQLite: true,
15 | },
16 | },
17 | },
18 | },
19 | },
20 | },
21 | });
22 |
--------------------------------------------------------------------------------