rivetkit 2.0.2 → 2.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -5
- package/dist/schemas/actor-persist/v1.ts +225 -0
- package/dist/schemas/client-protocol/v1.ts +435 -0
- package/dist/schemas/file-system-driver/v1.ts +102 -0
- package/dist/tsup/actor/errors.cjs +77 -0
- package/dist/tsup/actor/errors.cjs.map +1 -0
- package/dist/tsup/actor/errors.d.cts +156 -0
- package/dist/tsup/actor/errors.d.ts +156 -0
- package/dist/tsup/actor/errors.js +77 -0
- package/dist/tsup/actor/errors.js.map +1 -0
- package/dist/tsup/chunk-3F2YSRJL.js +117 -0
- package/dist/tsup/chunk-3F2YSRJL.js.map +1 -0
- package/dist/tsup/chunk-4CXBCT26.cjs +250 -0
- package/dist/tsup/chunk-4CXBCT26.cjs.map +1 -0
- package/dist/tsup/chunk-4R73YDN3.cjs +20 -0
- package/dist/tsup/chunk-4R73YDN3.cjs.map +1 -0
- package/dist/tsup/chunk-6LJT3QRL.cjs +539 -0
- package/dist/tsup/chunk-6LJT3QRL.cjs.map +1 -0
- package/dist/tsup/chunk-GICQ3YCU.cjs +1792 -0
- package/dist/tsup/chunk-GICQ3YCU.cjs.map +1 -0
- package/dist/tsup/chunk-H26RP6GD.js +251 -0
- package/dist/tsup/chunk-H26RP6GD.js.map +1 -0
- package/dist/tsup/chunk-HI3HWJRC.js +20 -0
- package/dist/tsup/chunk-HI3HWJRC.js.map +1 -0
- package/dist/tsup/chunk-HLLF4B4Q.js +1792 -0
- package/dist/tsup/chunk-HLLF4B4Q.js.map +1 -0
- package/dist/tsup/chunk-IH6CKNDW.cjs +117 -0
- package/dist/tsup/chunk-IH6CKNDW.cjs.map +1 -0
- package/dist/tsup/chunk-LV2S3OU3.js +250 -0
- package/dist/tsup/chunk-LV2S3OU3.js.map +1 -0
- package/dist/tsup/chunk-LWNKVZG5.cjs +251 -0
- package/dist/tsup/chunk-LWNKVZG5.cjs.map +1 -0
- package/dist/tsup/chunk-NFU2BBT5.js +374 -0
- package/dist/tsup/chunk-NFU2BBT5.js.map +1 -0
- package/dist/tsup/chunk-PQY7KKTL.js +539 -0
- package/dist/tsup/chunk-PQY7KKTL.js.map +1 -0
- package/dist/tsup/chunk-QK72M5JB.js +45 -0
- package/dist/tsup/chunk-QK72M5JB.js.map +1 -0
- package/dist/tsup/chunk-QNNXFOQV.cjs +45 -0
- package/dist/tsup/chunk-QNNXFOQV.cjs.map +1 -0
- package/dist/tsup/chunk-SBHHJ6QS.cjs +374 -0
- package/dist/tsup/chunk-SBHHJ6QS.cjs.map +1 -0
- package/dist/tsup/chunk-TQ62L3X7.js +325 -0
- package/dist/tsup/chunk-TQ62L3X7.js.map +1 -0
- package/dist/tsup/chunk-VO7ZRVVD.cjs +6293 -0
- package/dist/tsup/chunk-VO7ZRVVD.cjs.map +1 -0
- package/dist/tsup/chunk-WHBPJNGW.cjs +325 -0
- package/dist/tsup/chunk-WHBPJNGW.cjs.map +1 -0
- package/dist/tsup/chunk-XJQHKJ4P.js +6293 -0
- package/dist/tsup/chunk-XJQHKJ4P.js.map +1 -0
- package/dist/tsup/client/mod.cjs +32 -0
- package/dist/tsup/client/mod.cjs.map +1 -0
- package/dist/tsup/client/mod.d.cts +20 -0
- package/dist/tsup/client/mod.d.ts +20 -0
- package/dist/tsup/client/mod.js +32 -0
- package/dist/tsup/client/mod.js.map +1 -0
- package/dist/tsup/common/log.cjs +21 -0
- package/dist/tsup/common/log.cjs.map +1 -0
- package/dist/tsup/common/log.d.cts +26 -0
- package/dist/tsup/common/log.d.ts +26 -0
- package/dist/tsup/common/log.js +21 -0
- package/dist/tsup/common/log.js.map +1 -0
- package/dist/tsup/common/websocket.cjs +10 -0
- package/dist/tsup/common/websocket.cjs.map +1 -0
- package/dist/tsup/common/websocket.d.cts +3 -0
- package/dist/tsup/common/websocket.d.ts +3 -0
- package/dist/tsup/common/websocket.js +10 -0
- package/dist/tsup/common/websocket.js.map +1 -0
- package/dist/tsup/common-CXCe7s6i.d.cts +218 -0
- package/dist/tsup/common-CXCe7s6i.d.ts +218 -0
- package/dist/tsup/connection-BI-6UIBJ.d.ts +2087 -0
- package/dist/tsup/connection-Dyd4NLGW.d.cts +2087 -0
- package/dist/tsup/driver-helpers/mod.cjs +30 -0
- package/dist/tsup/driver-helpers/mod.cjs.map +1 -0
- package/dist/tsup/driver-helpers/mod.d.cts +17 -0
- package/dist/tsup/driver-helpers/mod.d.ts +17 -0
- package/dist/tsup/driver-helpers/mod.js +30 -0
- package/dist/tsup/driver-helpers/mod.js.map +1 -0
- package/dist/tsup/driver-test-suite/mod.cjs +3411 -0
- package/dist/tsup/driver-test-suite/mod.cjs.map +1 -0
- package/dist/tsup/driver-test-suite/mod.d.cts +63 -0
- package/dist/tsup/driver-test-suite/mod.d.ts +63 -0
- package/dist/tsup/driver-test-suite/mod.js +3411 -0
- package/dist/tsup/driver-test-suite/mod.js.map +1 -0
- package/dist/tsup/inspector/mod.cjs +51 -0
- package/dist/tsup/inspector/mod.cjs.map +1 -0
- package/dist/tsup/inspector/mod.d.cts +408 -0
- package/dist/tsup/inspector/mod.d.ts +408 -0
- package/dist/tsup/inspector/mod.js +51 -0
- package/dist/tsup/inspector/mod.js.map +1 -0
- package/dist/tsup/mod.cjs +67 -0
- package/dist/tsup/mod.cjs.map +1 -0
- package/dist/tsup/mod.d.cts +105 -0
- package/dist/tsup/mod.d.ts +105 -0
- package/dist/tsup/mod.js +67 -0
- package/dist/tsup/mod.js.map +1 -0
- package/dist/tsup/router-endpoints-BTe_Rsdn.d.cts +65 -0
- package/dist/tsup/router-endpoints-CBSrKHmo.d.ts +65 -0
- package/dist/tsup/test/mod.cjs +17 -0
- package/dist/tsup/test/mod.cjs.map +1 -0
- package/dist/tsup/test/mod.d.cts +26 -0
- package/dist/tsup/test/mod.d.ts +26 -0
- package/dist/tsup/test/mod.js +17 -0
- package/dist/tsup/test/mod.js.map +1 -0
- package/dist/tsup/utils-fwx3o3K9.d.cts +18 -0
- package/dist/tsup/utils-fwx3o3K9.d.ts +18 -0
- package/dist/tsup/utils.cjs +26 -0
- package/dist/tsup/utils.cjs.map +1 -0
- package/dist/tsup/utils.d.cts +36 -0
- package/dist/tsup/utils.d.ts +36 -0
- package/dist/tsup/utils.js +26 -0
- package/dist/tsup/utils.js.map +1 -0
- package/package.json +208 -5
- package/src/actor/action.ts +178 -0
- package/src/actor/config.ts +497 -0
- package/src/actor/connection.ts +257 -0
- package/src/actor/context.ts +168 -0
- package/src/actor/database.ts +23 -0
- package/src/actor/definition.ts +82 -0
- package/src/actor/driver.ts +84 -0
- package/src/actor/errors.ts +422 -0
- package/src/actor/generic-conn-driver.ts +246 -0
- package/src/actor/instance.ts +1844 -0
- package/src/actor/keys.test.ts +266 -0
- package/src/actor/keys.ts +89 -0
- package/src/actor/log.ts +6 -0
- package/src/actor/mod.ts +108 -0
- package/src/actor/persisted.ts +42 -0
- package/src/actor/protocol/old.ts +297 -0
- package/src/actor/protocol/serde.ts +131 -0
- package/src/actor/router-endpoints.ts +688 -0
- package/src/actor/router.ts +265 -0
- package/src/actor/schedule.ts +17 -0
- package/src/actor/unstable-react.ts +110 -0
- package/src/actor/utils.ts +102 -0
- package/src/client/actor-common.ts +30 -0
- package/src/client/actor-conn.ts +865 -0
- package/src/client/actor-handle.ts +268 -0
- package/src/client/actor-query.ts +65 -0
- package/src/client/client.ts +554 -0
- package/src/client/config.ts +44 -0
- package/src/client/errors.ts +42 -0
- package/src/client/log.ts +5 -0
- package/src/client/mod.ts +60 -0
- package/src/client/raw-utils.ts +149 -0
- package/src/client/test.ts +44 -0
- package/src/client/utils.ts +152 -0
- package/src/common/eventsource-interface.ts +47 -0
- package/src/common/eventsource.ts +80 -0
- package/src/common/fake-event-source.ts +267 -0
- package/src/common/inline-websocket-adapter2.ts +454 -0
- package/src/common/log-levels.ts +27 -0
- package/src/common/log.ts +214 -0
- package/src/common/logfmt.ts +219 -0
- package/src/common/network.ts +2 -0
- package/src/common/router.ts +80 -0
- package/src/common/utils.ts +336 -0
- package/src/common/versioned-data.ts +95 -0
- package/src/common/websocket-interface.ts +49 -0
- package/src/common/websocket.ts +42 -0
- package/src/driver-helpers/mod.ts +22 -0
- package/src/driver-helpers/utils.ts +17 -0
- package/src/driver-test-suite/log.ts +5 -0
- package/src/driver-test-suite/mod.ts +239 -0
- package/src/driver-test-suite/tests/action-features.ts +136 -0
- package/src/driver-test-suite/tests/actor-conn-state.ts +249 -0
- package/src/driver-test-suite/tests/actor-conn.ts +349 -0
- package/src/driver-test-suite/tests/actor-driver.ts +25 -0
- package/src/driver-test-suite/tests/actor-error-handling.ts +158 -0
- package/src/driver-test-suite/tests/actor-handle.ts +292 -0
- package/src/driver-test-suite/tests/actor-inline-client.ts +152 -0
- package/src/driver-test-suite/tests/actor-inspector.ts +570 -0
- package/src/driver-test-suite/tests/actor-metadata.ts +116 -0
- package/src/driver-test-suite/tests/actor-onstatechange.ts +95 -0
- package/src/driver-test-suite/tests/actor-schedule.ts +108 -0
- package/src/driver-test-suite/tests/actor-sleep.ts +413 -0
- package/src/driver-test-suite/tests/actor-state.ts +54 -0
- package/src/driver-test-suite/tests/actor-vars.ts +93 -0
- package/src/driver-test-suite/tests/manager-driver.ts +367 -0
- package/src/driver-test-suite/tests/raw-http-direct-registry.ts +227 -0
- package/src/driver-test-suite/tests/raw-http-request-properties.ts +414 -0
- package/src/driver-test-suite/tests/raw-http.ts +347 -0
- package/src/driver-test-suite/tests/raw-websocket-direct-registry.ts +393 -0
- package/src/driver-test-suite/tests/raw-websocket.ts +484 -0
- package/src/driver-test-suite/tests/request-access.ts +230 -0
- package/src/driver-test-suite/utils.ts +71 -0
- package/src/drivers/default.ts +34 -0
- package/src/drivers/engine/actor-driver.ts +369 -0
- package/src/drivers/engine/config.ts +31 -0
- package/src/drivers/engine/kv.ts +3 -0
- package/src/drivers/engine/log.ts +5 -0
- package/src/drivers/engine/mod.ts +35 -0
- package/src/drivers/file-system/actor.ts +91 -0
- package/src/drivers/file-system/global-state.ts +686 -0
- package/src/drivers/file-system/log.ts +5 -0
- package/src/drivers/file-system/manager.ts +329 -0
- package/src/drivers/file-system/mod.ts +48 -0
- package/src/drivers/file-system/utils.ts +109 -0
- package/src/globals.d.ts +6 -0
- package/src/inspector/actor.ts +298 -0
- package/src/inspector/config.ts +88 -0
- package/src/inspector/log.ts +5 -0
- package/src/inspector/manager.ts +86 -0
- package/src/inspector/mod.ts +2 -0
- package/src/inspector/protocol/actor.ts +10 -0
- package/src/inspector/protocol/common.ts +196 -0
- package/src/inspector/protocol/manager.ts +10 -0
- package/src/inspector/protocol/mod.ts +2 -0
- package/src/inspector/utils.ts +76 -0
- package/src/manager/driver.ts +88 -0
- package/src/manager/hono-websocket-adapter.ts +342 -0
- package/src/manager/log.ts +5 -0
- package/src/manager/mod.ts +2 -0
- package/src/manager/protocol/mod.ts +24 -0
- package/src/manager/protocol/query.ts +89 -0
- package/src/manager/router.ts +412 -0
- package/src/manager-api/routes/actors-create.ts +16 -0
- package/src/manager-api/routes/actors-delete.ts +4 -0
- package/src/manager-api/routes/actors-get-by-id.ts +7 -0
- package/src/manager-api/routes/actors-get-or-create-by-id.ts +29 -0
- package/src/manager-api/routes/actors-get.ts +7 -0
- package/src/manager-api/routes/common.ts +18 -0
- package/src/mod.ts +18 -0
- package/src/registry/config.ts +32 -0
- package/src/registry/log.ts +5 -0
- package/src/registry/mod.ts +157 -0
- package/src/registry/run-config.ts +52 -0
- package/src/registry/serve.ts +52 -0
- package/src/remote-manager-driver/actor-http-client.ts +72 -0
- package/src/remote-manager-driver/actor-websocket-client.ts +63 -0
- package/src/remote-manager-driver/api-endpoints.ts +79 -0
- package/src/remote-manager-driver/api-utils.ts +43 -0
- package/src/remote-manager-driver/log.ts +5 -0
- package/src/remote-manager-driver/mod.ts +274 -0
- package/src/remote-manager-driver/ws-proxy.ts +180 -0
- package/src/schemas/actor-persist/mod.ts +1 -0
- package/src/schemas/actor-persist/versioned.ts +25 -0
- package/src/schemas/client-protocol/mod.ts +1 -0
- package/src/schemas/client-protocol/versioned.ts +63 -0
- package/src/schemas/file-system-driver/mod.ts +1 -0
- package/src/schemas/file-system-driver/versioned.ts +28 -0
- package/src/serde.ts +90 -0
- package/src/test/config.ts +16 -0
- package/src/test/log.ts +5 -0
- package/src/test/mod.ts +154 -0
- package/src/utils.ts +172 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import invariant from "invariant";
|
|
2
|
+
import { PATH_RAW_WEBSOCKET_PREFIX } from "@/actor/router";
|
|
3
|
+
import { deconstructError } from "@/common/utils";
|
|
4
|
+
import { HEADER_CONN_PARAMS, type ManagerDriver } from "@/driver-helpers/mod";
|
|
5
|
+
import type { ActorQuery } from "@/manager/protocol/query";
|
|
6
|
+
import { queryActor } from "./actor-query";
|
|
7
|
+
import { ActorError } from "./errors";
|
|
8
|
+
import { logger } from "./log";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Shared implementation for raw HTTP fetch requests
|
|
12
|
+
*/
|
|
13
|
+
export async function rawHttpFetch(
|
|
14
|
+
driver: ManagerDriver,
|
|
15
|
+
actorQuery: ActorQuery,
|
|
16
|
+
params: unknown,
|
|
17
|
+
input: string | URL | Request,
|
|
18
|
+
init?: RequestInit,
|
|
19
|
+
): Promise<Response> {
|
|
20
|
+
// Extract path and merge init options
|
|
21
|
+
let path: string;
|
|
22
|
+
let mergedInit: RequestInit = init || {};
|
|
23
|
+
|
|
24
|
+
if (typeof input === "string") {
|
|
25
|
+
path = input;
|
|
26
|
+
} else if (input instanceof URL) {
|
|
27
|
+
path = input.pathname + input.search;
|
|
28
|
+
} else if (input instanceof Request) {
|
|
29
|
+
// Extract path from Request URL
|
|
30
|
+
const url = new URL(input.url);
|
|
31
|
+
path = url.pathname + url.search;
|
|
32
|
+
// Merge Request properties with init
|
|
33
|
+
const requestHeaders = new Headers(input.headers);
|
|
34
|
+
const initHeaders = new Headers(init?.headers || {});
|
|
35
|
+
|
|
36
|
+
// Merge headers - init headers override request headers
|
|
37
|
+
const mergedHeaders = new Headers(requestHeaders);
|
|
38
|
+
for (const [key, value] of initHeaders) {
|
|
39
|
+
mergedHeaders.set(key, value);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
mergedInit = {
|
|
43
|
+
method: input.method,
|
|
44
|
+
body: input.body,
|
|
45
|
+
mode: input.mode,
|
|
46
|
+
credentials: input.credentials,
|
|
47
|
+
redirect: input.redirect,
|
|
48
|
+
referrer: input.referrer,
|
|
49
|
+
referrerPolicy: input.referrerPolicy,
|
|
50
|
+
integrity: input.integrity,
|
|
51
|
+
keepalive: input.keepalive,
|
|
52
|
+
signal: input.signal,
|
|
53
|
+
...mergedInit, // init overrides Request properties
|
|
54
|
+
headers: mergedHeaders, // headers must be set after spread to ensure proper merge
|
|
55
|
+
};
|
|
56
|
+
// Add duplex if body is present
|
|
57
|
+
if (mergedInit.body) {
|
|
58
|
+
(mergedInit as any).duplex = "half";
|
|
59
|
+
}
|
|
60
|
+
} else {
|
|
61
|
+
throw new TypeError("Invalid input type for fetch");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
// Get the actor ID
|
|
66
|
+
const { actorId } = await queryActor(undefined, actorQuery, driver);
|
|
67
|
+
logger().debug({ msg: "found actor for raw http", actorId });
|
|
68
|
+
invariant(actorId, "Missing actor ID");
|
|
69
|
+
|
|
70
|
+
// Build the URL with normalized path
|
|
71
|
+
const normalizedPath = path.startsWith("/") ? path.slice(1) : path;
|
|
72
|
+
const url = new URL(`http://actor/raw/http/${normalizedPath}`);
|
|
73
|
+
|
|
74
|
+
// Forward conn params if provided
|
|
75
|
+
const proxyRequestHeaders = new Headers(mergedInit.headers);
|
|
76
|
+
if (params) {
|
|
77
|
+
proxyRequestHeaders.set(HEADER_CONN_PARAMS, JSON.stringify(params));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Forward the request to the actor
|
|
81
|
+
const proxyRequest = new Request(url, {
|
|
82
|
+
...init,
|
|
83
|
+
headers: proxyRequestHeaders,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
return driver.sendRequest(actorId, proxyRequest);
|
|
87
|
+
} catch (err) {
|
|
88
|
+
// Standardize to ClientActorError instead of the native backend error
|
|
89
|
+
const { group, code, message, metadata } = deconstructError(
|
|
90
|
+
err,
|
|
91
|
+
logger(),
|
|
92
|
+
{},
|
|
93
|
+
true,
|
|
94
|
+
);
|
|
95
|
+
throw new ActorError(group, code, message, metadata);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Shared implementation for raw WebSocket connections
|
|
101
|
+
*/
|
|
102
|
+
export async function rawWebSocket(
|
|
103
|
+
driver: ManagerDriver,
|
|
104
|
+
actorQuery: ActorQuery,
|
|
105
|
+
params: unknown,
|
|
106
|
+
path?: string,
|
|
107
|
+
// TODO: Supportp rotocols
|
|
108
|
+
protocols?: string | string[],
|
|
109
|
+
): Promise<any> {
|
|
110
|
+
// TODO: Do we need encoding in rawWebSocket?
|
|
111
|
+
const encoding = "bare";
|
|
112
|
+
|
|
113
|
+
// Get the actor ID
|
|
114
|
+
const { actorId } = await queryActor(undefined, actorQuery, driver);
|
|
115
|
+
logger().debug({ msg: "found actor for action", actorId });
|
|
116
|
+
invariant(actorId, "Missing actor ID");
|
|
117
|
+
|
|
118
|
+
// Parse path and query parameters
|
|
119
|
+
let pathPortion = "";
|
|
120
|
+
let queryPortion = "";
|
|
121
|
+
if (path) {
|
|
122
|
+
const queryIndex = path.indexOf("?");
|
|
123
|
+
if (queryIndex !== -1) {
|
|
124
|
+
pathPortion = path.substring(0, queryIndex);
|
|
125
|
+
queryPortion = path.substring(queryIndex); // includes the '?'
|
|
126
|
+
} else {
|
|
127
|
+
pathPortion = path;
|
|
128
|
+
}
|
|
129
|
+
// Remove leading slash if present
|
|
130
|
+
if (pathPortion.startsWith("/")) {
|
|
131
|
+
pathPortion = pathPortion.slice(1);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const fullPath = `${PATH_RAW_WEBSOCKET_PREFIX}${pathPortion}${queryPortion}`;
|
|
136
|
+
|
|
137
|
+
logger().debug({
|
|
138
|
+
msg: "opening websocket",
|
|
139
|
+
actorId,
|
|
140
|
+
encoding,
|
|
141
|
+
path: fullPath,
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// Open WebSocket
|
|
145
|
+
const ws = await driver.openWebSocket(fullPath, actorId, encoding, params);
|
|
146
|
+
|
|
147
|
+
// Node & browser WebSocket types are incompatible
|
|
148
|
+
return ws as any;
|
|
149
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
//import { exec as execCallback } from "node:child_process";
|
|
2
|
+
//import { setupLogging } from "@/common//log";
|
|
3
|
+
//import type { ClientOptions } from "./client";
|
|
4
|
+
//import { InternalError } from "./errors";
|
|
5
|
+
//import { Client } from "./mod.ts";
|
|
6
|
+
//
|
|
7
|
+
///**
|
|
8
|
+
// * Uses the Rivet CLI to read the manager endpoint to connect to. This allows
|
|
9
|
+
// * for writing tests that run locally without hardcoding the manager endpoint.
|
|
10
|
+
// */
|
|
11
|
+
//export async function readEndpointFromCli(): Promise<string> {
|
|
12
|
+
// // Read endpoint
|
|
13
|
+
// const cliPath = process.env.RIVET_CLI_PATH ?? "rivet";
|
|
14
|
+
//
|
|
15
|
+
// try {
|
|
16
|
+
// const { stdout, stderr } = await new Promise<{
|
|
17
|
+
// stdout: string;
|
|
18
|
+
// stderr: string;
|
|
19
|
+
// }>((resolve, reject) => {
|
|
20
|
+
// execCallback(`${cliPath} manager endpoint`, (error, stdout, stderr) => {
|
|
21
|
+
// if (error) reject(error);
|
|
22
|
+
// else resolve({ stdout, stderr });
|
|
23
|
+
// });
|
|
24
|
+
// });
|
|
25
|
+
//
|
|
26
|
+
// if (stderr) {
|
|
27
|
+
// throw new Error(stderr);
|
|
28
|
+
// }
|
|
29
|
+
//
|
|
30
|
+
// // Decode output
|
|
31
|
+
// return stdout.trim();
|
|
32
|
+
// } catch (error) {
|
|
33
|
+
// throw new InternalError(`Read endpoint failed: ${error}`);
|
|
34
|
+
// }
|
|
35
|
+
//}
|
|
36
|
+
//
|
|
37
|
+
//export class TestClient extends Client {
|
|
38
|
+
// public constructor(opts?: ClientOptions) {
|
|
39
|
+
// // Setup logging automatically
|
|
40
|
+
// setupLogging();
|
|
41
|
+
//
|
|
42
|
+
// super(readEndpointFromCli(), opts);
|
|
43
|
+
// }
|
|
44
|
+
//}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import * as cbor from "cbor-x";
|
|
2
|
+
import invariant from "invariant";
|
|
3
|
+
import { assertUnreachable } from "@/common/utils";
|
|
4
|
+
import type { VersionedDataHandler } from "@/common/versioned-data";
|
|
5
|
+
import type { Encoding } from "@/mod";
|
|
6
|
+
import type { HttpResponseError } from "@/schemas/client-protocol/mod";
|
|
7
|
+
import { HTTP_RESPONSE_ERROR_VERSIONED } from "@/schemas/client-protocol/versioned";
|
|
8
|
+
import {
|
|
9
|
+
contentTypeForEncoding,
|
|
10
|
+
deserializeWithEncoding,
|
|
11
|
+
serializeWithEncoding,
|
|
12
|
+
} from "@/serde";
|
|
13
|
+
import { httpUserAgent } from "@/utils";
|
|
14
|
+
import { ActorError, HttpRequestError } from "./errors";
|
|
15
|
+
import { logger } from "./log";
|
|
16
|
+
|
|
17
|
+
export type WebSocketMessage = string | Blob | ArrayBuffer | Uint8Array;
|
|
18
|
+
|
|
19
|
+
export function messageLength(message: WebSocketMessage): number {
|
|
20
|
+
if (message instanceof Blob) {
|
|
21
|
+
return message.size;
|
|
22
|
+
}
|
|
23
|
+
if (message instanceof ArrayBuffer) {
|
|
24
|
+
return message.byteLength;
|
|
25
|
+
}
|
|
26
|
+
if (message instanceof Uint8Array) {
|
|
27
|
+
return message.byteLength;
|
|
28
|
+
}
|
|
29
|
+
if (typeof message === "string") {
|
|
30
|
+
return message.length;
|
|
31
|
+
}
|
|
32
|
+
assertUnreachable(message);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface HttpRequestOpts<RequestBody, ResponseBody> {
|
|
36
|
+
method: string;
|
|
37
|
+
url: string;
|
|
38
|
+
headers: Record<string, string>;
|
|
39
|
+
body?: RequestBody;
|
|
40
|
+
encoding: Encoding;
|
|
41
|
+
skipParseResponse?: boolean;
|
|
42
|
+
signal?: AbortSignal;
|
|
43
|
+
customFetch?: (req: Request) => Promise<Response>;
|
|
44
|
+
requestVersionedDataHandler: VersionedDataHandler<RequestBody> | undefined;
|
|
45
|
+
responseVersionedDataHandler: VersionedDataHandler<ResponseBody> | undefined;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export async function sendHttpRequest<
|
|
49
|
+
RequestBody = unknown,
|
|
50
|
+
ResponseBody = unknown,
|
|
51
|
+
>(opts: HttpRequestOpts<RequestBody, ResponseBody>): Promise<ResponseBody> {
|
|
52
|
+
logger().debug({
|
|
53
|
+
msg: "sending http request",
|
|
54
|
+
url: opts.url,
|
|
55
|
+
encoding: opts.encoding,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Serialize body
|
|
59
|
+
let contentType: string | undefined;
|
|
60
|
+
let bodyData: string | Uint8Array | undefined;
|
|
61
|
+
if (opts.method === "POST" || opts.method === "PUT") {
|
|
62
|
+
invariant(opts.body !== undefined, "missing body");
|
|
63
|
+
contentType = contentTypeForEncoding(opts.encoding);
|
|
64
|
+
bodyData = serializeWithEncoding<RequestBody>(
|
|
65
|
+
opts.encoding,
|
|
66
|
+
opts.body,
|
|
67
|
+
opts.requestVersionedDataHandler,
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Send request
|
|
72
|
+
let response: Response;
|
|
73
|
+
try {
|
|
74
|
+
// Make the HTTP request
|
|
75
|
+
response = await (opts.customFetch ?? fetch)(
|
|
76
|
+
new Request(opts.url, {
|
|
77
|
+
method: opts.method,
|
|
78
|
+
headers: {
|
|
79
|
+
...opts.headers,
|
|
80
|
+
...(contentType
|
|
81
|
+
? {
|
|
82
|
+
"Content-Type": contentType,
|
|
83
|
+
}
|
|
84
|
+
: {}),
|
|
85
|
+
"User-Agent": httpUserAgent(),
|
|
86
|
+
},
|
|
87
|
+
body: bodyData,
|
|
88
|
+
credentials: "include",
|
|
89
|
+
signal: opts.signal,
|
|
90
|
+
}),
|
|
91
|
+
);
|
|
92
|
+
} catch (error) {
|
|
93
|
+
throw new HttpRequestError(`Request failed: ${error}`, {
|
|
94
|
+
cause: error,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Parse response error
|
|
99
|
+
if (!response.ok) {
|
|
100
|
+
// Attempt to parse structured data
|
|
101
|
+
const bufferResponse = await response.arrayBuffer();
|
|
102
|
+
let responseData: HttpResponseError;
|
|
103
|
+
try {
|
|
104
|
+
responseData = deserializeWithEncoding(
|
|
105
|
+
opts.encoding,
|
|
106
|
+
new Uint8Array(bufferResponse),
|
|
107
|
+
HTTP_RESPONSE_ERROR_VERSIONED,
|
|
108
|
+
);
|
|
109
|
+
} catch (error) {
|
|
110
|
+
//logger().warn("failed to cleanly parse error, this is likely because a non-structured response is being served", {
|
|
111
|
+
// error: stringifyError(error),
|
|
112
|
+
//});
|
|
113
|
+
|
|
114
|
+
// Error is not structured
|
|
115
|
+
const textResponse = new TextDecoder("utf-8", { fatal: false }).decode(
|
|
116
|
+
bufferResponse,
|
|
117
|
+
);
|
|
118
|
+
throw new HttpRequestError(
|
|
119
|
+
`${response.statusText} (${response.status}):\n${textResponse}`,
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Throw structured error
|
|
124
|
+
throw new ActorError(
|
|
125
|
+
responseData.group,
|
|
126
|
+
responseData.code,
|
|
127
|
+
responseData.message,
|
|
128
|
+
responseData.metadata
|
|
129
|
+
? cbor.decode(new Uint8Array(responseData.metadata))
|
|
130
|
+
: undefined,
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Some requests don't need the success response to be parsed, so this can speed things up
|
|
135
|
+
if (opts.skipParseResponse) {
|
|
136
|
+
return undefined as ResponseBody;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Parse the response based on encoding
|
|
140
|
+
try {
|
|
141
|
+
const buffer = new Uint8Array(await response.arrayBuffer());
|
|
142
|
+
return deserializeWithEncoding(
|
|
143
|
+
opts.encoding,
|
|
144
|
+
buffer,
|
|
145
|
+
opts.responseVersionedDataHandler,
|
|
146
|
+
);
|
|
147
|
+
} catch (error) {
|
|
148
|
+
throw new HttpRequestError(`Failed to parse response: ${error}`, {
|
|
149
|
+
cause: error,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Define minimal event interfaces to avoid conflicts between different EventSource implementations
|
|
2
|
+
export interface UniversalEvent {
|
|
3
|
+
type: string;
|
|
4
|
+
target?: any;
|
|
5
|
+
currentTarget?: any;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface UniversalMessageEvent extends UniversalEvent {
|
|
9
|
+
data: string;
|
|
10
|
+
lastEventId: string;
|
|
11
|
+
origin: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface UniversalErrorEvent extends UniversalEvent {
|
|
15
|
+
message: string;
|
|
16
|
+
filename?: string;
|
|
17
|
+
lineno?: number;
|
|
18
|
+
colno?: number;
|
|
19
|
+
error?: any;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Common EventSource interface that can be implemented by different EventSource-like classes
|
|
24
|
+
* This is compatible with the standard EventSource API but allows for custom implementations
|
|
25
|
+
*/
|
|
26
|
+
export interface UniversalEventSource {
|
|
27
|
+
// EventSource readyState values
|
|
28
|
+
readonly CONNECTING: 0;
|
|
29
|
+
readonly OPEN: 1;
|
|
30
|
+
readonly CLOSED: 2;
|
|
31
|
+
|
|
32
|
+
// Properties
|
|
33
|
+
readonly readyState: 0 | 1 | 2;
|
|
34
|
+
readonly url: string;
|
|
35
|
+
readonly withCredentials: boolean;
|
|
36
|
+
|
|
37
|
+
// Methods
|
|
38
|
+
close(): void;
|
|
39
|
+
addEventListener(type: string, listener: (event: any) => void): void;
|
|
40
|
+
removeEventListener(type: string, listener: (event: any) => void): void;
|
|
41
|
+
dispatchEvent(event: UniversalEvent): boolean;
|
|
42
|
+
|
|
43
|
+
// Event handlers (optional)
|
|
44
|
+
onopen?: ((event: UniversalEvent) => void) | null;
|
|
45
|
+
onmessage?: ((event: UniversalMessageEvent) => void) | null;
|
|
46
|
+
onerror?: ((event: UniversalErrorEvent) => void) | null;
|
|
47
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { EventSource } from "eventsource";
|
|
2
|
+
import { logger } from "@/client/log";
|
|
3
|
+
|
|
4
|
+
// Global singleton promise that will be reused for subsequent calls
|
|
5
|
+
let eventSourcePromise: Promise<typeof EventSource> | null = null;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Import `eventsource` from the custom `eventsource` library. We need a custom implemnetation since we need to attach our own custom headers to the request.
|
|
9
|
+
**/
|
|
10
|
+
export async function importEventSource(): Promise<typeof EventSource> {
|
|
11
|
+
// Return existing promise if we already started loading
|
|
12
|
+
if (eventSourcePromise !== null) {
|
|
13
|
+
return eventSourcePromise;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Create and store the promise
|
|
17
|
+
eventSourcePromise = (async () => {
|
|
18
|
+
let _EventSource: typeof EventSource;
|
|
19
|
+
|
|
20
|
+
// Node.js environment
|
|
21
|
+
try {
|
|
22
|
+
const es = await import("eventsource");
|
|
23
|
+
_EventSource = es.EventSource;
|
|
24
|
+
logger().debug("using eventsource from npm");
|
|
25
|
+
} catch (err) {
|
|
26
|
+
// EventSource not available
|
|
27
|
+
_EventSource = class MockEventSource {
|
|
28
|
+
constructor() {
|
|
29
|
+
throw new Error(
|
|
30
|
+
'EventSource support requires installing the "eventsource" peer dependency.',
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
} as unknown as typeof EventSource;
|
|
34
|
+
logger().debug("using mock eventsource");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return _EventSource;
|
|
38
|
+
})();
|
|
39
|
+
|
|
40
|
+
return eventSourcePromise;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
//export async function importEventSource(): Promise<typeof EventSource> {
|
|
44
|
+
// // Return existing promise if we already started loading
|
|
45
|
+
// if (eventSourcePromise !== null) {
|
|
46
|
+
// return eventSourcePromise;
|
|
47
|
+
// }
|
|
48
|
+
//
|
|
49
|
+
// // Create and store the promise
|
|
50
|
+
// eventSourcePromise = (async () => {
|
|
51
|
+
// let _EventSource: typeof EventSource;
|
|
52
|
+
//
|
|
53
|
+
// if (typeof EventSource !== "undefined") {
|
|
54
|
+
// // Browser environment
|
|
55
|
+
// _EventSource = EventSource;
|
|
56
|
+
// logger().debug("using native eventsource");
|
|
57
|
+
// } else {
|
|
58
|
+
// // Node.js environment
|
|
59
|
+
// try {
|
|
60
|
+
// const es = await import("eventsource");
|
|
61
|
+
// _EventSource = es.EventSource;
|
|
62
|
+
// logger().debug("using eventsource from npm");
|
|
63
|
+
// } catch (err) {
|
|
64
|
+
// // EventSource not available
|
|
65
|
+
// _EventSource = class MockEventSource {
|
|
66
|
+
// constructor() {
|
|
67
|
+
// throw new Error(
|
|
68
|
+
// 'EventSource support requires installing the "eventsource" peer dependency.',
|
|
69
|
+
// );
|
|
70
|
+
// }
|
|
71
|
+
// } as unknown as typeof EventSource;
|
|
72
|
+
// logger().debug("using mock eventsource");
|
|
73
|
+
// }
|
|
74
|
+
// }
|
|
75
|
+
//
|
|
76
|
+
// return _EventSource;
|
|
77
|
+
// })();
|
|
78
|
+
//
|
|
79
|
+
// return eventSourcePromise;
|
|
80
|
+
//}
|