workerstack 0.1.0-beta.0
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/CHANGELOG.md +13 -0
- package/LICENSE +21 -0
- package/README.md +138 -0
- package/dist/access.d.ts +131 -0
- package/dist/access.d.ts.map +1 -0
- package/dist/access.js +333 -0
- package/dist/access.js.map +1 -0
- package/dist/api/builder.d.ts +457 -0
- package/dist/api/builder.d.ts.map +1 -0
- package/dist/api/builder.js +45 -0
- package/dist/api/builder.js.map +1 -0
- package/dist/api/catalog.d.ts +8 -0
- package/dist/api/catalog.d.ts.map +1 -0
- package/dist/api/catalog.js +56 -0
- package/dist/api/catalog.js.map +1 -0
- package/dist/api/context.d.ts +47 -0
- package/dist/api/context.d.ts.map +1 -0
- package/dist/api/context.js +40 -0
- package/dist/api/context.js.map +1 -0
- package/dist/api/crud-router.d.ts +476 -0
- package/dist/api/crud-router.d.ts.map +1 -0
- package/dist/api/crud-router.js +354 -0
- package/dist/api/crud-router.js.map +1 -0
- package/dist/api/list-input-schema.d.ts +37 -0
- package/dist/api/list-input-schema.d.ts.map +1 -0
- package/dist/api/list-input-schema.js +63 -0
- package/dist/api/list-input-schema.js.map +1 -0
- package/dist/api/list-spec.d.ts +44 -0
- package/dist/api/list-spec.d.ts.map +1 -0
- package/dist/api/list-spec.js +49 -0
- package/dist/api/list-spec.js.map +1 -0
- package/dist/api/live-view.d.ts +14 -0
- package/dist/api/live-view.d.ts.map +1 -0
- package/dist/api/live-view.js +42 -0
- package/dist/api/live-view.js.map +1 -0
- package/dist/api/live-window.d.ts +40 -0
- package/dist/api/live-window.d.ts.map +1 -0
- package/dist/api/live-window.js +93 -0
- package/dist/api/live-window.js.map +1 -0
- package/dist/api/openapi.d.ts +6 -0
- package/dist/api/openapi.d.ts.map +1 -0
- package/dist/api/openapi.js +146 -0
- package/dist/api/openapi.js.map +1 -0
- package/dist/api/realtime-router.d.ts +94 -0
- package/dist/api/realtime-router.d.ts.map +1 -0
- package/dist/api/realtime-router.js +45 -0
- package/dist/api/realtime-router.js.map +1 -0
- package/dist/api/registry.d.ts +30 -0
- package/dist/api/registry.d.ts.map +1 -0
- package/dist/api/registry.js +236 -0
- package/dist/api/registry.js.map +1 -0
- package/dist/api/router.d.ts +15 -0
- package/dist/api/router.d.ts.map +1 -0
- package/dist/api/router.js +32 -0
- package/dist/api/router.js.map +1 -0
- package/dist/api/storage-router.d.ts +349 -0
- package/dist/api/storage-router.d.ts.map +1 -0
- package/dist/api/storage-router.js +155 -0
- package/dist/api/storage-router.js.map +1 -0
- package/dist/api/types.d.ts +55 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/api/types.js +2 -0
- package/dist/api/types.js.map +1 -0
- package/dist/auth-password.d.ts +27 -0
- package/dist/auth-password.d.ts.map +1 -0
- package/dist/auth-password.js +60 -0
- package/dist/auth-password.js.map +1 -0
- package/dist/auth.d.ts +59 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +146 -0
- package/dist/auth.js.map +1 -0
- package/dist/backend-internals.d.ts +35 -0
- package/dist/backend-internals.d.ts.map +1 -0
- package/dist/backend-internals.js +2 -0
- package/dist/backend-internals.js.map +1 -0
- package/dist/backend.d.ts +63 -0
- package/dist/backend.d.ts.map +1 -0
- package/dist/backend.js +59 -0
- package/dist/backend.js.map +1 -0
- package/dist/blueprint-generator.d.ts +21 -0
- package/dist/blueprint-generator.d.ts.map +1 -0
- package/dist/blueprint-generator.js +199 -0
- package/dist/blueprint-generator.js.map +1 -0
- package/dist/blueprint.d.ts +99 -0
- package/dist/blueprint.d.ts.map +1 -0
- package/dist/blueprint.js +257 -0
- package/dist/blueprint.js.map +1 -0
- package/dist/cli-skills.d.ts +16 -0
- package/dist/cli-skills.d.ts.map +1 -0
- package/dist/cli-skills.js +108 -0
- package/dist/cli-skills.js.map +1 -0
- package/dist/cli.d.ts +18 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +205 -0
- package/dist/cli.js.map +1 -0
- package/dist/client/client.d.ts +53 -0
- package/dist/client/client.d.ts.map +1 -0
- package/dist/client/client.js +111 -0
- package/dist/client/client.js.map +1 -0
- package/dist/client/index.d.ts +4 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +4 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/live-view.d.ts +49 -0
- package/dist/client/live-view.d.ts.map +1 -0
- package/dist/client/live-view.js +184 -0
- package/dist/client/live-view.js.map +1 -0
- package/dist/client/react.d.ts +4 -0
- package/dist/client/react.d.ts.map +1 -0
- package/dist/client/react.js +6 -0
- package/dist/client/react.js.map +1 -0
- package/dist/client/realtime.d.ts +54 -0
- package/dist/client/realtime.d.ts.map +1 -0
- package/dist/client/realtime.js +105 -0
- package/dist/client/realtime.js.map +1 -0
- package/dist/client/rest.d.ts +2 -0
- package/dist/client/rest.d.ts.map +1 -0
- package/dist/client/rest.js +2 -0
- package/dist/client/rest.js.map +1 -0
- package/dist/client/rpc-client.d.ts +38 -0
- package/dist/client/rpc-client.d.ts.map +1 -0
- package/dist/client/rpc-client.js +59 -0
- package/dist/client/rpc-client.js.map +1 -0
- package/dist/client/solid.d.ts +7 -0
- package/dist/client/solid.d.ts.map +1 -0
- package/dist/client/solid.js +21 -0
- package/dist/client/solid.js.map +1 -0
- package/dist/client/svelte.d.ts +6 -0
- package/dist/client/svelte.d.ts.map +1 -0
- package/dist/client/svelte.js +9 -0
- package/dist/client/svelte.js.map +1 -0
- package/dist/client/vue.d.ts +5 -0
- package/dist/client/vue.d.ts.map +1 -0
- package/dist/client/vue.js +11 -0
- package/dist/client/vue.js.map +1 -0
- package/dist/codegen.d.ts +36 -0
- package/dist/codegen.d.ts.map +1 -0
- package/dist/codegen.js +235 -0
- package/dist/codegen.js.map +1 -0
- package/dist/config.d.ts +129 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +75 -0
- package/dist/config.js.map +1 -0
- package/dist/cron.d.ts +4 -0
- package/dist/cron.d.ts.map +1 -0
- package/dist/cron.js +3 -0
- package/dist/cron.js.map +1 -0
- package/dist/crud-operations.d.ts +43 -0
- package/dist/crud-operations.d.ts.map +1 -0
- package/dist/crud-operations.js +249 -0
- package/dist/crud-operations.js.map +1 -0
- package/dist/database/adapter.d.ts +26 -0
- package/dist/database/adapter.d.ts.map +1 -0
- package/dist/database/adapter.js +2 -0
- package/dist/database/adapter.js.map +1 -0
- package/dist/database/libsql.d.ts +3 -0
- package/dist/database/libsql.d.ts.map +1 -0
- package/dist/database/libsql.js +39 -0
- package/dist/database/libsql.js.map +1 -0
- package/dist/db.d.ts +15 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +8 -0
- package/dist/db.js.map +1 -0
- package/dist/dev/binaries.d.ts +22 -0
- package/dist/dev/binaries.d.ts.map +1 -0
- package/dist/dev/binaries.js +119 -0
- package/dist/dev/binaries.js.map +1 -0
- package/dist/dev/env.d.ts +11 -0
- package/dist/dev/env.d.ts.map +1 -0
- package/dist/dev/env.js +71 -0
- package/dist/dev/env.js.map +1 -0
- package/dist/dev/index.d.ts +39 -0
- package/dist/dev/index.d.ts.map +1 -0
- package/dist/dev/index.js +273 -0
- package/dist/dev/index.js.map +1 -0
- package/dist/dev/processes.d.ts +37 -0
- package/dist/dev/processes.d.ts.map +1 -0
- package/dist/dev/processes.js +104 -0
- package/dist/dev/processes.js.map +1 -0
- package/dist/dev/push.d.ts +2 -0
- package/dist/dev/push.d.ts.map +1 -0
- package/dist/dev/push.js +30 -0
- package/dist/dev/push.js.map +1 -0
- package/dist/dialect.d.ts +17 -0
- package/dist/dialect.d.ts.map +1 -0
- package/dist/dialect.js +12 -0
- package/dist/dialect.js.map +1 -0
- package/dist/email/smtp.d.ts +20 -0
- package/dist/email/smtp.d.ts.map +1 -0
- package/dist/email/smtp.js +31 -0
- package/dist/email/smtp.js.map +1 -0
- package/dist/email.d.ts +26 -0
- package/dist/email.d.ts.map +1 -0
- package/dist/email.js +2 -0
- package/dist/email.js.map +1 -0
- package/dist/env-probe.d.ts +9 -0
- package/dist/env-probe.d.ts.map +1 -0
- package/dist/env-probe.js +72 -0
- package/dist/env-probe.js.map +1 -0
- package/dist/env.d.ts +62 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +86 -0
- package/dist/env.js.map +1 -0
- package/dist/errors.d.ts +153 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +106 -0
- package/dist/errors.js.map +1 -0
- package/dist/handler.d.ts +11 -0
- package/dist/handler.d.ts.map +1 -0
- package/dist/handler.js +21 -0
- package/dist/handler.js.map +1 -0
- package/dist/hosted-contract.d.ts +11 -0
- package/dist/hosted-contract.d.ts.map +1 -0
- package/dist/hosted-contract.js +50 -0
- package/dist/hosted-contract.js.map +1 -0
- package/dist/idempotency.d.ts +17 -0
- package/dist/idempotency.d.ts.map +1 -0
- package/dist/idempotency.js +65 -0
- package/dist/idempotency.js.map +1 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/inspect.d.ts +15 -0
- package/dist/inspect.d.ts.map +1 -0
- package/dist/inspect.js +44 -0
- package/dist/inspect.js.map +1 -0
- package/dist/internal-tables.d.ts +1767 -0
- package/dist/internal-tables.d.ts.map +1 -0
- package/dist/internal-tables.js +114 -0
- package/dist/internal-tables.js.map +1 -0
- package/dist/jobs/cron.d.ts +15 -0
- package/dist/jobs/cron.d.ts.map +1 -0
- package/dist/jobs/cron.js +74 -0
- package/dist/jobs/cron.js.map +1 -0
- package/dist/jobs/define.d.ts +186 -0
- package/dist/jobs/define.d.ts.map +1 -0
- package/dist/jobs/define.js +99 -0
- package/dist/jobs/define.js.map +1 -0
- package/dist/jobs/index.d.ts +9 -0
- package/dist/jobs/index.d.ts.map +1 -0
- package/dist/jobs/index.js +7 -0
- package/dist/jobs/index.js.map +1 -0
- package/dist/jobs/queue.d.ts +13 -0
- package/dist/jobs/queue.d.ts.map +1 -0
- package/dist/jobs/queue.js +71 -0
- package/dist/jobs/queue.js.map +1 -0
- package/dist/jobs/slots.d.ts +30 -0
- package/dist/jobs/slots.d.ts.map +1 -0
- package/dist/jobs/slots.js +53 -0
- package/dist/jobs/slots.js.map +1 -0
- package/dist/jobs/worker.d.ts +45 -0
- package/dist/jobs/worker.d.ts.map +1 -0
- package/dist/jobs/worker.js +605 -0
- package/dist/jobs/worker.js.map +1 -0
- package/dist/lifecycle.d.ts +10 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +37 -0
- package/dist/lifecycle.js.map +1 -0
- package/dist/list-query.d.ts +62 -0
- package/dist/list-query.d.ts.map +1 -0
- package/dist/list-query.js +190 -0
- package/dist/list-query.js.map +1 -0
- package/dist/live/apply.d.ts +13 -0
- package/dist/live/apply.d.ts.map +1 -0
- package/dist/live/apply.js +32 -0
- package/dist/live/apply.js.map +1 -0
- package/dist/live/index.d.ts +48 -0
- package/dist/live/index.d.ts.map +1 -0
- package/dist/live/index.js +108 -0
- package/dist/live/index.js.map +1 -0
- package/dist/live/protocol.d.ts +47 -0
- package/dist/live/protocol.d.ts.map +1 -0
- package/dist/live/protocol.js +12 -0
- package/dist/live/protocol.js.map +1 -0
- package/dist/live/sse.d.ts +22 -0
- package/dist/live/sse.d.ts.map +1 -0
- package/dist/live/sse.js +41 -0
- package/dist/live/sse.js.map +1 -0
- package/dist/logging.d.ts +8 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +6 -0
- package/dist/logging.js.map +1 -0
- package/dist/manifest-diff.d.ts +6 -0
- package/dist/manifest-diff.d.ts.map +1 -0
- package/dist/manifest-diff.js +42 -0
- package/dist/manifest-diff.js.map +1 -0
- package/dist/manifest.d.ts +87 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +237 -0
- package/dist/manifest.js.map +1 -0
- package/dist/messaging/email.d.ts +16 -0
- package/dist/messaging/email.d.ts.map +1 -0
- package/dist/messaging/email.js +8 -0
- package/dist/messaging/email.js.map +1 -0
- package/dist/messaging/index.d.ts +8 -0
- package/dist/messaging/index.d.ts.map +1 -0
- package/dist/messaging/index.js +4 -0
- package/dist/messaging/index.js.map +1 -0
- package/dist/messaging/journal.d.ts +4 -0
- package/dist/messaging/journal.d.ts.map +1 -0
- package/dist/messaging/journal.js +19 -0
- package/dist/messaging/journal.js.map +1 -0
- package/dist/messaging/runtime.d.ts +16 -0
- package/dist/messaging/runtime.d.ts.map +1 -0
- package/dist/messaging/runtime.js +213 -0
- package/dist/messaging/runtime.js.map +1 -0
- package/dist/messaging/standalone.d.ts +27 -0
- package/dist/messaging/standalone.d.ts.map +1 -0
- package/dist/messaging/standalone.js +18 -0
- package/dist/messaging/standalone.js.map +1 -0
- package/dist/messaging/telegram.d.ts +16 -0
- package/dist/messaging/telegram.d.ts.map +1 -0
- package/dist/messaging/telegram.js +5 -0
- package/dist/messaging/telegram.js.map +1 -0
- package/dist/messaging/types.d.ts +22 -0
- package/dist/messaging/types.d.ts.map +1 -0
- package/dist/messaging/types.js +17 -0
- package/dist/messaging/types.js.map +1 -0
- package/dist/platform.d.ts +25 -0
- package/dist/platform.d.ts.map +1 -0
- package/dist/platform.js +24 -0
- package/dist/platform.js.map +1 -0
- package/dist/provision-internals.d.ts +23 -0
- package/dist/provision-internals.d.ts.map +1 -0
- package/dist/provision-internals.js +7 -0
- package/dist/provision-internals.js.map +1 -0
- package/dist/provision-runtime.d.ts +6 -0
- package/dist/provision-runtime.d.ts.map +1 -0
- package/dist/provision-runtime.js +41 -0
- package/dist/provision-runtime.js.map +1 -0
- package/dist/provision-schema.d.ts +16 -0
- package/dist/provision-schema.d.ts.map +1 -0
- package/dist/provision-schema.js +59 -0
- package/dist/provision-schema.js.map +1 -0
- package/dist/provision.d.ts +8 -0
- package/dist/provision.d.ts.map +1 -0
- package/dist/provision.js +16 -0
- package/dist/provision.js.map +1 -0
- package/dist/query/api.d.ts +10 -0
- package/dist/query/api.d.ts.map +1 -0
- package/dist/query/api.js +7 -0
- package/dist/query/api.js.map +1 -0
- package/dist/query/client.d.ts +28 -0
- package/dist/query/client.d.ts.map +1 -0
- package/dist/query/client.js +87 -0
- package/dist/query/client.js.map +1 -0
- package/dist/query/fetch.d.ts +3 -0
- package/dist/query/fetch.d.ts.map +1 -0
- package/dist/query/fetch.js +4 -0
- package/dist/query/fetch.js.map +1 -0
- package/dist/query/index.d.ts +8 -0
- package/dist/query/index.d.ts.map +1 -0
- package/dist/query/index.js +4 -0
- package/dist/query/index.js.map +1 -0
- package/dist/query/infer.d.ts +25 -0
- package/dist/query/infer.d.ts.map +1 -0
- package/dist/query/infer.js +2 -0
- package/dist/query/infer.js.map +1 -0
- package/dist/query/react.d.ts +3 -0
- package/dist/query/react.d.ts.map +1 -0
- package/dist/query/react.js +2 -0
- package/dist/query/react.js.map +1 -0
- package/dist/query/realtime-flush.d.ts +26 -0
- package/dist/query/realtime-flush.d.ts.map +1 -0
- package/dist/query/realtime-flush.js +45 -0
- package/dist/query/realtime-flush.js.map +1 -0
- package/dist/query/realtime-stream.d.ts +3 -0
- package/dist/query/realtime-stream.d.ts.map +1 -0
- package/dist/query/realtime-stream.js +3 -0
- package/dist/query/realtime-stream.js.map +1 -0
- package/dist/query/realtime.d.ts +88 -0
- package/dist/query/realtime.d.ts.map +1 -0
- package/dist/query/realtime.js +255 -0
- package/dist/query/realtime.js.map +1 -0
- package/dist/rate-limit.d.ts +8 -0
- package/dist/rate-limit.d.ts.map +1 -0
- package/dist/rate-limit.js +46 -0
- package/dist/rate-limit.js.map +1 -0
- package/dist/readiness-probes.d.ts +4 -0
- package/dist/readiness-probes.d.ts.map +1 -0
- package/dist/readiness-probes.js +23 -0
- package/dist/readiness-probes.js.map +1 -0
- package/dist/readiness.d.ts +39 -0
- package/dist/readiness.d.ts.map +1 -0
- package/dist/readiness.js +72 -0
- package/dist/readiness.js.map +1 -0
- package/dist/realtime/facade.d.ts +20 -0
- package/dist/realtime/facade.d.ts.map +1 -0
- package/dist/realtime/facade.js +37 -0
- package/dist/realtime/facade.js.map +1 -0
- package/dist/realtime/filter.d.ts +42 -0
- package/dist/realtime/filter.d.ts.map +1 -0
- package/dist/realtime/filter.js +86 -0
- package/dist/realtime/filter.js.map +1 -0
- package/dist/realtime/heartbeat.d.ts +20 -0
- package/dist/realtime/heartbeat.d.ts.map +1 -0
- package/dist/realtime/heartbeat.js +64 -0
- package/dist/realtime/heartbeat.js.map +1 -0
- package/dist/realtime/publisher.d.ts +19 -0
- package/dist/realtime/publisher.d.ts.map +1 -0
- package/dist/realtime/publisher.js +8 -0
- package/dist/realtime/publisher.js.map +1 -0
- package/dist/runtime.d.ts +141 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +463 -0
- package/dist/runtime.js.map +1 -0
- package/dist/schema-export.d.ts +2 -0
- package/dist/schema-export.d.ts.map +1 -0
- package/dist/schema-export.js +2 -0
- package/dist/schema-export.js.map +1 -0
- package/dist/scope.d.ts +4 -0
- package/dist/scope.d.ts.map +1 -0
- package/dist/scope.js +13 -0
- package/dist/scope.js.map +1 -0
- package/dist/standard-schema.d.ts +13 -0
- package/dist/standard-schema.d.ts.map +1 -0
- package/dist/standard-schema.js +34 -0
- package/dist/standard-schema.js.map +1 -0
- package/dist/start/auth-client.d.ts +11 -0
- package/dist/start/auth-client.d.ts.map +1 -0
- package/dist/start/auth-client.js +15 -0
- package/dist/start/auth-client.js.map +1 -0
- package/dist/start/create-start-worker.d.ts +16 -0
- package/dist/start/create-start-worker.d.ts.map +1 -0
- package/dist/start/create-start-worker.js +24 -0
- package/dist/start/create-start-worker.js.map +1 -0
- package/dist/start/index.d.ts +66 -0
- package/dist/start/index.d.ts.map +1 -0
- package/dist/start/index.js +49 -0
- package/dist/start/index.js.map +1 -0
- package/dist/start/isomorphic-fetch.d.ts +22 -0
- package/dist/start/isomorphic-fetch.d.ts.map +1 -0
- package/dist/start/isomorphic-fetch.js +49 -0
- package/dist/start/isomorphic-fetch.js.map +1 -0
- package/dist/start/server-entry.d.ts +7 -0
- package/dist/start/server-entry.d.ts.map +1 -0
- package/dist/start/server-entry.js +8 -0
- package/dist/start/server-entry.js.map +1 -0
- package/dist/storage/background.d.ts +3 -0
- package/dist/storage/background.d.ts.map +1 -0
- package/dist/storage/background.js +3 -0
- package/dist/storage/background.js.map +1 -0
- package/dist/storage/buckets.d.ts +78 -0
- package/dist/storage/buckets.d.ts.map +1 -0
- package/dist/storage/buckets.js +177 -0
- package/dist/storage/buckets.js.map +1 -0
- package/dist/storage/delete.d.ts +8 -0
- package/dist/storage/delete.d.ts.map +1 -0
- package/dist/storage/delete.js +10 -0
- package/dist/storage/delete.js.map +1 -0
- package/dist/storage/file-meta.d.ts +37 -0
- package/dist/storage/file-meta.d.ts.map +1 -0
- package/dist/storage/file-meta.js +166 -0
- package/dist/storage/file-meta.js.map +1 -0
- package/dist/storage/index.d.ts +28 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +5 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/local.d.ts +15 -0
- package/dist/storage/local.d.ts.map +1 -0
- package/dist/storage/local.js +56 -0
- package/dist/storage/local.js.map +1 -0
- package/dist/storage/operations.d.ts +54 -0
- package/dist/storage/operations.d.ts.map +1 -0
- package/dist/storage/operations.js +212 -0
- package/dist/storage/operations.js.map +1 -0
- package/dist/storage/registry.d.ts +11 -0
- package/dist/storage/registry.d.ts.map +1 -0
- package/dist/storage/registry.js +23 -0
- package/dist/storage/registry.js.map +1 -0
- package/dist/storage/s3.d.ts +35 -0
- package/dist/storage/s3.d.ts.map +1 -0
- package/dist/storage/s3.js +125 -0
- package/dist/storage/s3.js.map +1 -0
- package/dist/storage/sigv4.d.ts +24 -0
- package/dist/storage/sigv4.d.ts.map +1 -0
- package/dist/storage/sigv4.js +107 -0
- package/dist/storage/sigv4.js.map +1 -0
- package/dist/storage/sweep.d.ts +9 -0
- package/dist/storage/sweep.d.ts.map +1 -0
- package/dist/storage/sweep.js +17 -0
- package/dist/storage/sweep.js.map +1 -0
- package/dist/sync/collection.d.ts +106 -0
- package/dist/sync/collection.d.ts.map +1 -0
- package/dist/sync/collection.js +258 -0
- package/dist/sync/collection.js.map +1 -0
- package/dist/sync/index.d.ts +8 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +4 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/realtime-sync.d.ts +31 -0
- package/dist/sync/realtime-sync.d.ts.map +1 -0
- package/dist/sync/realtime-sync.js +46 -0
- package/dist/sync/realtime-sync.js.map +1 -0
- package/dist/sync/sync-client.d.ts +28 -0
- package/dist/sync/sync-client.d.ts.map +1 -0
- package/dist/sync/sync-client.js +52 -0
- package/dist/sync/sync-client.js.map +1 -0
- package/dist/sync/update-queue.d.ts +27 -0
- package/dist/sync/update-queue.d.ts.map +1 -0
- package/dist/sync/update-queue.js +66 -0
- package/dist/sync/update-queue.js.map +1 -0
- package/dist/testing/auth.d.ts +85 -0
- package/dist/testing/auth.d.ts.map +1 -0
- package/dist/testing/auth.js +140 -0
- package/dist/testing/auth.js.map +1 -0
- package/dist/testing/client.d.ts +6 -0
- package/dist/testing/client.d.ts.map +1 -0
- package/dist/testing/client.js +9 -0
- package/dist/testing/client.js.map +1 -0
- package/dist/testing/database.d.ts +6 -0
- package/dist/testing/database.d.ts.map +1 -0
- package/dist/testing/database.js +8 -0
- package/dist/testing/database.js.map +1 -0
- package/dist/testing/email.d.ts +15 -0
- package/dist/testing/email.d.ts.map +1 -0
- package/dist/testing/email.js +32 -0
- package/dist/testing/email.js.map +1 -0
- package/dist/testing/fixture.d.ts +51 -0
- package/dist/testing/fixture.d.ts.map +1 -0
- package/dist/testing/fixture.js +177 -0
- package/dist/testing/fixture.js.map +1 -0
- package/dist/testing/jobs.d.ts +40 -0
- package/dist/testing/jobs.d.ts.map +1 -0
- package/dist/testing/jobs.js +76 -0
- package/dist/testing/jobs.js.map +1 -0
- package/dist/testing/logs.d.ts +18 -0
- package/dist/testing/logs.d.ts.map +1 -0
- package/dist/testing/logs.js +53 -0
- package/dist/testing/logs.js.map +1 -0
- package/dist/testing/messaging.d.ts +21 -0
- package/dist/testing/messaging.d.ts.map +1 -0
- package/dist/testing/messaging.js +34 -0
- package/dist/testing/messaging.js.map +1 -0
- package/dist/testing/storage.d.ts +7 -0
- package/dist/testing/storage.d.ts.map +1 -0
- package/dist/testing/storage.js +29 -0
- package/dist/testing/storage.js.map +1 -0
- package/dist/testing/workers-fakes.d.ts +17 -0
- package/dist/testing/workers-fakes.d.ts.map +1 -0
- package/dist/testing/workers-fakes.js +98 -0
- package/dist/testing/workers-fakes.js.map +1 -0
- package/dist/testing.d.ts +12 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +5 -0
- package/dist/testing.js.map +1 -0
- package/dist/typeid.d.ts +46 -0
- package/dist/typeid.d.ts.map +1 -0
- package/dist/typeid.js +130 -0
- package/dist/typeid.js.map +1 -0
- package/dist/vite.d.ts +26 -0
- package/dist/vite.d.ts.map +1 -0
- package/dist/vite.js +100 -0
- package/dist/vite.js.map +1 -0
- package/dist/worker-plan.d.ts +37 -0
- package/dist/worker-plan.d.ts.map +1 -0
- package/dist/worker-plan.js +63 -0
- package/dist/worker-plan.js.map +1 -0
- package/dist/workers/app.d.ts +19 -0
- package/dist/workers/app.d.ts.map +1 -0
- package/dist/workers/app.js +56 -0
- package/dist/workers/app.js.map +1 -0
- package/dist/workers/entry.d.ts +7 -0
- package/dist/workers/entry.d.ts.map +1 -0
- package/dist/workers/entry.js +8 -0
- package/dist/workers/entry.js.map +1 -0
- package/dist/workers/index.d.ts +23 -0
- package/dist/workers/index.d.ts.map +1 -0
- package/dist/workers/index.js +39 -0
- package/dist/workers/index.js.map +1 -0
- package/dist/workers/r2.d.ts +24 -0
- package/dist/workers/r2.d.ts.map +1 -0
- package/dist/workers/r2.js +76 -0
- package/dist/workers/r2.js.map +1 -0
- package/dist/workers/rate-limiter.d.ts +9 -0
- package/dist/workers/rate-limiter.d.ts.map +1 -0
- package/dist/workers/rate-limiter.js +22 -0
- package/dist/workers/rate-limiter.js.map +1 -0
- package/dist/workers/realtime-hub.d.ts +20 -0
- package/dist/workers/realtime-hub.d.ts.map +1 -0
- package/dist/workers/realtime-hub.js +117 -0
- package/dist/workers/realtime-hub.js.map +1 -0
- package/dist/workers/registry.d.ts +13 -0
- package/dist/workers/registry.d.ts.map +1 -0
- package/dist/workers/registry.js +19 -0
- package/dist/workers/registry.js.map +1 -0
- package/dist/workers/scheduler.d.ts +13 -0
- package/dist/workers/scheduler.d.ts.map +1 -0
- package/dist/workers/scheduler.js +71 -0
- package/dist/workers/scheduler.js.map +1 -0
- package/dist/workers/types.d.ts +55 -0
- package/dist/workers/types.d.ts.map +1 -0
- package/dist/workers/types.js +4 -0
- package/dist/workers/types.js.map +1 -0
- package/dist/workers/wrangler.d.ts +62 -0
- package/dist/workers/wrangler.d.ts.map +1 -0
- package/dist/workers/wrangler.js +90 -0
- package/dist/workers/wrangler.js.map +1 -0
- package/package.json +286 -0
- package/skills/creating-workerstack-apps/SKILL.md +45 -0
- package/skills/creating-workerstack-apps/agents/openai.yaml +4 -0
- package/skills/creating-workerstack-apps/references/application-structure.md +219 -0
- package/skills/creating-workerstack-apps/references/runtime-integrations.md +96 -0
- package/skills/creating-workerstack-apps/references/verification.md +29 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/** Cloudflare's per-Worker Cron Trigger limit on the free plan. */
|
|
2
|
+
const MAX_CRONS = 5;
|
|
3
|
+
export function bucketBindingName(bucketName) {
|
|
4
|
+
return `BUCKET_${bucketName.toUpperCase().replace(/[^A-Z0-9]/g, '_')}`;
|
|
5
|
+
}
|
|
6
|
+
export function workerPlanFromBlueprint(blueprint) {
|
|
7
|
+
const { worker } = blueprint.application;
|
|
8
|
+
const buckets = blueprint.resources.storage.buckets;
|
|
9
|
+
const crons = [
|
|
10
|
+
...new Set([
|
|
11
|
+
...blueprint.background.cron.map((cron) => cron.schedule),
|
|
12
|
+
...(buckets.length > 0
|
|
13
|
+
? blueprint.background.maintenance.map((task) => task.schedule)
|
|
14
|
+
: []),
|
|
15
|
+
]),
|
|
16
|
+
].sort();
|
|
17
|
+
// Operations without their own path are served through /api/rpc.
|
|
18
|
+
const runWorkerFirst = [
|
|
19
|
+
...new Set([
|
|
20
|
+
'/api/*',
|
|
21
|
+
...(blueprint.api?.operations ?? [])
|
|
22
|
+
.filter((op) => op.path)
|
|
23
|
+
.map((op) => `/${op.path.split('/')[1]}/*`),
|
|
24
|
+
]),
|
|
25
|
+
];
|
|
26
|
+
const ssr = worker.render === 'ssr';
|
|
27
|
+
return {
|
|
28
|
+
render: worker.render,
|
|
29
|
+
main: worker.main,
|
|
30
|
+
compatibilityDate: worker.compatibilityDate,
|
|
31
|
+
compatibilityFlags: ['nodejs_compat'],
|
|
32
|
+
durableObjects: {
|
|
33
|
+
bindings: [
|
|
34
|
+
{ name: 'SCHEDULER', className: 'Scheduler' },
|
|
35
|
+
{ name: 'REALTIME', className: 'RealtimeHub' },
|
|
36
|
+
{ name: 'RATE_LIMITER', className: 'RateLimiter' },
|
|
37
|
+
],
|
|
38
|
+
migrations: [
|
|
39
|
+
{
|
|
40
|
+
tag: 'v1',
|
|
41
|
+
newSqliteClasses: ['Scheduler', 'RealtimeHub', 'RateLimiter'],
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
buckets: buckets.map((bucket) => ({
|
|
46
|
+
name: bucket.name,
|
|
47
|
+
binding: bucketBindingName(bucket.name),
|
|
48
|
+
})),
|
|
49
|
+
crons: crons.length > MAX_CRONS ? ['* * * * *'] : crons,
|
|
50
|
+
assets: {
|
|
51
|
+
directory: worker.assets,
|
|
52
|
+
notFoundHandling: ssr ? 'none' : 'single-page-application',
|
|
53
|
+
// SSR: a path without a file already reaches the Worker.
|
|
54
|
+
runWorkerFirst: ssr ? [] : runWorkerFirst,
|
|
55
|
+
},
|
|
56
|
+
artifact: {
|
|
57
|
+
main: 'dist/server/index.js',
|
|
58
|
+
assets: worker.assets,
|
|
59
|
+
modules: true,
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=worker-plan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-plan.js","sourceRoot":"","sources":["../src/worker-plan.ts"],"names":[],"mappings":"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","sourcesContent":["// src/worker-plan.ts — what a Worker app needs from its host, derived only\n// from the committed version 2 blueprint. Physical names (script, buckets) are\n// the renderer's job: `wrangler.json` locally, a host's own config in hosting.\nimport type { WorkerBlueprint, WorkerRender } from './blueprint'\n\n/** Cloudflare's per-Worker Cron Trigger limit on the free plan. */\nconst MAX_CRONS = 5\n\nexport type WorkerPlan = {\n render: WorkerRender\n /** The source entry for the Vite plugin and wrangler. */\n main: string\n compatibilityDate: string\n compatibilityFlags: string[]\n durableObjects: {\n bindings: { name: string; className: string }[]\n migrations: { tag: string; newSqliteClasses: string[] }[]\n }\n buckets: { name: string; binding: string }[]\n crons: string[]\n assets: {\n directory: string\n notFoundHandling: 'none' | 'single-page-application'\n runWorkerFirst: string[]\n }\n /** What a host deploys after `bun run build`, in both render modes. */\n artifact: { main: 'dist/server/index.js'; assets: string; modules: true }\n}\n\nexport function bucketBindingName(bucketName: string): string {\n return `BUCKET_${bucketName.toUpperCase().replace(/[^A-Z0-9]/g, '_')}`\n}\n\nexport function workerPlanFromBlueprint(\n blueprint: WorkerBlueprint,\n): WorkerPlan {\n const { worker } = blueprint.application\n const buckets = blueprint.resources.storage.buckets\n const crons = [\n ...new Set([\n ...blueprint.background.cron.map((cron) => cron.schedule),\n ...(buckets.length > 0\n ? blueprint.background.maintenance.map((task) => task.schedule)\n : []),\n ]),\n ].sort()\n // Operations without their own path are served through /api/rpc.\n const runWorkerFirst = [\n ...new Set([\n '/api/*',\n ...(blueprint.api?.operations ?? [])\n .filter((op) => op.path)\n .map((op) => `/${op.path!.split('/')[1]}/*`),\n ]),\n ]\n const ssr = worker.render === 'ssr'\n return {\n render: worker.render,\n main: worker.main,\n compatibilityDate: worker.compatibilityDate,\n compatibilityFlags: ['nodejs_compat'],\n durableObjects: {\n bindings: [\n { name: 'SCHEDULER', className: 'Scheduler' },\n { name: 'REALTIME', className: 'RealtimeHub' },\n { name: 'RATE_LIMITER', className: 'RateLimiter' },\n ],\n migrations: [\n {\n tag: 'v1',\n newSqliteClasses: ['Scheduler', 'RealtimeHub', 'RateLimiter'],\n },\n ],\n },\n buckets: buckets.map((bucket) => ({\n name: bucket.name,\n binding: bucketBindingName(bucket.name),\n })),\n crons: crons.length > MAX_CRONS ? ['* * * * *'] : crons,\n assets: {\n directory: worker.assets,\n notFoundHandling: ssr ? 'none' : 'single-page-application',\n // SSR: a path without a file already reaches the Worker.\n runWorkerFirst: ssr ? [] : runWorkerFirst,\n },\n artifact: {\n main: 'dist/server/index.js',\n assets: worker.assets,\n modules: true,\n },\n }\n}\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { WorkerstackBackend } from '../backend.js';
|
|
2
|
+
import type { Platform } from '../platform.js';
|
|
3
|
+
import type { DurableObjectNamespaceLike, WorkerEnv } from './types.js';
|
|
4
|
+
export type WorkerApp = {
|
|
5
|
+
handler(request: Request): Promise<Response>;
|
|
6
|
+
jobs: {
|
|
7
|
+
tick(now?: number): Promise<{
|
|
8
|
+
claimed: number;
|
|
9
|
+
}>;
|
|
10
|
+
nextDueAt(now?: number, until?: number): Promise<number | null>;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
export declare function notifyScheduler(namespace: DurableObjectNamespaceLike, runAt: number): Promise<void>;
|
|
14
|
+
export declare function envStrings(env: WorkerEnv): Record<string, string>;
|
|
15
|
+
export declare function workerPlatform(env: WorkerEnv): Partial<Platform>;
|
|
16
|
+
type AnyBackend = WorkerstackBackend<any>;
|
|
17
|
+
export declare function appFor(backend: AnyBackend, env: WorkerEnv, role: 'fetch' | 'scheduler', platform?: Partial<Platform>): Promise<WorkerApp>;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=app.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/workers/app.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AACpD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,KAAK,EAAE,0BAA0B,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAOpE,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC5C,IAAI,EAAE;QACJ,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;YAAE,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;QAChD,SAAS,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;KAChE,CAAA;CACF,CAAA;AAED,wBAAsB,eAAe,CACnC,SAAS,EAAE,0BAA0B,EACrC,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAQf;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAMjE;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC,CAgBhE;AAED,KAAK,UAAU,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAA;AAGzC,wBAAgB,MAAM,CACpB,OAAO,EAAE,UAAU,EACnB,GAAG,EAAE,SAAS,EACd,IAAI,EAAE,OAAO,GAAG,WAAW,EAC3B,QAAQ,GAAE,OAAO,CAAC,QAAQ,CAAM,GAC/B,OAAO,CAAC,SAAS,CAAC,CAapB"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { workerStorageFactory } from './r2.js';
|
|
2
|
+
import { durableRateLimitStore } from './rate-limiter.js';
|
|
3
|
+
import { HubPublisher } from './realtime-hub.js';
|
|
4
|
+
import { stub } from './types.js';
|
|
5
|
+
export async function notifyScheduler(namespace, runAt) {
|
|
6
|
+
const res = await stub(namespace, 'main').fetch('https://scheduler/notify', {
|
|
7
|
+
method: 'POST',
|
|
8
|
+
body: JSON.stringify({ runAt }),
|
|
9
|
+
});
|
|
10
|
+
if (!res.ok) {
|
|
11
|
+
throw new Error(`[workerstack] scheduler notify failed (${res.status})`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function envStrings(env) {
|
|
15
|
+
const out = {};
|
|
16
|
+
for (const [key, value] of Object.entries(env)) {
|
|
17
|
+
if (typeof value === 'string')
|
|
18
|
+
out[key] = value;
|
|
19
|
+
}
|
|
20
|
+
return out;
|
|
21
|
+
}
|
|
22
|
+
export function workerPlatform(env) {
|
|
23
|
+
const { SCHEDULER, REALTIME, RATE_LIMITER } = env;
|
|
24
|
+
return {
|
|
25
|
+
...(SCHEDULER
|
|
26
|
+
? {
|
|
27
|
+
jobs: {
|
|
28
|
+
notify: (runAt) => notifyScheduler(SCHEDULER, runAt),
|
|
29
|
+
},
|
|
30
|
+
}
|
|
31
|
+
: {}),
|
|
32
|
+
...(REALTIME
|
|
33
|
+
? { realtime: new HubPublisher(() => stub(REALTIME, 'main')) }
|
|
34
|
+
: {}),
|
|
35
|
+
...(RATE_LIMITER ? { rateLimit: durableRateLimitStore(RATE_LIMITER) } : {}),
|
|
36
|
+
storage: workerStorageFactory(env),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
const apps = new WeakMap();
|
|
40
|
+
export function appFor(backend, env, role, platform = {}) {
|
|
41
|
+
let byRole = apps.get(backend);
|
|
42
|
+
if (!byRole)
|
|
43
|
+
apps.set(backend, (byRole = new Map()));
|
|
44
|
+
const cached = byRole.get(role);
|
|
45
|
+
if (cached)
|
|
46
|
+
return cached;
|
|
47
|
+
const started = backend.start({
|
|
48
|
+
env: envStrings(env),
|
|
49
|
+
platform: { ...workerPlatform(env), ...platform },
|
|
50
|
+
});
|
|
51
|
+
byRole.set(role, started);
|
|
52
|
+
// A failed start must not poison the isolate: the next request retries.
|
|
53
|
+
started.catch(() => byRole.delete(role));
|
|
54
|
+
return started;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=app.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/workers/app.ts"],"names":[],"mappings":"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","sourcesContent":["// src/workers/app.ts — one app per isolate and role, built from bindings.\nimport type { WorkerstackBackend } from '../backend'\nimport type { Platform } from '../platform'\nimport type { DurableObjectNamespaceLike, WorkerEnv } from './types'\n\nimport { workerStorageFactory } from './r2'\nimport { durableRateLimitStore } from './rate-limiter'\nimport { HubPublisher } from './realtime-hub'\nimport { stub } from './types'\n\nexport type WorkerApp = {\n handler(request: Request): Promise<Response>\n jobs: {\n tick(now?: number): Promise<{ claimed: number }>\n nextDueAt(now?: number, until?: number): Promise<number | null>\n }\n}\n\nexport async function notifyScheduler(\n namespace: DurableObjectNamespaceLike,\n runAt: number,\n): Promise<void> {\n const res = await stub(namespace, 'main').fetch('https://scheduler/notify', {\n method: 'POST',\n body: JSON.stringify({ runAt }),\n })\n if (!res.ok) {\n throw new Error(`[workerstack] scheduler notify failed (${res.status})`)\n }\n}\n\nexport function envStrings(env: WorkerEnv): Record<string, string> {\n const out: Record<string, string> = {}\n for (const [key, value] of Object.entries(env)) {\n if (typeof value === 'string') out[key] = value\n }\n return out\n}\n\nexport function workerPlatform(env: WorkerEnv): Partial<Platform> {\n const { SCHEDULER, REALTIME, RATE_LIMITER } = env\n return {\n ...(SCHEDULER\n ? {\n jobs: {\n notify: (runAt: number) => notifyScheduler(SCHEDULER, runAt),\n },\n }\n : {}),\n ...(REALTIME\n ? { realtime: new HubPublisher(() => stub(REALTIME, 'main')) }\n : {}),\n ...(RATE_LIMITER ? { rateLimit: durableRateLimitStore(RATE_LIMITER) } : {}),\n storage: workerStorageFactory(env),\n }\n}\n\ntype AnyBackend = WorkerstackBackend<any>\nconst apps = new WeakMap<AnyBackend, Map<string, Promise<WorkerApp>>>()\n\nexport function appFor(\n backend: AnyBackend,\n env: WorkerEnv,\n role: 'fetch' | 'scheduler',\n platform: Partial<Platform> = {},\n): Promise<WorkerApp> {\n let byRole = apps.get(backend)\n if (!byRole) apps.set(backend, (byRole = new Map()))\n const cached = byRole.get(role)\n if (cached) return cached\n const started = backend.start({\n env: envStrings(env),\n platform: { ...workerPlatform(env), ...platform },\n }) as Promise<WorkerApp>\n byRole.set(role, started)\n // A failed start must not poison the isolate: the next request retries.\n started.catch(() => byRole.delete(role))\n return started\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const Scheduler: import("./scheduler.js").SchedulerClass, RealtimeHub: typeof import("./realtime-hub.js").RealtimeHub, RateLimiter: typeof import("./rate-limiter.js").RateLimiter;
|
|
2
|
+
declare const _default: {
|
|
3
|
+
fetch(request: Request, env: import("./types.js").WorkerEnv, _ctx: import("./types.js").ExecutionContextLike): Promise<Response>;
|
|
4
|
+
scheduled(_controller: unknown, env: import("./types.js").WorkerEnv, ctx: import("./types.js").ExecutionContextLike): Promise<void>;
|
|
5
|
+
};
|
|
6
|
+
export default _default;
|
|
7
|
+
//# sourceMappingURL=entry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry.d.ts","sourceRoot":"","sources":["../../src/workers/entry.ts"],"names":[],"mappings":"AAOA,eAAO,MAAQ,SAAS,wCAAE,WAAW,+CAAE,WAAW,6CAA0B,CAAA;;;;;AAC5E,wBAA6B"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// workerstack/workers/entry — the Worker of an SPA. The app backend comes from
|
|
2
|
+
// the Vite virtual module that workerstack() resolves.
|
|
3
|
+
import { backend } from 'virtual:workerstack/backend';
|
|
4
|
+
import { createWorker } from './index.js';
|
|
5
|
+
const worker = createWorker(backend);
|
|
6
|
+
export const { Scheduler, RealtimeHub, RateLimiter } = worker.durableObjects;
|
|
7
|
+
export default worker.handler;
|
|
8
|
+
//# sourceMappingURL=entry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry.js","sourceRoot":"","sources":["../../src/workers/entry.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,uDAAuD;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAA;AAErD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAEtC,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,CAAA;AACpC,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC,cAAc,CAAA;AAC5E,eAAe,MAAM,CAAC,OAAO,CAAA","sourcesContent":["// workerstack/workers/entry — the Worker of an SPA. The app backend comes from\n// the Vite virtual module that workerstack() resolves.\nimport { backend } from 'virtual:workerstack/backend'\n\nimport { createWorker } from './index'\n\nconst worker = createWorker(backend)\nexport const { Scheduler, RealtimeHub, RateLimiter } = worker.durableObjects\nexport default worker.handler\n"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { WorkerstackBackend } from '../backend.js';
|
|
2
|
+
import type { ExecutionContextLike, WorkerEnv } from './types.js';
|
|
3
|
+
import { RateLimiter } from './rate-limiter.js';
|
|
4
|
+
import { RealtimeHub } from './realtime-hub.js';
|
|
5
|
+
export declare function createWorker(backend: WorkerstackBackend<any>): {
|
|
6
|
+
handler: {
|
|
7
|
+
fetch(request: Request, env: WorkerEnv, _ctx: ExecutionContextLike): Promise<Response>;
|
|
8
|
+
scheduled(_controller: unknown, env: WorkerEnv, ctx: ExecutionContextLike): Promise<void>;
|
|
9
|
+
};
|
|
10
|
+
durableObjects: {
|
|
11
|
+
Scheduler: import("./scheduler.js").SchedulerClass;
|
|
12
|
+
RealtimeHub: typeof RealtimeHub;
|
|
13
|
+
RateLimiter: typeof RateLimiter;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
export { createSchedulerClass, type SchedulerClass, type SchedulerObject, } from './scheduler.js';
|
|
17
|
+
export { HubPublisher, RealtimeHub } from './realtime-hub.js';
|
|
18
|
+
export { registeredWorker, registerWorker, rememberWorkerEnv, type RegisteredWorker, } from './registry.js';
|
|
19
|
+
export { durableRateLimitStore, RateLimiter } from './rate-limiter.js';
|
|
20
|
+
export { bucketBindingName, R2StorageAdapter } from './r2.js';
|
|
21
|
+
export type * from './types.js';
|
|
22
|
+
export { workerPlanFromBlueprint, type WorkerPlan } from '../worker-plan.js';
|
|
23
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/workers/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AACpD,OAAO,KAAK,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAG9D,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAI5C,wBAAgB,YAAY,CAAC,OAAO,EAAE,kBAAkB,CAAC,GAAG,CAAC;;uBAG9C,OAAO,OACX,SAAS,QACR,oBAAoB,GACzB,OAAO,CAAC,QAAQ,CAAC;+BAUL,OAAO,OACf,SAAS,OACT,oBAAoB,GACxB,OAAO,CAAC,IAAI,CAAC;;;;;;;EAenB;AAED,OAAO,EACL,oBAAoB,EACpB,KAAK,cAAc,EACnB,KAAK,eAAe,GACrB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC1D,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,KAAK,gBAAgB,GACtB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACnE,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,MAAM,CAAA;AAC1D,mBAAmB,SAAS,CAAA;AAC5B,OAAO,EAAE,uBAAuB,EAAE,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAA"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { appFor, notifyScheduler } from './app.js';
|
|
2
|
+
import { RateLimiter } from './rate-limiter.js';
|
|
3
|
+
import { RealtimeHub } from './realtime-hub.js';
|
|
4
|
+
import { registerWorker, rememberWorkerEnv } from './registry.js';
|
|
5
|
+
import { createSchedulerClass } from './scheduler.js';
|
|
6
|
+
export function createWorker(backend) {
|
|
7
|
+
const handler = {
|
|
8
|
+
async fetch(request, env, _ctx) {
|
|
9
|
+
rememberWorkerEnv(env);
|
|
10
|
+
const app = await appFor(backend, env, 'fetch');
|
|
11
|
+
const response = await app.handler(request);
|
|
12
|
+
// A path that reached the Worker but has no route: let the SPA answer.
|
|
13
|
+
if (response.status === 404 && env.ASSETS)
|
|
14
|
+
return env.ASSETS.fetch(request);
|
|
15
|
+
return response;
|
|
16
|
+
},
|
|
17
|
+
async scheduled(_controller, env, ctx) {
|
|
18
|
+
if (env.SCHEDULER)
|
|
19
|
+
ctx.waitUntil(notifyScheduler(env.SCHEDULER, Date.now()));
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
// Start server code in this isolate calls the API through it.
|
|
23
|
+
registerWorker(handler);
|
|
24
|
+
return {
|
|
25
|
+
handler,
|
|
26
|
+
durableObjects: {
|
|
27
|
+
Scheduler: createSchedulerClass(backend),
|
|
28
|
+
RealtimeHub,
|
|
29
|
+
RateLimiter,
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export { createSchedulerClass, } from './scheduler.js';
|
|
34
|
+
export { HubPublisher, RealtimeHub } from './realtime-hub.js';
|
|
35
|
+
export { registeredWorker, registerWorker, rememberWorkerEnv, } from './registry.js';
|
|
36
|
+
export { durableRateLimitStore, RateLimiter } from './rate-limiter.js';
|
|
37
|
+
export { bucketBindingName, R2StorageAdapter } from './r2.js';
|
|
38
|
+
export { workerPlanFromBlueprint } from '../worker-plan.js';
|
|
39
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/workers/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,OAAO,CAAA;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAElD,MAAM,UAAU,YAAY,CAAC,OAAgC;IAC3D,MAAM,OAAO,GAAG;QACd,KAAK,CAAC,KAAK,CACT,OAAgB,EAChB,GAAc,EACd,IAA0B;YAE1B,iBAAiB,CAAC,GAAG,CAAC,CAAA;YACtB,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,CAAA;YAC/C,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;YAC3C,uEAAuE;YACvE,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM;gBACvC,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;YAClC,OAAO,QAAQ,CAAA;QACjB,CAAC;QACD,KAAK,CAAC,SAAS,CACb,WAAoB,EACpB,GAAc,EACd,GAAyB;YAEzB,IAAI,GAAG,CAAC,SAAS;gBACf,GAAG,CAAC,SAAS,CAAC,eAAe,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;QAC7D,CAAC;KACF,CAAA;IACD,8DAA8D;IAC9D,cAAc,CAAC,OAAO,CAAC,CAAA;IACvB,OAAO;QACL,OAAO;QACP,cAAc,EAAE;YACd,SAAS,EAAE,oBAAoB,CAAC,OAAO,CAAC;YACxC,WAAW;YACX,WAAW;SACZ;KACF,CAAA;AACH,CAAC;AAED,OAAO,EACL,oBAAoB,GAGrB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC1D,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,iBAAiB,GAElB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACnE,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,MAAM,CAAA;AAE1D,OAAO,EAAE,uBAAuB,EAAmB,MAAM,gBAAgB,CAAA","sourcesContent":["// src/workers/index.ts — `workerstack/workers`: run an app as a Worker on\n// Cloudflare or celld. See the Workers runtime spec for the binding names.\nimport type { WorkerstackBackend } from '../backend'\nimport type { ExecutionContextLike, WorkerEnv } from './types'\n\nimport { appFor, notifyScheduler } from './app'\nimport { RateLimiter } from './rate-limiter'\nimport { RealtimeHub } from './realtime-hub'\nimport { registerWorker, rememberWorkerEnv } from './registry'\nimport { createSchedulerClass } from './scheduler'\n\nexport function createWorker(backend: WorkerstackBackend<any>) {\n const handler = {\n async fetch(\n request: Request,\n env: WorkerEnv,\n _ctx: ExecutionContextLike,\n ): Promise<Response> {\n rememberWorkerEnv(env)\n const app = await appFor(backend, env, 'fetch')\n const response = await app.handler(request)\n // A path that reached the Worker but has no route: let the SPA answer.\n if (response.status === 404 && env.ASSETS)\n return env.ASSETS.fetch(request)\n return response\n },\n async scheduled(\n _controller: unknown,\n env: WorkerEnv,\n ctx: ExecutionContextLike,\n ): Promise<void> {\n if (env.SCHEDULER)\n ctx.waitUntil(notifyScheduler(env.SCHEDULER, Date.now()))\n },\n }\n // Start server code in this isolate calls the API through it.\n registerWorker(handler)\n return {\n handler,\n durableObjects: {\n Scheduler: createSchedulerClass(backend),\n RealtimeHub,\n RateLimiter,\n },\n }\n}\n\nexport {\n createSchedulerClass,\n type SchedulerClass,\n type SchedulerObject,\n} from './scheduler'\nexport { HubPublisher, RealtimeHub } from './realtime-hub'\nexport {\n registeredWorker,\n registerWorker,\n rememberWorkerEnv,\n type RegisteredWorker,\n} from './registry'\nexport { durableRateLimitStore, RateLimiter } from './rate-limiter'\nexport { bucketBindingName, R2StorageAdapter } from './r2'\nexport type * from './types'\nexport { workerPlanFromBlueprint, type WorkerPlan } from '../worker-plan'\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { StorageAdapterFactory } from '../platform.js';
|
|
2
|
+
import type { PresignGetOptions, PresignPutOptions, StorageAdapter } from '../storage/index.js';
|
|
3
|
+
import type { R2BucketLike, WorkerEnv } from './types.js';
|
|
4
|
+
import { S3StorageAdapter } from '../storage/s3.js';
|
|
5
|
+
import { bucketBindingName } from '../worker-plan.js';
|
|
6
|
+
export { bucketBindingName };
|
|
7
|
+
export declare class R2StorageAdapter implements StorageAdapter {
|
|
8
|
+
private readonly bucket;
|
|
9
|
+
presignPut?: (key: string, opts: PresignPutOptions) => Promise<string>;
|
|
10
|
+
presignGet?: (key: string, opts: PresignGetOptions) => Promise<string>;
|
|
11
|
+
publicUrlFor?: (key: string) => string | undefined;
|
|
12
|
+
constructor(bucket: R2BucketLike, presigner?: S3StorageAdapter);
|
|
13
|
+
upload(fileId: string, data: Blob | ArrayBuffer, contentType: string): Promise<void>;
|
|
14
|
+
get(fileId: string): Promise<Response>;
|
|
15
|
+
delete(fileId: string): Promise<void>;
|
|
16
|
+
exists(fileId: string): Promise<boolean>;
|
|
17
|
+
stat(key: string): Promise<{
|
|
18
|
+
size: number;
|
|
19
|
+
contentType: string;
|
|
20
|
+
} | null>;
|
|
21
|
+
list(prefix: string): Promise<string[]>;
|
|
22
|
+
}
|
|
23
|
+
export declare function workerStorageFactory(env: WorkerEnv): StorageAdapterFactory;
|
|
24
|
+
//# sourceMappingURL=r2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"r2.d.ts","sourceRoot":"","sources":["../../src/workers/r2.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AACxD,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACf,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAEtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAElD,OAAO,EAAE,iBAAiB,EAAE,CAAA;AAE5B,qBAAa,gBAAiB,YAAW,cAAc;IAMnD,OAAO,CAAC,QAAQ,CAAC,MAAM;IALzB,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IACtE,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IACtE,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAA;gBAG/B,MAAM,EAAE,YAAY,EACrC,SAAS,CAAC,EAAE,gBAAgB;IASxB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,WAAW,EAAE,WAAW,EAAE,MAAM;IAKpE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAWtC,MAAM,CAAC,MAAM,EAAE,MAAM;IAIrB,MAAM,CAAC,MAAM,EAAE,MAAM;IAIrB,IAAI,CAAC,GAAG,EAAE,MAAM;;;;IAUhB,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;CAU9C;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,SAAS,GAAG,qBAAqB,CAY1E"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { S3StorageAdapter } from '../storage/s3.js';
|
|
2
|
+
import { bucketBindingName } from '../worker-plan.js';
|
|
3
|
+
export { bucketBindingName };
|
|
4
|
+
export class R2StorageAdapter {
|
|
5
|
+
bucket;
|
|
6
|
+
presignPut;
|
|
7
|
+
presignGet;
|
|
8
|
+
publicUrlFor;
|
|
9
|
+
constructor(bucket, presigner) {
|
|
10
|
+
this.bucket = bucket;
|
|
11
|
+
if (presigner) {
|
|
12
|
+
this.presignPut = (key, opts) => presigner.presignPut(key, opts);
|
|
13
|
+
this.presignGet = (key, opts) => presigner.presignGet(key, opts);
|
|
14
|
+
this.publicUrlFor = (key) => presigner.publicUrlFor(key);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
async upload(fileId, data, contentType) {
|
|
18
|
+
const bytes = data instanceof Blob ? await data.arrayBuffer() : data;
|
|
19
|
+
await this.bucket.put(fileId, bytes, { httpMetadata: { contentType } });
|
|
20
|
+
}
|
|
21
|
+
async get(fileId) {
|
|
22
|
+
const object = await this.bucket.get(fileId);
|
|
23
|
+
if (!object)
|
|
24
|
+
return new Response('Not found', { status: 404 });
|
|
25
|
+
return new Response(object.body, {
|
|
26
|
+
headers: {
|
|
27
|
+
'Content-Type': object.httpMetadata?.contentType || 'application/octet-stream',
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
async delete(fileId) {
|
|
32
|
+
await this.bucket.delete(fileId);
|
|
33
|
+
}
|
|
34
|
+
async exists(fileId) {
|
|
35
|
+
return (await this.bucket.head(fileId)) !== null;
|
|
36
|
+
}
|
|
37
|
+
async stat(key) {
|
|
38
|
+
const object = await this.bucket.head(key);
|
|
39
|
+
return object
|
|
40
|
+
? {
|
|
41
|
+
size: object.size,
|
|
42
|
+
contentType: object.httpMetadata?.contentType ?? '',
|
|
43
|
+
}
|
|
44
|
+
: null;
|
|
45
|
+
}
|
|
46
|
+
async list(prefix) {
|
|
47
|
+
const keys = [];
|
|
48
|
+
let cursor;
|
|
49
|
+
do {
|
|
50
|
+
const page = await this.bucket.list({ prefix, cursor });
|
|
51
|
+
keys.push(...page.objects.map((object) => object.key));
|
|
52
|
+
cursor = page.truncated ? page.cursor : undefined;
|
|
53
|
+
} while (cursor);
|
|
54
|
+
return keys;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export function workerStorageFactory(env) {
|
|
58
|
+
return (backend, bucket) => {
|
|
59
|
+
const binding = env[bucketBindingName(bucket.name)];
|
|
60
|
+
const s3 = backend.type === 's3' ? new S3StorageAdapter(backend) : undefined;
|
|
61
|
+
if (binding)
|
|
62
|
+
return new R2StorageAdapter(binding, s3);
|
|
63
|
+
if (s3)
|
|
64
|
+
return s3;
|
|
65
|
+
// The core builds an adapter for every resolved bucket at start, even the
|
|
66
|
+
// implicit default one; fail on use, not on start.
|
|
67
|
+
return missingBinding(bucket.name);
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function missingBinding(bucketName) {
|
|
71
|
+
const fail = async () => {
|
|
72
|
+
throw new Error(`[workerstack] storage bucket "${bucketName}" needs the R2 binding ${bucketBindingName(bucketName)}`);
|
|
73
|
+
};
|
|
74
|
+
return { upload: fail, get: fail, delete: fail, exists: fail };
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=r2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"r2.js","sourceRoot":"","sources":["../../src/workers/r2.ts"],"names":[],"mappings":"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","sourcesContent":["// src/workers/r2.ts — storage on an R2 binding. Presign needs S3 keys to the\n// same bucket; without them uploads go through the Worker (proxy mode).\nimport type { StorageAdapterFactory } from '../platform'\nimport type {\n PresignGetOptions,\n PresignPutOptions,\n StorageAdapter,\n} from '../storage/index'\nimport type { R2BucketLike, WorkerEnv } from './types'\n\nimport { S3StorageAdapter } from '../storage/s3'\nimport { bucketBindingName } from '../worker-plan'\n\nexport { bucketBindingName }\n\nexport class R2StorageAdapter implements StorageAdapter {\n presignPut?: (key: string, opts: PresignPutOptions) => Promise<string>\n presignGet?: (key: string, opts: PresignGetOptions) => Promise<string>\n publicUrlFor?: (key: string) => string | undefined\n\n constructor(\n private readonly bucket: R2BucketLike,\n presigner?: S3StorageAdapter,\n ) {\n if (presigner) {\n this.presignPut = (key, opts) => presigner.presignPut(key, opts)\n this.presignGet = (key, opts) => presigner.presignGet(key, opts)\n this.publicUrlFor = (key) => presigner.publicUrlFor(key)\n }\n }\n\n async upload(fileId: string, data: Blob | ArrayBuffer, contentType: string) {\n const bytes = data instanceof Blob ? await data.arrayBuffer() : data\n await this.bucket.put(fileId, bytes, { httpMetadata: { contentType } })\n }\n\n async get(fileId: string): Promise<Response> {\n const object = await this.bucket.get(fileId)\n if (!object) return new Response('Not found', { status: 404 })\n return new Response(object.body, {\n headers: {\n 'Content-Type':\n object.httpMetadata?.contentType || 'application/octet-stream',\n },\n })\n }\n\n async delete(fileId: string) {\n await this.bucket.delete(fileId)\n }\n\n async exists(fileId: string) {\n return (await this.bucket.head(fileId)) !== null\n }\n\n async stat(key: string) {\n const object = await this.bucket.head(key)\n return object\n ? {\n size: object.size,\n contentType: object.httpMetadata?.contentType ?? '',\n }\n : null\n }\n\n async list(prefix: string): Promise<string[]> {\n const keys: string[] = []\n let cursor: string | undefined\n do {\n const page = await this.bucket.list({ prefix, cursor })\n keys.push(...page.objects.map((object) => object.key))\n cursor = page.truncated ? page.cursor : undefined\n } while (cursor)\n return keys\n }\n}\n\nexport function workerStorageFactory(env: WorkerEnv): StorageAdapterFactory {\n return (backend, bucket) => {\n const binding = env[bucketBindingName(bucket.name)] as\n | R2BucketLike\n | undefined\n const s3 = backend.type === 's3' ? new S3StorageAdapter(backend) : undefined\n if (binding) return new R2StorageAdapter(binding, s3)\n if (s3) return s3\n // The core builds an adapter for every resolved bucket at start, even the\n // implicit default one; fail on use, not on start.\n return missingBinding(bucket.name)\n }\n}\n\nfunction missingBinding(bucketName: string): StorageAdapter {\n const fail = async (): Promise<never> => {\n throw new Error(\n `[workerstack] storage bucket \"${bucketName}\" needs the R2 binding ${bucketBindingName(bucketName)}`,\n )\n }\n return { upload: fail, get: fail, delete: fail, exists: fail }\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { RateLimitStore } from '../platform.js';
|
|
2
|
+
import type { DurableObjectNamespaceLike, DurableObjectStateLike } from './types.js';
|
|
3
|
+
export declare class RateLimiter {
|
|
4
|
+
private readonly store;
|
|
5
|
+
constructor(_state: DurableObjectStateLike, _env: unknown);
|
|
6
|
+
fetch(request: Request): Promise<Response>;
|
|
7
|
+
}
|
|
8
|
+
export declare function durableRateLimitStore(namespace: DurableObjectNamespaceLike): RateLimitStore;
|
|
9
|
+
//# sourceMappingURL=rate-limiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../src/workers/rate-limiter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,KAAK,EACV,0BAA0B,EAC1B,sBAAsB,EACvB,MAAM,SAAS,CAAA;AAOhB,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA+B;gBAEzC,MAAM,EAAE,sBAAsB,EAAE,IAAI,EAAE,OAAO;IAEnD,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;CAIjD;AAED,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,0BAA0B,GACpC,cAAc,CAUhB"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createMemoryRateLimitStore } from '../platform.js';
|
|
2
|
+
import { stub } from './types.js';
|
|
3
|
+
export class RateLimiter {
|
|
4
|
+
store = createMemoryRateLimitStore();
|
|
5
|
+
constructor(_state, _env) { }
|
|
6
|
+
async fetch(request) {
|
|
7
|
+
const { windowMs, max, now } = (await request.json());
|
|
8
|
+
return Response.json(await this.store.hit('window', windowMs, max, now));
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export function durableRateLimitStore(namespace) {
|
|
12
|
+
return {
|
|
13
|
+
async hit(key, windowMs, max, now = Date.now()) {
|
|
14
|
+
const res = await stub(namespace, key).fetch('https://rate-limiter/hit', {
|
|
15
|
+
method: 'POST',
|
|
16
|
+
body: JSON.stringify({ windowMs, max, now }),
|
|
17
|
+
});
|
|
18
|
+
return res.json();
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=rate-limiter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../src/workers/rate-limiter.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAA;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAI9B,MAAM,OAAO,WAAW;IACL,KAAK,GAAG,0BAA0B,EAAE,CAAA;IAErD,YAAY,MAA8B,EAAE,IAAa,IAAG,CAAC;IAE7D,KAAK,CAAC,KAAK,CAAC,OAAgB;QAC1B,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,EAAE,CAAe,CAAA;QACnE,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAA;IAC1E,CAAC;CACF;AAED,MAAM,UAAU,qBAAqB,CACnC,SAAqC;IAErC,OAAO;QACL,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;YAC5C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,0BAA0B,EAAE;gBACvE,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAuB,CAAC;aAClE,CAAC,CAAA;YACF,OAAO,GAAG,CAAC,IAAI,EAAE,CAAA;QACnB,CAAC;KACF,CAAA;AACH,CAAC","sourcesContent":["// src/workers/rate-limiter.ts — one Durable Object per client+path key. Its\n// memory is the window; a reset after eviction only forgives a few requests.\nimport type { RateLimitStore } from '../platform'\nimport type {\n DurableObjectNamespaceLike,\n DurableObjectStateLike,\n} from './types'\n\nimport { createMemoryRateLimitStore } from '../platform'\nimport { stub } from './types'\n\ntype HitRequest = { windowMs: number; max: number; now: number }\n\nexport class RateLimiter {\n private readonly store = createMemoryRateLimitStore()\n\n constructor(_state: DurableObjectStateLike, _env: unknown) {}\n\n async fetch(request: Request): Promise<Response> {\n const { windowMs, max, now } = (await request.json()) as HitRequest\n return Response.json(await this.store.hit('window', windowMs, max, now))\n }\n}\n\nexport function durableRateLimitStore(\n namespace: DurableObjectNamespaceLike,\n): RateLimitStore {\n return {\n async hit(key, windowMs, max, now = Date.now()) {\n const res = await stub(namespace, key).fetch('https://rate-limiter/hit', {\n method: 'POST',\n body: JSON.stringify({ windowMs, max, now } satisfies HitRequest),\n })\n return res.json()\n },\n }\n}\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { PublisherOptions, PublisherSubscribeListenerOptions } from '@orpc/publisher';
|
|
2
|
+
import { Publisher } from '@orpc/publisher';
|
|
3
|
+
import type { RealtimeEvents } from '../realtime/publisher.js';
|
|
4
|
+
import type { DurableObjectStateLike, FetcherLike } from './types.js';
|
|
5
|
+
export declare class RealtimeHub {
|
|
6
|
+
/** celld closes a stream after 60 s of silence. */
|
|
7
|
+
heartbeatMs: number;
|
|
8
|
+
private readonly publisher;
|
|
9
|
+
constructor(_state: DurableObjectStateLike, _env: unknown);
|
|
10
|
+
fetch(request: Request): Promise<Response>;
|
|
11
|
+
private subscribe;
|
|
12
|
+
}
|
|
13
|
+
export declare class HubPublisher extends Publisher<RealtimeEvents> {
|
|
14
|
+
private readonly hub;
|
|
15
|
+
constructor(hub: () => FetcherLike, options?: PublisherOptions);
|
|
16
|
+
private readonly serializer;
|
|
17
|
+
publish<K extends keyof RealtimeEvents & string>(event: K, payload: RealtimeEvents[K]): Promise<void>;
|
|
18
|
+
protected subscribeListener<K extends keyof RealtimeEvents & string>(event: K, listener: (payload: RealtimeEvents[K]) => void, options?: PublisherSubscribeListenerOptions): Promise<() => Promise<void>>;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=realtime-hub.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"realtime-hub.d.ts","sourceRoot":"","sources":["../../src/workers/realtime-hub.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,gBAAgB,EAChB,iCAAiC,EAClC,MAAM,iBAAiB,CAAA;AAGxB,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAI3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAC3D,OAAO,KAAK,EAAE,sBAAsB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAMlE,qBAAa,WAAW;IACtB,mDAAmD;IACnD,WAAW,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAExB;gBAEU,MAAM,EAAE,sBAAsB,EAAE,IAAI,EAAE,OAAO;IAEnD,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;YAelC,SAAS;CAgCxB;AAED,qBAAa,YAAa,SAAQ,SAAS,CAAC,cAAc,CAAC;IAEvD,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,MAAM,WAAW,EACvC,OAAO,CAAC,EAAE,gBAAgB;IAK5B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA0B;IAE/C,OAAO,CAAC,CAAC,SAAS,MAAM,cAAc,GAAG,MAAM,EACnD,KAAK,EAAE,CAAC,EACR,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,GACzB,OAAO,CAAC,IAAI,CAAC;cAeA,iBAAiB,CAAC,CAAC,SAAS,MAAM,cAAc,GAAG,MAAM,EACvE,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,KAAK,IAAI,EAC9C,OAAO,CAAC,EAAE,iCAAiC,GAC1C,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CA6ChC"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { RPCJsonSerializer } from '@orpc/client';
|
|
2
|
+
import { Publisher } from '@orpc/publisher';
|
|
3
|
+
import { MemoryPublisher } from '@orpc/publisher/memory';
|
|
4
|
+
import { getEventMeta, withEventMeta } from '@orpc/server';
|
|
5
|
+
export class RealtimeHub {
|
|
6
|
+
/** celld closes a stream after 60 s of silence. */
|
|
7
|
+
heartbeatMs = 20_000;
|
|
8
|
+
publisher = new MemoryPublisher({
|
|
9
|
+
resume: { enabled: true, seconds: 300 },
|
|
10
|
+
});
|
|
11
|
+
constructor(_state, _env) { }
|
|
12
|
+
async fetch(request) {
|
|
13
|
+
const url = new URL(request.url);
|
|
14
|
+
if (url.pathname === '/publish' && request.method === 'POST') {
|
|
15
|
+
const { event, payload } = (await request.json());
|
|
16
|
+
await this.publisher.publish(event, payload);
|
|
17
|
+
return new Response(null, { status: 204 });
|
|
18
|
+
}
|
|
19
|
+
if (url.pathname === '/subscribe')
|
|
20
|
+
return this.subscribe(url, request.signal);
|
|
21
|
+
return new Response('Not found', { status: 404 });
|
|
22
|
+
}
|
|
23
|
+
async subscribe(url, signal) {
|
|
24
|
+
const event = url.searchParams.get('event') ?? 'change';
|
|
25
|
+
const lastEventId = url.searchParams.get('lastEventId') ?? undefined;
|
|
26
|
+
const { readable, writable } = new TransformStream();
|
|
27
|
+
const writer = writable.getWriter();
|
|
28
|
+
const encoder = new TextEncoder();
|
|
29
|
+
let closed = false;
|
|
30
|
+
let timer;
|
|
31
|
+
let unsubscribe;
|
|
32
|
+
const close = () => {
|
|
33
|
+
if (closed)
|
|
34
|
+
return;
|
|
35
|
+
closed = true;
|
|
36
|
+
clearInterval(timer);
|
|
37
|
+
void unsubscribe?.();
|
|
38
|
+
void writer.close().catch(() => { });
|
|
39
|
+
};
|
|
40
|
+
const write = (line) => {
|
|
41
|
+
if (closed)
|
|
42
|
+
return;
|
|
43
|
+
writer.write(encoder.encode(`${JSON.stringify(line)}\n`)).catch(close);
|
|
44
|
+
};
|
|
45
|
+
unsubscribe = await this.publisher.subscribe(event, (payload) => write({ type: 'event', id: getEventMeta(payload)?.id, payload }), { lastEventId });
|
|
46
|
+
timer = setInterval(() => write({ type: 'heartbeat' }), this.heartbeatMs);
|
|
47
|
+
signal?.addEventListener('abort', close);
|
|
48
|
+
return new Response(readable, {
|
|
49
|
+
headers: { 'content-type': 'application/x-ndjson' },
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export class HubPublisher extends Publisher {
|
|
54
|
+
hub;
|
|
55
|
+
constructor(hub, options) {
|
|
56
|
+
super(options);
|
|
57
|
+
this.hub = hub;
|
|
58
|
+
}
|
|
59
|
+
serializer = new RPCJsonSerializer();
|
|
60
|
+
async publish(event, payload) {
|
|
61
|
+
const res = await this.hub().fetch('https://hub/publish', {
|
|
62
|
+
method: 'POST',
|
|
63
|
+
body: JSON.stringify({
|
|
64
|
+
event,
|
|
65
|
+
payload: this.serializer.serialize(payload),
|
|
66
|
+
}),
|
|
67
|
+
});
|
|
68
|
+
if (!res.ok) {
|
|
69
|
+
throw new Error(`[workerstack] realtime hub publish failed (${res.status})`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async subscribeListener(event, listener, options) {
|
|
73
|
+
const url = new URL('https://hub/subscribe');
|
|
74
|
+
url.searchParams.set('event', event);
|
|
75
|
+
if (options?.lastEventId) {
|
|
76
|
+
url.searchParams.set('lastEventId', options.lastEventId);
|
|
77
|
+
}
|
|
78
|
+
const controller = new AbortController();
|
|
79
|
+
const res = await this.hub().fetch(url, { signal: controller.signal });
|
|
80
|
+
if (!res.ok || !res.body) {
|
|
81
|
+
throw new Error(`[workerstack] realtime hub subscribe failed (${res.status})`);
|
|
82
|
+
}
|
|
83
|
+
const reader = res.body.pipeThrough(new TextDecoderStream()).getReader();
|
|
84
|
+
void (async () => {
|
|
85
|
+
let buffer = '';
|
|
86
|
+
try {
|
|
87
|
+
for (;;) {
|
|
88
|
+
const { value, done } = await reader.read();
|
|
89
|
+
if (done)
|
|
90
|
+
return;
|
|
91
|
+
buffer += value;
|
|
92
|
+
let newline;
|
|
93
|
+
while ((newline = buffer.indexOf('\n')) >= 0) {
|
|
94
|
+
const text = buffer.slice(0, newline);
|
|
95
|
+
buffer = buffer.slice(newline + 1);
|
|
96
|
+
if (!text)
|
|
97
|
+
continue;
|
|
98
|
+
const line = JSON.parse(text);
|
|
99
|
+
if (line.type !== 'event')
|
|
100
|
+
continue;
|
|
101
|
+
const payload = this.serializer.deserialize(line.payload);
|
|
102
|
+
listener(line.id ? withEventMeta(payload, { id: line.id }) : payload);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
if (!controller.signal.aborted)
|
|
108
|
+
options?.onError?.(error);
|
|
109
|
+
}
|
|
110
|
+
})();
|
|
111
|
+
return async () => {
|
|
112
|
+
controller.abort();
|
|
113
|
+
await reader.cancel().catch(() => { });
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=realtime-hub.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"realtime-hub.js","sourceRoot":"","sources":["../../src/workers/realtime-hub.ts"],"names":[],"mappings":"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","sourcesContent":["// src/workers/realtime-hub.ts — realtime fan-out for one app. The hub holds a\n// MemoryPublisher with resume; Workers reach it over a line-delimited stream.\n// Payloads cross as oRPC's RPC JSON, as with the Redis publisher, so Date and\n// BigInt values survive; the hub itself never looks inside them.\nimport type {\n PublisherOptions,\n PublisherSubscribeListenerOptions,\n} from '@orpc/publisher'\n\nimport { RPCJsonSerializer } from '@orpc/client'\nimport { Publisher } from '@orpc/publisher'\nimport { MemoryPublisher } from '@orpc/publisher/memory'\nimport { getEventMeta, withEventMeta } from '@orpc/server'\n\nimport type { RealtimeEvents } from '../realtime/publisher'\nimport type { DurableObjectStateLike, FetcherLike } from './types'\n\ntype HubLine =\n | { type: 'event'; id?: string; payload: object }\n | { type: 'heartbeat' }\n\nexport class RealtimeHub {\n /** celld closes a stream after 60 s of silence. */\n heartbeatMs = 20_000\n private readonly publisher = new MemoryPublisher<Record<string, object>>({\n resume: { enabled: true, seconds: 300 },\n })\n\n constructor(_state: DurableObjectStateLike, _env: unknown) {}\n\n async fetch(request: Request): Promise<Response> {\n const url = new URL(request.url)\n if (url.pathname === '/publish' && request.method === 'POST') {\n const { event, payload } = (await request.json()) as {\n event: string\n payload: object\n }\n await this.publisher.publish(event, payload)\n return new Response(null, { status: 204 })\n }\n if (url.pathname === '/subscribe')\n return this.subscribe(url, request.signal)\n return new Response('Not found', { status: 404 })\n }\n\n private async subscribe(url: URL, signal: AbortSignal): Promise<Response> {\n const event = url.searchParams.get('event') ?? 'change'\n const lastEventId = url.searchParams.get('lastEventId') ?? undefined\n const { readable, writable } = new TransformStream<Uint8Array, Uint8Array>()\n const writer = writable.getWriter()\n const encoder = new TextEncoder()\n let closed = false\n let timer: ReturnType<typeof setInterval> | undefined\n let unsubscribe: (() => Promise<void>) | undefined\n const close = () => {\n if (closed) return\n closed = true\n clearInterval(timer)\n void unsubscribe?.()\n void writer.close().catch(() => {})\n }\n const write = (line: HubLine) => {\n if (closed) return\n writer.write(encoder.encode(`${JSON.stringify(line)}\\n`)).catch(close)\n }\n unsubscribe = await this.publisher.subscribe(\n event,\n (payload) =>\n write({ type: 'event', id: getEventMeta(payload)?.id, payload }),\n { lastEventId },\n )\n timer = setInterval(() => write({ type: 'heartbeat' }), this.heartbeatMs)\n signal?.addEventListener('abort', close)\n return new Response(readable, {\n headers: { 'content-type': 'application/x-ndjson' },\n })\n }\n}\n\nexport class HubPublisher extends Publisher<RealtimeEvents> {\n constructor(\n private readonly hub: () => FetcherLike,\n options?: PublisherOptions,\n ) {\n super(options)\n }\n\n private readonly serializer = new RPCJsonSerializer()\n\n async publish<K extends keyof RealtimeEvents & string>(\n event: K,\n payload: RealtimeEvents[K],\n ): Promise<void> {\n const res = await this.hub().fetch('https://hub/publish', {\n method: 'POST',\n body: JSON.stringify({\n event,\n payload: this.serializer.serialize(payload),\n }),\n })\n if (!res.ok) {\n throw new Error(\n `[workerstack] realtime hub publish failed (${res.status})`,\n )\n }\n }\n\n protected async subscribeListener<K extends keyof RealtimeEvents & string>(\n event: K,\n listener: (payload: RealtimeEvents[K]) => void,\n options?: PublisherSubscribeListenerOptions,\n ): Promise<() => Promise<void>> {\n const url = new URL('https://hub/subscribe')\n url.searchParams.set('event', event)\n if (options?.lastEventId) {\n url.searchParams.set('lastEventId', options.lastEventId)\n }\n const controller = new AbortController()\n const res = await this.hub().fetch(url, { signal: controller.signal })\n if (!res.ok || !res.body) {\n throw new Error(\n `[workerstack] realtime hub subscribe failed (${res.status})`,\n )\n }\n const reader = res.body.pipeThrough(new TextDecoderStream()).getReader()\n void (async () => {\n let buffer = ''\n try {\n for (;;) {\n const { value, done } = await reader.read()\n if (done) return\n buffer += value\n let newline: number\n while ((newline = buffer.indexOf('\\n')) >= 0) {\n const text = buffer.slice(0, newline)\n buffer = buffer.slice(newline + 1)\n if (!text) continue\n const line = JSON.parse(text) as HubLine\n if (line.type !== 'event') continue\n const payload = this.serializer.deserialize(\n line.payload as Parameters<RPCJsonSerializer['deserialize']>[0],\n ) as RealtimeEvents[K]\n listener(\n line.id ? withEventMeta(payload, { id: line.id }) : payload,\n )\n }\n }\n } catch (error) {\n if (!controller.signal.aborted) options?.onError?.(error as Error)\n }\n })()\n return async () => {\n controller.abort()\n await reader.cancel().catch(() => {})\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ExecutionContextLike, WorkerEnv } from './types.js';
|
|
2
|
+
export type RegisteredWorker = {
|
|
3
|
+
fetch(request: Request, env: WorkerEnv, ctx: ExecutionContextLike): Promise<Response>;
|
|
4
|
+
};
|
|
5
|
+
export declare function registerWorker(worker: RegisteredWorker): void;
|
|
6
|
+
export declare function rememberWorkerEnv(env: WorkerEnv): void;
|
|
7
|
+
/** The registered Worker and its env, once a request has reached it. */
|
|
8
|
+
export declare function registeredWorker(): {
|
|
9
|
+
worker: RegisteredWorker;
|
|
10
|
+
env: WorkerEnv;
|
|
11
|
+
} | undefined;
|
|
12
|
+
export declare function resetRegistryForTests(): void;
|
|
13
|
+
//# sourceMappingURL=registry.d.ts.map
|