@rigkit/runtime-client 0.0.0-canary-20260518T014918-c5bc0c2
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 -0
- package/package.json +35 -0
- package/src/api.ts +242 -0
- package/src/client.ts +261 -0
- package/src/errors.ts +124 -0
- package/src/http.ts +96 -0
- package/src/index.ts +105 -0
- package/src/manager.test.ts +347 -0
- package/src/manager.ts +643 -0
- package/src/schemas.ts +97 -0
- package/src/session.ts +140 -0
- package/src/version.ts +1 -0
package/src/schemas.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
|
|
3
|
+
export class RuntimeClientSchemaError extends Error {
|
|
4
|
+
constructor(readonly cause: unknown) {
|
|
5
|
+
super(String(cause));
|
|
6
|
+
this.name = "RuntimeClientSchemaError";
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
type ParseResult<T> =
|
|
11
|
+
| { success: true; data: T }
|
|
12
|
+
| { success: false; error: RuntimeClientSchemaError };
|
|
13
|
+
|
|
14
|
+
type RuntimeClientSchema<T> = {
|
|
15
|
+
parse(value: unknown): T;
|
|
16
|
+
safeParse(value: unknown): ParseResult<T>;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
function runtimeClientSchema<T, I>(schema: Schema.Schema<T, I, never>): RuntimeClientSchema<T> {
|
|
20
|
+
const decode = Schema.decodeUnknownSync(schema);
|
|
21
|
+
return {
|
|
22
|
+
parse(value) {
|
|
23
|
+
try {
|
|
24
|
+
return decode(value);
|
|
25
|
+
} catch (error) {
|
|
26
|
+
throw new RuntimeClientSchemaError(error);
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
safeParse(value) {
|
|
30
|
+
try {
|
|
31
|
+
return { success: true, data: decode(value) };
|
|
32
|
+
} catch (error) {
|
|
33
|
+
return { success: false, error: new RuntimeClientSchemaError(error) };
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const RuntimeHandleEffectSchema = Schema.Struct({
|
|
40
|
+
projectId: Schema.String,
|
|
41
|
+
runtimeFingerprint: Schema.optional(Schema.String),
|
|
42
|
+
projectDir: Schema.String,
|
|
43
|
+
configPath: Schema.String,
|
|
44
|
+
statePath: Schema.optional(Schema.String),
|
|
45
|
+
globalFragmentRoot: Schema.optional(Schema.String),
|
|
46
|
+
pid: Schema.Int,
|
|
47
|
+
url: Schema.String,
|
|
48
|
+
tokenPath: Schema.String,
|
|
49
|
+
engineVersion: Schema.optional(Schema.String),
|
|
50
|
+
runtimeVersion: Schema.optional(Schema.String),
|
|
51
|
+
startedAt: Schema.optional(Schema.String),
|
|
52
|
+
expiresAt: Schema.optional(Schema.String),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
export const RuntimeReadyEffectSchema = Schema.Struct({
|
|
56
|
+
type: Schema.Literal("ready"),
|
|
57
|
+
url: Schema.String,
|
|
58
|
+
token: Schema.optional(Schema.String),
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
export const RuntimeHealthEffectSchema = Schema.Struct({
|
|
62
|
+
ok: Schema.Boolean,
|
|
63
|
+
projectId: Schema.String,
|
|
64
|
+
runtimeFingerprint: Schema.optional(Schema.String),
|
|
65
|
+
projectDir: Schema.optional(Schema.String),
|
|
66
|
+
configPath: Schema.optional(Schema.String),
|
|
67
|
+
statePath: Schema.optional(Schema.String),
|
|
68
|
+
globalFragmentRoot: Schema.optional(Schema.String),
|
|
69
|
+
engineVersion: Schema.optional(Schema.String),
|
|
70
|
+
runtimeVersion: Schema.optional(Schema.String),
|
|
71
|
+
expiresAt: Schema.optional(Schema.String),
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
export const RuntimeMetadataEffectSchema = Schema.Struct({
|
|
75
|
+
apiVersion: Schema.Int,
|
|
76
|
+
engineVersion: Schema.String,
|
|
77
|
+
runtimeVersion: Schema.String,
|
|
78
|
+
protocolHash: Schema.String,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
export const RuntimeErrorResponseEffectSchema = Schema.Struct({
|
|
82
|
+
error: Schema.Struct({
|
|
83
|
+
message: Schema.String,
|
|
84
|
+
}),
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
export type RuntimeHandle = Schema.Schema.Type<typeof RuntimeHandleEffectSchema>;
|
|
88
|
+
export type RuntimeReady = Schema.Schema.Type<typeof RuntimeReadyEffectSchema>;
|
|
89
|
+
export type RuntimeHealth = Schema.Schema.Type<typeof RuntimeHealthEffectSchema>;
|
|
90
|
+
export type RuntimeMetadata = Schema.Schema.Type<typeof RuntimeMetadataEffectSchema>;
|
|
91
|
+
|
|
92
|
+
export const RuntimeHandleSchema: RuntimeClientSchema<RuntimeHandle> = runtimeClientSchema(RuntimeHandleEffectSchema);
|
|
93
|
+
export const RuntimeReadySchema: RuntimeClientSchema<RuntimeReady> = runtimeClientSchema(RuntimeReadyEffectSchema);
|
|
94
|
+
export const RuntimeHealthSchema: RuntimeClientSchema<RuntimeHealth> = runtimeClientSchema(RuntimeHealthEffectSchema);
|
|
95
|
+
export const RuntimeMetadataSchema: RuntimeClientSchema<RuntimeMetadata> = runtimeClientSchema(RuntimeMetadataEffectSchema);
|
|
96
|
+
export const RuntimeErrorResponseSchema: RuntimeClientSchema<Schema.Schema.Type<typeof RuntimeErrorResponseEffectSchema>> =
|
|
97
|
+
runtimeClientSchema(RuntimeErrorResponseEffectSchema);
|
package/src/session.ts
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import {
|
|
3
|
+
RuntimeSessionError,
|
|
4
|
+
type RuntimeClientError,
|
|
5
|
+
} from "./errors.ts";
|
|
6
|
+
import { toRuntimeTransportError } from "./http.ts";
|
|
7
|
+
|
|
8
|
+
export type RuntimeSessionHandlers = {
|
|
9
|
+
hello?: RuntimeSessionHello;
|
|
10
|
+
onOpen?(session: RuntimeSessionConnection): Promise<void> | void;
|
|
11
|
+
onMessage(message: unknown, session: RuntimeSessionConnection): Promise<void> | void;
|
|
12
|
+
onClose?(): Promise<void> | void;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export type RuntimeSessionHello = {
|
|
16
|
+
type: "hello";
|
|
17
|
+
transportVersion: number;
|
|
18
|
+
host: {
|
|
19
|
+
name: string;
|
|
20
|
+
version: string;
|
|
21
|
+
};
|
|
22
|
+
hostMethods: Array<{ id: string; modes?: string[] }>;
|
|
23
|
+
hostCapabilities: Array<{ id: string; schemaHash?: string }>;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export type RuntimeSessionConnection = {
|
|
27
|
+
send(message: unknown): void;
|
|
28
|
+
close(code?: number, reason?: string): void;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export function runtimeSessionEffect(
|
|
32
|
+
baseUrl: string,
|
|
33
|
+
token: string,
|
|
34
|
+
path: string,
|
|
35
|
+
handlers: RuntimeSessionHandlers,
|
|
36
|
+
): Effect.Effect<void, RuntimeClientError> {
|
|
37
|
+
return Effect.tryPromise({
|
|
38
|
+
try: () => connectSession(baseUrl, token, path, handlers),
|
|
39
|
+
catch: (cause) => toRuntimeTransportError(cause, { method: "WS", path }),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function connectSession(
|
|
44
|
+
baseUrl: string,
|
|
45
|
+
token: string,
|
|
46
|
+
path: string,
|
|
47
|
+
handlers: RuntimeSessionHandlers,
|
|
48
|
+
): Promise<void> {
|
|
49
|
+
const url = new URL(path, baseUrl);
|
|
50
|
+
url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
|
|
51
|
+
|
|
52
|
+
return createRuntimeWebSocket(url, token).then((ws) => new Promise((resolvePromise, rejectPromise) => {
|
|
53
|
+
let settled = false;
|
|
54
|
+
|
|
55
|
+
const connection: RuntimeSessionConnection = {
|
|
56
|
+
send(message) {
|
|
57
|
+
ws.send(JSON.stringify(message));
|
|
58
|
+
},
|
|
59
|
+
close(code, reason) {
|
|
60
|
+
ws.close(code, reason);
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const settle = (error?: unknown) => {
|
|
65
|
+
if (settled) return;
|
|
66
|
+
settled = true;
|
|
67
|
+
if (error) rejectPromise(error);
|
|
68
|
+
else resolvePromise();
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
ws.addEventListener("open", async () => {
|
|
72
|
+
try {
|
|
73
|
+
connection.send(handlers.hello ?? defaultHello());
|
|
74
|
+
await handlers.onOpen?.(connection);
|
|
75
|
+
} catch (error) {
|
|
76
|
+
ws.close(1011, error instanceof Error ? error.message : String(error));
|
|
77
|
+
settle(error);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
ws.addEventListener("message", async (event) => {
|
|
81
|
+
try {
|
|
82
|
+
const data = typeof event.data === "string" ? JSON.parse(event.data) : event.data;
|
|
83
|
+
await handlers.onMessage(data, connection);
|
|
84
|
+
} catch (error) {
|
|
85
|
+
ws.close(1011, error instanceof Error ? error.message : String(error));
|
|
86
|
+
settle(error);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
ws.addEventListener("close", async () => {
|
|
90
|
+
try {
|
|
91
|
+
await handlers.onClose?.();
|
|
92
|
+
settle();
|
|
93
|
+
} catch (error) {
|
|
94
|
+
settle(error);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
ws.addEventListener("error", () => settle(new RuntimeSessionError({ url: url.toString() })));
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
type RuntimeWebSocketConstructor = {
|
|
102
|
+
new(url: string | URL, options?: { headers?: Record<string, string> }): WebSocket;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
async function createRuntimeWebSocket(url: URL, token: string): Promise<WebSocket> {
|
|
106
|
+
if (typeof Bun !== "undefined") {
|
|
107
|
+
return new (WebSocket as unknown as RuntimeWebSocketConstructor)(url, {
|
|
108
|
+
headers: { authorization: `Bearer ${token}` },
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const ws = await importWebSocketModule("ws") as {
|
|
113
|
+
default?: RuntimeWebSocketConstructor;
|
|
114
|
+
WebSocket?: RuntimeWebSocketConstructor;
|
|
115
|
+
};
|
|
116
|
+
const WebSocketConstructor = ws.default ?? ws.WebSocket;
|
|
117
|
+
if (!WebSocketConstructor) {
|
|
118
|
+
throw new RuntimeSessionError({ url: url.toString(), message: "No WebSocket implementation is available" });
|
|
119
|
+
}
|
|
120
|
+
return new WebSocketConstructor(url, {
|
|
121
|
+
headers: { authorization: `Bearer ${token}` },
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const importWebSocketModule = new Function("specifier", "return import(specifier)") as (
|
|
126
|
+
specifier: string,
|
|
127
|
+
) => Promise<unknown>;
|
|
128
|
+
|
|
129
|
+
function defaultHello(): RuntimeSessionHello {
|
|
130
|
+
return {
|
|
131
|
+
type: "hello",
|
|
132
|
+
transportVersion: 1,
|
|
133
|
+
host: {
|
|
134
|
+
name: "rigkit-runtime-client",
|
|
135
|
+
version: "0.0.0",
|
|
136
|
+
},
|
|
137
|
+
hostMethods: [],
|
|
138
|
+
hostCapabilities: [],
|
|
139
|
+
};
|
|
140
|
+
}
|
package/src/version.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const RIGKIT_RUNTIME_CLIENT_VERSION = "0.0.0-canary-20260518T014918-c5bc0c2";
|