@rivetkit/cloudflare-workers 2.1.6 → 2.1.7

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.
@@ -6,7 +6,6 @@ import type {
6
6
  RegistryConfig,
7
7
  } from "rivetkit";
8
8
  import { lookupInRegistry } from "rivetkit";
9
- import type { Client } from "rivetkit/client";
10
9
  import type {
11
10
  ActorDriver,
12
11
  AnyActorInstance,
@@ -14,7 +13,14 @@ import type {
14
13
  } from "rivetkit/driver-helpers";
15
14
  import { promiseWithResolvers } from "rivetkit/utils";
16
15
  import { logger } from "./log";
17
- import { kvDelete, kvGet, kvListPrefix, kvPut } from "./actor-kv";
16
+ import {
17
+ kvDelete,
18
+ kvDeleteRange,
19
+ kvGet,
20
+ kvListPrefix,
21
+ kvListRange,
22
+ kvPut,
23
+ } from "./actor-kv";
18
24
  import { GLOBAL_KV_KEYS } from "./global-kv";
19
25
  import { getCloudflareAmbientEnv } from "./handler";
20
26
  import { parseActorId } from "./actor-id";
@@ -105,13 +111,13 @@ export class ActorGlobalState {
105
111
  export class CloudflareActorsActorDriver implements ActorDriver {
106
112
  #registryConfig: RegistryConfig;
107
113
  #managerDriver: ManagerDriver;
108
- #inlineClient: Client<any>;
114
+ #inlineClient: any;
109
115
  #globalState: CloudflareDurableObjectGlobalState;
110
116
 
111
117
  constructor(
112
118
  registryConfig: RegistryConfig,
113
119
  managerDriver: ManagerDriver,
114
- inlineClient: Client<any>,
120
+ inlineClient: any,
115
121
  globalState: CloudflareDurableObjectGlobalState,
116
122
  ) {
117
123
  this.#registryConfig = registryConfig;
@@ -143,7 +149,12 @@ export class CloudflareActorsActorDriver implements ActorDriver {
143
149
  // Create new actor state if it doesn't exist
144
150
  if (!actorState) {
145
151
  actorState = new ActorGlobalState();
146
- actorState.actorPromise = promiseWithResolvers((reason) => logger().warn({ msg: "unhandled actor promise rejection", reason }));
152
+ actorState.actorPromise = promiseWithResolvers((reason) =>
153
+ logger().warn({
154
+ msg: "unhandled actor promise rejection",
155
+ reason,
156
+ }),
157
+ );
147
158
  this.#globalState.setActorState(doState.ctx, actorState);
148
159
  } else if (actorState.actorPromise) {
149
160
  // Another request is already loading this actor, wait for it
@@ -191,7 +202,8 @@ export class CloudflareActorsActorDriver implements ActorDriver {
191
202
  actorState.actorInstance = definition.instantiate();
192
203
 
193
204
  // Start actor
194
- await actorState.actorInstance.start(
205
+ const actorInstance = actorState.actorInstance as any;
206
+ await actorInstance.start(
195
207
  this,
196
208
  this.#inlineClient,
197
209
  actorId,
@@ -256,13 +268,39 @@ export class CloudflareActorsActorDriver implements ActorDriver {
256
268
  }
257
269
  }
258
270
 
271
+ async kvDeleteRange(
272
+ actorId: string,
273
+ start: Uint8Array,
274
+ end: Uint8Array,
275
+ ): Promise<void> {
276
+ const sql = this.#getDOCtx(actorId).storage.sql;
277
+ kvDeleteRange(sql, start, end);
278
+ }
279
+
259
280
  async kvListPrefix(
260
281
  actorId: string,
261
282
  prefix: Uint8Array,
283
+ options?: {
284
+ reverse?: boolean;
285
+ limit?: number;
286
+ },
262
287
  ): Promise<[Uint8Array, Uint8Array][]> {
263
288
  const sql = this.#getDOCtx(actorId).storage.sql;
264
289
 
265
- return kvListPrefix(sql, prefix);
290
+ return kvListPrefix(sql, prefix, options);
291
+ }
292
+
293
+ async kvListRange(
294
+ actorId: string,
295
+ start: Uint8Array,
296
+ end: Uint8Array,
297
+ options?: {
298
+ reverse?: boolean;
299
+ limit?: number;
300
+ },
301
+ ): Promise<[Uint8Array, Uint8Array][]> {
302
+ const sql = this.#getDOCtx(actorId).storage.sql;
303
+ return kvListRange(sql, start, end, options);
266
304
  }
267
305
 
268
306
  startDestroy(actorId: string): void {
@@ -323,7 +361,7 @@ export function createCloudflareActorsActorDriverBuilder(
323
361
  return (
324
362
  config: RegistryConfig,
325
363
  managerDriver: ManagerDriver,
326
- inlineClient: Client<any>,
364
+ inlineClient: any,
327
365
  ) => {
328
366
  return new CloudflareActorsActorDriver(
329
367
  config,
@@ -175,7 +175,10 @@ export function createActorDurableObject(
175
175
  const managerDriver = new CloudflareActorsManagerDriver();
176
176
 
177
177
  // Create inline client
178
- const inlineClient = createClientWithDriver(managerDriver);
178
+ // Avoid expensive type expansion in downstream DTS generation.
179
+ const inlineClient: any = (createClientWithDriver as any)(
180
+ managerDriver,
181
+ );
179
182
 
180
183
  // Create actor driver builder
181
184
  const actorDriverBuilder =
package/src/actor-kv.ts CHANGED
@@ -1,3 +1,5 @@
1
+ const DEFAULT_LIST_LIMIT = 16_384;
2
+
1
3
  export function kvGet(sql: SqlStorage, key: Uint8Array): Uint8Array | null {
2
4
  const cursor = sql.exec(
3
5
  "SELECT value FROM _rivetkit_kv_storage WHERE key = ?",
@@ -27,27 +29,61 @@ export function kvDelete(sql: SqlStorage, key: Uint8Array): void {
27
29
  sql.exec("DELETE FROM _rivetkit_kv_storage WHERE key = ?", key);
28
30
  }
29
31
 
32
+ export function kvDeleteRange(
33
+ sql: SqlStorage,
34
+ start: Uint8Array,
35
+ end: Uint8Array,
36
+ ): void {
37
+ sql.exec(
38
+ "DELETE FROM _rivetkit_kv_storage WHERE key >= ? AND key < ?",
39
+ start,
40
+ end,
41
+ );
42
+ }
43
+
30
44
  export function kvListPrefix(
31
45
  sql: SqlStorage,
32
46
  prefix: Uint8Array,
47
+ options?: {
48
+ reverse?: boolean;
49
+ limit?: number;
50
+ },
33
51
  ): [Uint8Array, Uint8Array][] {
34
- const cursor = sql.exec("SELECT key, value FROM _rivetkit_kv_storage");
35
- const entries: [Uint8Array, Uint8Array][] = [];
36
-
37
- for (const row of cursor.raw()) {
38
- const key = toUint8Array(row[0]);
39
- const value = toUint8Array(row[1]);
40
-
41
- // Check if key starts with prefix
42
- if (hasPrefix(key, prefix)) {
43
- entries.push([key, value]);
44
- }
52
+ const upperBound = computePrefixUpperBound(prefix);
53
+ if (upperBound) {
54
+ return kvListRange(sql, prefix, upperBound, options);
45
55
  }
46
56
 
47
- return entries;
57
+ const direction = options?.reverse ? "DESC" : "ASC";
58
+ const limit = options?.limit ?? DEFAULT_LIST_LIMIT;
59
+ const cursor = sql.exec(
60
+ `SELECT key, value FROM _rivetkit_kv_storage WHERE key >= ? ORDER BY key ${direction} LIMIT ?`,
61
+ prefix,
62
+ limit,
63
+ );
64
+ return readEntries(cursor);
65
+ }
66
+
67
+ export function kvListRange(
68
+ sql: SqlStorage,
69
+ start: Uint8Array,
70
+ end: Uint8Array,
71
+ options?: {
72
+ reverse?: boolean;
73
+ limit?: number;
74
+ },
75
+ ): [Uint8Array, Uint8Array][] {
76
+ const direction = options?.reverse ? "DESC" : "ASC";
77
+ const limit = options?.limit ?? DEFAULT_LIST_LIMIT;
78
+ const cursor = sql.exec(
79
+ `SELECT key, value FROM _rivetkit_kv_storage WHERE key >= ? AND key < ? ORDER BY key ${direction} LIMIT ?`,
80
+ start,
81
+ end,
82
+ limit,
83
+ );
84
+ return readEntries(cursor);
48
85
  }
49
86
 
50
- // Helper function to convert SqlStorageValue to Uint8Array
51
87
  function toUint8Array(
52
88
  value: string | number | ArrayBuffer | Uint8Array | null,
53
89
  ): Uint8Array {
@@ -62,10 +98,23 @@ function toUint8Array(
62
98
  );
63
99
  }
64
100
 
65
- function hasPrefix(arr: Uint8Array, prefix: Uint8Array): boolean {
66
- if (prefix.length > arr.length) return false;
67
- for (let i = 0; i < prefix.length; i++) {
68
- if (arr[i] !== prefix[i]) return false;
101
+ function readEntries(
102
+ cursor: ReturnType<SqlStorage["exec"]>,
103
+ ): [Uint8Array, Uint8Array][] {
104
+ const entries: [Uint8Array, Uint8Array][] = [];
105
+ for (const row of cursor.raw()) {
106
+ entries.push([toUint8Array(row[0]), toUint8Array(row[1])]);
69
107
  }
70
- return true;
108
+ return entries;
109
+ }
110
+
111
+ function computePrefixUpperBound(prefix: Uint8Array): Uint8Array | null {
112
+ const upperBound = prefix.slice();
113
+ for (let i = upperBound.length - 1; i >= 0; i--) {
114
+ if (upperBound[i] !== 0xff) {
115
+ upperBound[i]++;
116
+ return upperBound.slice(0, i + 1);
117
+ }
118
+ }
119
+ return null;
71
120
  }
package/src/config.ts CHANGED
@@ -5,16 +5,14 @@ const ConfigSchemaBase = z.object({
5
5
  /** Path that the Rivet manager API will be mounted. */
6
6
  managerPath: z.string().optional().default("/api/rivet"),
7
7
 
8
- /** Runner key for authentication. */
8
+ /** Deprecated. Runner key for authentication. */
9
9
  runnerKey: z.string().optional(),
10
10
 
11
11
  /** Disable the welcome message. */
12
12
  noWelcome: z.boolean().optional().default(false),
13
13
 
14
14
  fetch: z
15
- .custom<
16
- ExportedHandlerFetchHandler<{ RIVET: Client<any> }, unknown>
17
- >()
15
+ .custom<ExportedHandlerFetchHandler<{ RIVET: Client<any> }, unknown>>()
18
16
  .optional(),
19
17
  });
20
18
  export const ConfigSchema = ConfigSchemaBase.default(() =>
package/src/handler.ts CHANGED
@@ -91,7 +91,8 @@ export function createInlineClient<R extends Registry<any>>(
91
91
  );
92
92
 
93
93
  // Create client using the manager driver
94
- const client = createClientWithDriver<R>(managerDriver);
94
+ // Avoid excessive generic expansion in DTS generation.
95
+ const client = (createClientWithDriver as any)(managerDriver) as Client<R>;
95
96
 
96
97
  return { client, fetch: router.fetch.bind(router), config, ActorHandler };
97
98
  }
@@ -103,14 +104,18 @@ export function createInlineClient<R extends Registry<any>>(
103
104
  *
104
105
  * This includes a `fetch` handler and `ActorHandler` Durable Object.
105
106
  */
106
- export function createHandler<R extends Registry<any>>(
107
- registry: R,
107
+ export function createHandler(
108
+ registry: Registry<any>,
108
109
  inputConfig?: InputConfig,
109
110
  ): HandlerOutput {
110
- const { client, fetch, config, ActorHandler } = createInlineClient(
111
- registry,
112
- inputConfig,
113
- );
111
+ const inline = (createInlineClient as any)(registry, inputConfig);
112
+ const client = inline.client as any;
113
+ const fetch = inline.fetch as (
114
+ request: Request,
115
+ ...args: any
116
+ ) => Response | Promise<Response>;
117
+ const config = inline.config as Config;
118
+ const ActorHandler = inline.ActorHandler as DurableObjectConstructor;
114
119
 
115
120
  // Create Cloudflare handler
116
121
  const handler = {