@methodacting/actor-kit 0.47.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/LICENSE.md +7 -0
- package/README.md +2042 -0
- package/dist/browser.d.ts +384 -0
- package/dist/browser.js +2 -0
- package/dist/browser.js.map +1 -0
- package/dist/index.d.ts +644 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/react.d.ts +416 -0
- package/dist/react.js +2 -0
- package/dist/react.js.map +1 -0
- package/dist/src/alarms.d.ts +47 -0
- package/dist/src/alarms.d.ts.map +1 -0
- package/dist/src/browser.d.ts +2 -0
- package/dist/src/browser.d.ts.map +1 -0
- package/dist/src/constants.d.ts +12 -0
- package/dist/src/constants.d.ts.map +1 -0
- package/dist/src/createAccessToken.d.ts +9 -0
- package/dist/src/createAccessToken.d.ts.map +1 -0
- package/dist/src/createActorFetch.d.ts +18 -0
- package/dist/src/createActorFetch.d.ts.map +1 -0
- package/dist/src/createActorKitClient.d.ts +13 -0
- package/dist/src/createActorKitClient.d.ts.map +1 -0
- package/dist/src/createActorKitContext.d.ts +29 -0
- package/dist/src/createActorKitContext.d.ts.map +1 -0
- package/dist/src/createActorKitMockClient.d.ts +11 -0
- package/dist/src/createActorKitMockClient.d.ts.map +1 -0
- package/dist/src/createActorKitRouter.d.ts +4 -0
- package/dist/src/createActorKitRouter.d.ts.map +1 -0
- package/dist/src/createMachineServer.d.ts +20 -0
- package/dist/src/createMachineServer.d.ts.map +1 -0
- package/dist/src/durable-object-system.d.ts +36 -0
- package/dist/src/durable-object-system.d.ts.map +1 -0
- package/dist/src/index.d.ts +7 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/react.d.ts +2 -0
- package/dist/src/react.d.ts.map +1 -0
- package/dist/src/schemas.d.ts +312 -0
- package/dist/src/schemas.d.ts.map +1 -0
- package/dist/src/server.d.ts +3 -0
- package/dist/src/server.d.ts.map +1 -0
- package/dist/src/storage.d.ts +64 -0
- package/dist/src/storage.d.ts.map +1 -0
- package/dist/src/storybook.d.ts +13 -0
- package/dist/src/storybook.d.ts.map +1 -0
- package/dist/src/test.d.ts +2 -0
- package/dist/src/test.d.ts.map +1 -0
- package/dist/src/types.d.ts +181 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/utils.d.ts +30 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/src/withActorKit.d.ts +9 -0
- package/dist/src/withActorKit.d.ts.map +1 -0
- package/dist/src/worker.d.ts +3 -0
- package/dist/src/worker.d.ts.map +1 -0
- package/package.json +87 -0
- package/src/alarms.ts +237 -0
- package/src/browser.ts +1 -0
- package/src/constants.ts +31 -0
- package/src/createAccessToken.ts +29 -0
- package/src/createActorFetch.ts +111 -0
- package/src/createActorKitClient.ts +224 -0
- package/src/createActorKitContext.tsx +228 -0
- package/src/createActorKitMockClient.ts +138 -0
- package/src/createActorKitRouter.ts +149 -0
- package/src/createMachineServer.ts +844 -0
- package/src/durable-object-system.ts +212 -0
- package/src/global.d.ts +7 -0
- package/src/index.ts +6 -0
- package/src/react.ts +1 -0
- package/src/schemas.ts +95 -0
- package/src/server.ts +3 -0
- package/src/storage.ts +404 -0
- package/src/storybook.ts +42 -0
- package/src/test.ts +1 -0
- package/src/types.ts +334 -0
- package/src/utils.ts +171 -0
- package/src/withActorKit.tsx +103 -0
- package/src/worker.ts +2 -0
package/src/storage.ts
ADDED
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
import { PERSISTED_SNAPSHOT_KEY } from "./constants";
|
|
2
|
+
import type { Caller } from "./types";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* SQL schema for the actor-kit SQLite storage
|
|
6
|
+
*/
|
|
7
|
+
const SQL_SCHEMA = `
|
|
8
|
+
-- Alarms table - supports one-time and recurring alarms
|
|
9
|
+
CREATE TABLE IF NOT EXISTS alarms (
|
|
10
|
+
id TEXT PRIMARY KEY,
|
|
11
|
+
type TEXT NOT NULL,
|
|
12
|
+
scheduled_at INTEGER NOT NULL,
|
|
13
|
+
repeat_interval INTEGER,
|
|
14
|
+
payload TEXT,
|
|
15
|
+
created_at INTEGER NOT NULL
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
-- Index for efficient due alarm queries
|
|
19
|
+
CREATE INDEX IF NOT EXISTS idx_alarms_scheduled_at ON alarms(scheduled_at);
|
|
20
|
+
|
|
21
|
+
-- Actor metadata (replaces KV keys: actorType, actorId, initialCaller, input)
|
|
22
|
+
CREATE TABLE IF NOT EXISTS actor_meta (
|
|
23
|
+
actor_id TEXT PRIMARY KEY,
|
|
24
|
+
actor_type TEXT NOT NULL,
|
|
25
|
+
initial_caller TEXT NOT NULL,
|
|
26
|
+
input TEXT NOT NULL,
|
|
27
|
+
created_at INTEGER NOT NULL,
|
|
28
|
+
updated_at INTEGER NOT NULL
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
-- Snapshots table (replaces PERSISTED_SNAPSHOT_KEY)
|
|
32
|
+
CREATE TABLE IF NOT EXISTS snapshots (
|
|
33
|
+
actor_id TEXT PRIMARY KEY,
|
|
34
|
+
snapshot TEXT NOT NULL,
|
|
35
|
+
checksum TEXT,
|
|
36
|
+
updated_at INTEGER NOT NULL
|
|
37
|
+
);
|
|
38
|
+
`;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Alarm record from the database
|
|
42
|
+
*/
|
|
43
|
+
export interface AlarmRecord {
|
|
44
|
+
id: string;
|
|
45
|
+
type: string;
|
|
46
|
+
scheduled_at: number;
|
|
47
|
+
repeat_interval: number | null;
|
|
48
|
+
payload: string | null;
|
|
49
|
+
created_at: number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Scheduled alarm options
|
|
54
|
+
*/
|
|
55
|
+
export interface AlarmScheduleOptions {
|
|
56
|
+
id: string;
|
|
57
|
+
type: string;
|
|
58
|
+
scheduledAt: number;
|
|
59
|
+
repeatInterval?: number;
|
|
60
|
+
payload: Record<string, unknown>;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Actor metadata record
|
|
65
|
+
*/
|
|
66
|
+
export interface ActorMetaRecord {
|
|
67
|
+
actor_id: string;
|
|
68
|
+
actor_type: string;
|
|
69
|
+
initial_caller: string; // JSON stringified Caller
|
|
70
|
+
input: string; // JSON stringified
|
|
71
|
+
created_at: number;
|
|
72
|
+
updated_at: number;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Actor metadata as an object
|
|
77
|
+
*/
|
|
78
|
+
export interface ActorMeta {
|
|
79
|
+
actorId: string;
|
|
80
|
+
actorType: string;
|
|
81
|
+
initialCaller: Caller;
|
|
82
|
+
input: Record<string, unknown>;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Snapshot record
|
|
87
|
+
*/
|
|
88
|
+
export interface SnapshotRecord {
|
|
89
|
+
actor_id: string;
|
|
90
|
+
snapshot: string; // JSON stringified
|
|
91
|
+
checksum: string | null;
|
|
92
|
+
updated_at: number;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Snapshot as an object
|
|
97
|
+
*/
|
|
98
|
+
export interface Snapshot {
|
|
99
|
+
actorId: string;
|
|
100
|
+
snapshot: unknown;
|
|
101
|
+
checksum?: string;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* SQLite storage wrapper for actor-kit Durable Objects
|
|
106
|
+
* Provides methods for managing alarms, actor metadata, and snapshots
|
|
107
|
+
*/
|
|
108
|
+
export class ActorKitStorage {
|
|
109
|
+
private initialized = false;
|
|
110
|
+
private sql: DurableObjectStorage["sql"];
|
|
111
|
+
|
|
112
|
+
constructor(private storage: DurableObjectStorage) {
|
|
113
|
+
this.sql = storage.sql;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Initialize the database schema if not already done
|
|
118
|
+
*/
|
|
119
|
+
async ensureInitialized(): Promise<void> {
|
|
120
|
+
if (this.initialized) return;
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
// Execute schema creation - SQLite will ignore IF NOT EXISTS if tables exist
|
|
124
|
+
await this.sql.exec(SQL_SCHEMA);
|
|
125
|
+
this.initialized = true;
|
|
126
|
+
} catch (error) {
|
|
127
|
+
console.error("Failed to initialize database schema:", error);
|
|
128
|
+
throw error;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// ==================== Alarms ====================
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Get all alarms, optionally filtered by actor
|
|
136
|
+
*/
|
|
137
|
+
async getAlarms(): Promise<AlarmRecord[]> {
|
|
138
|
+
await this.ensureInitialized();
|
|
139
|
+
const result = await this.sql.exec(
|
|
140
|
+
"SELECT id, type, scheduled_at, repeat_interval, payload, created_at FROM alarms ORDER BY scheduled_at ASC"
|
|
141
|
+
);
|
|
142
|
+
return (await this.parseRows(result)) as AlarmRecord[];
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Get alarms that are due before a given timestamp
|
|
147
|
+
*/
|
|
148
|
+
async getDueAlarms(before: number): Promise<AlarmRecord[]> {
|
|
149
|
+
await this.ensureInitialized();
|
|
150
|
+
const result = await this.sql.exec(
|
|
151
|
+
"SELECT id, type, scheduled_at, repeat_interval, payload, created_at FROM alarms WHERE scheduled_at <= ? ORDER BY scheduled_at ASC",
|
|
152
|
+
[before]
|
|
153
|
+
);
|
|
154
|
+
return (await this.parseRows(result)) as AlarmRecord[];
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Get the earliest scheduled alarm
|
|
159
|
+
*/
|
|
160
|
+
async getEarliestAlarm(): Promise<AlarmRecord | null> {
|
|
161
|
+
await this.ensureInitialized();
|
|
162
|
+
const result = await this.sql.exec(
|
|
163
|
+
"SELECT id, type, scheduled_at, repeat_interval, payload, created_at FROM alarms ORDER BY scheduled_at ASC LIMIT 1"
|
|
164
|
+
);
|
|
165
|
+
const rows = (await this.parseRows(result)) as AlarmRecord[];
|
|
166
|
+
return rows[0] || null;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Insert a new alarm
|
|
171
|
+
*/
|
|
172
|
+
async insertAlarm(options: AlarmScheduleOptions): Promise<void> {
|
|
173
|
+
await this.ensureInitialized();
|
|
174
|
+
await this.sql.exec(
|
|
175
|
+
"INSERT INTO alarms (id, type, scheduled_at, repeat_interval, payload, created_at) VALUES (?, ?, ?, ?, ?, ?)",
|
|
176
|
+
[
|
|
177
|
+
options.id,
|
|
178
|
+
options.type,
|
|
179
|
+
options.scheduledAt,
|
|
180
|
+
options.repeatInterval ?? null,
|
|
181
|
+
JSON.stringify(options.payload),
|
|
182
|
+
Date.now(),
|
|
183
|
+
]
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Update an alarm's scheduled time (for recurring alarms)
|
|
189
|
+
*/
|
|
190
|
+
async updateAlarm(options: AlarmScheduleOptions): Promise<void> {
|
|
191
|
+
await this.ensureInitialized();
|
|
192
|
+
await this.sql.exec(
|
|
193
|
+
"UPDATE alarms SET scheduled_at = ?, repeat_interval = ?, payload = ? WHERE id = ?",
|
|
194
|
+
[options.scheduledAt, options.repeatInterval ?? null, JSON.stringify(options.payload), options.id]
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Delete an alarm by ID
|
|
200
|
+
*/
|
|
201
|
+
async deleteAlarm(id: string): Promise<void> {
|
|
202
|
+
await this.ensureInitialized();
|
|
203
|
+
await this.sql.exec("DELETE FROM alarms WHERE id = ?", [id]);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Delete all alarms of a specific type
|
|
208
|
+
*/
|
|
209
|
+
async deleteAlarmsByType(type: string): Promise<void> {
|
|
210
|
+
await this.ensureInitialized();
|
|
211
|
+
await this.sql.exec("DELETE FROM alarms WHERE type = ?", [type]);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// ==================== Actor Metadata ====================
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Get actor metadata by ID
|
|
218
|
+
*/
|
|
219
|
+
async getActorMeta(actorId?: string): Promise<ActorMeta | null> {
|
|
220
|
+
await this.ensureInitialized();
|
|
221
|
+
|
|
222
|
+
if (!actorId) {
|
|
223
|
+
// Get the first (and only) actor metadata
|
|
224
|
+
const result = await this.sql.exec(
|
|
225
|
+
"SELECT actor_id, actor_type, initial_caller, input, created_at, updated_at FROM actor_meta LIMIT 1"
|
|
226
|
+
);
|
|
227
|
+
const rows = (await this.parseRows(result)) as ActorMetaRecord[];
|
|
228
|
+
if (rows.length === 0) return null;
|
|
229
|
+
|
|
230
|
+
const row = rows[0];
|
|
231
|
+
return {
|
|
232
|
+
actorId: row.actor_id,
|
|
233
|
+
actorType: row.actor_type,
|
|
234
|
+
initialCaller: JSON.parse(row.initial_caller) as Caller,
|
|
235
|
+
input: JSON.parse(row.input),
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const result = await this.sql.exec(
|
|
240
|
+
"SELECT actor_id, actor_type, initial_caller, input, created_at, updated_at FROM actor_meta WHERE actor_id = ?",
|
|
241
|
+
[actorId]
|
|
242
|
+
);
|
|
243
|
+
const rows = (await this.parseRows(result)) as ActorMetaRecord[];
|
|
244
|
+
if (rows.length === 0) return null;
|
|
245
|
+
|
|
246
|
+
const row = rows[0];
|
|
247
|
+
return {
|
|
248
|
+
actorId: row.actor_id,
|
|
249
|
+
actorType: row.actor_type,
|
|
250
|
+
initialCaller: JSON.parse(row.initial_caller) as Caller,
|
|
251
|
+
input: JSON.parse(row.input),
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Set actor metadata
|
|
257
|
+
*/
|
|
258
|
+
async setActorMeta(meta: ActorMeta): Promise<void> {
|
|
259
|
+
await this.ensureInitialized();
|
|
260
|
+
const now = Date.now();
|
|
261
|
+
await this.sql.exec(
|
|
262
|
+
`INSERT INTO actor_meta (actor_id, actor_type, initial_caller, input, created_at, updated_at)
|
|
263
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
264
|
+
ON CONFLICT(actor_id) DO UPDATE SET
|
|
265
|
+
actor_type = excluded.actor_type,
|
|
266
|
+
initial_caller = excluded.initial_caller,
|
|
267
|
+
input = excluded.input,
|
|
268
|
+
updated_at = excluded.updated_at`,
|
|
269
|
+
[
|
|
270
|
+
meta.actorId,
|
|
271
|
+
meta.actorType,
|
|
272
|
+
JSON.stringify(meta.initialCaller),
|
|
273
|
+
JSON.stringify(meta.input),
|
|
274
|
+
now,
|
|
275
|
+
now,
|
|
276
|
+
]
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Delete actor metadata
|
|
282
|
+
*/
|
|
283
|
+
async deleteActorMeta(actorId: string): Promise<void> {
|
|
284
|
+
await this.ensureInitialized();
|
|
285
|
+
await this.sql.exec("DELETE FROM actor_meta WHERE actor_id = ?", [actorId]);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// ==================== Snapshots ====================
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Get a snapshot by actor ID
|
|
292
|
+
*/
|
|
293
|
+
async getSnapshot(actorId: string): Promise<Snapshot | null> {
|
|
294
|
+
await this.ensureInitialized();
|
|
295
|
+
const result = await this.sql.exec(
|
|
296
|
+
"SELECT actor_id, snapshot, checksum, updated_at FROM snapshots WHERE actor_id = ?",
|
|
297
|
+
[actorId]
|
|
298
|
+
);
|
|
299
|
+
const rows = (await this.parseRows(result)) as SnapshotRecord[];
|
|
300
|
+
if (rows.length === 0) return null;
|
|
301
|
+
|
|
302
|
+
const row = rows[0];
|
|
303
|
+
return {
|
|
304
|
+
actorId: row.actor_id,
|
|
305
|
+
snapshot: JSON.parse(row.snapshot),
|
|
306
|
+
checksum: row.checksum ?? undefined,
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Set a snapshot for an actor
|
|
312
|
+
*/
|
|
313
|
+
async setSnapshot(actorId: string, snapshot: unknown, checksum?: string): Promise<void> {
|
|
314
|
+
await this.ensureInitialized();
|
|
315
|
+
await this.sql.exec(
|
|
316
|
+
`INSERT INTO snapshots (actor_id, snapshot, checksum, updated_at)
|
|
317
|
+
VALUES (?, ?, ?, ?)
|
|
318
|
+
ON CONFLICT(actor_id) DO UPDATE SET
|
|
319
|
+
snapshot = excluded.snapshot,
|
|
320
|
+
checksum = excluded.checksum,
|
|
321
|
+
updated_at = excluded.updated_at`,
|
|
322
|
+
[actorId, JSON.stringify(snapshot), checksum ?? null, Date.now()]
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Delete a snapshot
|
|
328
|
+
*/
|
|
329
|
+
async deleteSnapshot(actorId: string): Promise<void> {
|
|
330
|
+
await this.ensureInitialized();
|
|
331
|
+
await this.sql.exec("DELETE FROM snapshots WHERE actor_id = ?", [actorId]);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// ==================== Migration Helpers ====================
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Migrate data from legacy KV storage to SQLite
|
|
338
|
+
* This is a one-time migration helper
|
|
339
|
+
*/
|
|
340
|
+
async migrateFromKV(storage: DurableObjectStorage): Promise<void> {
|
|
341
|
+
await this.ensureInitialized();
|
|
342
|
+
|
|
343
|
+
// Migrate actor metadata
|
|
344
|
+
const [actorType, actorId, initialCallerString, inputString] = await Promise.all([
|
|
345
|
+
storage.get("actorType"),
|
|
346
|
+
storage.get("actorId"),
|
|
347
|
+
storage.get("initialCaller"),
|
|
348
|
+
storage.get("input"),
|
|
349
|
+
]);
|
|
350
|
+
|
|
351
|
+
if (actorType && actorId && initialCallerString && inputString) {
|
|
352
|
+
await this.setActorMeta({
|
|
353
|
+
actorId: actorId as string,
|
|
354
|
+
actorType: actorType as string,
|
|
355
|
+
initialCaller: JSON.parse(initialCallerString as string) as Caller,
|
|
356
|
+
input: JSON.parse(inputString as string),
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// Migrate persisted snapshot
|
|
361
|
+
const persistedSnapshot = await storage.get(PERSISTED_SNAPSHOT_KEY);
|
|
362
|
+
if (persistedSnapshot) {
|
|
363
|
+
const snapshot = JSON.parse(persistedSnapshot as string);
|
|
364
|
+
await this.setSnapshot(actorId as string, snapshot);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// ==================== Utility Methods ====================
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Parse SQL result rows - handles both arrays and cursors
|
|
372
|
+
*/
|
|
373
|
+
private async parseRows(result: any): Promise<unknown[]> {
|
|
374
|
+
// Check if result is an async iterable (cursor)
|
|
375
|
+
if (result && typeof result[Symbol.asyncIterator] === "function") {
|
|
376
|
+
const cursor = result as AsyncIterable<{ columns: string[]; results: (string | number | null)[][] }>;
|
|
377
|
+
const rows: unknown[] = [];
|
|
378
|
+
let columns: string[] = [];
|
|
379
|
+
|
|
380
|
+
for await (const batch of cursor) {
|
|
381
|
+
if (!columns) columns = batch.columns;
|
|
382
|
+
for (const row of batch.results) {
|
|
383
|
+
const obj: Record<string, unknown> = {};
|
|
384
|
+
columns.forEach((col, i) => {
|
|
385
|
+
obj[col] = row[i];
|
|
386
|
+
});
|
|
387
|
+
rows.push(obj);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
return rows;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// Handle array format
|
|
394
|
+
if (Array.isArray(result) && result.length === 0) return [];
|
|
395
|
+
const { columns, rows } = result[0];
|
|
396
|
+
return rows.map((row: unknown[]) => {
|
|
397
|
+
const obj: Record<string, unknown> = {};
|
|
398
|
+
columns.forEach((col: string, i: number) => {
|
|
399
|
+
obj[col] = row[i];
|
|
400
|
+
});
|
|
401
|
+
return obj;
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
}
|
package/src/storybook.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { AnyActorKitStateMachine, CallerSnapshotFrom } from "./types";
|
|
2
|
+
|
|
3
|
+
export { withActorKit } from "./withActorKit";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Configuration interface for actor-kit state machines in stories.
|
|
7
|
+
* Allows configuring multiple actors with different initial states.
|
|
8
|
+
*
|
|
9
|
+
* @template TMachine - Type of the actor-kit state machine
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* parameters: {
|
|
14
|
+
* actorKit: {
|
|
15
|
+
* session: {
|
|
16
|
+
* "session-123": {
|
|
17
|
+
* public: { userId: "123" },
|
|
18
|
+
* private: {},
|
|
19
|
+
* value: "ready"
|
|
20
|
+
* }
|
|
21
|
+
* }
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export interface ActorKitParameters<TMachine extends AnyActorKitStateMachine> {
|
|
27
|
+
actorKit: {
|
|
28
|
+
[K: string]: {
|
|
29
|
+
[actorId: string]: CallerSnapshotFrom<TMachine>;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Helper type for stories that use actor-kit state machines.
|
|
36
|
+
* Combines the story type with actor-kit parameters.
|
|
37
|
+
*
|
|
38
|
+
* @template TMachine - Type of the actor-kit state machine
|
|
39
|
+
*/
|
|
40
|
+
export type StoryWithActorKit<TMachine extends AnyActorKitStateMachine> = {
|
|
41
|
+
parameters: ActorKitParameters<TMachine>;
|
|
42
|
+
};
|
package/src/test.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { createActorKitMockClient } from "./createActorKitMockClient";
|