{"_id":"chat-state-cloudflare-do","_rev":"3-5b58b997c6fecce5b50cd931be7d7f3f","name":"chat-state-cloudflare-do","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"chat-state-cloudflare-do","version":"0.1.0","keywords":["chat-sdk","chat-adapter","state","cloudflare","durable-objects","workers"],"license":"MIT","_id":"chat-state-cloudflare-do@0.1.0","maintainers":[{"name":"dcartertwo","email":"dl.carter00@gmail.com"}],"homepage":"https://github.com/dcartertwo/chat-state-cloudflare-do#readme","bugs":{"url":"https://github.com/dcartertwo/chat-state-cloudflare-do/issues"},"dist":{"shasum":"bf94a9d47a15482d02707bcfbe0e89b744113d2d","tarball":"https://registry.npmjs.org/chat-state-cloudflare-do/-/chat-state-cloudflare-do-0.1.0.tgz","fileCount":6,"integrity":"sha512-Hr55aUSG083cDqh/DvdF+BgaAqnshjpWpVwpKSMjr3CfACcIkSRqP2twjUlBzF44dG2N3vVhUTIsBd9kAmvM0Q==","signatures":[{"sig":"MEQCIFhvT8hQYFk8uF8yMetf4YjA6FjphApUPcdIORwbSjtBAiAcirRvmXodaUoZ5kIJfrky5Ku7hbakc5y4KYm7KxOONg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":42875},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"e5bf8e32380f17e09b3252601e1eeb96374b304d","scripts":{"dev":"tsup --watch","test":"vitest run --coverage","build":"tsup","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"dcartertwo","email":"dl.carter00@gmail.com"},"repository":{"url":"git+https://github.com/dcartertwo/chat-state-cloudflare-do.git","type":"git"},"_npmVersion":"11.6.2","description":"Cloudflare Durable Objects state adapter for Chat SDK","directories":{},"_nodeVersion":"24.13.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"chat":"^4.15.0","tsup":"^8.3.5","vitest":"^4.0.18","typescript":"^5.7.2","@types/node":"^25.3.2","@cloudflare/workers-types":"^4.20250214.0"},"peerDependencies":{"chat":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/chat-state-cloudflare-do_0.1.0_1772378034137_0.21392915306020455","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"chat-state-cloudflare-do","version":"0.1.1","keywords":["chat-sdk","chat-adapter","state","cloudflare","durable-objects","workers"],"license":"MIT","_id":"chat-state-cloudflare-do@0.1.1","maintainers":[{"name":"dcartertwo","email":"dl.carter00@gmail.com"}],"homepage":"https://github.com/dcartertwo/chat-state-cloudflare-do#readme","bugs":{"url":"https://github.com/dcartertwo/chat-state-cloudflare-do/issues"},"dist":{"shasum":"8479251dd863e5e3ae8ebcedda9d51e812ce070d","tarball":"https://registry.npmjs.org/chat-state-cloudflare-do/-/chat-state-cloudflare-do-0.1.1.tgz","fileCount":6,"integrity":"sha512-RlhSypNPZOwyJhPzqNdnX64J9lnlaftNYvz8D+uSEb14sIEYgaxjW3PGId5gKYXNRxKhYa6gIHyo/Y+ED9Y8KQ==","signatures":[{"sig":"MEUCIQDvKZMevMaU8Gy9cdFbqGVzYK0R11NEdu0vmfbLlnCWIgIgJbVNT/jH9hYoI8H2TNGnFiX36Em4Vz67wQx3XmvEDvI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/chat-state-cloudflare-do@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":43116},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"500876b4aa3a9aca7cb04ee87d5497d22a7753a7","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:8243a067-03f7-4f48-be69-993a660d67e3"}},"repository":{"url":"git+https://github.com/dcartertwo/chat-state-cloudflare-do.git","type":"git"},"_npmVersion":"11.8.0","description":"Cloudflare Durable Objects state adapter for Chat SDK","directories":{},"_nodeVersion":"24.13.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"chat":"^4.15.0","tsup":"^8.3.5","vitest":"^4.0.18","typescript":"^5.7.2","@types/node":"^25.3.2","@cloudflare/workers-types":"^4.20250214.0"},"peerDependencies":{"chat":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/chat-state-cloudflare-do_0.1.1_1772383435105_0.9303619319810699","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"chat-state-cloudflare-do","version":"0.2.0","description":"Cloudflare Durable Objects state adapter for Chat SDK","type":"module","main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"build":"tsup","dev":"tsup --watch","test":"vitest run","test:watch":"vitest","typecheck":"tsc --noEmit","clean":"rm -rf dist"},"peerDependencies":{"chat":"^4.26.0"},"devDependencies":{"@cloudflare/workers-types":"^4.20250214.0","@types/node":"^25.3.2","chat":"^4.26.0","tsup":"^8.3.5","typescript":"^5.7.2","vitest":"^4.0.18"},"repository":{"type":"git","url":"git+https://github.com/dcartertwo/chat-state-cloudflare-do.git"},"homepage":"https://github.com/dcartertwo/chat-state-cloudflare-do#readme","bugs":{"url":"https://github.com/dcartertwo/chat-state-cloudflare-do/issues"},"publishConfig":{"access":"public"},"keywords":["chat-sdk","chat-adapter","state","cloudflare","durable-objects","workers"],"author":{"name":"Dan Carter"},"license":"MIT","gitHead":"47e169a9c939f9ab0944fc389147d3bcbc39797d","_id":"chat-state-cloudflare-do@0.2.0","_nodeVersion":"24.14.1","_npmVersion":"11.11.0","dist":{"integrity":"sha512-ZBOwJXcj5p0fduzRwgVeiH/I7/QFyXFt2ObffSvdMg492j8ulLa+1dzOaiMJlE8isIfxgY9sJkC3b5hNlvURSA==","shasum":"1ea15776a6fb76f3f6cbf9229560af46282ec39b","tarball":"https://registry.npmjs.org/chat-state-cloudflare-do/-/chat-state-cloudflare-do-0.2.0.tgz","fileCount":6,"unpackedSize":62940,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/chat-state-cloudflare-do@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIDZBytqFoFrGQ6/wmCFnpFCqiHUuswLYOdcf/tMRc/AWAiEA7GdyWMc3Qaw8aLaJq5RFwLs4pG5uQupY3hudYaE2tmY="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:8243a067-03f7-4f48-be69-993a660d67e3"}},"directories":{},"maintainers":[{"name":"dcartertwo","email":"dl.carter00@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/chat-state-cloudflare-do_0.2.0_1776344294595_0.3256676721665761"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-01T15:13:54.042Z","modified":"2026-04-16T12:58:15.075Z","0.1.0":"2026-03-01T15:13:54.291Z","0.1.1":"2026-03-01T16:43:55.269Z","0.2.0":"2026-04-16T12:58:14.748Z"},"bugs":{"url":"https://github.com/dcartertwo/chat-state-cloudflare-do/issues"},"license":"MIT","homepage":"https://github.com/dcartertwo/chat-state-cloudflare-do#readme","keywords":["chat-sdk","chat-adapter","state","cloudflare","durable-objects","workers"],"repository":{"type":"git","url":"git+https://github.com/dcartertwo/chat-state-cloudflare-do.git"},"description":"Cloudflare Durable Objects state adapter for Chat SDK","maintainers":[{"name":"dcartertwo","email":"dl.carter00@gmail.com"}],"readme":"# chat-state-cloudflare-do\n\n[![CI](https://github.com/dcartertwo/chat-state-cloudflare-do/actions/workflows/ci.yml/badge.svg)](https://github.com/dcartertwo/chat-state-cloudflare-do/actions/workflows/ci.yml)\n[![npm version](https://img.shields.io/npm/v/chat-state-cloudflare-do)](https://www.npmjs.com/package/chat-state-cloudflare-do)\n[![npm downloads](https://img.shields.io/npm/dm/chat-state-cloudflare-do)](https://www.npmjs.com/package/chat-state-cloudflare-do)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)\n\nCloudflare Durable Objects state adapter for [Chat SDK](https://chat-sdk.dev/docs). Uses a SQLite-backed [Durable Object](https://developers.cloudflare.com/durable-objects/) for persistent subscriptions, distributed locking, and caching — with zero external dependencies beyond the Workers runtime.\n\n## Installation\n\n```bash\nnpm install chat chat-state-cloudflare-do\n```\n\n## Usage\n\n```typescript\nimport { Chat } from \"chat\";\nimport { createSlackAdapter } from \"@chat-adapter/slack\";\nimport { createCloudflareState, ChatStateDO } from \"chat-state-cloudflare-do\";\n\n// Re-export the Durable Object class so Cloudflare can find it\nexport { ChatStateDO };\n\nexport default {\n  async fetch(request: Request, env: Env) {\n    const bot = new Chat({\n      userName: \"my-bot\",\n      adapters: { slack: createSlackAdapter() },\n      state: createCloudflareState({ namespace: env.CHAT_STATE }),\n    });\n    return bot.webhooks.slack(request);\n  },\n};\n```\n\n### Wrangler configuration\n\nAdd the Durable Object binding and migration to your `wrangler.jsonc` (recommended) or `wrangler.toml`:\n\n**wrangler.jsonc** (recommended)\n\n```jsonc\n{\n  \"durable_objects\": {\n    \"bindings\": [\n      { \"name\": \"CHAT_STATE\", \"class_name\": \"ChatStateDO\" }\n    ]\n  },\n  \"migrations\": [\n    { \"tag\": \"v1\", \"new_sqlite_classes\": [\"ChatStateDO\"] }\n  ]\n}\n```\n\n**wrangler.toml**\n\n```toml\n[durable_objects]\nbindings = [\n  { name = \"CHAT_STATE\", class_name = \"ChatStateDO\" }\n]\n\n[[migrations]]\ntag = \"v1\"\nnew_sqlite_classes = [\"ChatStateDO\"]\n```\n\n### Environment type\n\n```typescript\nimport type { ChatStateDO } from \"chat-state-cloudflare-do\";\n\ninterface Env {\n  CHAT_STATE: DurableObjectNamespace<ChatStateDO>;\n}\n```\n\n## Configuration\n\n| Option | Type | Required | Default | Description |\n|--------|------|----------|---------|-------------|\n| `namespace` | `DurableObjectNamespace<ChatStateDO>` | Yes | — | Durable Object namespace binding from wrangler config |\n| `name` | `string` | No | `\"default\"` | Name for the DO instance |\n| `shardKey` | `(threadId: string) => string` | No | — | Function to derive a shard name from a thread ID |\n| `locationHint` | `DurableObjectLocationHint` | No | — | [Location hint](https://developers.cloudflare.com/durable-objects/reference/data-location/) for DO placement |\n\n## Sharding\n\nA single Durable Object handles approximately 500-1,000 requests per second. For high-traffic bots, use `shardKey` to distribute load across multiple DO instances:\n\n```typescript\nconst state = createCloudflareState({\n  namespace: env.CHAT_STATE,\n  shardKey: (threadId) => threadId.split(\":\")[0], // One DO per platform\n});\n```\n\nLocks and subscriptions are per-thread, so sharding by any prefix of the thread ID is safe. Cache operations (`get`/`set`/`delete`) always route to the default shard since their keys are not thread-scoped.\n\n| Strategy | `shardKey` | DOs created |\n|----------|-----------|-------------|\n| No sharding (default) | — | 1 |\n| Per platform | `(id) => id.split(\":\")[0]` | 1 per platform |\n| Per channel | `(id) => id.split(\":\").slice(0, 2).join(\":\")` | 1 per channel |\n\n## Architecture\n\nThe adapter uses a single Durable Object class (`ChatStateDO`) with three SQLite tables:\n\n- **`subscriptions`** — thread IDs the bot is subscribed to\n- **`locks`** — distributed locks with token-based ownership and TTL\n- **`cache`** — key-value pairs with optional TTL\n\nAll operations are single-threaded within a DO instance, providing distributed locking via DO atomicity rather than Lua scripts. Expired entries are cleaned up automatically via the [Alarms API](https://developers.cloudflare.com/durable-objects/api/alarms/).\n\nEach method call creates a fresh DO stub. Stubs are cheap (just a JS object) and the [Cloudflare docs recommend](https://developers.cloudflare.com/durable-objects/best-practices/error-handling/) creating new stubs rather than reusing them after errors.\n\n## Features\n\n- Persistent subscriptions across deployments\n- Distributed locking via single-threaded DO atomicity\n- Key-value caching with TTL\n- Automatic TTL cleanup via Alarms\n- Optional sharding for high-traffic bots\n- Location hints for latency optimization\n- Zero external dependencies (no Redis, no database)\n\n## Production recommendations\n\n- Use [Smart Placement](https://developers.cloudflare.com/workers/configuration/smart-placement/) to co-locate your Worker with the DO\n- Monitor DO metrics in the [Cloudflare dashboard](https://dash.cloudflare.com/)\n- Enable sharding if you expect >500 req/s to a single DO instance\n- Use `locationHint` to place the DO near your primary user base\n\n## Documentation\n\n- [npm package](https://www.npmjs.com/package/chat-state-cloudflare-do)\n- [Chat SDK docs](https://chat-sdk.dev/docs)\n- [State adapters overview](https://chat-sdk.dev/docs/state)\n- [Cloudflare Durable Objects](https://developers.cloudflare.com/durable-objects/)\n\n## License\n\nMIT\n","readmeFilename":"README.md","author":{"name":"Dan Carter"}}