@rivetkit/core
Version:
1 lines • 14.8 kB
Source Map (JSON)
{"version":3,"sources":["/home/nathan/rivetkit/packages/core/dist/chunk-ZCUB7MR5.cjs","../src/client/http-client-driver.ts","../src/client/mod.ts"],"names":[],"mappings":"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","file":"/home/nathan/rivetkit/packages/core/dist/chunk-ZCUB7MR5.cjs","sourcesContent":[null,"import type { Context as HonoContext } from \"hono\";\nimport type { WebSocket } from \"ws\";\nimport type { ActionRequest } from \"@/actor/protocol/http/action\";\nimport type * as protoHttpResolve from \"@/actor/protocol/http/resolve\";\nimport type { ActionResponse } from \"@/actor/protocol/message/to-client\";\nimport type * as wsToServer from \"@/actor/protocol/message/to-server\";\nimport type { Encoding } from \"@/actor/protocol/serde\";\nimport {\n\tHEADER_ACTOR_ID,\n\tHEADER_ACTOR_QUERY,\n\tHEADER_CONN_ID,\n\tHEADER_CONN_PARAMS,\n\tHEADER_CONN_TOKEN,\n\tHEADER_ENCODING,\n} from \"@/actor/router-endpoints\";\nimport { importEventSource } from \"@/common/eventsource\";\nimport type { UniversalEventSource } from \"@/common/eventsource-interface\";\nimport { importWebSocket } from \"@/common/websocket\";\nimport type { ActorQuery } from \"@/manager/protocol/query\";\nimport { assertUnreachable, httpUserAgent } from \"@/utils\";\nimport type { ClientDriver } from \"./client\";\nimport * as errors from \"./errors\";\nimport { logger } from \"./log\";\nimport { sendHttpRequest, serializeWithEncoding } from \"./utils\";\n\n/**\n * Client driver that communicates with the manager via HTTP.\n */\nexport function createHttpClientDriver(managerEndpoint: string): ClientDriver {\n\t// Lazily import the dynamic imports so we don't have to turn `createClient` in to an aysnc fn\n\tconst dynamicImports = (async () => {\n\t\t// Import dynamic dependencies\n\t\tconst [WebSocket, EventSource] = await Promise.all([\n\t\t\timportWebSocket(),\n\t\t\timportEventSource(),\n\t\t]);\n\t\treturn {\n\t\t\tWebSocket,\n\t\t\tEventSource,\n\t\t};\n\t})();\n\n\tconst driver: ClientDriver = {\n\t\taction: async <Args extends Array<unknown> = unknown[], Response = unknown>(\n\t\t\t_c: HonoContext | undefined,\n\t\t\tactorQuery: ActorQuery,\n\t\t\tencoding: Encoding,\n\t\t\tparams: unknown,\n\t\t\tname: string,\n\t\t\targs: Args,\n\t\t\topts: { signal?: AbortSignal } | undefined,\n\t\t): Promise<Response> => {\n\t\t\tlogger().debug(\"actor handle action\", {\n\t\t\t\tname,\n\t\t\t\targs,\n\t\t\t\tquery: actorQuery,\n\t\t\t});\n\n\t\t\tconst responseData = await sendHttpRequest<ActionRequest, ActionResponse>(\n\t\t\t\t{\n\t\t\t\t\turl: `${managerEndpoint}/registry/actors/actions/${encodeURIComponent(name)}`,\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t[HEADER_ENCODING]: encoding,\n\t\t\t\t\t\t[HEADER_ACTOR_QUERY]: JSON.stringify(actorQuery),\n\t\t\t\t\t\t...(params !== undefined\n\t\t\t\t\t\t\t? { [HEADER_CONN_PARAMS]: JSON.stringify(params) }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t},\n\t\t\t\t\tbody: { a: args } satisfies ActionRequest,\n\t\t\t\t\tencoding: encoding,\n\t\t\t\t\tsignal: opts?.signal,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\treturn responseData.o as Response;\n\t\t},\n\n\t\tresolveActorId: async (\n\t\t\t_c: HonoContext | undefined,\n\t\t\tactorQuery: ActorQuery,\n\t\t\tencodingKind: Encoding,\n\t\t\tparams: unknown,\n\t\t): Promise<string> => {\n\t\t\tlogger().debug(\"resolving actor ID\", { query: actorQuery });\n\n\t\t\ttry {\n\t\t\t\tconst result = await sendHttpRequest<\n\t\t\t\t\tRecord<never, never>,\n\t\t\t\t\tprotoHttpResolve.ResolveResponse\n\t\t\t\t>({\n\t\t\t\t\turl: `${managerEndpoint}/registry/actors/resolve`,\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t[HEADER_ENCODING]: encodingKind,\n\t\t\t\t\t\t[HEADER_ACTOR_QUERY]: JSON.stringify(actorQuery),\n\t\t\t\t\t\t...(params !== undefined\n\t\t\t\t\t\t\t? { [HEADER_CONN_PARAMS]: JSON.stringify(params) }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t},\n\t\t\t\t\tbody: {},\n\t\t\t\t\tencoding: encodingKind,\n\t\t\t\t});\n\n\t\t\t\tlogger().debug(\"resolved actor ID\", { actorId: result.i });\n\t\t\t\treturn result.i;\n\t\t\t} catch (error) {\n\t\t\t\tlogger().error(\"failed to resolve actor ID\", { error });\n\t\t\t\tif (error instanceof errors.ActorError) {\n\t\t\t\t\tthrow error;\n\t\t\t\t} else {\n\t\t\t\t\tthrow new errors.InternalError(\n\t\t\t\t\t\t`Failed to resolve actor ID: ${String(error)}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tconnectWebSocket: async (\n\t\t\t_c: HonoContext | undefined,\n\t\t\tactorQuery: ActorQuery,\n\t\t\tencodingKind: Encoding,\n\t\t\tparams: unknown,\n\t\t): Promise<WebSocket> => {\n\t\t\tconst { WebSocket } = await dynamicImports;\n\n\t\t\tconst endpoint = managerEndpoint\n\t\t\t\t.replace(/^http:/, \"ws:\")\n\t\t\t\t.replace(/^https:/, \"wss:\");\n\t\t\tconst url = `${endpoint}/registry/actors/connect/websocket`;\n\n\t\t\t// Pass sensitive data via protocol\n\t\t\tconst protocol = [\n\t\t\t\t`query.${encodeURIComponent(JSON.stringify(actorQuery))}`,\n\t\t\t\t`encoding.${encodingKind}`,\n\t\t\t];\n\t\t\tif (params)\n\t\t\t\tprotocol.push(\n\t\t\t\t\t`conn_params.${encodeURIComponent(JSON.stringify(params))}`,\n\t\t\t\t);\n\n\t\t\t// HACK: See packages/drivers/cloudflare-workers/src/websocket.ts\n\t\t\tprotocol.push(\"rivetkit\");\n\n\t\t\tlogger().debug(\"connecting to websocket\", { url });\n\t\t\tconst ws = new WebSocket(url, protocol);\n\t\t\tif (encodingKind === \"cbor\") {\n\t\t\t\tws.binaryType = \"arraybuffer\";\n\t\t\t} else if (encodingKind === \"json\") {\n\t\t\t\t// HACK: Bun bug prevents changing binary type, so we ignore the error https://github.com/oven-sh/bun/issues/17005\n\t\t\t\ttry {\n\t\t\t\t\tws.binaryType = \"blob\" as any;\n\t\t\t\t} catch (error) {}\n\t\t\t} else {\n\t\t\t\tassertUnreachable(encodingKind);\n\t\t\t}\n\n\t\t\t// Node & web WebSocket types not compatible\n\t\t\treturn ws as any;\n\t\t},\n\n\t\tconnectSse: async (\n\t\t\t_c: HonoContext | undefined,\n\t\t\tactorQuery: ActorQuery,\n\t\t\tencodingKind: Encoding,\n\t\t\tparams: unknown,\n\t\t): Promise<UniversalEventSource> => {\n\t\t\tconst { EventSource } = await dynamicImports;\n\n\t\t\tconst url = `${managerEndpoint}/registry/actors/connect/sse`;\n\n\t\t\tlogger().debug(\"connecting to sse\", { url });\n\t\t\tconst eventSource = new EventSource(url, {\n\t\t\t\tfetch: (input, init) => {\n\t\t\t\t\treturn fetch(input, {\n\t\t\t\t\t\t...init,\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t...init?.headers,\n\t\t\t\t\t\t\t\"User-Agent\": httpUserAgent(),\n\t\t\t\t\t\t\t[HEADER_ENCODING]: encodingKind,\n\t\t\t\t\t\t\t[HEADER_ACTOR_QUERY]: JSON.stringify(actorQuery),\n\t\t\t\t\t\t\t...(params !== undefined\n\t\t\t\t\t\t\t\t? { [HEADER_CONN_PARAMS]: JSON.stringify(params) }\n\t\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t},\n\t\t\t\t\t\tcredentials: \"include\",\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t});\n\n\t\t\treturn eventSource as UniversalEventSource;\n\t\t},\n\n\t\tsendHttpMessage: async (\n\t\t\t_c: HonoContext | undefined,\n\t\t\tactorId: string,\n\t\t\tencoding: Encoding,\n\t\t\tconnectionId: string,\n\t\t\tconnectionToken: string,\n\t\t\tmessage: wsToServer.ToServer,\n\t\t): Promise<Response> => {\n\t\t\t// TODO: Implement ordered messages, this is not guaranteed order. Needs to use an index in order to ensure we can pipeline requests efficiently.\n\t\t\t// TODO: Validate that we're using HTTP/3 whenever possible for pipelining requests\n\t\t\tconst messageSerialized = serializeWithEncoding(encoding, message);\n\t\t\tconst res = await fetch(`${managerEndpoint}/registry/actors/message`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\t\"User-Agent\": httpUserAgent(),\n\t\t\t\t\t[HEADER_ENCODING]: encoding,\n\t\t\t\t\t[HEADER_ACTOR_ID]: actorId,\n\t\t\t\t\t[HEADER_CONN_ID]: connectionId,\n\t\t\t\t\t[HEADER_CONN_TOKEN]: connectionToken,\n\t\t\t\t},\n\t\t\t\tbody: messageSerialized,\n\t\t\t\tcredentials: \"include\",\n\t\t\t});\n\t\t\treturn res;\n\t\t},\n\n\t\trawHttpRequest: async (\n\t\t\t_c: HonoContext | undefined,\n\t\t\tactorQuery: ActorQuery,\n\t\t\tencoding: Encoding,\n\t\t\tparams: unknown,\n\t\t\tpath: string,\n\t\t\tinit: RequestInit,\n\t\t): Promise<Response> => {\n\t\t\t// Build the full URL\n\t\t\t// Remove leading slash from path to avoid double slashes\n\t\t\tconst normalizedPath = path.startsWith(\"/\") ? path.slice(1) : path;\n\t\t\tconst url = `${managerEndpoint}/registry/actors/raw/http/${normalizedPath}`;\n\n\t\t\tlogger().debug(\"rewriting http url\", {\n\t\t\t\tfrom: path,\n\t\t\t\tto: url,\n\t\t\t});\n\n\t\t\t// Merge headers properly\n\t\t\tconst headers = new Headers(init.headers);\n\t\t\theaders.set(\"User-Agent\", httpUserAgent());\n\t\t\theaders.set(HEADER_ACTOR_QUERY, JSON.stringify(actorQuery));\n\t\t\theaders.set(HEADER_ENCODING, encoding);\n\t\t\tif (params !== undefined) {\n\t\t\t\theaders.set(HEADER_CONN_PARAMS, JSON.stringify(params));\n\t\t\t}\n\n\t\t\t// Forward the request with query in headers\n\t\t\treturn await fetch(url, {\n\t\t\t\t...init,\n\t\t\t\theaders,\n\t\t\t});\n\t\t},\n\n\t\trawWebSocket: async (\n\t\t\t_c: HonoContext | undefined,\n\t\t\tactorQuery: ActorQuery,\n\t\t\tencoding: Encoding,\n\t\t\tparams: unknown,\n\t\t\tpath: string,\n\t\t\tprotocols: string | string[] | undefined,\n\t\t): Promise<WebSocket> => {\n\t\t\tconst { WebSocket } = await dynamicImports;\n\n\t\t\t// Build the WebSocket URL with normalized path\n\t\t\tconst wsEndpoint = managerEndpoint\n\t\t\t\t.replace(/^http:/, \"ws:\")\n\t\t\t\t.replace(/^https:/, \"wss:\");\n\t\t\t// Normalize path to match raw HTTP behavior\n\t\t\tconst normalizedPath = path.startsWith(\"/\") ? path.slice(1) : path;\n\t\t\tconst url = `${wsEndpoint}/registry/actors/raw/websocket/${normalizedPath}`;\n\n\t\t\tlogger().debug(\"rewriting websocket url\", {\n\t\t\t\tfrom: path,\n\t\t\t\tto: url,\n\t\t\t});\n\n\t\t\t// Pass data via WebSocket protocol subprotocols\n\t\t\tconst protocolList: string[] = [];\n\t\t\tprotocolList.push(\n\t\t\t\t`query.${encodeURIComponent(JSON.stringify(actorQuery))}`,\n\t\t\t);\n\t\t\tprotocolList.push(`encoding.${encoding}`);\n\t\t\tif (params) {\n\t\t\t\tprotocolList.push(\n\t\t\t\t\t`conn_params.${encodeURIComponent(JSON.stringify(params))}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// HACK: See packages/drivers/cloudflare-workers/src/websocket.ts\n\t\t\tprotocolList.push(\"rivetkit\");\n\n\t\t\t// Add user protocols\n\t\t\tif (protocols) {\n\t\t\t\tif (Array.isArray(protocols)) {\n\t\t\t\t\tprotocolList.push(...protocols);\n\t\t\t\t} else {\n\t\t\t\t\tprotocolList.push(protocols);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Create WebSocket connection\n\t\t\tlogger().debug(\"opening raw websocket\", { url });\n\t\t\treturn new WebSocket(url, protocolList) as any;\n\t\t},\n\t};\n\n\treturn driver;\n}\n","import type { Registry } from \"@/registry/mod\";\nimport {\n\ttype Client,\n\ttype ClientOptions,\n\tcreateClientWithDriver,\n} from \"./client\";\nimport { createHttpClientDriver } from \"./http-client-driver\";\n\nexport {\n\tActorDefinition,\n\tAnyActorDefinition,\n} from \"@/actor/definition\";\nexport type { Transport } from \"@/actor/protocol/message/mod\";\nexport type { Encoding } from \"@/actor/protocol/serde\";\nexport {\n\tActorClientError,\n\tActorError,\n\tInternalError,\n\tMalformedResponseMessage,\n\tManagerError,\n} from \"@/client/errors\";\nexport type { CreateRequest } from \"@/manager/protocol/query\";\nexport type { ActorActionFunction } from \"./actor-common\";\nexport type { ActorConn, EventUnsubscribe } from \"./actor-conn\";\nexport { ActorConnRaw } from \"./actor-conn\";\nexport type { ActorHandle } from \"./actor-handle\";\nexport { ActorHandleRaw } from \"./actor-handle\";\nexport type {\n\tActorAccessor,\n\tClient,\n\tClientOptions,\n\tClientRaw,\n\tCreateOptions,\n\tExtractActorsFromRegistry,\n\tExtractRegistryFromClient,\n\tGetOptions,\n\tGetWithIdOptions,\n\tQueryOptions,\n\tRegion,\n} from \"./client\";\n\n/**\n * Creates a client with the actor accessor proxy.\n *\n * @template A The actor application type.\n * @param {string} managerEndpoint - The manager endpoint.\n * @param {ClientOptions} [opts] - Options for configuring the client.\n * @returns {Client<A>} - A proxied client that supports the `client.myActor.connect()` syntax.\n */\nexport function createClient<A extends Registry<any>>(\n\tendpoint: string,\n\topts?: ClientOptions,\n): Client<A> {\n\tconst driver = createHttpClientDriver(endpoint);\n\treturn createClientWithDriver<A>(driver, opts);\n}\n"]}