rivetkit 2.3.11-rc.8 → 2.3.11

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.
Files changed (153) hide show
  1. package/dist/browser/client.d.ts +96 -14
  2. package/dist/browser/client.js +12 -2
  3. package/dist/browser/client.js.map +1 -1
  4. package/dist/browser/inspector/client.d.ts +139 -139
  5. package/dist/browser/inspector/client.js +12 -2
  6. package/dist/browser/inspector/client.js.map +1 -1
  7. package/dist/tsup/agent-os/index.cjs +146 -76
  8. package/dist/tsup/agent-os/index.cjs.map +1 -1
  9. package/dist/tsup/agent-os/index.d.cts +83 -9
  10. package/dist/tsup/agent-os/index.d.ts +83 -9
  11. package/dist/tsup/agent-os/index.js +146 -76
  12. package/dist/tsup/agent-os/index.js.map +1 -1
  13. package/dist/tsup/{chunk-JBQ63WSM.js → chunk-3ZR542SK.js} +4 -4
  14. package/dist/tsup/chunk-3ZR542SK.js.map +1 -0
  15. package/dist/tsup/{chunk-HNHLBM3Y.cjs → chunk-4KGXFC6M.cjs} +42 -5
  16. package/dist/tsup/chunk-4KGXFC6M.cjs.map +1 -0
  17. package/dist/tsup/chunk-5UYWLCRO.js +14 -0
  18. package/dist/tsup/chunk-5UYWLCRO.js.map +1 -0
  19. package/dist/tsup/{chunk-QWLJCP3X.js → chunk-6W5VGLFT.js} +42 -5
  20. package/dist/tsup/chunk-6W5VGLFT.js.map +1 -0
  21. package/dist/tsup/chunk-6WYATRS4.js +243 -0
  22. package/dist/tsup/chunk-6WYATRS4.js.map +1 -0
  23. package/dist/tsup/chunk-B3W74FBB.cjs +14 -0
  24. package/dist/tsup/chunk-B3W74FBB.cjs.map +1 -0
  25. package/dist/tsup/{chunk-V6ANE6JM.js → chunk-FWROC5LA.js} +2 -2
  26. package/dist/tsup/{chunk-ZVM35ICH.cjs → chunk-GLIPKKEC.cjs} +7 -7
  27. package/dist/tsup/{chunk-ZVM35ICH.cjs.map → chunk-GLIPKKEC.cjs.map} +1 -1
  28. package/dist/tsup/{chunk-CCUO5OKD.cjs → chunk-GN2EUMEW.cjs} +3 -3
  29. package/dist/tsup/{chunk-CCUO5OKD.cjs.map → chunk-GN2EUMEW.cjs.map} +1 -1
  30. package/dist/tsup/{chunk-2ROUKH7W.cjs → chunk-GU7ML3KE.cjs} +13 -3
  31. package/dist/tsup/chunk-GU7ML3KE.cjs.map +1 -0
  32. package/dist/tsup/{chunk-WRRB24UY.js → chunk-JQ2AZ5FN.js} +3 -3
  33. package/dist/tsup/{chunk-7AFZMFPQ.js → chunk-JTHHCZCZ.js} +10 -1
  34. package/dist/tsup/chunk-JTHHCZCZ.js.map +1 -0
  35. package/dist/tsup/{chunk-UEULFXUI.cjs → chunk-KVFIONKQ.cjs} +11 -2
  36. package/dist/tsup/chunk-KVFIONKQ.cjs.map +1 -0
  37. package/dist/tsup/chunk-LWQFXGKS.cjs +243 -0
  38. package/dist/tsup/chunk-LWQFXGKS.cjs.map +1 -0
  39. package/dist/tsup/{chunk-KVD6ZWNM.js → chunk-MO2SSUOR.js} +8 -7
  40. package/dist/tsup/chunk-MO2SSUOR.js.map +1 -0
  41. package/dist/tsup/{chunk-AGNBLCNJ.js → chunk-OUENKQHB.js} +13 -3
  42. package/dist/tsup/chunk-OUENKQHB.js.map +1 -0
  43. package/dist/tsup/{chunk-E6WB2BLO.cjs → chunk-PUZY2XCD.cjs} +10 -9
  44. package/dist/tsup/chunk-PUZY2XCD.cjs.map +1 -0
  45. package/dist/tsup/{chunk-4EDGOGCB.js → chunk-QFJ24MBU.js} +27 -2
  46. package/dist/tsup/{chunk-4EDGOGCB.js.map → chunk-QFJ24MBU.js.map} +1 -1
  47. package/dist/tsup/{chunk-A55CGZIV.cjs → chunk-RXXDNJXB.cjs} +140 -140
  48. package/dist/tsup/{chunk-A55CGZIV.cjs.map → chunk-RXXDNJXB.cjs.map} +1 -1
  49. package/dist/tsup/{chunk-N6MBTYGX.cjs → chunk-VBJQIBXI.cjs} +30 -5
  50. package/dist/tsup/chunk-VBJQIBXI.cjs.map +1 -0
  51. package/dist/tsup/client/mod.cjs +6 -6
  52. package/dist/tsup/client/mod.d.cts +4 -3
  53. package/dist/tsup/client/mod.d.ts +4 -3
  54. package/dist/tsup/client/mod.js +5 -5
  55. package/dist/tsup/common/log.cjs +2 -2
  56. package/dist/tsup/common/log.js +1 -1
  57. package/dist/tsup/common/websocket.cjs +3 -3
  58. package/dist/tsup/common/websocket.js +2 -2
  59. package/dist/tsup/{config-CZcjyT5B.d.ts → config-C4OSv0QP.d.ts} +92 -7
  60. package/dist/tsup/{config-rGWrumlO.d.cts → config-DTGoWdkG.d.cts} +92 -7
  61. package/dist/tsup/{config-BxOimoGX.d.cts → config-ey2I2zz5.d.cts} +46 -6
  62. package/dist/tsup/{config-BxOimoGX.d.ts → config-ey2I2zz5.d.ts} +46 -6
  63. package/dist/tsup/{context-B8W8E8nW.d.cts → context-C6cvDNyk.d.cts} +2 -2
  64. package/dist/tsup/{context-_UrDZhEh.d.ts → context-CMygeBxS.d.ts} +2 -2
  65. package/dist/tsup/db/drizzle.cjs +18 -10
  66. package/dist/tsup/db/drizzle.cjs.map +1 -1
  67. package/dist/tsup/db/drizzle.d.cts +5 -6
  68. package/dist/tsup/db/drizzle.d.ts +5 -6
  69. package/dist/tsup/db/drizzle.js +13 -5
  70. package/dist/tsup/db/drizzle.js.map +1 -1
  71. package/dist/tsup/db/mod.cjs +5 -175
  72. package/dist/tsup/db/mod.cjs.map +1 -1
  73. package/dist/tsup/db/mod.d.cts +11 -4
  74. package/dist/tsup/db/mod.d.ts +11 -4
  75. package/dist/tsup/db/mod.js +4 -174
  76. package/dist/tsup/db/mod.js.map +1 -1
  77. package/dist/tsup/dynamic/mod.cjs +2 -2
  78. package/dist/tsup/dynamic/mod.d.cts +3 -2
  79. package/dist/tsup/dynamic/mod.d.ts +3 -2
  80. package/dist/tsup/dynamic/mod.js +1 -1
  81. package/dist/tsup/inspector/mod.cjs +5 -4
  82. package/dist/tsup/inspector/mod.cjs.map +1 -1
  83. package/dist/tsup/inspector/mod.d.cts +12 -146
  84. package/dist/tsup/inspector/mod.d.ts +12 -146
  85. package/dist/tsup/inspector/mod.js +4 -3
  86. package/dist/tsup/inspector/mod.js.map +1 -1
  87. package/dist/tsup/inspector/workflow.cjs +21 -0
  88. package/dist/tsup/inspector/workflow.cjs.map +1 -0
  89. package/dist/tsup/inspector/workflow.d.cts +144 -0
  90. package/dist/tsup/inspector/workflow.d.ts +144 -0
  91. package/dist/tsup/inspector/workflow.js +21 -0
  92. package/dist/tsup/inspector/workflow.js.map +1 -0
  93. package/dist/tsup/inspector-tab/mod.cjs +2 -2
  94. package/dist/tsup/inspector-tab/mod.d.cts +4 -3
  95. package/dist/tsup/inspector-tab/mod.d.ts +4 -3
  96. package/dist/tsup/inspector-tab/mod.js +1 -1
  97. package/dist/tsup/mod.cjs +837 -243
  98. package/dist/tsup/mod.cjs.map +1 -1
  99. package/dist/tsup/mod.d.cts +6 -5
  100. package/dist/tsup/mod.d.ts +6 -5
  101. package/dist/tsup/mod.js +766 -172
  102. package/dist/tsup/mod.js.map +1 -1
  103. package/dist/tsup/test/mod.cjs +7 -7
  104. package/dist/tsup/test/mod.d.cts +3 -2
  105. package/dist/tsup/test/mod.d.ts +3 -2
  106. package/dist/tsup/test/mod.js +5 -5
  107. package/dist/tsup/unstable/migrations.d.cts +1 -1
  108. package/dist/tsup/unstable/migrations.d.ts +1 -1
  109. package/dist/tsup/utils.cjs +2 -2
  110. package/dist/tsup/utils.js +1 -1
  111. package/dist/tsup/workflow/mod.cjs +89 -95
  112. package/dist/tsup/workflow/mod.cjs.map +1 -1
  113. package/dist/tsup/workflow/mod.d.cts +5 -4
  114. package/dist/tsup/workflow/mod.d.ts +5 -4
  115. package/dist/tsup/workflow/mod.js +86 -92
  116. package/dist/tsup/workflow/mod.js.map +1 -1
  117. package/package.json +19 -9
  118. package/src/actor/config.test.ts +65 -1
  119. package/src/actor/config.ts +169 -5
  120. package/src/actor/mod.ts +10 -1
  121. package/src/client/actor-common.ts +5 -14
  122. package/src/common/database/config.ts +50 -3
  123. package/src/common/database/mod.test.ts +142 -4
  124. package/src/common/database/mod.ts +210 -98
  125. package/src/common/database/native-database.ts +42 -3
  126. package/src/common/database/shared.ts +9 -0
  127. package/src/db/drizzle.test.ts +8 -1
  128. package/src/db/drizzle.ts +15 -4
  129. package/src/db/mod.ts +3 -0
  130. package/src/inspector/workflow.ts +61 -0
  131. package/src/registry/napi-runtime.ts +69 -1
  132. package/src/registry/native.ts +505 -155
  133. package/src/registry/run-handler-coordinator.test.ts +252 -0
  134. package/src/registry/run-handler-coordinator.ts +219 -0
  135. package/src/registry/runtime.ts +34 -1
  136. package/src/registry/wasm-runtime.ts +122 -17
  137. package/src/registry/write-through-proxy.ts +101 -0
  138. package/src/utils/node.ts +44 -28
  139. package/src/workflow/driver.ts +56 -58
  140. package/src/workflow/inspector.ts +10 -15
  141. package/src/workflow/mod.ts +48 -70
  142. package/dist/tsup/chunk-2ROUKH7W.cjs.map +0 -1
  143. package/dist/tsup/chunk-7AFZMFPQ.js.map +0 -1
  144. package/dist/tsup/chunk-AGNBLCNJ.js.map +0 -1
  145. package/dist/tsup/chunk-E6WB2BLO.cjs.map +0 -1
  146. package/dist/tsup/chunk-HNHLBM3Y.cjs.map +0 -1
  147. package/dist/tsup/chunk-JBQ63WSM.js.map +0 -1
  148. package/dist/tsup/chunk-KVD6ZWNM.js.map +0 -1
  149. package/dist/tsup/chunk-N6MBTYGX.cjs.map +0 -1
  150. package/dist/tsup/chunk-QWLJCP3X.js.map +0 -1
  151. package/dist/tsup/chunk-UEULFXUI.cjs.map +0 -1
  152. /package/dist/tsup/{chunk-V6ANE6JM.js.map → chunk-FWROC5LA.js.map} +0 -0
  153. /package/dist/tsup/{chunk-WRRB24UY.js.map → chunk-JQ2AZ5FN.js.map} +0 -0
@@ -1,11 +1,3 @@
1
- import type {
2
- ActorContext as WasmActorContext,
3
- ActorFactory as WasmActorFactory,
4
- CancellationToken as WasmCancellationToken,
5
- ConnHandle as WasmConnHandle,
6
- CoreRegistry as WasmCoreRegistry,
7
- WebSocketHandle as WasmWebSocketHandle,
8
- } from "@rivetkit/rivetkit-wasm";
9
1
  import { decodeBridgeRivetError, RivetError } from "@/actor/errors";
10
2
  import type {
11
3
  WasmRuntimeBindings,
@@ -15,6 +7,7 @@ import type {
15
7
  import type {
16
8
  ActorContextHandle,
17
9
  ActorFactoryHandle,
10
+ ActorStateTransactionHandle,
18
11
  CancellationTokenHandle,
19
12
  ConnHandle,
20
13
  CoreRuntime,
@@ -23,6 +16,8 @@ import type {
23
16
  RuntimeActorKeySegment,
24
17
  RuntimeApplicationListenerConfig,
25
18
  RuntimeBytes,
19
+ RuntimeCronFire,
20
+ RuntimeCronJobInfo,
26
21
  RuntimeHttpRequest,
27
22
  RuntimeInspectorSnapshot,
28
23
  RuntimeKvEntry,
@@ -34,12 +29,10 @@ import type {
34
29
  RuntimeQueueNextBatchOptions,
35
30
  RuntimeQueueTryNextBatchOptions,
36
31
  RuntimeQueueWaitOptions,
37
- RuntimeCronFire,
38
- RuntimeCronJobInfo,
39
32
  RuntimeRegistryRouteResponse,
40
33
  RuntimeRequestSaveOpts,
41
- RuntimeServeConfig,
42
34
  RuntimeScheduledEventInfo,
35
+ RuntimeServeConfig,
43
36
  RuntimeServerlessRequest,
44
37
  RuntimeServerlessResponseHead,
45
38
  RuntimeServerlessStreamCallback,
@@ -62,6 +55,35 @@ type WasmBindings = WasmRuntimeBindings;
62
55
  export type WasmInitInput = WasmRuntimeInitInput;
63
56
  type AnyFunction = (...args: unknown[]) => unknown;
64
57
  type WasmRuntimeLoadConfig = Pick<WasmRuntimeConfig, "bindings" | "initInput">;
58
+ type WasmActorContext = object;
59
+ type WasmActorFactory = object;
60
+ type WasmConnHandle = object;
61
+ type WasmWebSocketHandle = object;
62
+
63
+ interface WasmCancellationToken {
64
+ aborted(): boolean;
65
+ cancel(): void;
66
+ onCancelled(callback: (...args: unknown[]) => unknown): void;
67
+ }
68
+
69
+ interface WasmCoreRegistry {
70
+ register(name: string, factory: WasmActorFactory): void;
71
+ serve(config: RuntimeServeConfig): Promise<void>;
72
+ shutdown(): Promise<void>;
73
+ }
74
+
75
+ interface WasmConstructors {
76
+ CoreRegistry: new () => WasmCoreRegistry;
77
+ ActorFactory: new (
78
+ callbacks: object,
79
+ config: RuntimeActorConfig | undefined | null,
80
+ ) => WasmActorFactory;
81
+ CancellationToken: new () => WasmCancellationToken;
82
+ }
83
+
84
+ function asWasmConstructors(bindings: WasmBindings): WasmConstructors {
85
+ return bindings as unknown as WasmConstructors;
86
+ }
65
87
 
66
88
  function asWasmRegistry(handle: RegistryHandle): WasmCoreRegistry {
67
89
  return handle as unknown as WasmCoreRegistry;
@@ -235,11 +257,11 @@ function childHandle<T>(handle: unknown, name: string): T {
235
257
  export class WasmCoreRuntime implements CoreRuntime {
236
258
  readonly kind = "wasm";
237
259
 
238
- #bindings: WasmBindings;
260
+ #constructors: WasmConstructors;
239
261
  #sql = new WeakMap<WasmActorContext, RuntimeSqlDatabase>();
240
262
 
241
263
  constructor(bindings: WasmBindings) {
242
- this.#bindings = bindings;
264
+ this.#constructors = asWasmConstructors(bindings);
243
265
  }
244
266
 
245
267
  #actorSql(ctx: ActorContextHandle): RuntimeSqlDatabase {
@@ -254,7 +276,7 @@ export class WasmCoreRuntime implements CoreRuntime {
254
276
 
255
277
  createRegistry(): RegistryHandle {
256
278
  return callWasmSync(() =>
257
- asRegistryHandle(new this.#bindings.CoreRegistry()),
279
+ asRegistryHandle(new this.#constructors.CoreRegistry()),
258
280
  );
259
281
  }
260
282
 
@@ -342,7 +364,7 @@ export class WasmCoreRuntime implements CoreRuntime {
342
364
  ): ActorFactoryHandle {
343
365
  return callWasmSync(() =>
344
366
  asActorFactoryHandle(
345
- new this.#bindings.ActorFactory(callbacks, config),
367
+ new this.#constructors.ActorFactory(callbacks, config),
346
368
  ),
347
369
  );
348
370
  }
@@ -350,7 +372,7 @@ export class WasmCoreRuntime implements CoreRuntime {
350
372
  createCancellationToken(): CancellationTokenHandle {
351
373
  return callWasmSync(
352
374
  () =>
353
- new this.#bindings.CancellationToken() as unknown as CancellationTokenHandle,
375
+ new this.#constructors.CancellationToken() as unknown as CancellationTokenHandle,
354
376
  );
355
377
  }
356
378
 
@@ -399,6 +421,17 @@ export class WasmCoreRuntime implements CoreRuntime {
399
421
  );
400
422
  }
401
423
 
424
+ async actorSetRunWakeAt(
425
+ ctx: ActorContextHandle,
426
+ timestampMs?: number | undefined | null,
427
+ ): Promise<void> {
428
+ await callHandleAsync(
429
+ asWasmActorContext(ctx),
430
+ "setRunWakeAt",
431
+ optionalWasmNumber(timestampMs),
432
+ );
433
+ }
434
+
402
435
  actorRequestSave(
403
436
  ctx: ActorContextHandle,
404
437
  opts?: RuntimeRequestSaveOpts | undefined | null,
@@ -748,9 +781,10 @@ export class WasmCoreRuntime implements CoreRuntime {
748
781
  async actorSqlBeginTransaction(
749
782
  ctx: ActorContextHandle,
750
783
  timeoutMs?: number,
784
+ name?: string,
751
785
  ): Promise<SqliteTransactionHandle> {
752
786
  return (await callWasm(() =>
753
- this.#actorSql(ctx).beginTransaction(timeoutMs),
787
+ this.#actorSql(ctx).beginTransaction(timeoutMs, name),
754
788
  )) as unknown as SqliteTransactionHandle;
755
789
  }
756
790
 
@@ -802,6 +836,61 @@ export class WasmCoreRuntime implements CoreRuntime {
802
836
  ).rollback(),
803
837
  );
804
838
  }
839
+ async actorBeginStateTransaction(
840
+ ctx: ActorContextHandle,
841
+ timeoutMs?: number,
842
+ ): Promise<ActorStateTransactionHandle> {
843
+ return (await callWasm(() =>
844
+ (
845
+ asWasmActorContext(ctx) as unknown as {
846
+ beginStateTransaction(
847
+ timeoutMs?: number,
848
+ ): Promise<ActorStateTransactionHandle>;
849
+ }
850
+ ).beginStateTransaction(timeoutMs),
851
+ )) as ActorStateTransactionHandle;
852
+ }
853
+
854
+ async actorStateTransactionExecute(
855
+ transaction: ActorStateTransactionHandle,
856
+ sql: string,
857
+ params?: RuntimeSqlBindParams,
858
+ ): Promise<RuntimeSqlExecuteResult> {
859
+ const result = await callWasm(() =>
860
+ (
861
+ transaction as unknown as {
862
+ execute(
863
+ sql: string,
864
+ params?: RuntimeSqlBindParams,
865
+ ): Promise<RuntimeSqlExecuteResult>;
866
+ }
867
+ ).execute(sql, params),
868
+ );
869
+ return normalizeRuntimeSqlExecuteResult(result);
870
+ }
871
+
872
+ async actorStateTransactionCommit(
873
+ transaction: ActorStateTransactionHandle,
874
+ payload: RuntimeStateDeltaPayload,
875
+ ): Promise<void> {
876
+ await callWasm(() =>
877
+ (
878
+ transaction as unknown as {
879
+ commit(payload: RuntimeStateDeltaPayload): Promise<void>;
880
+ }
881
+ ).commit(payload),
882
+ );
883
+ }
884
+
885
+ async actorStateTransactionRollback(
886
+ transaction: ActorStateTransactionHandle,
887
+ ): Promise<void> {
888
+ await callWasm(() =>
889
+ (
890
+ transaction as unknown as { rollback(): Promise<void> }
891
+ ).rollback(),
892
+ );
893
+ }
805
894
 
806
895
  async actorSqlQuery(
807
896
  ctx: ActorContextHandle,
@@ -912,6 +1001,22 @@ export class WasmCoreRuntime implements CoreRuntime {
912
1001
  );
913
1002
  }
914
1003
 
1004
+ async actorQueueCompletePersisted(
1005
+ ctx: ActorContextHandle,
1006
+ messageId: bigint,
1007
+ expectedName: string,
1008
+ response?: RuntimeBytes | undefined | null,
1009
+ ): Promise<boolean> {
1010
+ const queue = childHandle(asWasmActorContext(ctx), "queue");
1011
+ return await callHandleAsync(
1012
+ queue,
1013
+ "completePersisted",
1014
+ messageId,
1015
+ expectedName,
1016
+ response,
1017
+ );
1018
+ }
1019
+
915
1020
  async actorQueueEnqueueAndWait(
916
1021
  ctx: ActorContextHandle,
917
1022
  name: string,
@@ -38,3 +38,104 @@ export function createWriteThroughProxy<T>(
38
38
  },
39
39
  ) as T;
40
40
  }
41
+
42
+ /**
43
+ * Returns the raw target behind an `@rivetkit/on-change` proxy, following
44
+ * chains of proxies wrapping proxies until reaching a plain value.
45
+ */
46
+ function unwrapProxy(value: unknown): unknown {
47
+ let current = value;
48
+ while (current !== null && typeof current === "object") {
49
+ const target = onChange.target(current as Record<string, any>);
50
+ if (target === current) {
51
+ break;
52
+ }
53
+ current = target;
54
+ }
55
+ return current;
56
+ }
57
+
58
+ function isPlainObject(value: unknown): value is Record<string, unknown> {
59
+ const proto = Object.getPrototypeOf(value as object);
60
+ return proto === Object.prototype || proto === null;
61
+ }
62
+
63
+ function unwrapDeep(value: unknown, seen: Set<object>): unknown {
64
+ const unwrapped = unwrapProxy(value);
65
+ if (!unwrapped || typeof unwrapped !== "object") {
66
+ return unwrapped;
67
+ }
68
+ if (seen.has(unwrapped)) {
69
+ return unwrapped;
70
+ }
71
+ seen.add(unwrapped);
72
+
73
+ if (Array.isArray(unwrapped)) {
74
+ for (let i = 0; i < unwrapped.length; i++) {
75
+ const child = unwrapDeep(unwrapped[i], seen);
76
+ if (child !== unwrapped[i]) {
77
+ unwrapped[i] = child;
78
+ }
79
+ }
80
+ return unwrapped;
81
+ }
82
+
83
+ if (unwrapped instanceof Map) {
84
+ const replacements: [unknown, unknown, unknown][] = [];
85
+ for (const [key, child] of unwrapped.entries()) {
86
+ const nextKey = unwrapDeep(key, seen);
87
+ const nextChild = unwrapDeep(child, seen);
88
+ if (nextKey !== key || nextChild !== child) {
89
+ replacements.push([key, nextKey, nextChild]);
90
+ }
91
+ }
92
+ for (const [key, nextKey, nextChild] of replacements) {
93
+ if (nextKey !== key) {
94
+ unwrapped.delete(key);
95
+ }
96
+ unwrapped.set(nextKey, nextChild);
97
+ }
98
+ return unwrapped;
99
+ }
100
+
101
+ if (unwrapped instanceof Set) {
102
+ const replacements: [unknown, unknown][] = [];
103
+ for (const child of unwrapped.values()) {
104
+ const next = unwrapDeep(child, seen);
105
+ if (next !== child) {
106
+ replacements.push([child, next]);
107
+ }
108
+ }
109
+ for (const [child, next] of replacements) {
110
+ unwrapped.delete(child);
111
+ unwrapped.add(next);
112
+ }
113
+ return unwrapped;
114
+ }
115
+
116
+ if (isPlainObject(unwrapped)) {
117
+ for (const key of Object.keys(unwrapped)) {
118
+ const child = unwrapDeep(unwrapped[key], seen);
119
+ if (child !== unwrapped[key]) {
120
+ unwrapped[key] = child;
121
+ }
122
+ }
123
+ }
124
+
125
+ return unwrapped;
126
+ }
127
+
128
+ /**
129
+ * Strips every `@rivetkit/on-change` proxy out of a value in place, including
130
+ * proxies nested inside plain objects, arrays, `Map`s, and `Set`s.
131
+ *
132
+ * A read of `c.state` or `conn.state` hands back a deep write-through proxy,
133
+ * so an update written as `c.state = { ...c.state, foo }` produces a plain root
134
+ * object whose children are still proxies. Persisting that value as-is makes
135
+ * the next read wrap proxies in another proxy layer, and each layer multiplies
136
+ * the work of traversing the state, so repeated spread updates degrade
137
+ * exponentially. Unwrapping before persisting keeps stored state proxy-free.
138
+ */
139
+ export function unwrapWriteThroughProxy<T>(value: T): T {
140
+ return unwrapDeep(value, new Set()) as T;
141
+ }
package/src/utils/node.ts CHANGED
@@ -19,20 +19,35 @@ let nodeStream: typeof import("node:stream/promises") | undefined;
19
19
  let nodeUrl: typeof import("node:url") | undefined;
20
20
 
21
21
  let hasImportedDependencies = false;
22
+ type NodeBuiltin = `node:${string}`;
23
+ let fallbackRequire: ReturnType<typeof createRequire> | undefined;
22
24
 
23
- // Helper to get a require function that works in both CommonJS and ESM.
24
- // We use require() instead of await import() because registry.start() cannot
25
- // be async and needs immediate access to Node.js modules during setup.
26
- export function getRequireFn() {
27
- // TODO: This causes issues in tsup
28
- // CommonJS context - use global require
29
- // if (typeof require !== "undefined") {
30
- // console.log("existing require");
31
- // return require;
32
- // }
33
-
34
- // ESM context - use createRequire with import.meta.url
35
- return createRequire(import.meta.url);
25
+ /**
26
+ * Loads a Node.js built-in synchronously without relying on `import.meta`,
27
+ * which esbuild cannot preserve in CommonJS output. Prefer Node's dedicated
28
+ * built-in loader and retain `createRequire` for Node 22.0-22.2 compatibility.
29
+ *
30
+ * @see https://nodejs.org/api/process.html#processgetbuiltinmoduleid
31
+ * @see https://github.com/evanw/esbuild/issues/1492
32
+ */
33
+ export function loadNodeBuiltin<T>(id: NodeBuiltin): T {
34
+ const nodeProcess = globalThis.process;
35
+ const builtin = nodeProcess?.getBuiltinModule?.(id);
36
+
37
+ if (builtin !== undefined) {
38
+ return builtin as T;
39
+ }
40
+
41
+ if (!nodeProcess?.execPath) {
42
+ throw new Error("Node.js built-ins are not available");
43
+ }
44
+
45
+ // Node 22.0-22.2 does not provide getBuiltinModule(). Avoid import.meta here:
46
+ // esbuild replaces it with an empty shim in CommonJS output, leaving
47
+ // import_meta.url undefined. This loader only resolves built-ins, so the
48
+ // fallback base does not affect package resolution.
49
+ fallbackRequire ??= createRequire(nodeProcess.execPath);
50
+ return fallbackRequire(id) as T;
36
51
  }
37
52
 
38
53
  /**
@@ -48,22 +63,23 @@ export function importNodeDependencies(): void {
48
63
  if (hasImportedDependencies) return;
49
64
 
50
65
  try {
51
- // Get a require function that works in both CommonJS and ESM
52
- const requireFn = getRequireFn();
53
-
54
- // Use requireFn with webpack ignore comment to prevent bundling
55
- nodeCrypto = requireFn(/* webpackIgnore: true */ "node:crypto");
56
- nodeFsSync = requireFn(/* webpackIgnore: true */ "node:fs");
57
- nodeFs = requireFn(/* webpackIgnore: true */ "node:fs/promises");
58
- nodePath = requireFn(/* webpackIgnore: true */ "node:path");
59
- nodeOs = requireFn(/* webpackIgnore: true */ "node:os");
60
- nodeChildProcess = requireFn(
61
- /* webpackIgnore: true */ "node:child_process",
62
- );
63
- nodeStream = requireFn(
64
- /* webpackIgnore: true */ "node:stream/promises",
66
+ nodeCrypto =
67
+ loadNodeBuiltin<typeof import("node:crypto")>("node:crypto");
68
+ nodeFsSync = loadNodeBuiltin<typeof import("node:fs")>("node:fs");
69
+ nodeFs =
70
+ loadNodeBuiltin<typeof import("node:fs/promises")>(
71
+ "node:fs/promises",
72
+ );
73
+ nodePath = loadNodeBuiltin<typeof import("node:path")>("node:path");
74
+ nodeOs = loadNodeBuiltin<typeof import("node:os")>("node:os");
75
+ nodeChildProcess =
76
+ loadNodeBuiltin<typeof import("node:child_process")>(
77
+ "node:child_process",
78
+ );
79
+ nodeStream = loadNodeBuiltin<typeof import("node:stream/promises")>(
80
+ "node:stream/promises",
65
81
  );
66
- nodeUrl = requireFn(/* webpackIgnore: true */ "node:url");
82
+ nodeUrl = loadNodeBuiltin<typeof import("node:url")>("node:url");
67
83
  hasImportedDependencies = true;
68
84
  } catch (err) {
69
85
  console.warn(
@@ -8,7 +8,7 @@ import type {
8
8
  import type { RunContext } from "@/actor/config";
9
9
  import type { AnyStaticActorInstance } from "@/actor/definition";
10
10
  import { makeWorkflowKey, workflowStoragePrefix } from "@/actor/keys";
11
- import type { SqliteDatabase } from "@/common/database/config";
11
+ import type { RawAccess } from "@/common/database/config";
12
12
 
13
13
  const WORKFLOW_STORAGE_PREFIX = workflowStoragePrefix();
14
14
  // Keep workflow flushes below depot's 320-dirty-page commit ceiling. The
@@ -68,52 +68,40 @@ function normalizeSqlBlob(value: unknown): Uint8Array {
68
68
  throw new Error("workflow sqlite value was not a blob");
69
69
  }
70
70
 
71
- function runtimeSqlFromContext(
71
+ function runtimeDbFromContext(
72
72
  runCtx?: RunContext<any, any, any, any, any, any, any, any>,
73
- ): SqliteDatabase | undefined {
74
- const sql = (runCtx as unknown as { sql?: unknown } | undefined)?.sql;
73
+ ): RawAccess | undefined {
74
+ const db = (runCtx as unknown as { db?: unknown } | undefined)?.db;
75
75
  if (
76
- sql &&
77
- typeof sql === "object" &&
78
- "query" in sql &&
79
- "execute" in sql &&
80
- "executeBatch" in sql &&
81
- "run" in sql
76
+ db &&
77
+ typeof db === "object" &&
78
+ "execute" in db &&
79
+ "transaction" in db
82
80
  ) {
83
- return sql as SqliteDatabase;
81
+ return db as RawAccess;
84
82
  }
85
83
  return undefined;
86
84
  }
87
85
 
88
- type WorkflowSqliteDatabase = SqliteDatabase &
89
- Required<Pick<SqliteDatabase, "executeBatch">>;
90
-
91
86
  class WorkflowStorage {
92
- #sql: WorkflowSqliteDatabase;
87
+ #db: RawAccess;
93
88
 
94
- constructor(sql?: SqliteDatabase) {
95
- if (!sql) {
89
+ constructor(db?: RawAccess) {
90
+ if (!db) {
96
91
  throw new Error(
97
92
  "workflow storage requires embedded SQLite; actor KV workflow storage is no longer supported",
98
93
  );
99
94
  }
100
- if (!sql.executeBatch) {
101
- throw new Error(
102
- "workflow storage requires a SQLite database with executeBatch support",
103
- );
104
- }
105
- this.#sql = sql as WorkflowSqliteDatabase;
95
+ this.#db = db;
106
96
  }
107
97
 
108
98
  async get(key: Uint8Array): Promise<Uint8Array | null> {
109
99
  const prefixed = makeWorkflowKey(key);
110
- const result = await this.#sql.query(
100
+ const rows = await this.#db.execute<{ value: unknown }>(
111
101
  "SELECT value FROM _rivet_wf_kv WHERE key = ?",
112
- [prefixed],
102
+ prefixed,
113
103
  );
114
- return result.rows[0]?.[0] == null
115
- ? null
116
- : normalizeSqlBlob(result.rows[0][0]);
104
+ return rows[0]?.value == null ? null : normalizeSqlBlob(rows[0].value);
117
105
  }
118
106
 
119
107
  async set(key: Uint8Array, value: Uint8Array): Promise<void> {
@@ -122,18 +110,20 @@ class WorkflowStorage {
122
110
 
123
111
  async delete(key: Uint8Array): Promise<void> {
124
112
  const prefixed = makeWorkflowKey(key);
125
- await this.#sql.run("DELETE FROM _rivet_wf_kv WHERE key = ?", [
113
+ await this.#db.execute(
114
+ "DELETE FROM _rivet_wf_kv WHERE key = ?",
126
115
  prefixed,
127
- ]);
116
+ );
128
117
  }
129
118
 
130
119
  async deletePrefix(prefix: Uint8Array): Promise<void> {
131
120
  const start = makeWorkflowKey(prefix);
132
121
  const end = computeUpperBound(start);
133
122
  if (end) {
134
- await this.#sql.run(
123
+ await this.#db.execute(
135
124
  "DELETE FROM _rivet_wf_kv WHERE key >= ? AND key < ?",
136
- [start, end],
125
+ start,
126
+ end,
137
127
  );
138
128
  return;
139
129
  }
@@ -148,9 +138,10 @@ class WorkflowStorage {
148
138
  async deleteRange(start: Uint8Array, end: Uint8Array): Promise<void> {
149
139
  const prefixedStart = makeWorkflowKey(start);
150
140
  const prefixedEnd = makeWorkflowKey(end);
151
- await this.#sql.run(
141
+ await this.#db.execute(
152
142
  "DELETE FROM _rivet_wf_kv WHERE key >= ? AND key < ?",
153
- [prefixedStart, prefixedEnd],
143
+ prefixedStart,
144
+ prefixedEnd,
154
145
  );
155
146
  }
156
147
 
@@ -168,29 +159,33 @@ class WorkflowStorage {
168
159
  async batch(writes: KVWrite[]): Promise<void> {
169
160
  if (writes.length === 0) return;
170
161
  for (const chunk of chunkWorkflowWrites(writes)) {
171
- await this.#sql.executeBatch(
172
- chunk.map(({ key, value }) => ({
173
- sql: "INSERT INTO _rivet_wf_kv (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value",
174
- params: [makeWorkflowKey(key), value],
175
- })),
176
- );
162
+ await this.#db.transaction(async (tx) => {
163
+ for (const { key, value } of chunk) {
164
+ await tx.execute(
165
+ "INSERT INTO _rivet_wf_kv (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value",
166
+ makeWorkflowKey(key),
167
+ value,
168
+ );
169
+ }
170
+ });
177
171
  }
178
172
  }
179
173
 
180
174
  async listRaw(prefix: Uint8Array): Promise<KVEntryTuple[]> {
181
175
  const end = computeUpperBound(prefix);
182
- const result = end
183
- ? await this.#sql.query(
176
+ const rows = end
177
+ ? await this.#db.execute<{ key: unknown; value: unknown }>(
184
178
  "SELECT key, value FROM _rivet_wf_kv WHERE key >= ? AND key < ? ORDER BY key ASC",
185
- [prefix, end],
179
+ prefix,
180
+ end,
186
181
  )
187
- : await this.#sql.query(
182
+ : await this.#db.execute<{ key: unknown; value: unknown }>(
188
183
  "SELECT key, value FROM _rivet_wf_kv WHERE key >= ? ORDER BY key ASC",
189
- [prefix],
184
+ prefix,
190
185
  );
191
- return result.rows.map((row) => [
192
- normalizeSqlBlob(row[0]),
193
- normalizeSqlBlob(row[1]),
186
+ return rows.map((row) => [
187
+ normalizeSqlBlob(row.key),
188
+ normalizeSqlBlob(row.value),
194
189
  ]);
195
190
  }
196
191
 
@@ -200,14 +195,17 @@ class WorkflowStorage {
200
195
  start < keys.length;
201
196
  start += WORKFLOW_SQLITE_MAX_BATCH_ROWS
202
197
  ) {
203
- await this.#sql.executeBatch(
204
- keys
205
- .slice(start, start + WORKFLOW_SQLITE_MAX_BATCH_ROWS)
206
- .map((key) => ({
207
- sql: "DELETE FROM _rivet_wf_kv WHERE key = ?",
208
- params: [key],
209
- })),
210
- );
198
+ await this.#db.transaction(async (tx) => {
199
+ for (const key of keys.slice(
200
+ start,
201
+ start + WORKFLOW_SQLITE_MAX_BATCH_ROWS,
202
+ )) {
203
+ await tx.execute(
204
+ "DELETE FROM _rivet_wf_kv WHERE key = ?",
205
+ key,
206
+ );
207
+ }
208
+ });
211
209
  }
212
210
  }
213
211
  }
@@ -331,7 +329,7 @@ export class ActorWorkflowDriver implements EngineDriver {
331
329
  this.#actor = actor;
332
330
  this.#runCtx = runCtx;
333
331
  this.messageDriver = new ActorWorkflowMessageDriver(actor, runCtx);
334
- this.#storage = new WorkflowStorage(runtimeSqlFromContext(runCtx));
332
+ this.#storage = new WorkflowStorage(runtimeDbFromContext(runCtx));
335
333
  }
336
334
 
337
335
  async get(key: Uint8Array): Promise<Uint8Array | null> {
@@ -425,7 +423,7 @@ export class ActorWorkflowControlDriver implements EngineDriver {
425
423
  runCtx?: RunContext<any, any, any, any, any, any, any, any>,
426
424
  ) {
427
425
  this.#actor = actor;
428
- this.#storage = new WorkflowStorage(runtimeSqlFromContext(runCtx));
426
+ this.#storage = new WorkflowStorage(runtimeDbFromContext(runCtx));
429
427
  }
430
428
 
431
429
  async get(key: Uint8Array): Promise<Uint8Array | null> {
@@ -10,12 +10,14 @@ import type {
10
10
  WorkflowHistorySnapshot,
11
11
  WorkflowState,
12
12
  } from "@rivetkit/workflow-engine";
13
- import * as transport from "@/common/bare/transport/v1";
14
- import type { JsonCompatValue } from "@/common/encoding";
15
- import type { WorkflowHistoryBytes } from "@/common/inspector-transport";
16
- import { encodeWorkflowHistoryTransport } from "@/common/inspector-transport";
17
- import { encodeCborCompat } from "@/serde";
18
- import { assertUnreachable, bufferToArrayBuffer } from "@/utils";
13
+ import * as transport from "@/inspector/workflow";
14
+ import {
15
+ encodeWorkflowHistoryTransport,
16
+ encodeWorkflowInspectorValue,
17
+ type WorkflowInspectorAdapter as PublicWorkflowInspectorAdapter,
18
+ type WorkflowHistoryBytes,
19
+ } from "@/inspector/workflow";
20
+ import { assertUnreachable } from "@/utils";
19
21
 
20
22
  type HistoryListener = (history: WorkflowHistoryBytes) => void;
21
23
 
@@ -35,14 +37,7 @@ function createHistoryEmitter() {
35
37
  };
36
38
  }
37
39
 
38
- export interface WorkflowInspectorAdapter {
39
- getHistory: () => WorkflowHistoryBytes | null;
40
- getState: () => Promise<WorkflowState | null>;
41
- onHistoryUpdated: (
42
- listener: (history: WorkflowHistoryBytes) => void,
43
- ) => () => void;
44
- replayFromStep: (entryId?: string) => Promise<WorkflowHistoryBytes | null>;
45
- }
40
+ export type WorkflowInspectorAdapter = PublicWorkflowInspectorAdapter;
46
41
 
47
42
  export function createWorkflowInspectorAdapter(): {
48
43
  adapter: WorkflowInspectorAdapter;
@@ -88,7 +83,7 @@ export function createWorkflowInspectorAdapter(): {
88
83
  }
89
84
 
90
85
  function encodeCbor(value: unknown): ArrayBuffer {
91
- return bufferToArrayBuffer(encodeCborCompat(value as JsonCompatValue));
86
+ return encodeWorkflowInspectorValue(value);
92
87
  }
93
88
 
94
89
  function encodeOptionalCbor(value: unknown): ArrayBuffer | null {