@statewalker/cellb 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +323 -2
- package/dist/adapters/files-backup.d.ts +16 -0
- package/dist/adapters/files-backup.js +32 -0
- package/dist/adapters/files-backup.js.map +1 -0
- package/dist/adapters/files-changelog.d.ts +33 -0
- package/dist/adapters/files-changelog.js +96 -0
- package/dist/adapters/files-changelog.js.map +1 -0
- package/dist/adapters/files-ltx.d.ts +35 -0
- package/dist/adapters/files-ltx.js +9 -0
- package/dist/adapters/files-ltx.js.map +1 -0
- package/dist/adapters/ltx-vfs.d.ts +21 -0
- package/dist/adapters/ltx-vfs.js +286 -0
- package/dist/adapters/ltx-vfs.js.map +1 -0
- package/dist/adapters/node-sqlite.d.ts +45 -0
- package/dist/adapters/node-sqlite.js +254 -0
- package/dist/adapters/node-sqlite.js.map +1 -0
- package/dist/adapters/wasm-page-hook.d.ts +26 -0
- package/dist/adapters/wasm-page-hook.js +55 -0
- package/dist/adapters/wasm-page-hook.js.map +1 -0
- package/dist/adapters/wasm-session.d.ts +11 -0
- package/dist/adapters/wasm-session.js +76 -0
- package/dist/adapters/wasm-session.js.map +1 -0
- package/dist/adapters/wasm-sqlite.d.ts +89 -0
- package/dist/adapters/wasm-sqlite.js +258 -0
- package/dist/adapters/wasm-sqlite.js.map +1 -0
- package/dist/bindings/assets.d.ts +26 -0
- package/dist/bindings/assets.js +260 -0
- package/dist/bindings/assets.js.map +1 -0
- package/dist/bindings/cache.d.ts +16 -0
- package/dist/bindings/cache.js +34 -0
- package/dist/bindings/cache.js.map +1 -0
- package/dist/bindings/celld-kv.d.ts +26 -0
- package/dist/bindings/celld-kv.js +81 -0
- package/dist/bindings/celld-kv.js.map +1 -0
- package/dist/bindings/celld-queues.d.ts +56 -0
- package/dist/bindings/celld-queues.js +223 -0
- package/dist/bindings/celld-queues.js.map +1 -0
- package/dist/bindings/celld-workflows.d.ts +22 -0
- package/dist/bindings/celld-workflows.js +54 -0
- package/dist/bindings/celld-workflows.js.map +1 -0
- package/dist/bindings/cron.d.ts +27 -0
- package/dist/bindings/cron.js +232 -0
- package/dist/bindings/cron.js.map +1 -0
- package/dist/bindings/d1-migrations.d.ts +22 -0
- package/dist/bindings/d1-migrations.js +32 -0
- package/dist/bindings/d1-migrations.js.map +1 -0
- package/dist/bindings/html-rewriter.d.ts +8 -0
- package/dist/bindings/html-rewriter.js +75 -0
- package/dist/bindings/html-rewriter.js.map +1 -0
- package/dist/bindings/r2-celld.d.ts +3 -0
- package/dist/bindings/r2-celld.js +113 -0
- package/dist/bindings/r2-celld.js.map +1 -0
- package/dist/bindings/r2.d.ts +236 -0
- package/dist/bindings/r2.js +419 -0
- package/dist/bindings/r2.js.map +1 -0
- package/dist/bindings/worker-loader.d.ts +83 -0
- package/dist/bindings/worker-loader.js +183 -0
- package/dist/bindings/worker-loader.js.map +1 -0
- package/dist/bindings/workers-ai.d.ts +39 -0
- package/dist/bindings/workers-ai.js +175 -0
- package/dist/bindings/workers-ai.js.map +1 -0
- package/dist/browser.d.ts +7 -0
- package/dist/browser.js +8 -0
- package/dist/browser.js.map +1 -0
- package/dist/bucket/celld-cells.d.ts +86 -0
- package/dist/bucket/celld-cells.js +273 -0
- package/dist/bucket/celld-cells.js.map +1 -0
- package/dist/bucket/celld-format.d.ts +10 -0
- package/dist/bucket/celld-format.js +27 -0
- package/dist/bucket/celld-format.js.map +1 -0
- package/dist/bucket/idb-object-store.d.ts +9 -0
- package/dist/bucket/idb-object-store.js +73 -0
- package/dist/bucket/idb-object-store.js.map +1 -0
- package/dist/bucket/ltx-log.d.ts +34 -0
- package/dist/bucket/ltx-log.js +289 -0
- package/dist/bucket/ltx-log.js.map +1 -0
- package/dist/bucket/object-store.d.ts +51 -0
- package/dist/bucket/object-store.js +114 -0
- package/dist/bucket/object-store.js.map +1 -0
- package/dist/bucket/s3-object-store.d.ts +25 -0
- package/dist/bucket/s3-object-store.js +151 -0
- package/dist/bucket/s3-object-store.js.map +1 -0
- package/dist/bucket/sqlite-object-store.d.ts +10 -0
- package/dist/bucket/sqlite-object-store.js +107 -0
- package/dist/bucket/sqlite-object-store.js.map +1 -0
- package/dist/core/alarms.d.ts +27 -0
- package/dist/core/alarms.js +88 -0
- package/dist/core/alarms.js.map +1 -0
- package/dist/core/async-context.d.ts +34 -0
- package/dist/core/async-context.js +50 -0
- package/dist/core/async-context.js.map +1 -0
- package/dist/core/celld-schema.d.ts +14 -0
- package/dist/core/celld-schema.js +34 -0
- package/dist/core/celld-schema.js.map +1 -0
- package/dist/core/durable-object.d.ts +28 -0
- package/dist/core/durable-object.js +31 -0
- package/dist/core/durable-object.js.map +1 -0
- package/dist/core/gates.d.ts +33 -0
- package/dist/core/gates.js +89 -0
- package/dist/core/gates.js.map +1 -0
- package/dist/core/handles.d.ts +90 -0
- package/dist/core/handles.js +224 -0
- package/dist/core/handles.js.map +1 -0
- package/dist/core/id.d.ts +19 -0
- package/dist/core/id.js +64 -0
- package/dist/core/id.js.map +1 -0
- package/dist/core/namespace.d.ts +38 -0
- package/dist/core/namespace.js +141 -0
- package/dist/core/namespace.js.map +1 -0
- package/dist/core/object-host.d.ts +91 -0
- package/dist/core/object-host.js +616 -0
- package/dist/core/object-host.js.map +1 -0
- package/dist/core/request-body.d.ts +9 -0
- package/dist/core/request-body.js +55 -0
- package/dist/core/request-body.js.map +1 -0
- package/dist/core/runtime.d.ts +121 -0
- package/dist/core/runtime.js +366 -0
- package/dist/core/runtime.js.map +1 -0
- package/dist/core/shard.d.ts +7 -0
- package/dist/core/shard.js +10 -0
- package/dist/core/shard.js.map +1 -0
- package/dist/core/sql-split.d.ts +15 -0
- package/dist/core/sql-split.js +101 -0
- package/dist/core/sql-split.js.map +1 -0
- package/dist/core/sql-storage.d.ts +53 -0
- package/dist/core/sql-storage.js +407 -0
- package/dist/core/sql-storage.js.map +1 -0
- package/dist/core/state.d.ts +44 -0
- package/dist/core/state.js +93 -0
- package/dist/core/state.js.map +1 -0
- package/dist/core/storage.d.ts +103 -0
- package/dist/core/storage.js +351 -0
- package/dist/core/storage.js.map +1 -0
- package/dist/core/worker-rejections.d.ts +21 -0
- package/dist/core/worker-rejections.js +55 -0
- package/dist/core/worker-rejections.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/isolate/browser.d.ts +16 -0
- package/dist/isolate/browser.js +37 -0
- package/dist/isolate/browser.js.map +1 -0
- package/dist/isolate/host.d.ts +24 -0
- package/dist/isolate/host.js +74 -0
- package/dist/isolate/host.js.map +1 -0
- package/dist/isolate/isolate-worker.d.ts +1 -0
- package/dist/isolate/isolate-worker.js +53 -0
- package/dist/isolate/isolate-worker.js.map +1 -0
- package/dist/isolate/isolate.d.ts +10 -0
- package/dist/isolate/isolate.js +169 -0
- package/dist/isolate/isolate.js.map +1 -0
- package/dist/isolate/node-entry.d.ts +1 -0
- package/dist/isolate/node-entry.js +12 -0
- package/dist/isolate/node-entry.js.map +1 -0
- package/dist/isolate/protocol.d.ts +66 -0
- package/dist/isolate/protocol.js +205 -0
- package/dist/isolate/protocol.js.map +1 -0
- package/dist/ltx/crc64.d.ts +6 -0
- package/dist/ltx/crc64.js +46 -0
- package/dist/ltx/crc64.js.map +1 -0
- package/dist/ltx/ltx-page-server.d.ts +65 -0
- package/dist/ltx/ltx-page-server.js +309 -0
- package/dist/ltx/ltx-page-server.js.map +1 -0
- package/dist/ltx/ltx-pages.d.ts +81 -0
- package/dist/ltx/ltx-pages.js +315 -0
- package/dist/ltx/ltx-pages.js.map +1 -0
- package/dist/ltx/ltx-store-worker.d.ts +1 -0
- package/dist/ltx/ltx-store-worker.js +38 -0
- package/dist/ltx/ltx-store-worker.js.map +1 -0
- package/dist/ltx/ltx.d.ts +45 -0
- package/dist/ltx/ltx.js +203 -0
- package/dist/ltx/ltx.js.map +1 -0
- package/dist/ltx/lz4.d.ts +9 -0
- package/dist/ltx/lz4.js +156 -0
- package/dist/ltx/lz4.js.map +1 -0
- package/dist/ltx/opfs-sync-files.d.ts +23 -0
- package/dist/ltx/opfs-sync-files.js +191 -0
- package/dist/ltx/opfs-sync-files.js.map +1 -0
- package/dist/ltx/xxh32.d.ts +1 -0
- package/dist/ltx/xxh32.js +43 -0
- package/dist/ltx/xxh32.js.map +1 -0
- package/dist/miniflare-compat/blob-service.d.ts +13 -0
- package/dist/miniflare-compat/blob-service.js +66 -0
- package/dist/miniflare-compat/blob-service.js.map +1 -0
- package/dist/miniflare-compat/kv-binding.d.ts +44 -0
- package/dist/miniflare-compat/kv-binding.js +99 -0
- package/dist/miniflare-compat/kv-binding.js.map +1 -0
- package/dist/miniflare-compat/shims/assert.d.ts +15 -0
- package/dist/miniflare-compat/shims/assert.js +24 -0
- package/dist/miniflare-compat/shims/assert.js.map +1 -0
- package/dist/miniflare-compat/shims/workerd-cloudflare.d.ts +7 -0
- package/dist/miniflare-compat/shims/workerd-cloudflare.js +6 -0
- package/dist/miniflare-compat/shims/workerd-cloudflare.js.map +1 -0
- package/dist/miniflare-compat/shims/workerd-globals.d.ts +1 -0
- package/dist/miniflare-compat/shims/workerd-globals.js +30 -0
- package/dist/miniflare-compat/shims/workerd-globals.js.map +1 -0
- package/dist/miniflare-compat/shims/workerd-internal.d.ts +20 -0
- package/dist/miniflare-compat/shims/workerd-internal.js +23 -0
- package/dist/miniflare-compat/shims/workerd-internal.js.map +1 -0
- package/dist/miniflare-compat/shims/workerd-performance.d.ts +4 -0
- package/dist/miniflare-compat/shims/workerd-performance.js +17 -0
- package/dist/miniflare-compat/shims/workerd-performance.js.map +1 -0
- package/dist/miniflare-compat/simulator-fetcher.d.ts +9 -0
- package/dist/miniflare-compat/simulator-fetcher.js +14 -0
- package/dist/miniflare-compat/simulator-fetcher.js.map +1 -0
- package/dist/miniflare-compat/vendored.d.ts +15 -0
- package/dist/miniflare-compat/vendored.js +27 -0
- package/dist/miniflare-compat/vendored.js.map +1 -0
- package/dist/node-compat/async_hooks.d.ts +22 -0
- package/dist/node-compat/async_hooks.js +176 -0
- package/dist/node-compat/async_hooks.js.map +1 -0
- package/dist/node-compat/browser-registry.d.ts +3 -0
- package/dist/node-compat/browser-registry.js +39 -0
- package/dist/node-compat/browser-registry.js.map +1 -0
- package/dist/node-compat/crypto.d.ts +60 -0
- package/dist/node-compat/crypto.js +143 -0
- package/dist/node-compat/crypto.js.map +1 -0
- package/dist/node-compat/diagnostics_channel.d.ts +27 -0
- package/dist/node-compat/diagnostics_channel.js +46 -0
- package/dist/node-compat/diagnostics_channel.js.map +1 -0
- package/dist/node-compat/fs.d.ts +35 -0
- package/dist/node-compat/fs.js +40 -0
- package/dist/node-compat/fs.js.map +1 -0
- package/dist/node-compat/globals.d.ts +3 -0
- package/dist/node-compat/globals.js +4 -0
- package/dist/node-compat/globals.js.map +1 -0
- package/dist/node-compat/install.d.ts +5 -0
- package/dist/node-compat/install.js +12 -0
- package/dist/node-compat/install.js.map +1 -0
- package/dist/node-compat/module.d.ts +12 -0
- package/dist/node-compat/module.js +36 -0
- package/dist/node-compat/module.js.map +1 -0
- package/dist/node-compat/modules.d.ts +8 -0
- package/dist/node-compat/modules.js +23 -0
- package/dist/node-compat/modules.js.map +1 -0
- package/dist/node-compat/os.d.ts +36 -0
- package/dist/node-compat/os.js +36 -0
- package/dist/node-compat/os.js.map +1 -0
- package/dist/node-compat/process.d.ts +14 -0
- package/dist/node-compat/process.js +16 -0
- package/dist/node-compat/process.js.map +1 -0
- package/dist/node-compat/shims.d.ts +4 -0
- package/dist/node.d.ts +5 -0
- package/dist/node.js +6 -0
- package/dist/node.js.map +1 -0
- package/dist/peer/celld-peer.d.ts +53 -0
- package/dist/peer/celld-peer.js +555 -0
- package/dist/peer/celld-peer.js.map +1 -0
- package/dist/ports.d.ts +183 -0
- package/dist/ports.js +10 -0
- package/dist/ports.js.map +1 -0
- package/dist/project/browser-bundle.d.ts +17 -0
- package/dist/project/browser-bundle.js +125 -0
- package/dist/project/browser-bundle.js.map +1 -0
- package/dist/project/browser-cookies.d.ts +12 -0
- package/dist/project/browser-cookies.js +90 -0
- package/dist/project/browser-cookies.js.map +1 -0
- package/dist/project/browser-host.d.ts +173 -0
- package/dist/project/browser-host.js +200 -0
- package/dist/project/browser-host.js.map +1 -0
- package/dist/project/browser-modules.d.ts +17 -0
- package/dist/project/browser-modules.js +89 -0
- package/dist/project/browser-modules.js.map +1 -0
- package/dist/project/browser-shards.d.ts +62 -0
- package/dist/project/browser-shards.js +210 -0
- package/dist/project/browser-shards.js.map +1 -0
- package/dist/project/browser-tabs.d.ts +103 -0
- package/dist/project/browser-tabs.js +418 -0
- package/dist/project/browser-tabs.js.map +1 -0
- package/dist/project/cloudflare-email.d.ts +8 -0
- package/dist/project/cloudflare-email.js +11 -0
- package/dist/project/cloudflare-email.js.map +1 -0
- package/dist/project/cloudflare-workers.d.ts +12 -0
- package/dist/project/cloudflare-workers.js +16 -0
- package/dist/project/cloudflare-workers.js.map +1 -0
- package/dist/project/host-modules.d.ts +4 -0
- package/dist/project/host-modules.js +40 -0
- package/dist/project/host-modules.js.map +1 -0
- package/dist/project/jsonc.d.ts +2 -0
- package/dist/project/jsonc.js +27 -0
- package/dist/project/jsonc.js.map +1 -0
- package/dist/project/lower-await.d.ts +2 -0
- package/dist/project/lower-await.js +151 -0
- package/dist/project/lower-await.js.map +1 -0
- package/dist/project/node-project.d.ts +38 -0
- package/dist/project/node-project.js +373 -0
- package/dist/project/node-project.js.map +1 -0
- package/dist/project/own-module.d.ts +6 -0
- package/dist/project/own-module.js +13 -0
- package/dist/project/own-module.js.map +1 -0
- package/dist/project/scheduler.d.ts +2 -0
- package/dist/project/scheduler.js +3 -0
- package/dist/project/scheduler.js.map +1 -0
- package/dist/project/site.d.ts +74 -0
- package/dist/project/site.js +206 -0
- package/dist/project/site.js.map +1 -0
- package/dist/project/virtual-modules.d.ts +3 -0
- package/dist/project/worker-scope.d.ts +27 -0
- package/dist/project/worker-scope.js +46 -0
- package/dist/project/worker-scope.js.map +1 -0
- package/dist/project/workerd-message-channel.d.ts +13 -0
- package/dist/project/workerd-message-channel.js +137 -0
- package/dist/project/workerd-message-channel.js.map +1 -0
- package/dist/project/workers-global-names.d.ts +6 -0
- package/dist/project/workers-global-names.js +15 -0
- package/dist/project/workers-global-names.js.map +1 -0
- package/dist/project/workers-globals-module.d.ts +8 -0
- package/dist/project/workers-globals-module.js +9 -0
- package/dist/project/workers-globals-module.js.map +1 -0
- package/dist/project/workers-globals.d.ts +9 -0
- package/dist/project/workers-globals.js +19 -0
- package/dist/project/workers-globals.js.map +1 -0
- package/dist/project/wrangler.d.ts +116 -0
- package/dist/project/wrangler.js +342 -0
- package/dist/project/wrangler.js.map +1 -0
- package/dist/router/cell-router.d.ts +72 -0
- package/dist/router/cell-router.js +247 -0
- package/dist/router/cell-router.js.map +1 -0
- package/dist/router/shard-worker.d.ts +44 -0
- package/dist/router/shard-worker.js +163 -0
- package/dist/router/shard-worker.js.map +1 -0
- package/dist/transport/cells-http.d.ts +25 -0
- package/dist/transport/cells-http.js +141 -0
- package/dist/transport/cells-http.js.map +1 -0
- package/dist/transport/cells-link.d.ts +27 -0
- package/dist/transport/cells-link.js +71 -0
- package/dist/transport/cells-link.js.map +1 -0
- package/dist/transport/port.d.ts +26 -0
- package/dist/transport/port.js +100 -0
- package/dist/transport/port.js.map +1 -0
- package/dist/v8/codec.d.ts +6 -0
- package/dist/v8/codec.js +9 -0
- package/dist/v8/codec.js.map +1 -0
- package/dist/v8/serialize.d.ts +10 -0
- package/dist/v8/serialize.js +601 -0
- package/dist/v8/serialize.js.map +1 -0
- package/dist/ws/client.d.ts +25 -0
- package/dist/ws/client.js +203 -0
- package/dist/ws/client.js.map +1 -0
- package/dist/ws/control.d.ts +48 -0
- package/dist/ws/control.js +44 -0
- package/dist/ws/control.js.map +1 -0
- package/dist/ws/frames.d.ts +38 -0
- package/dist/ws/frames.js +39 -0
- package/dist/ws/frames.js.map +1 -0
- package/dist/ws/server.d.ts +99 -0
- package/dist/ws/server.js +295 -0
- package/dist/ws/server.js.map +1 -0
- package/dist/ws/sw-connector.d.ts +10 -0
- package/dist/ws/sw-connector.js +25 -0
- package/dist/ws/sw-connector.js.map +1 -0
- package/dist/ws/upgrade.d.ts +28 -0
- package/dist/ws/upgrade.js +75 -0
- package/dist/ws/upgrade.js.map +1 -0
- package/package.json +111 -3
- package/vendor/celld/LICENSE +202 -0
- package/vendor/celld/kv.js +1131 -0
- package/vendor/celld/queues.js +1656 -0
- package/vendor/celld/workflows.js +1610 -0
- package/vendor/html-rewriter-wasm/html_rewriter.js +925 -0
- package/vendor/html-rewriter-wasm/html_rewriter_bg.wasm +0 -0
- package/vendor/miniflare/d1-api.js +738 -0
- package/vendor/miniflare/d1-database.js +6978 -0
- package/vendor/miniflare/kv-namespace.js +3061 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static assets as celld serves them (docs/services/static-assets.md), checked against
|
|
3
|
+
* celld 0.6.2 by conformance/projects/assets-api:
|
|
4
|
+
* GET/HEAD only; `run_worker_first`; `_redirects` first (301/302/303/307/308 → Location,
|
|
5
|
+
* 200 → rewrite, `*` → `:splat`); `html_handling` auto-trailing-slash with 307 to canonical
|
|
6
|
+
* paths; `not_found_handling` (with a Worker, only for navigation requests); strong
|
|
7
|
+
* SHA-256 ETag, If-None-Match → 304, Range → 206/416, `_headers` rules,
|
|
8
|
+
* `Cache-Control: public, max-age=0, must-revalidate` by default; unknown extension → no
|
|
9
|
+
* Content-Type.
|
|
10
|
+
*/
|
|
11
|
+
export interface AssetsConfig {
|
|
12
|
+
directory?: string;
|
|
13
|
+
binding?: string;
|
|
14
|
+
html_handling?: "auto-trailing-slash" | "force-trailing-slash" | "drop-trailing-slash" | "none";
|
|
15
|
+
not_found_handling?: "single-page-application" | "404-page" | "none";
|
|
16
|
+
run_worker_first?: boolean | string[];
|
|
17
|
+
}
|
|
18
|
+
/** File path ("/about.html") → bytes. */
|
|
19
|
+
export type AssetFiles = Map<string, Uint8Array>;
|
|
20
|
+
export declare function createAssets(files: AssetFiles, config: AssetsConfig, hasWorker: boolean): {
|
|
21
|
+
route: (req: Request, viaBinding?: boolean) => Response | undefined;
|
|
22
|
+
/** The `env.ASSETS` binding. */
|
|
23
|
+
binding: {
|
|
24
|
+
fetch: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import { sha256 } from "@noble/hashes/sha256";
|
|
2
|
+
import { bytesToHex } from "@noble/hashes/utils";
|
|
3
|
+
const TYPES = {
|
|
4
|
+
html: "text/html; charset=utf-8",
|
|
5
|
+
htm: "text/html; charset=utf-8",
|
|
6
|
+
css: "text/css; charset=utf-8",
|
|
7
|
+
js: "text/javascript; charset=utf-8",
|
|
8
|
+
mjs: "text/javascript; charset=utf-8",
|
|
9
|
+
json: "application/json; charset=utf-8",
|
|
10
|
+
txt: "text/plain; charset=utf-8",
|
|
11
|
+
xml: "application/xml; charset=utf-8",
|
|
12
|
+
svg: "image/svg+xml",
|
|
13
|
+
png: "image/png",
|
|
14
|
+
jpg: "image/jpeg",
|
|
15
|
+
jpeg: "image/jpeg",
|
|
16
|
+
gif: "image/gif",
|
|
17
|
+
webp: "image/webp",
|
|
18
|
+
ico: "image/x-icon",
|
|
19
|
+
wasm: "application/wasm",
|
|
20
|
+
pdf: "application/pdf",
|
|
21
|
+
woff2: "font/woff2",
|
|
22
|
+
woff: "font/woff",
|
|
23
|
+
};
|
|
24
|
+
function globToRegExp(pattern) {
|
|
25
|
+
const names = [];
|
|
26
|
+
const src = pattern
|
|
27
|
+
.split(/(\*|:[A-Za-z_]\w*)/)
|
|
28
|
+
.map((part) => {
|
|
29
|
+
if (part === "*") {
|
|
30
|
+
names.push("splat");
|
|
31
|
+
return "(.*)";
|
|
32
|
+
}
|
|
33
|
+
if (part.startsWith(":")) {
|
|
34
|
+
names.push(part.slice(1));
|
|
35
|
+
return "([^/]+)";
|
|
36
|
+
}
|
|
37
|
+
return part.replace(/[.+?^${}()|[\]\\]/g, "\\$&");
|
|
38
|
+
})
|
|
39
|
+
.join("");
|
|
40
|
+
return { re: new RegExp(`^${src}$`), names };
|
|
41
|
+
}
|
|
42
|
+
function parseRedirects(text) {
|
|
43
|
+
const out = [];
|
|
44
|
+
for (const line of (text ?? "").split("\n")) {
|
|
45
|
+
const t = line.trim();
|
|
46
|
+
if (!t || t.startsWith("#"))
|
|
47
|
+
continue;
|
|
48
|
+
const [from, to, status] = t.split(/\s+/);
|
|
49
|
+
const { re, names } = globToRegExp(from);
|
|
50
|
+
out.push({ from: re, names, to, status: Number(status ?? 302) });
|
|
51
|
+
}
|
|
52
|
+
return out;
|
|
53
|
+
}
|
|
54
|
+
function parseHeaderRules(text) {
|
|
55
|
+
const rules = [];
|
|
56
|
+
for (const line of (text ?? "").split("\n")) {
|
|
57
|
+
if (!line.trim() || line.trim().startsWith("#"))
|
|
58
|
+
continue;
|
|
59
|
+
if (!/^\s/.test(line))
|
|
60
|
+
rules.push({ re: globToRegExp(line.trim()).re, headers: [] });
|
|
61
|
+
else {
|
|
62
|
+
const i = line.indexOf(":");
|
|
63
|
+
if (i > 0 && rules.length)
|
|
64
|
+
rules.at(-1).headers.push([line.slice(0, i).trim(), line.slice(i + 1).trim()]);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return rules;
|
|
68
|
+
}
|
|
69
|
+
const decoder = new TextDecoder();
|
|
70
|
+
export function createAssets(files, config, hasWorker) {
|
|
71
|
+
const redirects = parseRedirects(files.has("/_redirects") ? decoder.decode(files.get("/_redirects")) : undefined);
|
|
72
|
+
const headerRules = parseHeaderRules(files.has("/_headers") ? decoder.decode(files.get("/_headers")) : undefined);
|
|
73
|
+
const etags = new Map();
|
|
74
|
+
const etagOf = (path) => {
|
|
75
|
+
let e = etags.get(path);
|
|
76
|
+
if (!e) {
|
|
77
|
+
e = `"${bytesToHex(sha256(files.get(path)))}"`;
|
|
78
|
+
etags.set(path, e);
|
|
79
|
+
}
|
|
80
|
+
return e;
|
|
81
|
+
};
|
|
82
|
+
const exists = (p) => files.has(p) && p !== "/_headers" && p !== "/_redirects";
|
|
83
|
+
const workerFirst = (path) => {
|
|
84
|
+
const r = config.run_worker_first;
|
|
85
|
+
if (r === true)
|
|
86
|
+
return true;
|
|
87
|
+
if (!Array.isArray(r))
|
|
88
|
+
return false;
|
|
89
|
+
let hit = false;
|
|
90
|
+
for (const p of r) {
|
|
91
|
+
const neg = p.startsWith("!");
|
|
92
|
+
if (globToRegExp(neg ? p.slice(1) : p).re.test(path))
|
|
93
|
+
hit = !neg;
|
|
94
|
+
}
|
|
95
|
+
return hit;
|
|
96
|
+
};
|
|
97
|
+
/** Resolves a URL path to a file, or a canonical redirect (auto-trailing-slash). */
|
|
98
|
+
const lookup = (path) => {
|
|
99
|
+
const mode = config.html_handling ?? "auto-trailing-slash";
|
|
100
|
+
if (mode === "none")
|
|
101
|
+
return exists(path) ? { file: path } : undefined;
|
|
102
|
+
if (mode === "force-trailing-slash" || mode === "drop-trailing-slash")
|
|
103
|
+
return lookupSlash(path, mode);
|
|
104
|
+
if (path.endsWith("/index.html")) {
|
|
105
|
+
if (exists(path))
|
|
106
|
+
return { redirect: path.slice(0, -"index.html".length) };
|
|
107
|
+
}
|
|
108
|
+
else if (path.endsWith(".html")) {
|
|
109
|
+
if (exists(path))
|
|
110
|
+
return { redirect: path.slice(0, -".html".length) };
|
|
111
|
+
}
|
|
112
|
+
if (path.endsWith("/")) {
|
|
113
|
+
// `/` and `/dir/` → index.html. (celld 0.6.2 serves only the root index here and
|
|
114
|
+
// falls through for nested ones — a celld bug; we follow Cloudflare, see docs/celld-compatibility.md.)
|
|
115
|
+
return exists(`${path}index.html`) ? { file: `${path}index.html` } : undefined;
|
|
116
|
+
}
|
|
117
|
+
if (exists(path))
|
|
118
|
+
return { file: path };
|
|
119
|
+
if (exists(`${path}.html`))
|
|
120
|
+
return { file: `${path}.html` };
|
|
121
|
+
if (exists(`${path}/index.html`))
|
|
122
|
+
return { redirect: `${path}/` };
|
|
123
|
+
return undefined;
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* force-trailing-slash: HTML pages live at `/x/` (x.html or x/index.html); `/x`, `/x.html`
|
|
127
|
+
* and `/x/index.html` redirect there. drop-trailing-slash: they live at `/x`; `/x/`,
|
|
128
|
+
* `/x.html` and `/x/index.html` redirect there. The root is `/` in both.
|
|
129
|
+
* (celld 0.6.2 answers 404 for any path ending in "/" other than the root, so in force
|
|
130
|
+
* mode it redirects to pages it then refuses — a celld bug; we follow Cloudflare.)
|
|
131
|
+
*/
|
|
132
|
+
const lookupSlash = (path, mode) => {
|
|
133
|
+
if (path === "/")
|
|
134
|
+
return exists("/index.html") ? { file: "/index.html" } : undefined;
|
|
135
|
+
const page = (base) => exists(`${base}.html`)
|
|
136
|
+
? `${base}.html`
|
|
137
|
+
: exists(`${base}/index.html`)
|
|
138
|
+
? `${base}/index.html`
|
|
139
|
+
: undefined;
|
|
140
|
+
let base;
|
|
141
|
+
if (path.endsWith("/index.html"))
|
|
142
|
+
base = path.slice(0, -"/index.html".length);
|
|
143
|
+
else if (path.endsWith(".html"))
|
|
144
|
+
base = path.slice(0, -".html".length);
|
|
145
|
+
else if (path.endsWith("/"))
|
|
146
|
+
base = path.slice(0, -1);
|
|
147
|
+
if (base === "")
|
|
148
|
+
return exists(path) ? { redirect: "/" } : undefined;
|
|
149
|
+
const canonical = (b) => (mode === "force-trailing-slash" ? `${b}/` : b);
|
|
150
|
+
if (base !== undefined) {
|
|
151
|
+
const file = page(base);
|
|
152
|
+
if (!file)
|
|
153
|
+
return undefined;
|
|
154
|
+
return path === canonical(base) ? { file } : { redirect: canonical(base) };
|
|
155
|
+
}
|
|
156
|
+
if (exists(path))
|
|
157
|
+
return { file: path }; // non-HTML file
|
|
158
|
+
const file = page(path);
|
|
159
|
+
if (!file)
|
|
160
|
+
return undefined;
|
|
161
|
+
return mode === "drop-trailing-slash" ? { file } : { redirect: `${path}/` };
|
|
162
|
+
};
|
|
163
|
+
const serve = (req, file, status = 200) => {
|
|
164
|
+
const bytes = files.get(file);
|
|
165
|
+
const etag = etagOf(file);
|
|
166
|
+
const headers = new Headers();
|
|
167
|
+
const ext = file.split(".").pop()?.toLowerCase() ?? "";
|
|
168
|
+
for (const rule of headerRules)
|
|
169
|
+
if (rule.re.test(new URL(req.url).pathname))
|
|
170
|
+
for (const [k, v] of rule.headers)
|
|
171
|
+
headers.set(k, v);
|
|
172
|
+
headers.set("etag", etag);
|
|
173
|
+
if (req.headers.get("if-none-match") === etag) {
|
|
174
|
+
headers.delete("cache-control");
|
|
175
|
+
return new Response(null, { status: 304, headers });
|
|
176
|
+
}
|
|
177
|
+
const range = /^bytes=(\d*)-(\d*)$/.exec(req.headers.get("range") ?? "");
|
|
178
|
+
if (range && status === 200) {
|
|
179
|
+
const size = bytes.byteLength;
|
|
180
|
+
let start = range[1] === "" ? size - Number(range[2]) : Number(range[1]);
|
|
181
|
+
let end = range[1] === "" ? size - 1 : range[2] === "" ? size - 1 : Number(range[2]);
|
|
182
|
+
if (start >= size || start < 0 || start > end) {
|
|
183
|
+
headers.set("content-range", `bytes */${size}`);
|
|
184
|
+
headers.set("content-length", "0");
|
|
185
|
+
headers.delete("cache-control");
|
|
186
|
+
return new Response(null, { status: 416, headers });
|
|
187
|
+
}
|
|
188
|
+
end = Math.min(end, size - 1);
|
|
189
|
+
start = Math.max(0, start);
|
|
190
|
+
if (TYPES[ext])
|
|
191
|
+
headers.set("content-type", TYPES[ext]);
|
|
192
|
+
headers.set("content-range", `bytes ${start}-${end}/${size}`);
|
|
193
|
+
headers.set("content-length", String(end - start + 1));
|
|
194
|
+
headers.delete("cache-control");
|
|
195
|
+
return new Response(req.method === "HEAD" ? null : bytes.slice(start, end + 1), { status: 206, headers });
|
|
196
|
+
}
|
|
197
|
+
if (TYPES[ext])
|
|
198
|
+
headers.set("content-type", TYPES[ext]);
|
|
199
|
+
if (!headers.has("cache-control"))
|
|
200
|
+
headers.set("cache-control", "public, max-age=0, must-revalidate");
|
|
201
|
+
headers.set("content-length", String(bytes.byteLength));
|
|
202
|
+
return new Response(req.method === "HEAD" ? null : bytes, { status, headers });
|
|
203
|
+
};
|
|
204
|
+
const redirectTo = (location, status) => new Response(null, { status, headers: { location, "content-length": "0" } });
|
|
205
|
+
/** The asset router. `undefined` = not an asset: hand the request to the Worker. */
|
|
206
|
+
const route = (req, viaBinding = false) => {
|
|
207
|
+
if (req.method !== "GET" && req.method !== "HEAD")
|
|
208
|
+
return undefined;
|
|
209
|
+
const url = new URL(req.url);
|
|
210
|
+
let path = decodeURIComponent(url.pathname);
|
|
211
|
+
if (!viaBinding && hasWorker && workerFirst(path))
|
|
212
|
+
return undefined;
|
|
213
|
+
for (const r of redirects) {
|
|
214
|
+
const m = r.from.exec(path);
|
|
215
|
+
if (!m)
|
|
216
|
+
continue;
|
|
217
|
+
let to = r.to;
|
|
218
|
+
for (const [i, n] of r.names.entries())
|
|
219
|
+
to = to.replace(`:${n}`, m[i + 1]);
|
|
220
|
+
if (r.status === 200) {
|
|
221
|
+
path = to;
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
return redirectTo(to, r.status);
|
|
225
|
+
}
|
|
226
|
+
const hit = lookup(path);
|
|
227
|
+
if (hit && "redirect" in hit)
|
|
228
|
+
return redirectTo(`${hit.redirect}${url.search}`, 307);
|
|
229
|
+
if (hit)
|
|
230
|
+
return serve(req, hit.file);
|
|
231
|
+
// Miss: not_found_handling (with a Worker, only for navigation requests).
|
|
232
|
+
const nav = req.headers.get("sec-fetch-mode") === "navigate";
|
|
233
|
+
if (!hasWorker || nav || viaBinding) {
|
|
234
|
+
if (config.not_found_handling === "single-page-application" && exists("/index.html"))
|
|
235
|
+
return serve(req, "/index.html");
|
|
236
|
+
if (config.not_found_handling === "404-page") {
|
|
237
|
+
for (let dir = path.slice(0, path.lastIndexOf("/") + 1); dir; dir = dir.slice(0, dir.lastIndexOf("/", dir.length - 2) + 1)) {
|
|
238
|
+
if (exists(`${dir}404.html`))
|
|
239
|
+
return serve(req, `${dir}404.html`, 404);
|
|
240
|
+
if (dir === "/")
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
if (hasWorker && !viaBinding)
|
|
246
|
+
return undefined;
|
|
247
|
+
return new Response("Not found", {
|
|
248
|
+
status: 404,
|
|
249
|
+
headers: { "content-type": "application/json" },
|
|
250
|
+
});
|
|
251
|
+
};
|
|
252
|
+
return {
|
|
253
|
+
route,
|
|
254
|
+
/** The `env.ASSETS` binding. */
|
|
255
|
+
binding: {
|
|
256
|
+
fetch: async (input, init) => route(new Request(input, init), true),
|
|
257
|
+
},
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
//# sourceMappingURL=assets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assets.js","sourceRoot":"","sources":["../../src/bindings/assets.ts"],"names":[],"mappings":"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","sourcesContent":["import { sha256 } from \"@noble/hashes/sha256\";\nimport { bytesToHex } from \"@noble/hashes/utils\";\n\n/**\n * Static assets as celld serves them (docs/services/static-assets.md), checked against\n * celld 0.6.2 by conformance/projects/assets-api:\n * GET/HEAD only; `run_worker_first`; `_redirects` first (301/302/303/307/308 → Location,\n * 200 → rewrite, `*` → `:splat`); `html_handling` auto-trailing-slash with 307 to canonical\n * paths; `not_found_handling` (with a Worker, only for navigation requests); strong\n * SHA-256 ETag, If-None-Match → 304, Range → 206/416, `_headers` rules,\n * `Cache-Control: public, max-age=0, must-revalidate` by default; unknown extension → no\n * Content-Type.\n */\nexport interface AssetsConfig {\n directory?: string;\n binding?: string;\n html_handling?: \"auto-trailing-slash\" | \"force-trailing-slash\" | \"drop-trailing-slash\" | \"none\";\n not_found_handling?: \"single-page-application\" | \"404-page\" | \"none\";\n run_worker_first?: boolean | string[];\n}\n\n/** File path (\"/about.html\") → bytes. */\nexport type AssetFiles = Map<string, Uint8Array>;\n\nconst TYPES: Record<string, string> = {\n html: \"text/html; charset=utf-8\",\n htm: \"text/html; charset=utf-8\",\n css: \"text/css; charset=utf-8\",\n js: \"text/javascript; charset=utf-8\",\n mjs: \"text/javascript; charset=utf-8\",\n json: \"application/json; charset=utf-8\",\n txt: \"text/plain; charset=utf-8\",\n xml: \"application/xml; charset=utf-8\",\n svg: \"image/svg+xml\",\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n gif: \"image/gif\",\n webp: \"image/webp\",\n ico: \"image/x-icon\",\n wasm: \"application/wasm\",\n pdf: \"application/pdf\",\n woff2: \"font/woff2\",\n woff: \"font/woff\",\n};\n\ninterface Redirect {\n from: RegExp;\n names: string[];\n to: string;\n status: number;\n}\n\nfunction globToRegExp(pattern: string): { re: RegExp; names: string[] } {\n const names: string[] = [];\n const src = pattern\n .split(/(\\*|:[A-Za-z_]\\w*)/)\n .map((part) => {\n if (part === \"*\") {\n names.push(\"splat\");\n return \"(.*)\";\n }\n if (part.startsWith(\":\")) {\n names.push(part.slice(1));\n return \"([^/]+)\";\n }\n return part.replace(/[.+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n })\n .join(\"\");\n return { re: new RegExp(`^${src}$`), names };\n}\n\nfunction parseRedirects(text: string | undefined): Redirect[] {\n const out: Redirect[] = [];\n for (const line of (text ?? \"\").split(\"\\n\")) {\n const t = line.trim();\n if (!t || t.startsWith(\"#\")) continue;\n const [from, to, status] = t.split(/\\s+/);\n const { re, names } = globToRegExp(from);\n out.push({ from: re, names, to, status: Number(status ?? 302) });\n }\n return out;\n}\n\nfunction parseHeaderRules(text: string | undefined): { re: RegExp; headers: [string, string][] }[] {\n const rules: { re: RegExp; headers: [string, string][] }[] = [];\n for (const line of (text ?? \"\").split(\"\\n\")) {\n if (!line.trim() || line.trim().startsWith(\"#\")) continue;\n if (!/^\\s/.test(line)) rules.push({ re: globToRegExp(line.trim()).re, headers: [] });\n else {\n const i = line.indexOf(\":\");\n if (i > 0 && rules.length)\n rules.at(-1)!.headers.push([line.slice(0, i).trim(), line.slice(i + 1).trim()]);\n }\n }\n return rules;\n}\n\nconst decoder = new TextDecoder();\n\nexport function createAssets(files: AssetFiles, config: AssetsConfig, hasWorker: boolean) {\n const redirects = parseRedirects(\n files.has(\"/_redirects\") ? decoder.decode(files.get(\"/_redirects\")) : undefined,\n );\n const headerRules = parseHeaderRules(\n files.has(\"/_headers\") ? decoder.decode(files.get(\"/_headers\")) : undefined,\n );\n const etags = new Map<string, string>();\n const etagOf = (path: string) => {\n let e = etags.get(path);\n if (!e) {\n e = `\"${bytesToHex(sha256(files.get(path)!))}\"`;\n etags.set(path, e);\n }\n return e;\n };\n const exists = (p: string) => files.has(p) && p !== \"/_headers\" && p !== \"/_redirects\";\n\n const workerFirst = (path: string) => {\n const r = config.run_worker_first;\n if (r === true) return true;\n if (!Array.isArray(r)) return false;\n let hit = false;\n for (const p of r) {\n const neg = p.startsWith(\"!\");\n if (globToRegExp(neg ? p.slice(1) : p).re.test(path)) hit = !neg;\n }\n return hit;\n };\n\n /** Resolves a URL path to a file, or a canonical redirect (auto-trailing-slash). */\n const lookup = (path: string): { file: string } | { redirect: string } | undefined => {\n const mode = config.html_handling ?? \"auto-trailing-slash\";\n if (mode === \"none\") return exists(path) ? { file: path } : undefined;\n if (mode === \"force-trailing-slash\" || mode === \"drop-trailing-slash\")\n return lookupSlash(path, mode);\n if (path.endsWith(\"/index.html\")) {\n if (exists(path)) return { redirect: path.slice(0, -\"index.html\".length) };\n } else if (path.endsWith(\".html\")) {\n if (exists(path)) return { redirect: path.slice(0, -\".html\".length) };\n }\n if (path.endsWith(\"/\")) {\n // `/` and `/dir/` → index.html. (celld 0.6.2 serves only the root index here and\n // falls through for nested ones — a celld bug; we follow Cloudflare, see docs/celld-compatibility.md.)\n return exists(`${path}index.html`) ? { file: `${path}index.html` } : undefined;\n }\n if (exists(path)) return { file: path };\n if (exists(`${path}.html`)) return { file: `${path}.html` };\n if (exists(`${path}/index.html`)) return { redirect: `${path}/` };\n return undefined;\n };\n\n /**\n * force-trailing-slash: HTML pages live at `/x/` (x.html or x/index.html); `/x`, `/x.html`\n * and `/x/index.html` redirect there. drop-trailing-slash: they live at `/x`; `/x/`,\n * `/x.html` and `/x/index.html` redirect there. The root is `/` in both.\n * (celld 0.6.2 answers 404 for any path ending in \"/\" other than the root, so in force\n * mode it redirects to pages it then refuses — a celld bug; we follow Cloudflare.)\n */\n const lookupSlash = (path: string, mode: \"force-trailing-slash\" | \"drop-trailing-slash\") => {\n if (path === \"/\") return exists(\"/index.html\") ? { file: \"/index.html\" } : undefined;\n const page = (base: string) =>\n exists(`${base}.html`)\n ? `${base}.html`\n : exists(`${base}/index.html`)\n ? `${base}/index.html`\n : undefined;\n let base: string | undefined;\n if (path.endsWith(\"/index.html\")) base = path.slice(0, -\"/index.html\".length);\n else if (path.endsWith(\".html\")) base = path.slice(0, -\".html\".length);\n else if (path.endsWith(\"/\")) base = path.slice(0, -1);\n if (base === \"\") return exists(path) ? { redirect: \"/\" } : undefined;\n const canonical = (b: string) => (mode === \"force-trailing-slash\" ? `${b}/` : b);\n if (base !== undefined) {\n const file = page(base);\n if (!file) return undefined;\n return path === canonical(base) ? { file } : { redirect: canonical(base) };\n }\n if (exists(path)) return { file: path }; // non-HTML file\n const file = page(path);\n if (!file) return undefined;\n return mode === \"drop-trailing-slash\" ? { file } : { redirect: `${path}/` };\n };\n\n const serve = (req: Request, file: string, status = 200): Response => {\n const bytes = files.get(file)!;\n const etag = etagOf(file);\n const headers = new Headers();\n const ext = file.split(\".\").pop()?.toLowerCase() ?? \"\";\n for (const rule of headerRules)\n if (rule.re.test(new URL(req.url).pathname))\n for (const [k, v] of rule.headers) headers.set(k, v);\n headers.set(\"etag\", etag);\n if (req.headers.get(\"if-none-match\") === etag) {\n headers.delete(\"cache-control\");\n return new Response(null, { status: 304, headers });\n }\n const range = /^bytes=(\\d*)-(\\d*)$/.exec(req.headers.get(\"range\") ?? \"\");\n if (range && status === 200) {\n const size = bytes.byteLength;\n let start = range[1] === \"\" ? size - Number(range[2]) : Number(range[1]);\n let end = range[1] === \"\" ? size - 1 : range[2] === \"\" ? size - 1 : Number(range[2]);\n if (start >= size || start < 0 || start > end) {\n headers.set(\"content-range\", `bytes */${size}`);\n headers.set(\"content-length\", \"0\");\n headers.delete(\"cache-control\");\n return new Response(null, { status: 416, headers });\n }\n end = Math.min(end, size - 1);\n start = Math.max(0, start);\n if (TYPES[ext]) headers.set(\"content-type\", TYPES[ext]);\n headers.set(\"content-range\", `bytes ${start}-${end}/${size}`);\n headers.set(\"content-length\", String(end - start + 1));\n headers.delete(\"cache-control\");\n return new Response(\n req.method === \"HEAD\" ? null : (bytes.slice(start, end + 1) as BodyInit),\n { status: 206, headers },\n );\n }\n if (TYPES[ext]) headers.set(\"content-type\", TYPES[ext]);\n if (!headers.has(\"cache-control\"))\n headers.set(\"cache-control\", \"public, max-age=0, must-revalidate\");\n headers.set(\"content-length\", String(bytes.byteLength));\n return new Response(req.method === \"HEAD\" ? null : (bytes as BodyInit), { status, headers });\n };\n\n const redirectTo = (location: string, status: number) =>\n new Response(null, { status, headers: { location, \"content-length\": \"0\" } });\n\n /** The asset router. `undefined` = not an asset: hand the request to the Worker. */\n const route = (req: Request, viaBinding = false): Response | undefined => {\n if (req.method !== \"GET\" && req.method !== \"HEAD\") return undefined;\n const url = new URL(req.url);\n let path = decodeURIComponent(url.pathname);\n if (!viaBinding && hasWorker && workerFirst(path)) return undefined;\n for (const r of redirects) {\n const m = r.from.exec(path);\n if (!m) continue;\n let to = r.to;\n for (const [i, n] of r.names.entries()) to = to.replace(`:${n}`, m[i + 1]);\n if (r.status === 200) {\n path = to;\n break;\n }\n return redirectTo(to, r.status);\n }\n const hit = lookup(path);\n if (hit && \"redirect\" in hit) return redirectTo(`${hit.redirect}${url.search}`, 307);\n if (hit) return serve(req, hit.file);\n // Miss: not_found_handling (with a Worker, only for navigation requests).\n const nav = req.headers.get(\"sec-fetch-mode\") === \"navigate\";\n if (!hasWorker || nav || viaBinding) {\n if (config.not_found_handling === \"single-page-application\" && exists(\"/index.html\"))\n return serve(req, \"/index.html\");\n if (config.not_found_handling === \"404-page\") {\n for (\n let dir = path.slice(0, path.lastIndexOf(\"/\") + 1);\n dir;\n dir = dir.slice(0, dir.lastIndexOf(\"/\", dir.length - 2) + 1)\n ) {\n if (exists(`${dir}404.html`)) return serve(req, `${dir}404.html`, 404);\n if (dir === \"/\") break;\n }\n }\n }\n if (hasWorker && !viaBinding) return undefined;\n return new Response(\"Not found\", {\n status: 404,\n headers: { \"content-type\": \"application/json\" },\n });\n };\n\n return {\n route,\n /** The `env.ASSETS` binding. */\n binding: {\n fetch: async (input: RequestInfo | URL, init?: RequestInit) =>\n route(new Request(input, init), true)!,\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Workers Cache API as celld provides it (cloudflare-compat.md#cache): an always-miss
|
|
3
|
+
* cache, because there is no shared edge cache. `put()` validates and consumes the response
|
|
4
|
+
* but stores nothing, `match()` resolves to `undefined`, `delete()` to `false`.
|
|
5
|
+
* Substituted for the `caches` global of user code (browsers have a real CacheStorage).
|
|
6
|
+
*/
|
|
7
|
+
export declare class CellsCache {
|
|
8
|
+
put(request: RequestInfo | URL, response: Response): Promise<void>;
|
|
9
|
+
match(_request: RequestInfo | URL, _options?: unknown): Promise<Response | undefined>;
|
|
10
|
+
delete(_request: RequestInfo | URL, _options?: unknown): Promise<boolean>;
|
|
11
|
+
}
|
|
12
|
+
export declare class CellsCacheStorage {
|
|
13
|
+
readonly default: CellsCache;
|
|
14
|
+
open(_name: string): Promise<CellsCache>;
|
|
15
|
+
}
|
|
16
|
+
export declare const cellsCaches: CellsCacheStorage;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Workers Cache API as celld provides it (cloudflare-compat.md#cache): an always-miss
|
|
3
|
+
* cache, because there is no shared edge cache. `put()` validates and consumes the response
|
|
4
|
+
* but stores nothing, `match()` resolves to `undefined`, `delete()` to `false`.
|
|
5
|
+
* Substituted for the `caches` global of user code (browsers have a real CacheStorage).
|
|
6
|
+
*/
|
|
7
|
+
export class CellsCache {
|
|
8
|
+
async put(request, response) {
|
|
9
|
+
const req = request instanceof Request ? request : new Request(request);
|
|
10
|
+
if (req.method !== "GET")
|
|
11
|
+
throw new TypeError("Cache.put() only accepts GET requests");
|
|
12
|
+
if (!(response instanceof Response))
|
|
13
|
+
throw new TypeError("Cache.put() requires a Response");
|
|
14
|
+
if (response.status === 206)
|
|
15
|
+
throw new TypeError("Cache.put() cannot store a partial response");
|
|
16
|
+
if (response.headers.get("vary") === "*")
|
|
17
|
+
throw new TypeError("Cache.put() cannot store Vary: *");
|
|
18
|
+
await response.body?.cancel();
|
|
19
|
+
}
|
|
20
|
+
async match(_request, _options) {
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
async delete(_request, _options) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export class CellsCacheStorage {
|
|
28
|
+
default = new CellsCache();
|
|
29
|
+
async open(_name) {
|
|
30
|
+
return new CellsCache();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export const cellsCaches = new CellsCacheStorage();
|
|
34
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/bindings/cache.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,OAAO,UAAU;IACrB,KAAK,CAAC,GAAG,CAAC,OAA0B,EAAE,QAAkB;QACtD,MAAM,GAAG,GAAG,OAAO,YAAY,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;QACxE,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK;YAAE,MAAM,IAAI,SAAS,CAAC,uCAAuC,CAAC,CAAC;QACvF,IAAI,CAAC,CAAC,QAAQ,YAAY,QAAQ,CAAC;YAAE,MAAM,IAAI,SAAS,CAAC,iCAAiC,CAAC,CAAC;QAC5F,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG;YAAE,MAAM,IAAI,SAAS,CAAC,6CAA6C,CAAC,CAAC;QAChG,IAAI,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG;YACtC,MAAM,IAAI,SAAS,CAAC,kCAAkC,CAAC,CAAC;QAC1D,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAChC,CAAC;IACD,KAAK,CAAC,KAAK,CAAC,QAA2B,EAAE,QAAkB;QACzD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,KAAK,CAAC,MAAM,CAAC,QAA2B,EAAE,QAAkB;QAC1D,OAAO,KAAK,CAAC;IACf,CAAC;CACF;AAED,MAAM,OAAO,iBAAiB;IACnB,OAAO,GAAG,IAAI,UAAU,EAAE,CAAC;IACpC,KAAK,CAAC,IAAI,CAAC,KAAa;QACtB,OAAO,IAAI,UAAU,EAAE,CAAC;IAC1B,CAAC;CACF;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,iBAAiB,EAAE,CAAC","sourcesContent":["/**\n * The Workers Cache API as celld provides it (cloudflare-compat.md#cache): an always-miss\n * cache, because there is no shared edge cache. `put()` validates and consumes the response\n * but stores nothing, `match()` resolves to `undefined`, `delete()` to `false`.\n * Substituted for the `caches` global of user code (browsers have a real CacheStorage).\n */\nexport class CellsCache {\n async put(request: RequestInfo | URL, response: Response): Promise<void> {\n const req = request instanceof Request ? request : new Request(request);\n if (req.method !== \"GET\") throw new TypeError(\"Cache.put() only accepts GET requests\");\n if (!(response instanceof Response)) throw new TypeError(\"Cache.put() requires a Response\");\n if (response.status === 206) throw new TypeError(\"Cache.put() cannot store a partial response\");\n if (response.headers.get(\"vary\") === \"*\")\n throw new TypeError(\"Cache.put() cannot store Vary: *\");\n await response.body?.cancel();\n }\n async match(_request: RequestInfo | URL, _options?: unknown): Promise<Response | undefined> {\n return undefined;\n }\n async delete(_request: RequestInfo | URL, _options?: unknown): Promise<boolean> {\n return false;\n }\n}\n\nexport class CellsCacheStorage {\n readonly default = new CellsCache();\n async open(_name: string): Promise<CellsCache> {\n return new CellsCache();\n }\n}\n\nexport const cellsCaches = new CellsCacheStorage();\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { FilesApi } from "@statewalker/webrun-files";
|
|
2
|
+
/**
|
|
3
|
+
* KV exactly as celld implements it: celld's own `services/kv.js` (namespace cell + binding
|
|
4
|
+
* client, Apache-2.0) on a cellb host. The limits are celld_logic::kv's constants;
|
|
5
|
+
* values above 1 MiB go to a FilesApi (celld: the fleet bucket) through the same
|
|
6
|
+
* prepare / put / get / sweep protocol.
|
|
7
|
+
*/
|
|
8
|
+
export declare const CELLD_KV_LIMITS: {
|
|
9
|
+
maxKeyBytes: number;
|
|
10
|
+
maxValueBytes: number;
|
|
11
|
+
maxInlineValueBytes: number;
|
|
12
|
+
maxMetadataBytes: number;
|
|
13
|
+
minExpirationTtlMs: number;
|
|
14
|
+
maxBulkKeys: number;
|
|
15
|
+
maxListLimit: number;
|
|
16
|
+
sweepBatchRows: number;
|
|
17
|
+
blobSweepMs: number;
|
|
18
|
+
sweepDisabled: boolean;
|
|
19
|
+
legacySchema: boolean;
|
|
20
|
+
failAfterBlobWrite: boolean;
|
|
21
|
+
raceSweepPut: boolean;
|
|
22
|
+
};
|
|
23
|
+
export declare function celldKv(files: FilesApi, root?: string): {
|
|
24
|
+
KvNamespaceCell: unknown;
|
|
25
|
+
KvNamespace: new (ns: () => unknown, cellName: string) => unknown;
|
|
26
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// @ts-expect-error — vendored JS (scripts/vendor-celld.mjs)
|
|
2
|
+
import { kvService } from "../../vendor/celld/kv.js";
|
|
3
|
+
import { DurableObject } from "../core/durable-object.js";
|
|
4
|
+
/**
|
|
5
|
+
* KV exactly as celld implements it: celld's own `services/kv.js` (namespace cell + binding
|
|
6
|
+
* client, Apache-2.0) on a cellb host. The limits are celld_logic::kv's constants;
|
|
7
|
+
* values above 1 MiB go to a FilesApi (celld: the fleet bucket) through the same
|
|
8
|
+
* prepare / put / get / sweep protocol.
|
|
9
|
+
*/
|
|
10
|
+
export const CELLD_KV_LIMITS = {
|
|
11
|
+
maxKeyBytes: 512,
|
|
12
|
+
maxValueBytes: 25 * 1024 * 1024,
|
|
13
|
+
maxInlineValueBytes: 1024 * 1024,
|
|
14
|
+
maxMetadataBytes: 1024,
|
|
15
|
+
minExpirationTtlMs: 60_000,
|
|
16
|
+
maxBulkKeys: 100,
|
|
17
|
+
maxListLimit: 1000,
|
|
18
|
+
sweepBatchRows: 256,
|
|
19
|
+
blobSweepMs: 60_000,
|
|
20
|
+
sweepDisabled: false,
|
|
21
|
+
legacySchema: false,
|
|
22
|
+
failAfterBlobWrite: false,
|
|
23
|
+
raceSweepPut: false,
|
|
24
|
+
};
|
|
25
|
+
const b64 = (bytes) => {
|
|
26
|
+
let s = "";
|
|
27
|
+
for (let i = 0; i < bytes.length; i += 0x8000)
|
|
28
|
+
s += String.fromCharCode(...bytes.subarray(i, i + 0x8000));
|
|
29
|
+
return btoa(s);
|
|
30
|
+
};
|
|
31
|
+
const unb64 = (text) => Uint8Array.from(atob(text), (c) => c.charCodeAt(0));
|
|
32
|
+
async function readAll(files, path) {
|
|
33
|
+
if (!(await files.exists(path)))
|
|
34
|
+
return undefined;
|
|
35
|
+
const chunks = [];
|
|
36
|
+
for await (const c of files.read(path))
|
|
37
|
+
chunks.push(c);
|
|
38
|
+
const out = new Uint8Array(chunks.reduce((n, c) => n + c.byteLength, 0));
|
|
39
|
+
let o = 0;
|
|
40
|
+
for (const c of chunks) {
|
|
41
|
+
out.set(c, o);
|
|
42
|
+
o += c.byteLength;
|
|
43
|
+
}
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
export function celldKv(files, root = "/kv-blobs") {
|
|
47
|
+
const dirOf = (cell) => `${root}/${cell.ctx.id.toString()}`;
|
|
48
|
+
return kvService({
|
|
49
|
+
DurableObject,
|
|
50
|
+
limits: () => CELLD_KV_LIMITS,
|
|
51
|
+
blob: async (cell, request, value) => {
|
|
52
|
+
const dir = dirOf(cell);
|
|
53
|
+
switch (request.mode) {
|
|
54
|
+
case "prepare":
|
|
55
|
+
return { reference: `${request.digest}-${crypto.randomUUID().replace(/-/g, "")}` };
|
|
56
|
+
case "put":
|
|
57
|
+
await files.write(`${dir}/${request.reference}`, [value]);
|
|
58
|
+
return { ok: true };
|
|
59
|
+
case "get": {
|
|
60
|
+
const bytes = await readAll(files, `${dir}/${request.reference}`);
|
|
61
|
+
return bytes ? { found: true, value: bytes } : { found: false };
|
|
62
|
+
}
|
|
63
|
+
case "sweep": {
|
|
64
|
+
const live = new Set(request.live ?? []);
|
|
65
|
+
if (await files.exists(dir))
|
|
66
|
+
for await (const f of files.list(dir)) {
|
|
67
|
+
const name = f.path.split("/").pop() ?? "";
|
|
68
|
+
if (f.kind === "file" && !live.has(name))
|
|
69
|
+
await files.remove(f.path);
|
|
70
|
+
}
|
|
71
|
+
return { ok: true };
|
|
72
|
+
}
|
|
73
|
+
default:
|
|
74
|
+
throw new Error(`unknown KV blob mode ${request.mode}`);
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
btoa: (bytes) => b64(bytes),
|
|
78
|
+
atob: (text) => unb64(text),
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=celld-kv.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"celld-kv.js","sourceRoot":"","sources":["../../src/bindings/celld-kv.ts"],"names":[],"mappings":"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","sourcesContent":["import type { FilesApi } from \"@statewalker/webrun-files\";\n// @ts-expect-error — vendored JS (scripts/vendor-celld.mjs)\nimport { kvService } from \"../../vendor/celld/kv.js\";\nimport { DurableObject } from \"../core/durable-object.js\";\n\n/**\n * KV exactly as celld implements it: celld's own `services/kv.js` (namespace cell + binding\n * client, Apache-2.0) on a cellb host. The limits are celld_logic::kv's constants;\n * values above 1 MiB go to a FilesApi (celld: the fleet bucket) through the same\n * prepare / put / get / sweep protocol.\n */\nexport const CELLD_KV_LIMITS = {\n maxKeyBytes: 512,\n maxValueBytes: 25 * 1024 * 1024,\n maxInlineValueBytes: 1024 * 1024,\n maxMetadataBytes: 1024,\n minExpirationTtlMs: 60_000,\n maxBulkKeys: 100,\n maxListLimit: 1000,\n sweepBatchRows: 256,\n blobSweepMs: 60_000,\n sweepDisabled: false,\n legacySchema: false,\n failAfterBlobWrite: false,\n raceSweepPut: false,\n};\n\nconst b64 = (bytes: Uint8Array) => {\n let s = \"\";\n for (let i = 0; i < bytes.length; i += 0x8000)\n s += String.fromCharCode(...bytes.subarray(i, i + 0x8000));\n return btoa(s);\n};\nconst unb64 = (text: string) => Uint8Array.from(atob(text), (c) => c.charCodeAt(0));\n\nasync function readAll(files: FilesApi, path: string): Promise<Uint8Array | undefined> {\n if (!(await files.exists(path))) return undefined;\n const chunks: Uint8Array[] = [];\n for await (const c of files.read(path)) chunks.push(c);\n const out = new Uint8Array(chunks.reduce((n, c) => n + c.byteLength, 0));\n let o = 0;\n for (const c of chunks) {\n out.set(c, o);\n o += c.byteLength;\n }\n return out;\n}\n\nexport function celldKv(files: FilesApi, root = \"/kv-blobs\") {\n const dirOf = (cell: { ctx: { id: { toString(): string } } }) =>\n `${root}/${cell.ctx.id.toString()}`;\n return kvService({\n DurableObject,\n limits: () => CELLD_KV_LIMITS,\n blob: async (cell: any, request: any, value?: Uint8Array) => {\n const dir = dirOf(cell);\n switch (request.mode) {\n case \"prepare\":\n return { reference: `${request.digest}-${crypto.randomUUID().replace(/-/g, \"\")}` };\n case \"put\":\n await files.write(`${dir}/${request.reference}`, [value as Uint8Array]);\n return { ok: true };\n case \"get\": {\n const bytes = await readAll(files, `${dir}/${request.reference}`);\n return bytes ? { found: true, value: bytes } : { found: false };\n }\n case \"sweep\": {\n const live = new Set<string>(request.live ?? []);\n if (await files.exists(dir))\n for await (const f of files.list(dir)) {\n const name = f.path.split(\"/\").pop() ?? \"\";\n if (f.kind === \"file\" && !live.has(name)) await files.remove(f.path);\n }\n return { ok: true };\n }\n default:\n throw new Error(`unknown KV blob mode ${request.mode}`);\n }\n },\n btoa: (bytes: Uint8Array) => b64(bytes),\n atob: (text: string) => unb64(text),\n }) as {\n KvNamespaceCell: unknown;\n KvNamespace: new (ns: () => unknown, cellName: string) => unknown;\n };\n}\n"]}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Queues exactly as celld implements them: celld's own queue cell, producer binding and
|
|
3
|
+
* consumer batch (harness.js, vendored unchanged, Apache-2.0) on a cellb host. The
|
|
4
|
+
* queue cell's SQLite layout (`__queue_messages`, `__queue_stats`, …) is therefore celld's, so
|
|
5
|
+
* a queue's pending messages move between celld and cellb with its cell.
|
|
6
|
+
*
|
|
7
|
+
* What the host supplies, as celld's engine does:
|
|
8
|
+
* - `__queue_policy`: celld_logic::queue (Rust) ported below — every deadline and lease rule;
|
|
9
|
+
* - `__queue_dispatch`: runs the consumer's `queue()` with celld's batch object, then posts the
|
|
10
|
+
* settlement to the queue cell (`/__qSettle`), after the alarm that leased the batch;
|
|
11
|
+
* - limits, consumer configuration, lease duration (celld's defaults).
|
|
12
|
+
*/
|
|
13
|
+
/** celld_logic::queue and queue_batching defaults (celld 0.6.2). */
|
|
14
|
+
export declare const CELLD_QUEUE_LIMITS: {
|
|
15
|
+
maxMessageBytes: number;
|
|
16
|
+
maxBatchBytes: number;
|
|
17
|
+
maxBatchMessages: number;
|
|
18
|
+
producerGroupMs: number;
|
|
19
|
+
maxConcurrency: number;
|
|
20
|
+
maxDelaySeconds: number;
|
|
21
|
+
retentionMs: number;
|
|
22
|
+
sweepBatchRows: number;
|
|
23
|
+
};
|
|
24
|
+
export interface QueueConsumerConfig {
|
|
25
|
+
queue: string;
|
|
26
|
+
max_batch_size?: number;
|
|
27
|
+
max_batch_timeout?: number;
|
|
28
|
+
max_retries?: number;
|
|
29
|
+
dead_letter_queue?: string;
|
|
30
|
+
max_concurrency?: number;
|
|
31
|
+
retry_delay?: number;
|
|
32
|
+
}
|
|
33
|
+
type J = Record<string, any>;
|
|
34
|
+
export declare function queuePolicy(request: J): unknown;
|
|
35
|
+
export declare function celldQueues(opts: {
|
|
36
|
+
/** The namespace of the `__Queue` cells (celld's fleet-wide namespace). */
|
|
37
|
+
namespace: () => {
|
|
38
|
+
getByName(name: string): {
|
|
39
|
+
fetch(req: Request): Promise<Response>;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
consumers: QueueConsumerConfig[];
|
|
43
|
+
/** Runs the Worker's `queue(batch)` handler (celld: the consumer script's entrypoint). */
|
|
44
|
+
runConsumer: (batch: unknown) => Promise<void>;
|
|
45
|
+
/** Wrangler `compatibility_date` decides the default content type (json from 2024-03-18). */
|
|
46
|
+
compatibilityDate?: string;
|
|
47
|
+
/** Background work after the leasing alarm (the consumer runs outside the cell's event). */
|
|
48
|
+
defer?: (work: Promise<unknown>) => void;
|
|
49
|
+
}): {
|
|
50
|
+
QueueCell: {
|
|
51
|
+
new (ctx: any, env: any): {};
|
|
52
|
+
};
|
|
53
|
+
/** The producer binding (celld: `__makeQueue(queue, cellName, deliveryDelay)`). */
|
|
54
|
+
producer: (queue: string, deliveryDelay?: number) => unknown;
|
|
55
|
+
};
|
|
56
|
+
export {};
|