@ereo/rpc 0.1.6
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 +357 -0
- package/dist/client.d.ts +11 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +433 -0
- package/dist/src/client.d.ts +56 -0
- package/dist/src/client.d.ts.map +1 -0
- package/dist/src/context-bridge.d.ts +79 -0
- package/dist/src/context-bridge.d.ts.map +1 -0
- package/dist/src/hooks.d.ts +80 -0
- package/dist/src/hooks.d.ts.map +1 -0
- package/dist/src/index.d.ts +18 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +616 -0
- package/dist/src/middleware.d.ts +123 -0
- package/dist/src/middleware.d.ts.map +1 -0
- package/dist/src/plugin.d.ts +62 -0
- package/dist/src/plugin.d.ts.map +1 -0
- package/dist/src/procedure.d.ts +98 -0
- package/dist/src/procedure.d.ts.map +1 -0
- package/dist/src/router.d.ts +66 -0
- package/dist/src/router.d.ts.map +1 -0
- package/dist/src/types.d.ts +166 -0
- package/dist/src/types.d.ts.map +1 -0
- package/package.json +50 -0
package/dist/client.js
ADDED
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/client.ts
|
|
3
|
+
function createClient(optionsOrEndpoint) {
|
|
4
|
+
const options = typeof optionsOrEndpoint === "string" ? { httpEndpoint: optionsOrEndpoint } : optionsOrEndpoint;
|
|
5
|
+
const fetchFn = options.fetch ?? fetch;
|
|
6
|
+
const reconnectOpts = {
|
|
7
|
+
enabled: true,
|
|
8
|
+
maxAttempts: 10,
|
|
9
|
+
delayMs: 1000,
|
|
10
|
+
maxDelayMs: 30000,
|
|
11
|
+
...options.reconnect
|
|
12
|
+
};
|
|
13
|
+
const heartbeatOpts = {
|
|
14
|
+
enabled: options.heartbeatEnabled !== false,
|
|
15
|
+
interval: options.heartbeatInterval ?? 30000
|
|
16
|
+
};
|
|
17
|
+
let ws = null;
|
|
18
|
+
let wsConnecting = false;
|
|
19
|
+
let wsConnected = false;
|
|
20
|
+
let reconnectAttempts = 0;
|
|
21
|
+
let reconnectTimeout = null;
|
|
22
|
+
let heartbeatInterval = null;
|
|
23
|
+
let missedPongs = 0;
|
|
24
|
+
const subscriptions = new Map;
|
|
25
|
+
const pendingSubscriptions = [];
|
|
26
|
+
const connectionQueue = [];
|
|
27
|
+
function getHeaders() {
|
|
28
|
+
const base = { "Content-Type": "application/json" };
|
|
29
|
+
const custom = typeof options.headers === "function" ? options.headers() : options.headers;
|
|
30
|
+
return { ...base, ...custom };
|
|
31
|
+
}
|
|
32
|
+
function generateId() {
|
|
33
|
+
return Math.random().toString(36).slice(2) + Date.now().toString(36);
|
|
34
|
+
}
|
|
35
|
+
function connectWebSocket() {
|
|
36
|
+
return new Promise((resolve, reject) => {
|
|
37
|
+
if (!options.wsEndpoint) {
|
|
38
|
+
reject(new Error("WebSocket endpoint not configured"));
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (wsConnected) {
|
|
42
|
+
resolve();
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (wsConnecting) {
|
|
46
|
+
connectionQueue.push({ resolve, reject });
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
wsConnecting = true;
|
|
50
|
+
startConnection(resolve, reject);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
function startConnection(initialResolve, initialReject) {
|
|
54
|
+
connectionQueue.push({ resolve: initialResolve, reject: initialReject });
|
|
55
|
+
try {
|
|
56
|
+
ws = new WebSocket(options.wsEndpoint);
|
|
57
|
+
ws.onopen = () => {
|
|
58
|
+
wsConnecting = false;
|
|
59
|
+
wsConnected = true;
|
|
60
|
+
reconnectAttempts = 0;
|
|
61
|
+
missedPongs = 0;
|
|
62
|
+
startHeartbeat();
|
|
63
|
+
while (connectionQueue.length > 0) {
|
|
64
|
+
const { resolve } = connectionQueue.shift();
|
|
65
|
+
resolve();
|
|
66
|
+
}
|
|
67
|
+
for (const [id, sub] of subscriptions) {
|
|
68
|
+
sendSubscribe(id, sub.path, sub.input);
|
|
69
|
+
}
|
|
70
|
+
while (pendingSubscriptions.length > 0) {
|
|
71
|
+
const pending = pendingSubscriptions.shift();
|
|
72
|
+
subscriptions.set(pending.id, pending.sub);
|
|
73
|
+
sendSubscribe(pending.id, pending.sub.path, pending.sub.input);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
ws.onmessage = (event) => {
|
|
77
|
+
try {
|
|
78
|
+
const msg = JSON.parse(event.data);
|
|
79
|
+
if (msg.type === "pong") {
|
|
80
|
+
missedPongs = 0;
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
handleServerMessage(msg);
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.error("Failed to parse WebSocket message:", error);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
ws.onerror = (error) => {
|
|
89
|
+
console.error("WebSocket error:", error);
|
|
90
|
+
};
|
|
91
|
+
ws.onclose = () => {
|
|
92
|
+
stopHeartbeat();
|
|
93
|
+
wsConnecting = false;
|
|
94
|
+
wsConnected = false;
|
|
95
|
+
ws = null;
|
|
96
|
+
while (connectionQueue.length > 0) {
|
|
97
|
+
const { reject } = connectionQueue.shift();
|
|
98
|
+
reject(new Error("WebSocket connection closed"));
|
|
99
|
+
}
|
|
100
|
+
if (reconnectOpts.enabled && subscriptions.size > 0) {
|
|
101
|
+
scheduleReconnect();
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
} catch (error) {
|
|
105
|
+
wsConnecting = false;
|
|
106
|
+
while (connectionQueue.length > 0) {
|
|
107
|
+
const { reject } = connectionQueue.shift();
|
|
108
|
+
reject(error instanceof Error ? error : new Error(String(error)));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function startHeartbeat() {
|
|
113
|
+
if (!heartbeatOpts.enabled)
|
|
114
|
+
return;
|
|
115
|
+
heartbeatInterval = setInterval(() => {
|
|
116
|
+
if (!ws || ws.readyState !== WebSocket.OPEN) {
|
|
117
|
+
stopHeartbeat();
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (missedPongs >= 2) {
|
|
121
|
+
console.warn("WebSocket heartbeat failed, closing connection");
|
|
122
|
+
ws.close();
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
missedPongs++;
|
|
126
|
+
ws.send(JSON.stringify({ type: "ping" }));
|
|
127
|
+
}, heartbeatOpts.interval);
|
|
128
|
+
}
|
|
129
|
+
function stopHeartbeat() {
|
|
130
|
+
if (heartbeatInterval) {
|
|
131
|
+
clearInterval(heartbeatInterval);
|
|
132
|
+
heartbeatInterval = null;
|
|
133
|
+
}
|
|
134
|
+
missedPongs = 0;
|
|
135
|
+
}
|
|
136
|
+
function scheduleReconnect() {
|
|
137
|
+
if (reconnectTimeout)
|
|
138
|
+
return;
|
|
139
|
+
stopHeartbeat();
|
|
140
|
+
if (reconnectAttempts >= reconnectOpts.maxAttempts) {
|
|
141
|
+
console.error("Max reconnection attempts reached");
|
|
142
|
+
for (const [, sub] of subscriptions) {
|
|
143
|
+
sub.callbacks.onError?.(new Error("Connection lost"));
|
|
144
|
+
}
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const delay = Math.min(reconnectOpts.delayMs * Math.pow(2, reconnectAttempts), reconnectOpts.maxDelayMs);
|
|
148
|
+
reconnectAttempts++;
|
|
149
|
+
console.log(`Reconnecting in ${delay}ms (attempt ${reconnectAttempts})`);
|
|
150
|
+
reconnectTimeout = setTimeout(() => {
|
|
151
|
+
reconnectTimeout = null;
|
|
152
|
+
connectWebSocket().catch(() => {});
|
|
153
|
+
}, delay);
|
|
154
|
+
}
|
|
155
|
+
function handleServerMessage(msg) {
|
|
156
|
+
if (msg.type === "pong") {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const sub = subscriptions.get(msg.id);
|
|
160
|
+
if (!sub)
|
|
161
|
+
return;
|
|
162
|
+
switch (msg.type) {
|
|
163
|
+
case "data":
|
|
164
|
+
sub.callbacks.onData(msg.data);
|
|
165
|
+
break;
|
|
166
|
+
case "error":
|
|
167
|
+
sub.callbacks.onError?.(new Error(msg.error.message));
|
|
168
|
+
break;
|
|
169
|
+
case "complete":
|
|
170
|
+
subscriptions.delete(msg.id);
|
|
171
|
+
sub.callbacks.onComplete?.();
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
function sendSubscribe(id, path, input) {
|
|
176
|
+
if (!ws || ws.readyState !== WebSocket.OPEN)
|
|
177
|
+
return;
|
|
178
|
+
const msg = { type: "subscribe", id, path, input };
|
|
179
|
+
ws.send(JSON.stringify(msg));
|
|
180
|
+
}
|
|
181
|
+
function sendUnsubscribe(id) {
|
|
182
|
+
if (!ws || ws.readyState !== WebSocket.OPEN)
|
|
183
|
+
return;
|
|
184
|
+
const msg = { type: "unsubscribe", id };
|
|
185
|
+
ws.send(JSON.stringify(msg));
|
|
186
|
+
}
|
|
187
|
+
function createProxy(path) {
|
|
188
|
+
return new Proxy(() => {}, {
|
|
189
|
+
get(_target, prop) {
|
|
190
|
+
if (prop === "query") {
|
|
191
|
+
return async (input) => {
|
|
192
|
+
const usePost = options.usePostForQueries ?? false;
|
|
193
|
+
if (usePost) {
|
|
194
|
+
const response = await fetchFn(options.httpEndpoint, {
|
|
195
|
+
method: "POST",
|
|
196
|
+
headers: getHeaders(),
|
|
197
|
+
body: JSON.stringify({ path, type: "query", input })
|
|
198
|
+
});
|
|
199
|
+
return handleHttpResponse(response, path);
|
|
200
|
+
} else {
|
|
201
|
+
const url = new URL(options.httpEndpoint, window.location.origin);
|
|
202
|
+
url.searchParams.set("path", path.join("."));
|
|
203
|
+
if (input !== undefined) {
|
|
204
|
+
const inputStr = JSON.stringify(input);
|
|
205
|
+
if (inputStr.length > 1500) {
|
|
206
|
+
console.warn("RPC query input is large. Consider using usePostForQueries option to avoid URL length limits.");
|
|
207
|
+
}
|
|
208
|
+
url.searchParams.set("input", inputStr);
|
|
209
|
+
}
|
|
210
|
+
const response = await fetchFn(url.toString(), {
|
|
211
|
+
method: "GET",
|
|
212
|
+
headers: getHeaders()
|
|
213
|
+
});
|
|
214
|
+
return handleHttpResponse(response, path);
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
if (prop === "mutate") {
|
|
219
|
+
return async (input) => {
|
|
220
|
+
const response = await fetchFn(options.httpEndpoint, {
|
|
221
|
+
method: "POST",
|
|
222
|
+
headers: getHeaders(),
|
|
223
|
+
body: JSON.stringify({ path, type: "mutation", input })
|
|
224
|
+
});
|
|
225
|
+
return handleHttpResponse(response, path);
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
if (prop === "subscribe") {
|
|
229
|
+
return (inputOrCallbacks, maybeCallbacks) => {
|
|
230
|
+
const hasInput = maybeCallbacks !== undefined;
|
|
231
|
+
const input = hasInput ? inputOrCallbacks : undefined;
|
|
232
|
+
const callbacks = hasInput ? maybeCallbacks : inputOrCallbacks;
|
|
233
|
+
const id = generateId();
|
|
234
|
+
const sub = { path, input, callbacks };
|
|
235
|
+
if (!wsConnected && !wsConnecting) {
|
|
236
|
+
pendingSubscriptions.push({ id, sub });
|
|
237
|
+
connectWebSocket().catch((error) => {
|
|
238
|
+
callbacks.onError?.(error instanceof Error ? error : new Error(String(error)));
|
|
239
|
+
});
|
|
240
|
+
} else if (wsConnected) {
|
|
241
|
+
subscriptions.set(id, sub);
|
|
242
|
+
sendSubscribe(id, path, input);
|
|
243
|
+
} else {
|
|
244
|
+
pendingSubscriptions.push({ id, sub });
|
|
245
|
+
}
|
|
246
|
+
return () => {
|
|
247
|
+
subscriptions.delete(id);
|
|
248
|
+
sendUnsubscribe(id);
|
|
249
|
+
if (subscriptions.size === 0 && pendingSubscriptions.length === 0) {
|
|
250
|
+
if (reconnectTimeout) {
|
|
251
|
+
clearTimeout(reconnectTimeout);
|
|
252
|
+
reconnectTimeout = null;
|
|
253
|
+
}
|
|
254
|
+
ws?.close();
|
|
255
|
+
ws = null;
|
|
256
|
+
wsConnected = false;
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
return createProxy([...path, prop]);
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
return createProxy([]);
|
|
266
|
+
}
|
|
267
|
+
async function handleHttpResponse(response, path) {
|
|
268
|
+
const result = await response.json();
|
|
269
|
+
if (!result.ok) {
|
|
270
|
+
const error = new Error(result.error.message);
|
|
271
|
+
error.name = "RPCClientError";
|
|
272
|
+
error.code = result.error.code;
|
|
273
|
+
error.path = path.join(".");
|
|
274
|
+
error.details = result.error.details;
|
|
275
|
+
throw error;
|
|
276
|
+
}
|
|
277
|
+
return result.data;
|
|
278
|
+
}
|
|
279
|
+
// src/hooks.ts
|
|
280
|
+
import { useState, useEffect, useCallback, useRef } from "react";
|
|
281
|
+
function useQuery(procedure, options = {}) {
|
|
282
|
+
const { input, enabled = true, refetchInterval } = options;
|
|
283
|
+
const [data, setData] = useState(undefined);
|
|
284
|
+
const [error, setError] = useState(undefined);
|
|
285
|
+
const [isLoading, setIsLoading] = useState(enabled);
|
|
286
|
+
const inputRef = useRef(input);
|
|
287
|
+
inputRef.current = input;
|
|
288
|
+
const fetchData = useCallback(async () => {
|
|
289
|
+
if (!enabled)
|
|
290
|
+
return;
|
|
291
|
+
setIsLoading(true);
|
|
292
|
+
setError(undefined);
|
|
293
|
+
try {
|
|
294
|
+
const result = await procedure.query(inputRef.current);
|
|
295
|
+
setData(result);
|
|
296
|
+
} catch (err) {
|
|
297
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
298
|
+
} finally {
|
|
299
|
+
setIsLoading(false);
|
|
300
|
+
}
|
|
301
|
+
}, [procedure, enabled]);
|
|
302
|
+
useEffect(() => {
|
|
303
|
+
fetchData();
|
|
304
|
+
}, [fetchData]);
|
|
305
|
+
useEffect(() => {
|
|
306
|
+
if (!refetchInterval || !enabled)
|
|
307
|
+
return;
|
|
308
|
+
const interval = setInterval(fetchData, refetchInterval);
|
|
309
|
+
return () => clearInterval(interval);
|
|
310
|
+
}, [refetchInterval, fetchData, enabled]);
|
|
311
|
+
return {
|
|
312
|
+
data,
|
|
313
|
+
error,
|
|
314
|
+
isLoading,
|
|
315
|
+
isError: error !== undefined,
|
|
316
|
+
isSuccess: data !== undefined && error === undefined,
|
|
317
|
+
refetch: fetchData
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
function useMutation(procedure, options = {}) {
|
|
321
|
+
const { onSuccess, onError, onSettled } = options;
|
|
322
|
+
const [data, setData] = useState(undefined);
|
|
323
|
+
const [error, setError] = useState(undefined);
|
|
324
|
+
const [isPending, setIsPending] = useState(false);
|
|
325
|
+
const [isSuccess, setIsSuccess] = useState(false);
|
|
326
|
+
const mutateAsync = useCallback(async (input) => {
|
|
327
|
+
setIsPending(true);
|
|
328
|
+
setError(undefined);
|
|
329
|
+
setIsSuccess(false);
|
|
330
|
+
try {
|
|
331
|
+
const result = await procedure.mutate(input);
|
|
332
|
+
setData(result);
|
|
333
|
+
setIsSuccess(true);
|
|
334
|
+
onSuccess?.(result);
|
|
335
|
+
return result;
|
|
336
|
+
} catch (err) {
|
|
337
|
+
const error2 = err instanceof Error ? err : new Error(String(err));
|
|
338
|
+
setError(error2);
|
|
339
|
+
onError?.(error2);
|
|
340
|
+
throw error2;
|
|
341
|
+
} finally {
|
|
342
|
+
setIsPending(false);
|
|
343
|
+
onSettled?.();
|
|
344
|
+
}
|
|
345
|
+
}, [procedure, onSuccess, onError, onSettled]);
|
|
346
|
+
const mutate = useCallback((input) => {
|
|
347
|
+
mutateAsync(input).catch(() => {});
|
|
348
|
+
}, [mutateAsync]);
|
|
349
|
+
const reset = useCallback(() => {
|
|
350
|
+
setData(undefined);
|
|
351
|
+
setError(undefined);
|
|
352
|
+
setIsPending(false);
|
|
353
|
+
setIsSuccess(false);
|
|
354
|
+
}, []);
|
|
355
|
+
return {
|
|
356
|
+
mutate,
|
|
357
|
+
mutateAsync,
|
|
358
|
+
data,
|
|
359
|
+
error,
|
|
360
|
+
isPending,
|
|
361
|
+
isError: error !== undefined,
|
|
362
|
+
isSuccess,
|
|
363
|
+
reset
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
function useSubscription(procedure, options = {}) {
|
|
367
|
+
const { input, enabled = true, onData, onError } = options;
|
|
368
|
+
const [data, setData] = useState(undefined);
|
|
369
|
+
const [history, setHistory] = useState([]);
|
|
370
|
+
const [error, setError] = useState(undefined);
|
|
371
|
+
const [status, setStatus] = useState("idle");
|
|
372
|
+
const unsubscribeRef = useRef(null);
|
|
373
|
+
const inputRef = useRef(input);
|
|
374
|
+
inputRef.current = input;
|
|
375
|
+
const subscribe = useCallback(() => {
|
|
376
|
+
if (!enabled)
|
|
377
|
+
return;
|
|
378
|
+
setStatus("connecting");
|
|
379
|
+
setError(undefined);
|
|
380
|
+
const callbacks = {
|
|
381
|
+
onData: (value) => {
|
|
382
|
+
setStatus("connected");
|
|
383
|
+
setData(value);
|
|
384
|
+
setHistory((prev) => [...prev, value]);
|
|
385
|
+
onData?.(value);
|
|
386
|
+
},
|
|
387
|
+
onError: (err) => {
|
|
388
|
+
setStatus("error");
|
|
389
|
+
setError(err);
|
|
390
|
+
onError?.(err);
|
|
391
|
+
},
|
|
392
|
+
onComplete: () => {
|
|
393
|
+
setStatus("closed");
|
|
394
|
+
}
|
|
395
|
+
};
|
|
396
|
+
if (inputRef.current !== undefined) {
|
|
397
|
+
unsubscribeRef.current = procedure.subscribe(inputRef.current, callbacks);
|
|
398
|
+
} else {
|
|
399
|
+
unsubscribeRef.current = procedure.subscribe(callbacks);
|
|
400
|
+
}
|
|
401
|
+
}, [procedure, enabled, onData, onError]);
|
|
402
|
+
const unsubscribe = useCallback(() => {
|
|
403
|
+
unsubscribeRef.current?.();
|
|
404
|
+
unsubscribeRef.current = null;
|
|
405
|
+
setStatus("closed");
|
|
406
|
+
}, []);
|
|
407
|
+
const resubscribe = useCallback(() => {
|
|
408
|
+
unsubscribe();
|
|
409
|
+
setHistory([]);
|
|
410
|
+
subscribe();
|
|
411
|
+
}, [subscribe, unsubscribe]);
|
|
412
|
+
useEffect(() => {
|
|
413
|
+
subscribe();
|
|
414
|
+
return () => {
|
|
415
|
+
unsubscribeRef.current?.();
|
|
416
|
+
};
|
|
417
|
+
}, [subscribe]);
|
|
418
|
+
return {
|
|
419
|
+
data,
|
|
420
|
+
history,
|
|
421
|
+
error,
|
|
422
|
+
status,
|
|
423
|
+
isActive: status === "connecting" || status === "connected",
|
|
424
|
+
unsubscribe,
|
|
425
|
+
resubscribe
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
export {
|
|
429
|
+
useSubscription,
|
|
430
|
+
useQuery,
|
|
431
|
+
useMutation,
|
|
432
|
+
createClient
|
|
433
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client - typed proxy for calling RPC procedures with WebSocket subscriptions
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* import { createClient } from '@ereo/rpc/client';
|
|
6
|
+
* import type { Api } from './api/router';
|
|
7
|
+
*
|
|
8
|
+
* const rpc = createClient<Api>({
|
|
9
|
+
* httpEndpoint: '/api/rpc',
|
|
10
|
+
* wsEndpoint: 'ws://localhost:3000/api/rpc',
|
|
11
|
+
* });
|
|
12
|
+
*
|
|
13
|
+
* // Queries and mutations
|
|
14
|
+
* const user = await rpc.users.me.query();
|
|
15
|
+
* const post = await rpc.posts.create.mutate({ title: 'Hello' });
|
|
16
|
+
*
|
|
17
|
+
* // Subscriptions with auto-reconnect
|
|
18
|
+
* const unsub = rpc.posts.onCreate.subscribe({
|
|
19
|
+
* onData: (post) => console.log('New post:', post),
|
|
20
|
+
* onError: (err) => console.error(err),
|
|
21
|
+
* });
|
|
22
|
+
*/
|
|
23
|
+
import type { Router, RouterDef, InferClient } from './types';
|
|
24
|
+
export interface RPCClientOptions {
|
|
25
|
+
/** HTTP endpoint for queries/mutations (e.g., '/api/rpc') */
|
|
26
|
+
httpEndpoint: string;
|
|
27
|
+
/** WebSocket endpoint for subscriptions (e.g., 'ws://localhost:3000/api/rpc') */
|
|
28
|
+
wsEndpoint?: string;
|
|
29
|
+
/** Custom fetch function */
|
|
30
|
+
fetch?: typeof fetch;
|
|
31
|
+
/** Custom headers */
|
|
32
|
+
headers?: Record<string, string> | (() => Record<string, string>);
|
|
33
|
+
/** WebSocket reconnect options */
|
|
34
|
+
reconnect?: {
|
|
35
|
+
enabled?: boolean;
|
|
36
|
+
maxAttempts?: number;
|
|
37
|
+
delayMs?: number;
|
|
38
|
+
maxDelayMs?: number;
|
|
39
|
+
};
|
|
40
|
+
/** Use POST for all requests (queries and mutations) instead of GET for queries */
|
|
41
|
+
usePostForQueries?: boolean;
|
|
42
|
+
/** WebSocket heartbeat interval in milliseconds (default: 30000) */
|
|
43
|
+
heartbeatInterval?: number;
|
|
44
|
+
/** Enable WebSocket heartbeat (default: true) */
|
|
45
|
+
heartbeatEnabled?: boolean;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Create a typed client from a router type
|
|
49
|
+
*/
|
|
50
|
+
export declare function createClient<T extends Router<RouterDef>>(optionsOrEndpoint: string | RPCClientOptions): InferClient<T['_def']>;
|
|
51
|
+
export interface RPCClientError extends Error {
|
|
52
|
+
code: string;
|
|
53
|
+
path: string;
|
|
54
|
+
details?: unknown;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EACV,MAAM,EACN,SAAS,EACT,WAAW,EAMZ,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,gBAAgB;IAC/B,6DAA6D;IAC7D,YAAY,EAAE,MAAM,CAAC;IACrB,iFAAiF;IACjF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,qBAAqB;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAClE,kCAAkC;IAClC,SAAS,CAAC,EAAE;QACV,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,mFAAmF;IACnF,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,oEAAoE;IACpE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iDAAiD;IACjD,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAQD;;GAEG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,SAAS,CAAC,EACtD,iBAAiB,EAAE,MAAM,GAAG,gBAAgB,GAC3C,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAkWxB;AAiBD,MAAM,WAAW,cAAe,SAAQ,KAAK;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ereo/rpc - Context Bridge for RPC and Loaders/Actions
|
|
3
|
+
*
|
|
4
|
+
* Provides shared context between RPC procedures and route loaders/actions.
|
|
5
|
+
* This allows auth state, database connections, and other context to be
|
|
6
|
+
* shared seamlessly between the two patterns.
|
|
7
|
+
*/
|
|
8
|
+
import type { BaseContext } from './types';
|
|
9
|
+
/**
|
|
10
|
+
* Context provider function - creates shared context from a request
|
|
11
|
+
* This is used by both RPC handlers and route loaders/actions
|
|
12
|
+
*/
|
|
13
|
+
export type ContextProvider<TContext = any> = (request: Request) => TContext | Promise<TContext>;
|
|
14
|
+
/**
|
|
15
|
+
* Set the global context provider that will be used by both RPC and loaders
|
|
16
|
+
*
|
|
17
|
+
* Usage in your app setup:
|
|
18
|
+
* import { setContextProvider } from '@ereo/rpc';
|
|
19
|
+
*
|
|
20
|
+
* setContextProvider(async (request) => {
|
|
21
|
+
* const session = await getSession(request);
|
|
22
|
+
* const db = createDbConnection();
|
|
23
|
+
* return { session, db, user: session?.user };
|
|
24
|
+
* });
|
|
25
|
+
*/
|
|
26
|
+
export declare function setContextProvider<TContext>(provider: ContextProvider<TContext>): void;
|
|
27
|
+
/**
|
|
28
|
+
* Get the current global context provider
|
|
29
|
+
*/
|
|
30
|
+
export declare function getContextProvider(): ContextProvider | null;
|
|
31
|
+
/**
|
|
32
|
+
* Clear the global context provider (useful for testing)
|
|
33
|
+
*/
|
|
34
|
+
export declare function clearContextProvider(): void;
|
|
35
|
+
/**
|
|
36
|
+
* Create context from a request using the global provider
|
|
37
|
+
* Falls back to an empty object if no provider is set
|
|
38
|
+
*/
|
|
39
|
+
export declare function createSharedContext(request: Request): Promise<any>;
|
|
40
|
+
/**
|
|
41
|
+
* RPC Router options with context bridge support
|
|
42
|
+
*/
|
|
43
|
+
export interface RouterWithContextOptions<TContext> {
|
|
44
|
+
/** Context provider for this router */
|
|
45
|
+
context?: ContextProvider<TContext>;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Enhanced router creation that supports context bridge
|
|
49
|
+
* This is an alternative to createRouter that provides better integration
|
|
50
|
+
*/
|
|
51
|
+
export interface ContextBridgeConfig<TContext> {
|
|
52
|
+
/** Context provider - called for each request */
|
|
53
|
+
context: ContextProvider<TContext>;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Helper to create a typed context provider
|
|
57
|
+
* Provides better type inference for TypeScript users
|
|
58
|
+
*/
|
|
59
|
+
export declare function createContextProvider<TContext>(provider: ContextProvider<TContext>): ContextProvider<TContext>;
|
|
60
|
+
/**
|
|
61
|
+
* Middleware that injects shared context into the procedure context
|
|
62
|
+
* Usage: procedure.use(withSharedContext())
|
|
63
|
+
*/
|
|
64
|
+
export declare function withSharedContext(): (opts: {
|
|
65
|
+
ctx: BaseContext;
|
|
66
|
+
next: <T>(ctx: T) => {
|
|
67
|
+
ok: true;
|
|
68
|
+
ctx: T;
|
|
69
|
+
} | {
|
|
70
|
+
ok: false;
|
|
71
|
+
error: any;
|
|
72
|
+
};
|
|
73
|
+
}) => Promise<any>;
|
|
74
|
+
/**
|
|
75
|
+
* Hook for React components to access shared context
|
|
76
|
+
* This bridges server context to the client
|
|
77
|
+
*/
|
|
78
|
+
export declare function useSharedContext<T>(): T | null;
|
|
79
|
+
//# sourceMappingURL=context-bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-bridge.d.ts","sourceRoot":"","sources":["../../src/context-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C;;;GAGG;AACH,MAAM,MAAM,eAAe,CAAC,QAAQ,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAOjG;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,EAAE,eAAe,CAAC,QAAQ,CAAC,GAAG,IAAI,CAEtF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,eAAe,GAAG,IAAI,CAE3D;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAKxE;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB,CAAC,QAAQ;IAChD,uCAAuC;IACvC,OAAO,CAAC,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAC;CACrC;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB,CAAC,QAAQ;IAC3C,iDAAiD;IACjD,OAAO,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAC;CACpC;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAC5C,QAAQ,EAAE,eAAe,CAAC,QAAQ,CAAC,GAClC,eAAe,CAAC,QAAQ,CAAC,CAE3B;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,CAAC,IAAI,EAAE;IAC1C,GAAG,EAAE,WAAW,CAAC;IACjB,IAAI,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,KAAK;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,GAAG,EAAE,CAAC,CAAA;KAAE,GAAG;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,GAAG,CAAA;KAAE,CAAC;CACvE,KAAK,OAAO,CAAC,GAAG,CAAC,CAMjB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,KAAK,CAAC,GAAG,IAAI,CAQ9C"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React hooks for RPC calls including subscriptions
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* const { data, isLoading } = useQuery(rpc.users.me);
|
|
6
|
+
* const { mutate, isPending } = useMutation(rpc.posts.create);
|
|
7
|
+
* const { data, status } = useSubscription(rpc.posts.onCreate);
|
|
8
|
+
*/
|
|
9
|
+
import type { SubscriptionCallbacks, Unsubscribe } from './types';
|
|
10
|
+
type QueryFn<TInput, TOutput> = TInput extends void ? {
|
|
11
|
+
query: () => Promise<TOutput>;
|
|
12
|
+
} : {
|
|
13
|
+
query: (input: TInput) => Promise<TOutput>;
|
|
14
|
+
};
|
|
15
|
+
export interface UseQueryOptions<TInput> {
|
|
16
|
+
input?: TInput;
|
|
17
|
+
enabled?: boolean;
|
|
18
|
+
refetchInterval?: number;
|
|
19
|
+
}
|
|
20
|
+
export interface UseQueryResult<TOutput> {
|
|
21
|
+
data: TOutput | undefined;
|
|
22
|
+
error: Error | undefined;
|
|
23
|
+
isLoading: boolean;
|
|
24
|
+
isError: boolean;
|
|
25
|
+
isSuccess: boolean;
|
|
26
|
+
refetch: () => Promise<void>;
|
|
27
|
+
}
|
|
28
|
+
export declare function useQuery<TInput, TOutput>(procedure: QueryFn<TInput, TOutput>, options?: UseQueryOptions<TInput>): UseQueryResult<TOutput>;
|
|
29
|
+
type MutationFn<TInput, TOutput> = TInput extends void ? {
|
|
30
|
+
mutate: () => Promise<TOutput>;
|
|
31
|
+
} : {
|
|
32
|
+
mutate: (input: TInput) => Promise<TOutput>;
|
|
33
|
+
};
|
|
34
|
+
export interface UseMutationOptions<TOutput> {
|
|
35
|
+
onSuccess?: (data: TOutput) => void;
|
|
36
|
+
onError?: (error: Error) => void;
|
|
37
|
+
onSettled?: () => void;
|
|
38
|
+
}
|
|
39
|
+
export interface UseMutationResult<TInput, TOutput> {
|
|
40
|
+
mutate: TInput extends void ? () => void : (input: TInput) => void;
|
|
41
|
+
mutateAsync: TInput extends void ? () => Promise<TOutput> : (input: TInput) => Promise<TOutput>;
|
|
42
|
+
data: TOutput | undefined;
|
|
43
|
+
error: Error | undefined;
|
|
44
|
+
isPending: boolean;
|
|
45
|
+
isError: boolean;
|
|
46
|
+
isSuccess: boolean;
|
|
47
|
+
reset: () => void;
|
|
48
|
+
}
|
|
49
|
+
export declare function useMutation<TInput, TOutput>(procedure: MutationFn<TInput, TOutput>, options?: UseMutationOptions<TOutput>): UseMutationResult<TInput, TOutput>;
|
|
50
|
+
type SubscribeFn<TInput, TOutput> = TInput extends void ? {
|
|
51
|
+
subscribe: (callbacks: SubscriptionCallbacks<TOutput>) => Unsubscribe;
|
|
52
|
+
} : {
|
|
53
|
+
subscribe: (input: TInput, callbacks: SubscriptionCallbacks<TOutput>) => Unsubscribe;
|
|
54
|
+
};
|
|
55
|
+
export type SubscriptionStatus = 'idle' | 'connecting' | 'connected' | 'error' | 'closed';
|
|
56
|
+
export interface UseSubscriptionOptions<TInput> {
|
|
57
|
+
input?: TInput;
|
|
58
|
+
enabled?: boolean;
|
|
59
|
+
onData?: (data: unknown) => void;
|
|
60
|
+
onError?: (error: Error) => void;
|
|
61
|
+
}
|
|
62
|
+
export interface UseSubscriptionResult<TOutput> {
|
|
63
|
+
/** Most recent data received */
|
|
64
|
+
data: TOutput | undefined;
|
|
65
|
+
/** All data received (for accumulating results) */
|
|
66
|
+
history: TOutput[];
|
|
67
|
+
/** Current error if any */
|
|
68
|
+
error: Error | undefined;
|
|
69
|
+
/** Connection status */
|
|
70
|
+
status: SubscriptionStatus;
|
|
71
|
+
/** Whether currently receiving data */
|
|
72
|
+
isActive: boolean;
|
|
73
|
+
/** Manually unsubscribe */
|
|
74
|
+
unsubscribe: () => void;
|
|
75
|
+
/** Resubscribe after unsubscribing */
|
|
76
|
+
resubscribe: () => void;
|
|
77
|
+
}
|
|
78
|
+
export declare function useSubscription<TInput, TOutput>(procedure: SubscribeFn<TInput, TOutput>, options?: UseSubscriptionOptions<TInput>): UseSubscriptionResult<TOutput>;
|
|
79
|
+
export {};
|
|
80
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/hooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ereo/rpc - Typed RPC layer for EreoJS
|
|
3
|
+
*
|
|
4
|
+
* Server-side exports for defining routers and procedures
|
|
5
|
+
*/
|
|
6
|
+
export { procedure } from './procedure';
|
|
7
|
+
export type { ProcedureBuilder } from './procedure';
|
|
8
|
+
export { query, mutation, subscription } from './procedure';
|
|
9
|
+
export { createRouter, RPCError, errors } from './router';
|
|
10
|
+
export type { Router, BunWebSocketHandler } from './router';
|
|
11
|
+
export { rpcPlugin } from './plugin';
|
|
12
|
+
export type { RPCPluginOptions, RPCPluginResult, BunWebSocketConfig, RPCPlugin } from './plugin';
|
|
13
|
+
export { setContextProvider, getContextProvider, clearContextProvider, createSharedContext, createContextProvider, withSharedContext, useSharedContext, } from './context-bridge';
|
|
14
|
+
export type { ContextProvider, RouterWithContextOptions, ContextBridgeConfig, } from './context-bridge';
|
|
15
|
+
export { logging, rateLimit, clearRateLimitStore, createAuthMiddleware, requireRoles, validate, extend, timing, catchErrors, } from './middleware';
|
|
16
|
+
export type { LoggingOptions, RateLimitOptions, TimingContext } from './middleware';
|
|
17
|
+
export type { Schema, BaseContext, ExtendedContext, MiddlewareFn, MiddlewareDef, MiddlewareResult, ProcedureType, ProcedureDef, QueryProcedure, MutationProcedure, SubscriptionProcedure, SubscriptionYield, AnyProcedure, RouterDef, InferClient, SubscriptionCallbacks, Unsubscribe, RPCRequest, RPCResponse, RPCErrorShape, WSClientMessage, WSServerMessage, WSConnectionData, } from './types';
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGpD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG5D,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAC1D,YAAY,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAG5D,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAEjG,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,eAAe,EACf,wBAAwB,EACxB,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,OAAO,EACP,SAAS,EACT,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,EACZ,QAAQ,EACR,MAAM,EACN,MAAM,EACN,WAAW,GACZ,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAGpF,YAAY,EAEV,MAAM,EAGN,WAAW,EACX,eAAe,EAGf,YAAY,EACZ,aAAa,EACb,gBAAgB,EAGhB,aAAa,EACb,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,YAAY,EAGZ,SAAS,EAGT,WAAW,EACX,qBAAqB,EACrB,WAAW,EAGX,UAAU,EACV,WAAW,EACX,aAAa,EACb,eAAe,EACf,eAAe,EACf,gBAAgB,GACjB,MAAM,SAAS,CAAC"}
|