@cloudwerk/durable-object 0.0.1 → 0.1.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/README.md +129 -0
- package/dist/index.d.ts +1 -1
- package/package.json +2 -2
package/README.md
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# @cloudwerk/durable-object
|
|
2
|
+
|
|
3
|
+
Convention-based Durable Objects for Cloudwerk applications with native RPC, SQLite/KV storage, WebSockets, and alarms.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @cloudwerk/durable-object
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
### 1. Define a Durable Object
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
// app/objects/counter.ts
|
|
17
|
+
import { defineDurableObject } from '@cloudwerk/durable-object'
|
|
18
|
+
|
|
19
|
+
interface CounterState {
|
|
20
|
+
count: number
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default defineDurableObject<CounterState>({
|
|
24
|
+
init: async (ctx) => ({ count: 0 }),
|
|
25
|
+
|
|
26
|
+
methods: {
|
|
27
|
+
async increment(ctx, amount: number = 1) {
|
|
28
|
+
ctx.setState({ count: ctx.state.count + amount })
|
|
29
|
+
await ctx.storage.put('state', ctx.state)
|
|
30
|
+
return ctx.state.count
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
async getCount(ctx) {
|
|
34
|
+
return ctx.state.count
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
})
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### 2. Use the Durable Object
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
import { durableObjects } from '@cloudwerk/core/bindings'
|
|
44
|
+
|
|
45
|
+
const counter = durableObjects.counter.get('user-123')
|
|
46
|
+
const count = await counter.increment(5)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Features
|
|
50
|
+
|
|
51
|
+
### Native RPC Methods
|
|
52
|
+
|
|
53
|
+
Methods are exposed as native Cloudflare RPC - no HTTP serialization needed.
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
const counter = durableObjects.counter.get('my-counter')
|
|
57
|
+
await counter.increment(5) // Direct RPC call
|
|
58
|
+
await counter.reset()
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Storage Options
|
|
62
|
+
|
|
63
|
+
#### Key-Value Storage
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
await ctx.storage.put('key', value)
|
|
67
|
+
const value = await ctx.storage.get('key')
|
|
68
|
+
await ctx.storage.delete('key')
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
#### SQLite Storage
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
ctx.sql.exec('CREATE TABLE IF NOT EXISTS messages (...)')
|
|
75
|
+
ctx.sql.prepare('SELECT * FROM messages WHERE user_id = ?').bind(userId).all()
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### WebSocket Support
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
export default defineDurableObject({
|
|
82
|
+
async fetch(request, ctx) {
|
|
83
|
+
const pair = new WebSocketPair()
|
|
84
|
+
ctx.acceptWebSocket(pair[1], ['room-123'])
|
|
85
|
+
return new Response(null, { status: 101, webSocket: pair[0] })
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
async webSocketMessage(ws, message, ctx) {
|
|
89
|
+
for (const client of ctx.getWebSockets('room-123')) {
|
|
90
|
+
client.send(message)
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
})
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Alarms
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
export default defineDurableObject({
|
|
100
|
+
async init(ctx) {
|
|
101
|
+
await ctx.setAlarm(Date.now() + 60_000)
|
|
102
|
+
return { count: 0 }
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
async alarm(ctx) {
|
|
106
|
+
await processScheduledWork(ctx)
|
|
107
|
+
await ctx.setAlarm(Date.now() + 60_000)
|
|
108
|
+
},
|
|
109
|
+
})
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Transactions
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
await ctx.storage.transaction(async () => {
|
|
116
|
+
const from = await ctx.storage.get('account:from')
|
|
117
|
+
const to = await ctx.storage.get('account:to')
|
|
118
|
+
// Atomic updates
|
|
119
|
+
await ctx.storage.put({ 'account:from': from, 'account:to': to })
|
|
120
|
+
})
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Documentation
|
|
124
|
+
|
|
125
|
+
For complete documentation, visit the [Cloudwerk Durable Objects Guide](https://cloudwerk.dev/guides/durable-objects/).
|
|
126
|
+
|
|
127
|
+
## License
|
|
128
|
+
|
|
129
|
+
MIT
|
package/dist/index.d.ts
CHANGED
|
@@ -156,7 +156,7 @@ interface DurableObjectNamespace<T = unknown> {
|
|
|
156
156
|
* Stub for interacting with a durable object instance.
|
|
157
157
|
* Methods defined in `defineDurableObject({ methods })` are directly callable via native RPC.
|
|
158
158
|
*/
|
|
159
|
-
interface DurableObjectStub<
|
|
159
|
+
interface DurableObjectStub<_T = unknown> {
|
|
160
160
|
id: DurableObjectId;
|
|
161
161
|
name?: string;
|
|
162
162
|
fetch(request: Request): Promise<Response>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudwerk/durable-object",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Durable Objects support for Cloudwerk",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"dist"
|
|
19
19
|
],
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@cloudwerk/core": "0.
|
|
21
|
+
"@cloudwerk/core": "0.13.0"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@cloudflare/workers-types": "^4.20241022.0",
|