rivetkit 2.0.13 → 2.0.15

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 (111) hide show
  1. package/dist/tsup/actor/errors.cjs +2 -2
  2. package/dist/tsup/actor/errors.d.cts +0 -8
  3. package/dist/tsup/actor/errors.d.ts +0 -8
  4. package/dist/tsup/actor/errors.js +1 -1
  5. package/dist/tsup/{chunk-W5AMA5MD.js → chunk-7MDKUHE4.js} +147 -145
  6. package/dist/tsup/chunk-7MDKUHE4.js.map +1 -0
  7. package/dist/tsup/{chunk-QLCMNNEA.js → chunk-AMLE3HUH.js} +2 -2
  8. package/dist/tsup/{chunk-QVMIMEYZ.cjs → chunk-BPQTS4VW.cjs} +274 -272
  9. package/dist/tsup/chunk-BPQTS4VW.cjs.map +1 -0
  10. package/dist/tsup/{chunk-SDB3B7ZO.js → chunk-BTEDNZSI.js} +2 -2
  11. package/dist/tsup/{chunk-2ALBSAT7.cjs → chunk-C66P3AU6.cjs} +10 -10
  12. package/dist/tsup/{chunk-2ALBSAT7.cjs.map → chunk-C66P3AU6.cjs.map} +1 -1
  13. package/dist/tsup/{chunk-HASQHAZF.cjs → chunk-CJJW2HVJ.cjs} +12 -12
  14. package/dist/tsup/{chunk-HASQHAZF.cjs.map → chunk-CJJW2HVJ.cjs.map} +1 -1
  15. package/dist/tsup/{chunk-XW5IS7NH.js → chunk-FUF4YPTZ.js} +2 -2
  16. package/dist/tsup/{chunk-YPZFLUO6.js → chunk-G64QUEDJ.js} +1 -11
  17. package/dist/tsup/chunk-G64QUEDJ.js.map +1 -0
  18. package/dist/tsup/{chunk-Y5JPI3EV.js → chunk-HMGH3AWC.js} +8 -6
  19. package/dist/tsup/chunk-HMGH3AWC.js.map +1 -0
  20. package/dist/tsup/{chunk-E7CPGIQE.js → chunk-IESTGXF3.js} +3 -3
  21. package/dist/tsup/{chunk-5QGQK44L.cjs → chunk-KSRXX3Z4.cjs} +1 -11
  22. package/dist/tsup/chunk-KSRXX3Z4.cjs.map +1 -0
  23. package/dist/tsup/{chunk-5VER7GR2.cjs → chunk-NRYLXYDB.cjs} +6 -6
  24. package/dist/tsup/{chunk-5VER7GR2.cjs.map → chunk-NRYLXYDB.cjs.map} +1 -1
  25. package/dist/tsup/{chunk-PL46WM3W.cjs → chunk-PBAZ6FDY.cjs} +3 -3
  26. package/dist/tsup/{chunk-PL46WM3W.cjs.map → chunk-PBAZ6FDY.cjs.map} +1 -1
  27. package/dist/tsup/{chunk-V4GFUBOJ.cjs → chunk-QLIJ6I3M.cjs} +3 -3
  28. package/dist/tsup/{chunk-V4GFUBOJ.cjs.map → chunk-QLIJ6I3M.cjs.map} +1 -1
  29. package/dist/tsup/{chunk-HBRZOISM.cjs → chunk-RQRDBVMA.cjs} +8 -8
  30. package/dist/tsup/{chunk-HBRZOISM.cjs.map → chunk-RQRDBVMA.cjs.map} +1 -1
  31. package/dist/tsup/{chunk-PKH3YCMG.cjs → chunk-T7MZMA5D.cjs} +17 -13
  32. package/dist/tsup/chunk-T7MZMA5D.cjs.map +1 -0
  33. package/dist/tsup/{chunk-WFADCZPK.js → chunk-TD5RNAZU.js} +2 -2
  34. package/dist/tsup/{chunk-W76ULFDH.js → chunk-U7ZDMHVJ.js} +104 -17
  35. package/dist/tsup/chunk-U7ZDMHVJ.js.map +1 -0
  36. package/dist/tsup/{chunk-IZKFTUF7.js → chunk-UBBJE54L.js} +3 -3
  37. package/dist/tsup/{chunk-IZKFTUF7.js.map → chunk-UBBJE54L.js.map} +1 -1
  38. package/dist/tsup/{chunk-QBDLQRFN.cjs → chunk-UWGWDHYS.cjs} +321 -234
  39. package/dist/tsup/{chunk-W76ULFDH.js.map → chunk-UWGWDHYS.cjs.map} +1 -1
  40. package/dist/tsup/{chunk-4LAWCEKE.cjs → chunk-WMEMX7ND.cjs} +7 -7
  41. package/dist/tsup/{chunk-4LAWCEKE.cjs.map → chunk-WMEMX7ND.cjs.map} +1 -1
  42. package/dist/tsup/{chunk-T33JFOMB.cjs → chunk-XR6ZIZEK.cjs} +34 -32
  43. package/dist/tsup/chunk-XR6ZIZEK.cjs.map +1 -0
  44. package/dist/tsup/{chunk-YCQL4TJR.js → chunk-YAUIBXG3.js} +4 -4
  45. package/dist/tsup/{chunk-CL67HHVB.js → chunk-ZT77CQXR.js} +11 -7
  46. package/dist/tsup/chunk-ZT77CQXR.js.map +1 -0
  47. package/dist/tsup/client/mod.cjs +10 -10
  48. package/dist/tsup/client/mod.d.cts +2 -2
  49. package/dist/tsup/client/mod.d.ts +2 -2
  50. package/dist/tsup/client/mod.js +9 -9
  51. package/dist/tsup/common/log.cjs +4 -4
  52. package/dist/tsup/common/log.js +3 -3
  53. package/dist/tsup/common/websocket.cjs +5 -5
  54. package/dist/tsup/common/websocket.js +4 -4
  55. package/dist/tsup/{conn-Cc9WHuN4.d.cts → conn-CxCsTz2s.d.cts} +27 -24
  56. package/dist/tsup/{conn-DfPG71FA.d.ts → conn-DhdZYlSX.d.ts} +27 -24
  57. package/dist/tsup/driver-helpers/mod.cjs +6 -6
  58. package/dist/tsup/driver-helpers/mod.d.cts +1 -1
  59. package/dist/tsup/driver-helpers/mod.d.ts +1 -1
  60. package/dist/tsup/driver-helpers/mod.js +5 -5
  61. package/dist/tsup/driver-test-suite/mod.cjs +77 -73
  62. package/dist/tsup/driver-test-suite/mod.cjs.map +1 -1
  63. package/dist/tsup/driver-test-suite/mod.d.cts +1 -1
  64. package/dist/tsup/driver-test-suite/mod.d.ts +1 -1
  65. package/dist/tsup/driver-test-suite/mod.js +17 -13
  66. package/dist/tsup/driver-test-suite/mod.js.map +1 -1
  67. package/dist/tsup/inspector/mod.cjs +7 -7
  68. package/dist/tsup/inspector/mod.d.cts +2 -2
  69. package/dist/tsup/inspector/mod.d.ts +2 -2
  70. package/dist/tsup/inspector/mod.js +6 -6
  71. package/dist/tsup/mod.cjs +11 -11
  72. package/dist/tsup/mod.d.cts +2 -2
  73. package/dist/tsup/mod.d.ts +2 -2
  74. package/dist/tsup/mod.js +10 -10
  75. package/dist/tsup/test/mod.cjs +12 -12
  76. package/dist/tsup/test/mod.d.cts +1 -1
  77. package/dist/tsup/test/mod.d.ts +1 -1
  78. package/dist/tsup/test/mod.js +11 -11
  79. package/dist/tsup/utils.cjs +3 -3
  80. package/dist/tsup/utils.js +2 -2
  81. package/package.json +1 -1
  82. package/src/actor/errors.ts +0 -11
  83. package/src/client/client.ts +4 -8
  84. package/src/client/config.ts +3 -0
  85. package/src/client/utils.ts +8 -3
  86. package/src/common/router.ts +60 -1
  87. package/src/driver-test-suite/mod.ts +5 -1
  88. package/src/drivers/default.ts +5 -7
  89. package/src/drivers/engine/actor-driver.ts +18 -17
  90. package/src/drivers/file-system/manager.ts +5 -1
  91. package/src/manager/router.ts +13 -15
  92. package/src/registry/config.ts +8 -0
  93. package/src/registry/mod.ts +32 -48
  94. package/src/remote-manager-driver/api-endpoints.ts +50 -0
  95. package/src/remote-manager-driver/mod.ts +104 -1
  96. package/src/test/mod.ts +5 -1
  97. package/dist/tsup/chunk-5QGQK44L.cjs.map +0 -1
  98. package/dist/tsup/chunk-CL67HHVB.js.map +0 -1
  99. package/dist/tsup/chunk-PKH3YCMG.cjs.map +0 -1
  100. package/dist/tsup/chunk-QBDLQRFN.cjs.map +0 -1
  101. package/dist/tsup/chunk-QVMIMEYZ.cjs.map +0 -1
  102. package/dist/tsup/chunk-T33JFOMB.cjs.map +0 -1
  103. package/dist/tsup/chunk-W5AMA5MD.js.map +0 -1
  104. package/dist/tsup/chunk-Y5JPI3EV.js.map +0 -1
  105. package/dist/tsup/chunk-YPZFLUO6.js.map +0 -1
  106. /package/dist/tsup/{chunk-QLCMNNEA.js.map → chunk-AMLE3HUH.js.map} +0 -0
  107. /package/dist/tsup/{chunk-SDB3B7ZO.js.map → chunk-BTEDNZSI.js.map} +0 -0
  108. /package/dist/tsup/{chunk-XW5IS7NH.js.map → chunk-FUF4YPTZ.js.map} +0 -0
  109. /package/dist/tsup/{chunk-E7CPGIQE.js.map → chunk-IESTGXF3.js.map} +0 -0
  110. /package/dist/tsup/{chunk-WFADCZPK.js.map → chunk-TD5RNAZU.js.map} +0 -0
  111. /package/dist/tsup/{chunk-YCQL4TJR.js.map → chunk-YAUIBXG3.js.map} +0 -0
@@ -24,9 +24,12 @@ import {
24
24
  WS_PROTOCOL_TRANSPORT,
25
25
  } from "@/common/actor-router-consts";
26
26
  import {
27
+ handleHealthRequest,
28
+ handleMetadataRequest,
27
29
  handleRouteError,
28
30
  handleRouteNotFound,
29
31
  loggerMiddleware,
32
+ type MetadataResponse,
30
33
  } from "@/common/router";
31
34
  import {
32
35
  assertUnreachable,
@@ -207,13 +210,11 @@ function addServerlessRoutes(
207
210
  return await actorDriver.serverlessHandleStart(c);
208
211
  });
209
212
 
210
- router.get("/health", (c) => {
211
- return c.json({
212
- status: "ok",
213
- runtime: "rivetkit",
214
- version: VERSION,
215
- });
216
- });
213
+ router.get("/health", (c) => handleHealthRequest(c));
214
+
215
+ router.get("/metadata", (c) =>
216
+ handleMetadataRequest(c, registryConfig, runConfig),
217
+ );
217
218
  }
218
219
 
219
220
  function addManagerRoutes(
@@ -642,14 +643,11 @@ function addManagerRoutes(
642
643
  });
643
644
  }
644
645
 
645
- router.get("/health", (c) => {
646
- return c.json({
647
- status: "ok",
648
- rivetkit: {
649
- version: VERSION,
650
- },
651
- });
652
- });
646
+ router.get("/health", (c) => handleHealthRequest(c));
647
+
648
+ router.get("/metadata", (c) =>
649
+ handleMetadataRequest(c, registryConfig, runConfig),
650
+ );
653
651
 
654
652
  managerDriver.modifyManagerRouter?.(
655
653
  registryConfig,
@@ -30,3 +30,11 @@ export type RegistryConfigInput<A extends RegistryActors> = Omit<
30
30
  z.input<typeof RegistryConfigSchema>,
31
31
  "use"
32
32
  > & { use: A };
33
+
34
+ export function buildActorNames(
35
+ registryConfig: RegistryConfig,
36
+ ): Record<string, { metadata: Record<string, any> }> {
37
+ return Object.fromEntries(
38
+ Object.keys(registryConfig.use).map((name) => [name, { metadata: {} }]),
39
+ );
40
+ }
@@ -1,5 +1,6 @@
1
1
  import invariant from "invariant";
2
2
  import { type Client, createClientWithDriver } from "@/client/client";
3
+ import type { ClientConfig } from "@/client/config";
3
4
  import { configureBaseLogger, configureDefaultLogger } from "@/common/log";
4
5
  import type { ActorDriver } from "@/driver-helpers/mod";
5
6
  import { chooseDefaultDriver } from "@/drivers/default";
@@ -10,6 +11,12 @@ import {
10
11
  isInspectorEnabled,
11
12
  } from "@/inspector/utils";
12
13
  import { createManagerRouter } from "@/manager/router";
14
+ import {
15
+ getDatacenters,
16
+ type RunnerConfigRequest,
17
+ updateRunnerConfig,
18
+ } from "@/remote-manager-driver/api-endpoints";
19
+ import { getEndpoint } from "@/remote-manager-driver/api-utils";
13
20
  import pkg from "../../package.json" with { type: "json" };
14
21
  import {
15
22
  type RegistryActors,
@@ -154,7 +161,7 @@ export class Registry<A extends RegistryActors> {
154
161
  console.log();
155
162
  console.log(` RivetKit ${pkg.version} (${displayInfo.name})`);
156
163
  if (!config.disableDefaultServer) {
157
- console.log(` - Endpoint: ${config.endpoint}`);
164
+ console.log(` - Endpoint: ${getEndpoint(config)}`);
158
165
  } else if (config.overrideServerAddress) {
159
166
  console.log(` - Endpoint: ${config.overrideServerAddress}`);
160
167
  }
@@ -231,32 +238,32 @@ async function configureServerlessRunner(config: RunnerConfig): Promise<void> {
231
238
  ? config.autoConfigureServerless
232
239
  : {};
233
240
 
234
- // Make the request to fetch all datacenters
235
- const dcsUrl = `${config.endpoint}/datacenters`;
241
+ // Create a ClientConfig from RunnerConfig for API calls
242
+ const clientConfig: ClientConfig = {
243
+ endpoint: config.endpoint,
244
+ token: config.token,
245
+ namespace: config.namespace,
246
+ runnerName: config.runnerName,
247
+ encoding: config.encoding,
248
+ transport: config.transport,
249
+ headers: config.headers,
250
+ getUpgradeWebSocket: config.getUpgradeWebSocket,
251
+ disableHealthCheck: true, // We don't need health check for this operation
252
+ };
236
253
 
254
+ // Fetch all datacenters
237
255
  logger().debug({
238
256
  msg: "fetching datacenters",
239
- url: dcsUrl,
257
+ endpoint: config.endpoint,
240
258
  });
241
-
242
- const dcsResponse = await fetch(dcsUrl, {
243
- headers: {
244
- ...(config.token ? { Authorization: `Bearer ${config.token}` } : {}),
245
- },
246
- });
247
-
248
- if (!dcsResponse.ok) {
249
- const errorText = await dcsResponse.text();
250
- throw new Error(
251
- `failed to configure serverless runner: ${dcsResponse.status} ${dcsResponse.statusText} - ${errorText}`,
252
- );
253
- }
254
-
255
- const dcsRes = (await dcsResponse.json()) as {
256
- datacenters: { name: string }[];
257
- };
259
+ const dcsRes = await getDatacenters(clientConfig);
258
260
 
259
261
  // Build the request body
262
+ logger().debug({
263
+ msg: "configuring serverless runner",
264
+ runnerName: config.runnerName,
265
+ namespace: config.namespace,
266
+ });
260
267
  const serverlessConfig = {
261
268
  serverless: {
262
269
  url:
@@ -271,35 +278,12 @@ async function configureServerlessRunner(config: RunnerConfig): Promise<void> {
271
278
  customConfig.slotsPerRunner ?? config.totalSlots ?? 1000,
272
279
  },
273
280
  };
274
- const requestBody = Object.fromEntries(
275
- dcsRes.datacenters.map((dc) => [dc.name, serverlessConfig]),
276
- );
277
-
278
- // Make the request to configure the serverless runner
279
- const configUrl = `${config.endpoint}/runner-configs/${config.runnerName}?namespace=${config.namespace}`;
280
-
281
- logger().debug({
282
- msg: "configuring serverless runner",
283
- url: configUrl,
284
- config: serverlessConfig.serverless,
281
+ await updateRunnerConfig(clientConfig, config.runnerName, {
282
+ datacenters: Object.fromEntries(
283
+ dcsRes.datacenters.map((dc) => [dc.name, serverlessConfig]),
284
+ ),
285
285
  });
286
286
 
287
- const response = await fetch(configUrl, {
288
- method: "PUT",
289
- headers: {
290
- "Content-Type": "application/json",
291
- ...(config.token ? { Authorization: `Bearer ${config.token}` } : {}),
292
- },
293
- body: JSON.stringify(requestBody),
294
- });
295
-
296
- if (!response.ok) {
297
- const errorText = await response.text();
298
- throw new Error(
299
- `failed to configure serverless runner: ${response.status} ${response.statusText} - ${errorText}`,
300
- );
301
- }
302
-
303
287
  logger().info({
304
288
  msg: "serverless runner configured successfully",
305
289
  runnerName: config.runnerName,
@@ -1,5 +1,6 @@
1
1
  import { serializeActorKey } from "@/actor/keys";
2
2
  import type { ClientConfig } from "@/client/client";
3
+ import type { MetadataResponse } from "@/common/router";
3
4
  import type {
4
5
  ActorsCreateRequest,
5
6
  ActorsCreateResponse,
@@ -75,3 +76,52 @@ export async function destroyActor(
75
76
  `/actors/${encodeURIComponent(actorId)}`,
76
77
  );
77
78
  }
79
+
80
+ // MARK: Get metadata
81
+ export async function getMetadata(
82
+ config: ClientConfig,
83
+ ): Promise<MetadataResponse> {
84
+ return apiCall<never, MetadataResponse>(config, "GET", `/metadata`);
85
+ }
86
+
87
+ // MARK: Get datacenters
88
+ export interface DatacentersResponse {
89
+ datacenters: { name: string }[];
90
+ }
91
+
92
+ export async function getDatacenters(
93
+ config: ClientConfig,
94
+ ): Promise<DatacentersResponse> {
95
+ return apiCall<never, DatacentersResponse>(config, "GET", `/datacenters`);
96
+ }
97
+
98
+ // MARK: Update runner config
99
+ export interface RunnerConfigRequest {
100
+ datacenters: Record<
101
+ string,
102
+ {
103
+ serverless: {
104
+ url: string;
105
+ headers: Record<string, string>;
106
+ max_runners: number;
107
+ min_runners: number;
108
+ request_lifespan: number;
109
+ runners_margin: number;
110
+ slots_per_runner: number;
111
+ };
112
+ }
113
+ >;
114
+ }
115
+
116
+ export async function updateRunnerConfig(
117
+ config: ClientConfig,
118
+ runnerName: string,
119
+ request: RunnerConfigRequest,
120
+ ): Promise<void> {
121
+ return apiCall<RunnerConfigRequest, void>(
122
+ config,
123
+ "PUT",
124
+ `/runner-configs/${runnerName}`,
125
+ request,
126
+ );
127
+ }
@@ -4,7 +4,7 @@ import invariant from "invariant";
4
4
  import { deserializeActorKey, serializeActorKey } from "@/actor/keys";
5
5
  import { generateRandomString } from "@/actor/utils";
6
6
  import type { ClientConfig } from "@/client/client";
7
- import { noopNext } from "@/common/utils";
7
+ import { noopNext, stringifyError } from "@/common/utils";
8
8
  import type {
9
9
  ActorOutput,
10
10
  CreateInput,
@@ -27,6 +27,7 @@ import {
27
27
  destroyActor,
28
28
  getActor,
29
29
  getActorByKey,
30
+ getMetadata,
30
31
  getOrCreateActor,
31
32
  } from "./api-endpoints";
32
33
  import { EngineApiError, getEndpoint } from "./api-utils";
@@ -47,11 +48,68 @@ import { createWebSocketProxy } from "./ws-proxy";
47
48
  // };
48
49
  // })();
49
50
 
51
+ // Global cache to store metadata check promises for each endpoint
52
+ const metadataCheckCache = new Map<string, Promise<void>>();
53
+
50
54
  export class RemoteManagerDriver implements ManagerDriver {
51
55
  #config: ClientConfig;
56
+ #metadataPromise: Promise<void> | undefined;
52
57
 
53
58
  constructor(runConfig: ClientConfig) {
54
59
  this.#config = runConfig;
60
+
61
+ // Perform metadata check if enabled
62
+ if (!runConfig.disableHealthCheck) {
63
+ this.#metadataPromise = this.#performMetadataCheck(runConfig);
64
+ this.#metadataPromise.catch((error) => {
65
+ logger().error({
66
+ msg: "metadata check failed",
67
+ error: error instanceof Error ? error.message : String(error),
68
+ });
69
+ });
70
+ }
71
+ }
72
+
73
+ async #performMetadataCheck(config: ClientConfig): Promise<void> {
74
+ const endpoint = getEndpoint(config);
75
+
76
+ // Check if metadata check is already in progress or completed for this endpoint
77
+ const existingPromise = metadataCheckCache.get(endpoint);
78
+ if (existingPromise) {
79
+ return existingPromise;
80
+ }
81
+
82
+ // Create and store the promise immediately to prevent racing requests
83
+ const metadataCheckPromise = (async () => {
84
+ try {
85
+ const metadataData = await getMetadata(config);
86
+
87
+ if (metadataData.clientEndpoint) {
88
+ logger().info({
89
+ msg: "received new client endpoint from metadata",
90
+ endpoint: metadataData.clientEndpoint,
91
+ });
92
+ this.#config.endpoint = metadataData.clientEndpoint;
93
+ }
94
+
95
+ // Log successful metadata check with runtime and version info
96
+ logger().info({
97
+ msg: "connected to rivetkit manager",
98
+ runtime: metadataData.runtime,
99
+ version: metadataData.version,
100
+ runner: metadataData.runner,
101
+ });
102
+ } catch (error) {
103
+ logger().error({
104
+ msg: "failed to connect to metadata endpoint",
105
+ endpoint,
106
+ error: stringifyError(error),
107
+ });
108
+ }
109
+ })();
110
+
111
+ metadataCheckCache.set(endpoint, metadataCheckPromise);
112
+ return metadataCheckPromise;
55
113
  }
56
114
 
57
115
  async getForId({
@@ -59,6 +117,11 @@ export class RemoteManagerDriver implements ManagerDriver {
59
117
  name,
60
118
  actorId,
61
119
  }: GetForIdInput): Promise<ActorOutput | undefined> {
120
+ // Wait for metadata check to complete if in progress
121
+ if (this.#metadataPromise) {
122
+ await this.#metadataPromise;
123
+ }
124
+
62
125
  // Fetch from API if not in cache
63
126
  const response = await getActor(this.#config, name, actorId);
64
127
  const actor = response.actors[0];
@@ -91,6 +154,11 @@ export class RemoteManagerDriver implements ManagerDriver {
91
154
  name,
92
155
  key,
93
156
  }: GetWithKeyInput): Promise<ActorOutput | undefined> {
157
+ // Wait for metadata check to complete if in progress
158
+ if (this.#metadataPromise) {
159
+ await this.#metadataPromise;
160
+ }
161
+
94
162
  logger().debug({ msg: "getWithKey: searching for actor", name, key });
95
163
 
96
164
  // If not in local cache, fetch by key from API
@@ -128,6 +196,11 @@ export class RemoteManagerDriver implements ManagerDriver {
128
196
  async getOrCreateWithKey(
129
197
  input: GetOrCreateWithKeyInput,
130
198
  ): Promise<ActorOutput> {
199
+ // Wait for metadata check to complete if in progress
200
+ if (this.#metadataPromise) {
201
+ await this.#metadataPromise;
202
+ }
203
+
131
204
  const { c, name, key, input: actorInput, region } = input;
132
205
 
133
206
  logger().info({
@@ -169,6 +242,11 @@ export class RemoteManagerDriver implements ManagerDriver {
169
242
  key,
170
243
  input,
171
244
  }: CreateInput): Promise<ActorOutput> {
245
+ // Wait for metadata check to complete if in progress
246
+ if (this.#metadataPromise) {
247
+ await this.#metadataPromise;
248
+ }
249
+
172
250
  logger().info({ msg: "creating actor via engine api", name, key });
173
251
 
174
252
  // Create actor via engine API
@@ -191,6 +269,11 @@ export class RemoteManagerDriver implements ManagerDriver {
191
269
  }
192
270
 
193
271
  async destroyActor(actorId: string): Promise<void> {
272
+ // Wait for metadata check to complete if in progress
273
+ if (this.#metadataPromise) {
274
+ await this.#metadataPromise;
275
+ }
276
+
194
277
  logger().info({ msg: "destroying actor via engine api", actorId });
195
278
 
196
279
  await destroyActor(this.#config, actorId);
@@ -199,6 +282,11 @@ export class RemoteManagerDriver implements ManagerDriver {
199
282
  }
200
283
 
201
284
  async sendRequest(actorId: string, actorRequest: Request): Promise<Response> {
285
+ // Wait for metadata check to complete if in progress
286
+ if (this.#metadataPromise) {
287
+ await this.#metadataPromise;
288
+ }
289
+
202
290
  return await sendHttpRequestToActor(this.#config, actorId, actorRequest);
203
291
  }
204
292
 
@@ -210,6 +298,11 @@ export class RemoteManagerDriver implements ManagerDriver {
210
298
  connId?: string,
211
299
  connToken?: string,
212
300
  ): Promise<UniversalWebSocket> {
301
+ // Wait for metadata check to complete if in progress
302
+ if (this.#metadataPromise) {
303
+ await this.#metadataPromise;
304
+ }
305
+
213
306
  return await openWebSocketToActor(
214
307
  this.#config,
215
308
  path,
@@ -226,6 +319,11 @@ export class RemoteManagerDriver implements ManagerDriver {
226
319
  actorRequest: Request,
227
320
  actorId: string,
228
321
  ): Promise<Response> {
322
+ // Wait for metadata check to complete if in progress
323
+ if (this.#metadataPromise) {
324
+ await this.#metadataPromise;
325
+ }
326
+
229
327
  return await sendHttpRequestToActor(this.#config, actorId, actorRequest);
230
328
  }
231
329
 
@@ -238,6 +336,11 @@ export class RemoteManagerDriver implements ManagerDriver {
238
336
  connId?: string,
239
337
  connToken?: string,
240
338
  ): Promise<Response> {
339
+ // Wait for metadata check to complete if in progress
340
+ if (this.#metadataPromise) {
341
+ await this.#metadataPromise;
342
+ }
343
+
241
344
  const upgradeWebSocket = this.#config.getUpgradeWebSocket?.();
242
345
  invariant(upgradeWebSocket, "missing getUpgradeWebSocket");
243
346
 
package/src/test/mod.ts CHANGED
@@ -2,6 +2,7 @@ import { createServer } from "node:net";
2
2
  import { serve as honoServe, type ServerType } from "@hono/node-server";
3
3
  import { createNodeWebSocket } from "@hono/node-ws";
4
4
  import { type TestContext, vi } from "vitest";
5
+ import { ClientConfigSchema } from "@/client/config";
5
6
  import { type Client, createClient } from "@/client/mod";
6
7
  import { chooseDefaultDriver } from "@/drivers/default";
7
8
  import { createFileSystemOrMemoryDriver } from "@/drivers/file-system/mod";
@@ -31,7 +32,10 @@ function serve(registry: Registry<any>, inputConfig?: InputConfig): ServerType {
31
32
  const runConfig = RunnerConfigSchema.parse(inputConfig);
32
33
  const driver = inputConfig.driver ?? createFileSystemOrMemoryDriver(false);
33
34
  const managerDriver = driver.manager(registry.config, config);
34
- const client = createClientWithDriver(managerDriver);
35
+ const client = createClientWithDriver(
36
+ managerDriver,
37
+ ClientConfigSchema.parse({}),
38
+ );
35
39
  configureInspectorAccessToken(config, managerDriver);
36
40
  const { router } = createManagerRouter(
37
41
  registry.config,
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/Users/nathan/rivetkit/packages/rivetkit/dist/tsup/chunk-5QGQK44L.cjs","../../src/actor/errors.ts"],"names":[],"mappings":"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A;AACb,IAAA;AACC,MAAA;AACA,MAAA;AACA,MAAA;AACe,MAAA;AAChB,IAAA;AACkB,IAAA;AACnB,EAAA;AACD;AAGO;AACQ,EAAA;AACb,IAAA;AACC,MAAA;AACA,MAAA;AACA,MAAA;AACe,MAAA;AAChB,IAAA;AACkB,IAAA;AACnB,EAAA;AACD;AAEO;AACQ,EAAA;AACb,IAAA;AACC,MAAA;AACA,MAAA;AACA,MAAA;AACe,MAAA;AAChB,IAAA;AACkB,IAAA;AACnB,EAAA;AACD;AAEO;AACuB,EAAA;AACX,IAAA;AACR,MAAA;AACR,IAAA;AACiB,IAAA;AACnB,EAAA;AACD;AAEO;AACQ,EAAA;AACe,IAAA;AACV,IAAA;AACnB,EAAA;AACD;ADvFiC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/Users/nathan/rivetkit/packages/rivetkit/dist/tsup/chunk-5QGQK44L.cjs","sourcesContent":[null,"import type { DeconstructedError } from \"@/common/utils\";\n\nexport const INTERNAL_ERROR_CODE = \"internal_error\";\nexport const INTERNAL_ERROR_DESCRIPTION =\n\t\"Internal error. Read the server logs for more details.\";\nexport type InternalErrorMetadata = {};\n\nexport const USER_ERROR_CODE = \"user_error\";\n\ninterface ActorErrorOptions extends ErrorOptions {\n\t/** Error data can safely be serialized in a response to the client. */\n\tpublic?: boolean;\n\t/** Metadata associated with this error. This will be sent to clients. */\n\tmetadata?: unknown;\n}\n\nexport class ActorError extends Error {\n\t__type = \"ActorError\";\n\n\tpublic public: boolean;\n\tpublic metadata?: unknown;\n\tpublic statusCode = 500;\n\tpublic readonly group: string;\n\tpublic readonly code: string;\n\n\tpublic static isActorError(\n\t\terror: unknown,\n\t): error is ActorError | DeconstructedError {\n\t\treturn (\n\t\t\ttypeof error === \"object\" &&\n\t\t\t(error as ActorError | DeconstructedError).__type === \"ActorError\"\n\t\t);\n\t}\n\n\tconstructor(\n\t\tgroup: string,\n\t\tcode: string,\n\t\tmessage: string,\n\t\topts?: ActorErrorOptions,\n\t) {\n\t\tsuper(message, { cause: opts?.cause });\n\t\tthis.group = group;\n\t\tthis.code = code;\n\t\tthis.public = opts?.public ?? false;\n\t\tthis.metadata = opts?.metadata;\n\n\t\t// Set status code based on error type\n\t\tif (opts?.public) {\n\t\t\tthis.statusCode = 400; // Bad request for public errors\n\t\t}\n\t}\n\n\ttoString() {\n\t\t// Force stringify to return the message\n\t\treturn this.message;\n\t}\n\n\t/**\n\t * Serialize error for HTTP response\n\t */\n\tserializeForHttp() {\n\t\treturn {\n\t\t\ttype: this.code,\n\t\t\tmessage: this.message,\n\t\t\tmetadata: this.metadata,\n\t\t};\n\t}\n}\n\nexport class InternalError extends ActorError {\n\tconstructor(message: string) {\n\t\tsuper(\"actor\", INTERNAL_ERROR_CODE, message);\n\t}\n}\n\nexport class Unreachable extends InternalError {\n\tconstructor(x: never) {\n\t\tsuper(`Unreachable case: ${x}`);\n\t}\n}\n\nexport class StateNotEnabled extends ActorError {\n\tconstructor() {\n\t\tsuper(\n\t\t\t\"actor\",\n\t\t\t\"state_not_enabled\",\n\t\t\t\"State not enabled. Must implement `createState` or `state` to use state. (https://www.rivet.dev/docs/actors/state/#initializing-state)\",\n\t\t);\n\t}\n}\n\nexport class ConnStateNotEnabled extends ActorError {\n\tconstructor() {\n\t\tsuper(\n\t\t\t\"actor\",\n\t\t\t\"conn_state_not_enabled\",\n\t\t\t\"Connection state not enabled. Must implement `createConnectionState` or `connectionState` to use connection state. (https://www.rivet.dev/docs/actors/connections/#connection-state)\",\n\t\t);\n\t}\n}\n\nexport class VarsNotEnabled extends ActorError {\n\tconstructor() {\n\t\tsuper(\n\t\t\t\"actor\",\n\t\t\t\"vars_not_enabled\",\n\t\t\t\"Variables not enabled. Must implement `createVars` or `vars` to use state. (https://www.rivet.dev/docs/actors/ephemeral-variables/#initializing-variables)\",\n\t\t);\n\t}\n}\n\nexport class ActionTimedOut extends ActorError {\n\tconstructor() {\n\t\tsuper(\n\t\t\t\"action\",\n\t\t\t\"timed_out\",\n\t\t\t\"Action timed out. This can be increased with: `actor({ options: { action: { timeout: ... } } })`\",\n\t\t\t{ public: true },\n\t\t);\n\t}\n}\n\nexport class ActionNotFound extends ActorError {\n\tconstructor(name: string) {\n\t\tsuper(\n\t\t\t\"action\",\n\t\t\t\"not_found\",\n\t\t\t`Action '${name}' not found. Validate the action exists on your actor.`,\n\t\t\t{ public: true },\n\t\t);\n\t}\n}\n\nexport class InvalidEncoding extends ActorError {\n\tconstructor(format?: string) {\n\t\tsuper(\n\t\t\t\"encoding\",\n\t\t\t\"invalid\",\n\t\t\t`Invalid encoding \\`${format}\\`. (https://www.rivet.dev/docs/actors/clients/#actor-client)`,\n\t\t\t{\n\t\t\t\tpublic: true,\n\t\t\t},\n\t\t);\n\t}\n}\n\nexport class ConnNotFound extends ActorError {\n\tconstructor(id?: string) {\n\t\tsuper(\"connection\", \"not_found\", `Connection not found for ID: ${id}`, {\n\t\t\tpublic: true,\n\t\t});\n\t}\n}\n\nexport class IncorrectConnToken extends ActorError {\n\tconstructor() {\n\t\tsuper(\"connection\", \"incorrect_token\", \"Incorrect connection token.\", {\n\t\t\tpublic: true,\n\t\t});\n\t}\n}\n\nexport class MessageTooLong extends ActorError {\n\tconstructor() {\n\t\tsuper(\n\t\t\t\"message\",\n\t\t\t\"too_long\",\n\t\t\t\"Message too long. This can be configured with: `registry.start({ maxIncomingMessageSize: ... })`\",\n\t\t\t{ public: true },\n\t\t);\n\t}\n}\n\nexport class MalformedMessage extends ActorError {\n\tconstructor(cause?: unknown) {\n\t\tsuper(\"message\", \"malformed\", `Malformed message: ${cause}`, {\n\t\t\tpublic: true,\n\t\t\tcause,\n\t\t});\n\t}\n}\n\nexport interface InvalidStateTypeOptions {\n\tpath?: unknown;\n}\n\nexport class InvalidStateType extends ActorError {\n\tconstructor(opts?: InvalidStateTypeOptions) {\n\t\tlet msg = \"\";\n\t\tif (opts?.path) {\n\t\t\tmsg += `Attempted to set invalid state at path \\`${opts.path}\\`.`;\n\t\t} else {\n\t\t\tmsg += \"Attempted to set invalid state.\";\n\t\t}\n\t\tmsg +=\n\t\t\t\" Valid types include: null, undefined, boolean, string, number, BigInt, Date, RegExp, Error, typed arrays (Uint8Array, Int8Array, Float32Array, etc.), Map, Set, Array, and plain objects. (https://www.rivet.dev/docs/actors/state/#limitations)\";\n\t\tsuper(\"state\", \"invalid_type\", msg);\n\t}\n}\n\nexport class Unsupported extends ActorError {\n\tconstructor(feature: string) {\n\t\tsuper(\"feature\", \"unsupported\", `Unsupported feature: ${feature}`);\n\t}\n}\n\n/**\n * Options for the UserError class.\n */\nexport interface UserErrorOptions extends ErrorOptions {\n\t/**\n\t * Machine readable code for this error. Useful for catching different types of errors in try-catch.\n\t */\n\tcode?: string;\n\n\t/**\n\t * Additional metadata related to the error. Useful for understanding context about the error.\n\t */\n\tmetadata?: unknown;\n}\n\n/** Error that can be safely returned to the user. */\nexport class UserError extends ActorError {\n\t/**\n\t * Constructs a new UserError instance.\n\t *\n\t * @param message - The error message to be displayed.\n\t * @param opts - Optional parameters for the error, including a machine-readable code and additional metadata.\n\t */\n\tconstructor(message: string, opts?: UserErrorOptions) {\n\t\tsuper(\"user\", opts?.code ?? USER_ERROR_CODE, message, {\n\t\t\tpublic: true,\n\t\t\tmetadata: opts?.metadata,\n\t\t});\n\t}\n}\n\nexport class InvalidQueryJSON extends ActorError {\n\tconstructor(error?: unknown) {\n\t\tsuper(\"request\", \"invalid_query_json\", `Invalid query JSON: ${error}`, {\n\t\t\tpublic: true,\n\t\t\tcause: error,\n\t\t});\n\t}\n}\n\nexport class InvalidRequest extends ActorError {\n\tconstructor(error?: unknown) {\n\t\tsuper(\"request\", \"invalid\", `Invalid request: ${error}`, {\n\t\t\tpublic: true,\n\t\t\tcause: error,\n\t\t});\n\t}\n}\n\nexport class ActorNotFound extends ActorError {\n\tconstructor(identifier?: string) {\n\t\tsuper(\n\t\t\t\"actor\",\n\t\t\t\"not_found\",\n\t\t\tidentifier\n\t\t\t\t? `Actor not found: ${identifier} (https://www.rivet.dev/docs/actors/clients/#actor-client)`\n\t\t\t\t: \"Actor not found (https://www.rivet.dev/docs/actors/clients/#actor-client)\",\n\t\t\t{ public: true },\n\t\t);\n\t}\n}\n\nexport class ActorAlreadyExists extends ActorError {\n\tconstructor(name: string, key: string[]) {\n\t\tsuper(\n\t\t\t\"actor\",\n\t\t\t\"already_exists\",\n\t\t\t`Actor already exists with name '${name}' and key '${JSON.stringify(key)}' (https://www.rivet.dev/docs/actors/clients/#actor-client)`,\n\t\t\t{ public: true },\n\t\t);\n\t}\n}\n\nexport class ProxyError extends ActorError {\n\tconstructor(operation: string, error?: unknown) {\n\t\tsuper(\n\t\t\t\"proxy\",\n\t\t\t\"error\",\n\t\t\t`Error proxying ${operation}, this is likely an internal error: ${error}`,\n\t\t\t{\n\t\t\t\tpublic: true,\n\t\t\t\tcause: error,\n\t\t\t},\n\t\t);\n\t}\n}\n\nexport class InvalidActionRequest extends ActorError {\n\tconstructor(message: string) {\n\t\tsuper(\"action\", \"invalid_request\", message, { public: true });\n\t}\n}\n\nexport class InvalidParams extends ActorError {\n\tconstructor(message: string) {\n\t\tsuper(\"params\", \"invalid\", message, { public: true });\n\t}\n}\n\nexport class Unauthorized extends ActorError {\n\tconstructor(message?: string) {\n\t\tsuper(\n\t\t\t\"auth\",\n\t\t\t\"unauthorized\",\n\t\t\tmessage ??\n\t\t\t\t\"Unauthorized. Access denied. (https://www.rivet.dev/docs/actors/authentication/)\",\n\t\t\t{\n\t\t\t\tpublic: true,\n\t\t\t},\n\t\t);\n\t\tthis.statusCode = 401;\n\t}\n}\n\nexport class Forbidden extends ActorError {\n\tconstructor(message?: string, opts?: { metadata?: unknown }) {\n\t\tsuper(\n\t\t\t\"auth\",\n\t\t\t\"forbidden\",\n\t\t\tmessage ??\n\t\t\t\t\"Forbidden. Access denied. (https://www.rivet.dev/docs/actors/authentication/)\",\n\t\t\t{\n\t\t\t\tpublic: true,\n\t\t\t\tmetadata: opts?.metadata,\n\t\t\t},\n\t\t);\n\t\tthis.statusCode = 403;\n\t}\n}\n\nexport class DatabaseNotEnabled extends ActorError {\n\tconstructor() {\n\t\tsuper(\n\t\t\t\"database\",\n\t\t\t\"not_enabled\",\n\t\t\t\"Database not enabled. Must implement `database` to use database.\",\n\t\t);\n\t}\n}\n\nexport class FetchHandlerNotDefined extends ActorError {\n\tconstructor() {\n\t\tsuper(\n\t\t\t\"handler\",\n\t\t\t\"fetch_not_defined\",\n\t\t\t\"Raw HTTP handler not defined. Actor must implement `onFetch` to handle raw HTTP requests. (https://www.rivet.dev/docs/actors/fetch-and-websocket-handler/)\",\n\t\t\t{ public: true },\n\t\t);\n\t\tthis.statusCode = 404;\n\t}\n}\n\nexport class WebSocketHandlerNotDefined extends ActorError {\n\tconstructor() {\n\t\tsuper(\n\t\t\t\"handler\",\n\t\t\t\"websocket_not_defined\",\n\t\t\t\"Raw WebSocket handler not defined. Actor must implement `onWebSocket` to handle raw WebSocket connections. (https://www.rivet.dev/docs/actors/fetch-and-websocket-handler/)\",\n\t\t\t{ public: true },\n\t\t);\n\t\tthis.statusCode = 404;\n\t}\n}\n\nexport class InvalidFetchResponse extends ActorError {\n\tconstructor() {\n\t\tsuper(\n\t\t\t\"handler\",\n\t\t\t\"invalid_fetch_response\",\n\t\t\t\"Actor's onFetch handler must return a Response object. Returning void/undefined is not allowed. (https://www.rivet.dev/docs/actors/fetch-and-websocket-handler/)\",\n\t\t\t{ public: true },\n\t\t);\n\t\tthis.statusCode = 500;\n\t}\n}\n\n// Manager-specific errors\nexport class MissingActorHeader extends ActorError {\n\tconstructor() {\n\t\tsuper(\n\t\t\t\"request\",\n\t\t\t\"missing_actor_header\",\n\t\t\t\"Missing x-rivet-actor header when x-rivet-target=actor\",\n\t\t\t{ public: true },\n\t\t);\n\t\tthis.statusCode = 400;\n\t}\n}\n\nexport class WebSocketsNotEnabled extends ActorError {\n\tconstructor() {\n\t\tsuper(\n\t\t\t\"driver\",\n\t\t\t\"websockets_not_enabled\",\n\t\t\t\"WebSockets are not enabled for this driver\",\n\t\t\t{ public: true },\n\t\t);\n\t\tthis.statusCode = 400;\n\t}\n}\n\nexport class FeatureNotImplemented extends ActorError {\n\tconstructor(feature: string) {\n\t\tsuper(\"feature\", \"not_implemented\", `${feature} is not implemented`, {\n\t\t\tpublic: true,\n\t\t});\n\t\tthis.statusCode = 501;\n\t}\n}\n\nexport class RouteNotFound extends ActorError {\n\tconstructor() {\n\t\tsuper(\"route\", \"not_found\", \"Route not found\", { public: true });\n\t\tthis.statusCode = 404;\n\t}\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/test/mod.ts","../../src/test/config.ts","../../src/test/log.ts"],"sourcesContent":["import { createServer } from \"node:net\";\nimport { serve as honoServe, type ServerType } from \"@hono/node-server\";\nimport { createNodeWebSocket } from \"@hono/node-ws\";\nimport { type TestContext, vi } from \"vitest\";\nimport { type Client, createClient } from \"@/client/mod\";\nimport { chooseDefaultDriver } from \"@/drivers/default\";\nimport { createFileSystemOrMemoryDriver } from \"@/drivers/file-system/mod\";\nimport {\n\tconfigureInspectorAccessToken,\n\tgetInspectorUrl,\n} from \"@/inspector/utils\";\nimport { createManagerRouter } from \"@/manager/router\";\nimport { createClientWithDriver } from \"@/mod\";\nimport type { Registry } from \"@/registry/mod\";\nimport { RunnerConfigSchema } from \"@/registry/run-config\";\nimport { ConfigSchema, type InputConfig } from \"./config\";\nimport { logger } from \"./log\";\n\nfunction serve(registry: Registry<any>, inputConfig?: InputConfig): ServerType {\n\t// Configure default configuration\n\tinputConfig ??= {};\n\n\tconst config = ConfigSchema.parse(inputConfig);\n\n\tlet upgradeWebSocket: any;\n\tif (!config.getUpgradeWebSocket) {\n\t\tconfig.getUpgradeWebSocket = () => upgradeWebSocket!;\n\t}\n\n\t// Create router\n\tconst runConfig = RunnerConfigSchema.parse(inputConfig);\n\tconst driver = inputConfig.driver ?? createFileSystemOrMemoryDriver(false);\n\tconst managerDriver = driver.manager(registry.config, config);\n\tconst client = createClientWithDriver(managerDriver);\n\tconfigureInspectorAccessToken(config, managerDriver);\n\tconst { router } = createManagerRouter(\n\t\tregistry.config,\n\t\trunConfig,\n\t\tmanagerDriver,\n\t\tdriver,\n\t\tclient,\n\t);\n\n\t// Inject WebSocket\n\tconst nodeWebSocket = createNodeWebSocket({ app: router });\n\tupgradeWebSocket = nodeWebSocket.upgradeWebSocket;\n\n\tconst server = honoServe({\n\t\tfetch: router.fetch,\n\t\thostname: config.hostname,\n\t\tport: config.port,\n\t});\n\tnodeWebSocket.injectWebSocket(server);\n\n\tlogger().info({\n\t\tmsg: \"rivetkit started\",\n\t\thostname: config.hostname,\n\t\tport: config.port,\n\t\tdefinitions: Object.keys(registry.config.use).length,\n\t});\n\n\treturn server;\n}\n\nexport interface SetupTestResult<A extends Registry<any>> {\n\tclient: Client<A>;\n\tmockDriver: {\n\t\tactorDriver: {\n\t\t\tsetCreateVarsContext: (ctx: any) => void;\n\t\t};\n\t};\n}\n\n// Must use `TestContext` since global hooks do not work when running concurrently\nexport async function setupTest<A extends Registry<any>>(\n\tc: TestContext,\n\tregistry: A,\n): Promise<SetupTestResult<A>> {\n\tvi.useFakeTimers();\n\n\t// Set up mock driver for testing createVars context\n\tconst mockDriverContext: any = {};\n\tconst setDriverContextFn = (ctx: any) => {\n\t\tmockDriverContext.current = ctx;\n\t};\n\n\t// We don't need to modify the driver context anymore since we're testing with the actual context\n\n\t// Start server with a random port\n\tconst port = await getPort();\n\tconst server = serve(registry, { port });\n\tc.onTestFinished(\n\t\tasync () => await new Promise((resolve) => server.close(() => resolve())),\n\t);\n\n\tthrow \"TODO: Fix engine port\";\n\n\t// // TODO: Figure out how to make this the correct endpoint\n\t// // Create client\n\t// const client = createClient<A>(`http://127.0.0.1:${port}`);\n\t// c.onTestFinished(async () => await client.dispose());\n\t//\n\t// return {\n\t// \tclient,\n\t// \tmockDriver: {\n\t// \t\tactorDriver: {\n\t// \t\t\tsetCreateVarsContext: setDriverContextFn,\n\t// \t\t},\n\t// \t},\n\t// };\n}\n\nexport async function getPort(): Promise<number> {\n\t// Pick random port between 10000 and 65535 (avoiding well-known and registered ports)\n\tconst MIN_PORT = 10000;\n\tconst MAX_PORT = 65535;\n\tconst getRandomPort = () =>\n\t\tMath.floor(Math.random() * (MAX_PORT - MIN_PORT + 1)) + MIN_PORT;\n\n\tlet port = getRandomPort();\n\tlet maxAttempts = 10;\n\n\twhile (maxAttempts > 0) {\n\t\ttry {\n\t\t\t// Try to create a server on the port to check if it's available\n\t\t\tconst server = await new Promise<any>((resolve, reject) => {\n\t\t\t\tconst server = createServer();\n\n\t\t\t\tserver.once(\"error\", (err: Error & { code?: string }) => {\n\t\t\t\t\tif (err.code === \"EADDRINUSE\") {\n\t\t\t\t\t\treject(new Error(`Port ${port} is in use`));\n\t\t\t\t\t} else {\n\t\t\t\t\t\treject(err);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tserver.once(\"listening\", () => {\n\t\t\t\t\tresolve(server);\n\t\t\t\t});\n\n\t\t\t\tserver.listen(port);\n\t\t\t});\n\n\t\t\t// Close the server since we're just checking availability\n\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\tserver.close(() => resolve());\n\t\t\t});\n\n\t\t\treturn port;\n\t\t} catch (err) {\n\t\t\t// If port is in use, try a different one\n\t\t\tmaxAttempts--;\n\t\t\tif (maxAttempts <= 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tport = getRandomPort();\n\t\t}\n\t}\n\n\tthrow new Error(\"Could not find an available port after multiple attempts\");\n}\n","import { z } from \"zod\";\nimport { RunnerConfigSchema } from \"@/registry/run-config\";\n\nexport const ConfigSchema = RunnerConfigSchema.removeDefault()\n\t.extend({\n\t\thostname: z\n\t\t\t.string()\n\t\t\t.optional()\n\t\t\t.default(process.env.HOSTNAME ?? \"127.0.0.1\"),\n\t\tport: z\n\t\t\t.number()\n\t\t\t.optional()\n\t\t\t.default(Number.parseInt(process.env.PORT ?? \"8080\")),\n\t})\n\t.default({});\nexport type InputConfig = z.input<typeof ConfigSchema>;\n","import { getLogger } from \"@/common/log\";\n\nexport function logger() {\n\treturn getLogger(\"test\");\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS,iBAAkC;AACpD,SAAS,2BAA2B;AACpC,SAA2B,UAAU;;;ACHrC,SAAS,SAAS;AAGX,IAAM,eAAe,mBAAmB,cAAc,EAC3D,OAAO;AAAA,EACP,UAAU,EACR,OAAO,EACP,SAAS,EACT,QAAQ,QAAQ,IAAI,YAAY,WAAW;AAAA,EAC7C,MAAM,EACJ,OAAO,EACP,SAAS,EACT,QAAQ,OAAO,SAAS,QAAQ,IAAI,QAAQ,MAAM,CAAC;AACtD,CAAC,EACA,QAAQ,CAAC,CAAC;;;ACZL,SAAS,SAAS;AACxB,SAAO,UAAU,MAAM;AACxB;;;AFcA,SAAS,MAAM,UAAyB,aAAuC;AAE9E,kBAAgB,CAAC;AAEjB,QAAM,SAAS,aAAa,MAAM,WAAW;AAE7C,MAAI;AACJ,MAAI,CAAC,OAAO,qBAAqB;AAChC,WAAO,sBAAsB,MAAM;AAAA,EACpC;AAGA,QAAM,YAAY,mBAAmB,MAAM,WAAW;AACtD,QAAM,SAAS,YAAY,UAAU,+BAA+B,KAAK;AACzE,QAAM,gBAAgB,OAAO,QAAQ,SAAS,QAAQ,MAAM;AAC5D,QAAM,SAAS,uBAAuB,aAAa;AACnD,gCAA8B,QAAQ,aAAa;AACnD,QAAM,EAAE,OAAO,IAAI;AAAA,IAClB,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AAGA,QAAM,gBAAgB,oBAAoB,EAAE,KAAK,OAAO,CAAC;AACzD,qBAAmB,cAAc;AAEjC,QAAM,SAAS,UAAU;AAAA,IACxB,OAAO,OAAO;AAAA,IACd,UAAU,OAAO;AAAA,IACjB,MAAM,OAAO;AAAA,EACd,CAAC;AACD,gBAAc,gBAAgB,MAAM;AAEpC,SAAO,EAAE,KAAK;AAAA,IACb,KAAK;AAAA,IACL,UAAU,OAAO;AAAA,IACjB,MAAM,OAAO;AAAA,IACb,aAAa,OAAO,KAAK,SAAS,OAAO,GAAG,EAAE;AAAA,EAC/C,CAAC;AAED,SAAO;AACR;AAYA,eAAsB,UACrB,GACA,UAC8B;AAC9B,KAAG,cAAc;AAGjB,QAAM,oBAAyB,CAAC;AAChC,QAAM,qBAAqB,CAAC,QAAa;AACxC,sBAAkB,UAAU;AAAA,EAC7B;AAKA,QAAM,OAAO,MAAM,QAAQ;AAC3B,QAAM,SAAS,MAAM,UAAU,EAAE,KAAK,CAAC;AACvC,IAAE;AAAA,IACD,YAAY,MAAM,IAAI,QAAQ,CAAC,YAAY,OAAO,MAAM,MAAM,QAAQ,CAAC,CAAC;AAAA,EACzE;AAEA,QAAM;AAeP;AAEA,eAAsB,UAA2B;AAEhD,QAAM,WAAW;AACjB,QAAM,WAAW;AACjB,QAAM,gBAAgB,MACrB,KAAK,MAAM,KAAK,OAAO,KAAK,WAAW,WAAW,EAAE,IAAI;AAEzD,MAAI,OAAO,cAAc;AACzB,MAAI,cAAc;AAElB,SAAO,cAAc,GAAG;AACvB,QAAI;AAEH,YAAM,SAAS,MAAM,IAAI,QAAa,CAAC,SAAS,WAAW;AAC1D,cAAMA,UAAS,aAAa;AAE5B,QAAAA,QAAO,KAAK,SAAS,CAAC,QAAmC;AACxD,cAAI,IAAI,SAAS,cAAc;AAC9B,mBAAO,IAAI,MAAM,QAAQ,IAAI,YAAY,CAAC;AAAA,UAC3C,OAAO;AACN,mBAAO,GAAG;AAAA,UACX;AAAA,QACD,CAAC;AAED,QAAAA,QAAO,KAAK,aAAa,MAAM;AAC9B,kBAAQA,OAAM;AAAA,QACf,CAAC;AAED,QAAAA,QAAO,OAAO,IAAI;AAAA,MACnB,CAAC;AAGD,YAAM,IAAI,QAAc,CAAC,YAAY;AACpC,eAAO,MAAM,MAAM,QAAQ,CAAC;AAAA,MAC7B,CAAC;AAED,aAAO;AAAA,IACR,SAAS,KAAK;AAEb;AACA,UAAI,eAAe,GAAG;AACrB;AAAA,MACD;AACA,aAAO,cAAc;AAAA,IACtB;AAAA,EACD;AAEA,QAAM,IAAI,MAAM,0DAA0D;AAC3E;","names":["server"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/Users/nathan/rivetkit/packages/rivetkit/dist/tsup/chunk-PKH3YCMG.cjs","../../src/test/mod.ts","../../src/test/config.ts","../../src/test/log.ts"],"names":["server"],"mappings":"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","file":"/Users/nathan/rivetkit/packages/rivetkit/dist/tsup/chunk-PKH3YCMG.cjs","sourcesContent":[null,"import { createServer } from \"node:net\";\nimport { serve as honoServe, type ServerType } from \"@hono/node-server\";\nimport { createNodeWebSocket } from \"@hono/node-ws\";\nimport { type TestContext, vi } from \"vitest\";\nimport { type Client, createClient } from \"@/client/mod\";\nimport { chooseDefaultDriver } from \"@/drivers/default\";\nimport { createFileSystemOrMemoryDriver } from \"@/drivers/file-system/mod\";\nimport {\n\tconfigureInspectorAccessToken,\n\tgetInspectorUrl,\n} from \"@/inspector/utils\";\nimport { createManagerRouter } from \"@/manager/router\";\nimport { createClientWithDriver } from \"@/mod\";\nimport type { Registry } from \"@/registry/mod\";\nimport { RunnerConfigSchema } from \"@/registry/run-config\";\nimport { ConfigSchema, type InputConfig } from \"./config\";\nimport { logger } from \"./log\";\n\nfunction serve(registry: Registry<any>, inputConfig?: InputConfig): ServerType {\n\t// Configure default configuration\n\tinputConfig ??= {};\n\n\tconst config = ConfigSchema.parse(inputConfig);\n\n\tlet upgradeWebSocket: any;\n\tif (!config.getUpgradeWebSocket) {\n\t\tconfig.getUpgradeWebSocket = () => upgradeWebSocket!;\n\t}\n\n\t// Create router\n\tconst runConfig = RunnerConfigSchema.parse(inputConfig);\n\tconst driver = inputConfig.driver ?? createFileSystemOrMemoryDriver(false);\n\tconst managerDriver = driver.manager(registry.config, config);\n\tconst client = createClientWithDriver(managerDriver);\n\tconfigureInspectorAccessToken(config, managerDriver);\n\tconst { router } = createManagerRouter(\n\t\tregistry.config,\n\t\trunConfig,\n\t\tmanagerDriver,\n\t\tdriver,\n\t\tclient,\n\t);\n\n\t// Inject WebSocket\n\tconst nodeWebSocket = createNodeWebSocket({ app: router });\n\tupgradeWebSocket = nodeWebSocket.upgradeWebSocket;\n\n\tconst server = honoServe({\n\t\tfetch: router.fetch,\n\t\thostname: config.hostname,\n\t\tport: config.port,\n\t});\n\tnodeWebSocket.injectWebSocket(server);\n\n\tlogger().info({\n\t\tmsg: \"rivetkit started\",\n\t\thostname: config.hostname,\n\t\tport: config.port,\n\t\tdefinitions: Object.keys(registry.config.use).length,\n\t});\n\n\treturn server;\n}\n\nexport interface SetupTestResult<A extends Registry<any>> {\n\tclient: Client<A>;\n\tmockDriver: {\n\t\tactorDriver: {\n\t\t\tsetCreateVarsContext: (ctx: any) => void;\n\t\t};\n\t};\n}\n\n// Must use `TestContext` since global hooks do not work when running concurrently\nexport async function setupTest<A extends Registry<any>>(\n\tc: TestContext,\n\tregistry: A,\n): Promise<SetupTestResult<A>> {\n\tvi.useFakeTimers();\n\n\t// Set up mock driver for testing createVars context\n\tconst mockDriverContext: any = {};\n\tconst setDriverContextFn = (ctx: any) => {\n\t\tmockDriverContext.current = ctx;\n\t};\n\n\t// We don't need to modify the driver context anymore since we're testing with the actual context\n\n\t// Start server with a random port\n\tconst port = await getPort();\n\tconst server = serve(registry, { port });\n\tc.onTestFinished(\n\t\tasync () => await new Promise((resolve) => server.close(() => resolve())),\n\t);\n\n\tthrow \"TODO: Fix engine port\";\n\n\t// // TODO: Figure out how to make this the correct endpoint\n\t// // Create client\n\t// const client = createClient<A>(`http://127.0.0.1:${port}`);\n\t// c.onTestFinished(async () => await client.dispose());\n\t//\n\t// return {\n\t// \tclient,\n\t// \tmockDriver: {\n\t// \t\tactorDriver: {\n\t// \t\t\tsetCreateVarsContext: setDriverContextFn,\n\t// \t\t},\n\t// \t},\n\t// };\n}\n\nexport async function getPort(): Promise<number> {\n\t// Pick random port between 10000 and 65535 (avoiding well-known and registered ports)\n\tconst MIN_PORT = 10000;\n\tconst MAX_PORT = 65535;\n\tconst getRandomPort = () =>\n\t\tMath.floor(Math.random() * (MAX_PORT - MIN_PORT + 1)) + MIN_PORT;\n\n\tlet port = getRandomPort();\n\tlet maxAttempts = 10;\n\n\twhile (maxAttempts > 0) {\n\t\ttry {\n\t\t\t// Try to create a server on the port to check if it's available\n\t\t\tconst server = await new Promise<any>((resolve, reject) => {\n\t\t\t\tconst server = createServer();\n\n\t\t\t\tserver.once(\"error\", (err: Error & { code?: string }) => {\n\t\t\t\t\tif (err.code === \"EADDRINUSE\") {\n\t\t\t\t\t\treject(new Error(`Port ${port} is in use`));\n\t\t\t\t\t} else {\n\t\t\t\t\t\treject(err);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tserver.once(\"listening\", () => {\n\t\t\t\t\tresolve(server);\n\t\t\t\t});\n\n\t\t\t\tserver.listen(port);\n\t\t\t});\n\n\t\t\t// Close the server since we're just checking availability\n\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\tserver.close(() => resolve());\n\t\t\t});\n\n\t\t\treturn port;\n\t\t} catch (err) {\n\t\t\t// If port is in use, try a different one\n\t\t\tmaxAttempts--;\n\t\t\tif (maxAttempts <= 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tport = getRandomPort();\n\t\t}\n\t}\n\n\tthrow new Error(\"Could not find an available port after multiple attempts\");\n}\n","import { z } from \"zod\";\nimport { RunnerConfigSchema } from \"@/registry/run-config\";\n\nexport const ConfigSchema = RunnerConfigSchema.removeDefault()\n\t.extend({\n\t\thostname: z\n\t\t\t.string()\n\t\t\t.optional()\n\t\t\t.default(process.env.HOSTNAME ?? \"127.0.0.1\"),\n\t\tport: z\n\t\t\t.number()\n\t\t\t.optional()\n\t\t\t.default(Number.parseInt(process.env.PORT ?? \"8080\")),\n\t})\n\t.default({});\nexport type InputConfig = z.input<typeof ConfigSchema>;\n","import { getLogger } from \"@/common/log\";\n\nexport function logger() {\n\treturn getLogger(\"test\");\n}\n"]}