@igoforth/ws-rpc 1.0.0
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/LICENSE +21 -0
- package/README.md +446 -0
- package/dist/adapters/client.d.ts +117 -0
- package/dist/adapters/client.js +241 -0
- package/dist/adapters/cloudflare-do.d.ts +72 -0
- package/dist/adapters/cloudflare-do.js +192 -0
- package/dist/adapters/index.d.ts +13 -0
- package/dist/adapters/index.js +16 -0
- package/dist/adapters/server.d.ts +10 -0
- package/dist/adapters/server.js +122 -0
- package/dist/adapters/types.d.ts +125 -0
- package/dist/adapters/types.js +3 -0
- package/dist/codecs/cbor.d.ts +16 -0
- package/dist/codecs/cbor.js +36 -0
- package/dist/codecs/factory.d.ts +3 -0
- package/dist/codecs/factory.js +3 -0
- package/dist/codecs/index.d.ts +5 -0
- package/dist/codecs/index.js +5 -0
- package/dist/codecs/json.d.ts +4 -0
- package/dist/codecs/json.js +4 -0
- package/dist/codecs/msgpack.d.ts +16 -0
- package/dist/codecs/msgpack.js +34 -0
- package/dist/codecs-BmYG2d_U.js +0 -0
- package/dist/default-BkrMd28n.js +253 -0
- package/dist/default-xDNNMrg0.d.ts +129 -0
- package/dist/durable-MZjkvyS6.js +165 -0
- package/dist/errors-5BfreE63.js +96 -0
- package/dist/errors.d.ts +69 -0
- package/dist/errors.js +7 -0
- package/dist/factory-3ziwTuZe.js +132 -0
- package/dist/factory-C1v0AEHY.d.ts +101 -0
- package/dist/index-Be7jjS77.d.ts +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +14 -0
- package/dist/interface-C4S-WCqW.d.ts +120 -0
- package/dist/json-54Z2bIIs.d.ts +22 -0
- package/dist/json-Bshec-bZ.js +41 -0
- package/dist/memory-Bqb3KEVr.js +48 -0
- package/dist/memory-D1nGjzzH.d.ts +41 -0
- package/dist/multi-peer-BAi9yVzp.js +242 -0
- package/dist/peers/default.d.ts +8 -0
- package/dist/peers/default.js +8 -0
- package/dist/peers/durable.d.ts +136 -0
- package/dist/peers/durable.js +9 -0
- package/dist/peers/index.d.ts +10 -0
- package/dist/peers/index.js +9 -0
- package/dist/protocol-DA84zrc2.d.ts +211 -0
- package/dist/protocol-_mpoOPp6.js +192 -0
- package/dist/protocol.d.ts +6 -0
- package/dist/protocol.js +6 -0
- package/dist/reconnect-CGAA_1Gf.js +26 -0
- package/dist/reconnect-DbcN0R_1.d.ts +35 -0
- package/dist/schema-CN5HHHku.d.ts +108 -0
- package/dist/schema.d.ts +2 -0
- package/dist/schema.js +43 -0
- package/dist/server-zTjpJpoX.d.ts +209 -0
- package/dist/sql-CCjc6Bid.js +142 -0
- package/dist/sql-DPmHOeZy.d.ts +131 -0
- package/dist/storage/index.d.ts +8 -0
- package/dist/storage/index.js +7 -0
- package/dist/storage/interface.d.ts +3 -0
- package/dist/storage/interface.js +0 -0
- package/dist/storage/memory.d.ts +7 -0
- package/dist/storage/memory.js +6 -0
- package/dist/storage/sql.d.ts +7 -0
- package/dist/storage/sql.js +6 -0
- package/dist/types-Be-qmQu0.d.ts +111 -0
- package/dist/types-D_psiH09.js +13 -0
- package/dist/types.d.ts +7 -0
- package/dist/types.js +3 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +3 -0
- package/dist/utils/reconnect.d.ts +2 -0
- package/dist/utils/reconnect.js +3 -0
- package/package.json +156 -0
- package/src/adapters/client.ts +396 -0
- package/src/adapters/cloudflare-do.ts +346 -0
- package/src/adapters/index.ts +16 -0
- package/src/adapters/multi-peer.ts +404 -0
- package/src/adapters/server.ts +192 -0
- package/src/adapters/types.ts +202 -0
- package/src/codecs/cbor.ts +42 -0
- package/src/codecs/factory.ts +210 -0
- package/src/codecs/index.ts +30 -0
- package/src/codecs/json.ts +42 -0
- package/src/codecs/msgpack.ts +36 -0
- package/src/errors.ts +105 -0
- package/src/index.ts +102 -0
- package/src/peers/default.ts +433 -0
- package/src/peers/durable.ts +280 -0
- package/src/peers/index.ts +13 -0
- package/src/protocol.ts +306 -0
- package/src/schema.ts +167 -0
- package/src/storage/index.ts +20 -0
- package/src/storage/interface.ts +146 -0
- package/src/storage/memory.ts +84 -0
- package/src/storage/sql.ts +266 -0
- package/src/types.ts +158 -0
- package/src/utils/index.ts +9 -0
- package/src/utils/reconnect.ts +51 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { t as RpcPeer } from "./default-BkrMd28n.js";
|
|
2
|
+
|
|
3
|
+
//#region src/peers/durable.ts
|
|
4
|
+
/**
|
|
5
|
+
* Durable RPC Peer
|
|
6
|
+
*
|
|
7
|
+
* Extends RpcPeer to add:
|
|
8
|
+
* - Hibernation-safe continuation-based calls via `callWithCallback`
|
|
9
|
+
* - Automatic recovery of pending calls after hibernation
|
|
10
|
+
* - Timeout cleanup for stale calls
|
|
11
|
+
*/
|
|
12
|
+
var DurableRpcPeer = class extends RpcPeer {
|
|
13
|
+
storage;
|
|
14
|
+
actor;
|
|
15
|
+
durableTimeout;
|
|
16
|
+
durableRequestCounter = 0;
|
|
17
|
+
/**
|
|
18
|
+
* Create a durable RPC peer
|
|
19
|
+
*
|
|
20
|
+
* @param options - Combined RPC peer and durable options
|
|
21
|
+
*/
|
|
22
|
+
constructor(options) {
|
|
23
|
+
super(options);
|
|
24
|
+
this.storage = options.storage;
|
|
25
|
+
this.actor = options.actor;
|
|
26
|
+
this.durableTimeout = options.durableTimeout ?? options.timeout ?? 3e4;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Make a hibernation-safe RPC call using continuation-passing style
|
|
30
|
+
*
|
|
31
|
+
* Instead of returning a Promise, the result will be passed to the
|
|
32
|
+
* named callback method on the actor. This survives DO hibernation.
|
|
33
|
+
*
|
|
34
|
+
* @param method - Remote method to call
|
|
35
|
+
* @param params - Parameters for the method
|
|
36
|
+
* @param callback - Name of method on actor to call with result
|
|
37
|
+
* @param timeout - Optional timeout override (ms)
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```ts
|
|
41
|
+
* // Make the call
|
|
42
|
+
* peer.callWithCallback('executeOrder', { market, side }, 'onOrderExecuted');
|
|
43
|
+
*
|
|
44
|
+
* // Define the callback on your actor
|
|
45
|
+
* onOrderExecuted(result: OrderResult, context: CallContext) {
|
|
46
|
+
* console.log('Order executed:', result);
|
|
47
|
+
* console.log('Latency:', context.latencyMs, 'ms');
|
|
48
|
+
* }
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
callWithCallback(method, params, callback, timeout) {
|
|
52
|
+
if (typeof this.actor[callback] !== "function") throw new Error(`Callback '${callback}' is not a function on the actor`);
|
|
53
|
+
const now = Date.now();
|
|
54
|
+
const timeoutMs = timeout ?? this.durableTimeout;
|
|
55
|
+
const call = {
|
|
56
|
+
id: `durable-${++this.durableRequestCounter}`,
|
|
57
|
+
method,
|
|
58
|
+
params,
|
|
59
|
+
callback,
|
|
60
|
+
sentAt: now,
|
|
61
|
+
timeoutAt: now + timeoutMs
|
|
62
|
+
};
|
|
63
|
+
this.storage.save(call);
|
|
64
|
+
const ws = this.getWebSocket();
|
|
65
|
+
if (ws.readyState === 1) ws.send(this.protocol.createRequest(call.id, method, params));
|
|
66
|
+
else console.warn(`Cannot send durable call '${method}': connection not open`);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Handle an incoming WebSocket message
|
|
70
|
+
*
|
|
71
|
+
* Checks durable storage for continuation-based calls before
|
|
72
|
+
* delegating to the base class for promise-based calls.
|
|
73
|
+
*
|
|
74
|
+
* @param data - Raw WebSocket message data
|
|
75
|
+
*/
|
|
76
|
+
handleMessage(data) {
|
|
77
|
+
const message = this.protocol.safeDecodeMessage(data);
|
|
78
|
+
if (!message) {
|
|
79
|
+
super.handleMessage(data);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (message.type === "rpc:response" || message.type === "rpc:error") {
|
|
83
|
+
const id = message.id;
|
|
84
|
+
const call = this.storage.get(id);
|
|
85
|
+
if (call) {
|
|
86
|
+
this.storage.delete(id);
|
|
87
|
+
const context = {
|
|
88
|
+
call,
|
|
89
|
+
latencyMs: Date.now() - call.sentAt
|
|
90
|
+
};
|
|
91
|
+
const callbackFn = this.actor[call.callback];
|
|
92
|
+
if (typeof callbackFn === "function") if (message.type === "rpc:response") callbackFn.call(this.actor, message.result, context);
|
|
93
|
+
else callbackFn.call(this.actor, new Error(message.message), context);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
super.handleMessage(data);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Get all pending durable calls (for debugging/monitoring)
|
|
101
|
+
*
|
|
102
|
+
* @returns Array of all pending calls
|
|
103
|
+
*/
|
|
104
|
+
getPendingCalls() {
|
|
105
|
+
return this.storage.listAll();
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Get expired calls that have exceeded their timeout
|
|
109
|
+
*
|
|
110
|
+
* @returns Array of calls that have exceeded their timeout
|
|
111
|
+
*/
|
|
112
|
+
getExpiredCalls() {
|
|
113
|
+
return this.storage.listExpired(Date.now());
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Clean up expired calls
|
|
117
|
+
*
|
|
118
|
+
* Call this periodically (e.g., on alarm) to remove stale calls.
|
|
119
|
+
*
|
|
120
|
+
* @returns The expired calls that were removed (for optional error handling)
|
|
121
|
+
*/
|
|
122
|
+
cleanupExpired() {
|
|
123
|
+
const expired = this.getExpiredCalls();
|
|
124
|
+
for (const call of expired) this.storage.delete(call.id);
|
|
125
|
+
return expired;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Clear all pending durable calls
|
|
129
|
+
*/
|
|
130
|
+
clearPendingCalls() {
|
|
131
|
+
this.storage.clear();
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Create a factory function for DurableRpcPeer instances
|
|
136
|
+
*
|
|
137
|
+
* Pre-configures the durable storage and actor, returning a function
|
|
138
|
+
* that only needs RPC options to create a new peer.
|
|
139
|
+
*
|
|
140
|
+
* @param durableOptions - Durable configuration (storage, actor, timeout)
|
|
141
|
+
* @returns Factory function that creates DurableRpcPeer instances
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```ts
|
|
145
|
+
* const createPeer = createDurableRpcPeerFactory({
|
|
146
|
+
* storage: new SqlPendingCallStorage(sql),
|
|
147
|
+
* actor: this,
|
|
148
|
+
* });
|
|
149
|
+
*
|
|
150
|
+
* // Later, create peers for each connection
|
|
151
|
+
* const peer = createPeer({
|
|
152
|
+
* ws,
|
|
153
|
+
* localSchema,
|
|
154
|
+
* remoteSchema,
|
|
155
|
+
* provider,
|
|
156
|
+
* });
|
|
157
|
+
* ```
|
|
158
|
+
*/
|
|
159
|
+
const createDurableRpcPeerFactory = (durableOptions) => (rpcOptions) => new DurableRpcPeer({
|
|
160
|
+
...durableOptions,
|
|
161
|
+
...rpcOptions
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
//#endregion
|
|
165
|
+
export { createDurableRpcPeerFactory as n, DurableRpcPeer as t };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { n as RpcErrorCodes } from "./protocol-_mpoOPp6.js";
|
|
2
|
+
|
|
3
|
+
//#region src/errors.ts
|
|
4
|
+
/**
|
|
5
|
+
* RPC Error Classes
|
|
6
|
+
*
|
|
7
|
+
* Custom error types for RPC operations.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Base class for all RPC errors
|
|
11
|
+
*
|
|
12
|
+
* @param code - RPC error code (from RpcErrorCodes)
|
|
13
|
+
* @param message - Human-readable error message
|
|
14
|
+
* @param data - Optional additional error data
|
|
15
|
+
*/
|
|
16
|
+
var RpcError = class extends Error {
|
|
17
|
+
code;
|
|
18
|
+
data;
|
|
19
|
+
constructor(code, message, data) {
|
|
20
|
+
super(message);
|
|
21
|
+
this.name = "RpcError";
|
|
22
|
+
this.code = code;
|
|
23
|
+
this.data = data;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Thrown when an RPC request times out waiting for a response
|
|
28
|
+
*
|
|
29
|
+
* @param method - Name of the method that timed out
|
|
30
|
+
* @param timeoutMs - Timeout duration in milliseconds
|
|
31
|
+
*/
|
|
32
|
+
var RpcTimeoutError = class extends RpcError {
|
|
33
|
+
method;
|
|
34
|
+
timeoutMs;
|
|
35
|
+
constructor(method, timeoutMs) {
|
|
36
|
+
super(RpcErrorCodes.TIMEOUT, `RPC request '${method}' timed out after ${timeoutMs}ms`);
|
|
37
|
+
this.name = "RpcTimeoutError";
|
|
38
|
+
this.method = method;
|
|
39
|
+
this.timeoutMs = timeoutMs;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Thrown when the remote handler returns an error
|
|
44
|
+
*
|
|
45
|
+
* @param method - Name of the remote method that failed
|
|
46
|
+
* @param code - RPC error code from the remote
|
|
47
|
+
* @param message - Error message from the remote
|
|
48
|
+
* @param data - Optional additional error data from the remote
|
|
49
|
+
*/
|
|
50
|
+
var RpcRemoteError = class extends RpcError {
|
|
51
|
+
method;
|
|
52
|
+
constructor(method, code, message, data) {
|
|
53
|
+
super(code, message, data);
|
|
54
|
+
this.name = "RpcRemoteError";
|
|
55
|
+
this.method = method;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Thrown when the WebSocket connection closes while a request is pending
|
|
60
|
+
*
|
|
61
|
+
* @param message - Optional custom message (defaults to "WebSocket connection closed")
|
|
62
|
+
*/
|
|
63
|
+
var RpcConnectionClosed = class extends RpcError {
|
|
64
|
+
constructor(message = "WebSocket connection closed") {
|
|
65
|
+
super(RpcErrorCodes.CONNECTION_CLOSED, message);
|
|
66
|
+
this.name = "RpcConnectionClosed";
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Thrown when input or output validation fails
|
|
71
|
+
*
|
|
72
|
+
* @param message - Description of the validation failure
|
|
73
|
+
* @param data - Optional Zod error or validation details
|
|
74
|
+
*/
|
|
75
|
+
var RpcValidationError = class extends RpcError {
|
|
76
|
+
constructor(message, data) {
|
|
77
|
+
super(RpcErrorCodes.VALIDATION_ERROR, message, data);
|
|
78
|
+
this.name = "RpcValidationError";
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Thrown when a requested method doesn't exist on the provider
|
|
83
|
+
*
|
|
84
|
+
* @param method - Name of the method that was not found
|
|
85
|
+
*/
|
|
86
|
+
var RpcMethodNotFoundError = class extends RpcError {
|
|
87
|
+
method;
|
|
88
|
+
constructor(method) {
|
|
89
|
+
super(RpcErrorCodes.METHOD_NOT_FOUND, `Method '${method}' not found`);
|
|
90
|
+
this.name = "RpcMethodNotFoundError";
|
|
91
|
+
this.method = method;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
//#endregion
|
|
96
|
+
export { RpcTimeoutError as a, RpcRemoteError as i, RpcError as n, RpcValidationError as o, RpcMethodNotFoundError as r, RpcConnectionClosed as t };
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
//#region src/errors.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* RPC Error Classes
|
|
4
|
+
*
|
|
5
|
+
* Custom error types for RPC operations.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Base class for all RPC errors
|
|
9
|
+
*
|
|
10
|
+
* @param code - RPC error code (from RpcErrorCodes)
|
|
11
|
+
* @param message - Human-readable error message
|
|
12
|
+
* @param data - Optional additional error data
|
|
13
|
+
*/
|
|
14
|
+
declare class RpcError extends Error {
|
|
15
|
+
readonly code: number;
|
|
16
|
+
readonly data?: unknown;
|
|
17
|
+
constructor(code: number, message: string, data?: unknown);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Thrown when an RPC request times out waiting for a response
|
|
21
|
+
*
|
|
22
|
+
* @param method - Name of the method that timed out
|
|
23
|
+
* @param timeoutMs - Timeout duration in milliseconds
|
|
24
|
+
*/
|
|
25
|
+
declare class RpcTimeoutError extends RpcError {
|
|
26
|
+
readonly method: string;
|
|
27
|
+
readonly timeoutMs: number;
|
|
28
|
+
constructor(method: string, timeoutMs: number);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Thrown when the remote handler returns an error
|
|
32
|
+
*
|
|
33
|
+
* @param method - Name of the remote method that failed
|
|
34
|
+
* @param code - RPC error code from the remote
|
|
35
|
+
* @param message - Error message from the remote
|
|
36
|
+
* @param data - Optional additional error data from the remote
|
|
37
|
+
*/
|
|
38
|
+
declare class RpcRemoteError extends RpcError {
|
|
39
|
+
readonly method: string;
|
|
40
|
+
constructor(method: string, code: number, message: string, data?: unknown);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Thrown when the WebSocket connection closes while a request is pending
|
|
44
|
+
*
|
|
45
|
+
* @param message - Optional custom message (defaults to "WebSocket connection closed")
|
|
46
|
+
*/
|
|
47
|
+
declare class RpcConnectionClosed extends RpcError {
|
|
48
|
+
constructor(message?: string);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Thrown when input or output validation fails
|
|
52
|
+
*
|
|
53
|
+
* @param message - Description of the validation failure
|
|
54
|
+
* @param data - Optional Zod error or validation details
|
|
55
|
+
*/
|
|
56
|
+
declare class RpcValidationError extends RpcError {
|
|
57
|
+
constructor(message: string, data?: unknown);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Thrown when a requested method doesn't exist on the provider
|
|
61
|
+
*
|
|
62
|
+
* @param method - Name of the method that was not found
|
|
63
|
+
*/
|
|
64
|
+
declare class RpcMethodNotFoundError extends RpcError {
|
|
65
|
+
readonly method: string;
|
|
66
|
+
constructor(method: string);
|
|
67
|
+
}
|
|
68
|
+
//#endregion
|
|
69
|
+
export { RpcConnectionClosed, RpcError, RpcMethodNotFoundError, RpcRemoteError, RpcTimeoutError, RpcValidationError };
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import "./factory-3ziwTuZe.js";
|
|
2
|
+
import "./json-Bshec-bZ.js";
|
|
3
|
+
import "./codecs-BmYG2d_U.js";
|
|
4
|
+
import "./protocol-_mpoOPp6.js";
|
|
5
|
+
import { a as RpcTimeoutError, i as RpcRemoteError, n as RpcError, o as RpcValidationError, r as RpcMethodNotFoundError, t as RpcConnectionClosed } from "./errors-5BfreE63.js";
|
|
6
|
+
|
|
7
|
+
export { RpcConnectionClosed, RpcError, RpcMethodNotFoundError, RpcRemoteError, RpcTimeoutError, RpcValidationError };
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
|
|
3
|
+
//#region src/codecs/factory.ts
|
|
4
|
+
/**
|
|
5
|
+
* RPC Codecs
|
|
6
|
+
*
|
|
7
|
+
* Zod-based codecs for serialization with built-in validation.
|
|
8
|
+
* Provides factories for creating codecs that encode to string or binary.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* // JSON codec with validation
|
|
13
|
+
* const MyDataCodec = jsonCodec(MyDataSchema);
|
|
14
|
+
* const encoded = MyDataCodec.encode(data); // string
|
|
15
|
+
* const decoded = MyDataCodec.decode(encoded); // validated MyData
|
|
16
|
+
*
|
|
17
|
+
* // Safe decode with error handling
|
|
18
|
+
* const result = MyDataCodec.safeDecode(encoded);
|
|
19
|
+
* if (result.success) {
|
|
20
|
+
* console.log(result.data);
|
|
21
|
+
* } else {
|
|
22
|
+
* console.error(result.error);
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Create a custom string codec factory
|
|
28
|
+
*
|
|
29
|
+
* Use this to integrate custom serialization libraries that encode to strings.
|
|
30
|
+
*
|
|
31
|
+
* @param serialize - Function to serialize a value to string
|
|
32
|
+
* @param deserialize - Function to deserialize a string to a value
|
|
33
|
+
* @param formatName - Name of the format for error messages
|
|
34
|
+
* @returns A codec factory function
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* import superjson from "superjson";
|
|
39
|
+
*
|
|
40
|
+
* const superJsonCodec = createStringCodecFactory(
|
|
41
|
+
* superjson.stringify,
|
|
42
|
+
* superjson.parse,
|
|
43
|
+
* "superjson"
|
|
44
|
+
* );
|
|
45
|
+
*
|
|
46
|
+
* // Now supports Date, Map, Set, BigInt, etc.
|
|
47
|
+
* const DataCodec = superJsonCodec(z.object({
|
|
48
|
+
* timestamp: z.date(),
|
|
49
|
+
* values: z.map(z.string(), z.number()),
|
|
50
|
+
* }));
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
function createStringCodecFactory(serialize, deserialize, formatName) {
|
|
54
|
+
return (schema, options) => {
|
|
55
|
+
return z.codec(z.string(), schema, {
|
|
56
|
+
decode: (text, ctx) => {
|
|
57
|
+
try {
|
|
58
|
+
return deserialize(text);
|
|
59
|
+
} catch (err) {
|
|
60
|
+
ctx.issues.push({
|
|
61
|
+
code: "invalid_format",
|
|
62
|
+
format: formatName,
|
|
63
|
+
input: text,
|
|
64
|
+
message: options?.errorMessage ?? (err instanceof Error ? err.message : `Invalid ${formatName}`)
|
|
65
|
+
});
|
|
66
|
+
return z.NEVER;
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
encode: (value) => serialize(value)
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Create a custom binary codec factory
|
|
75
|
+
*
|
|
76
|
+
* Use this to integrate binary serialization libraries like MessagePack or CBOR.
|
|
77
|
+
*
|
|
78
|
+
* @param serialize - Function to serialize a value to Uint8Array
|
|
79
|
+
* @param deserialize - Function to deserialize a Uint8Array to a value
|
|
80
|
+
* @param formatName - Name of the format for error messages
|
|
81
|
+
* @returns A codec factory function
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```ts
|
|
85
|
+
* import { encode, decode } from "@msgpack/msgpack";
|
|
86
|
+
*
|
|
87
|
+
* const msgpackCodec = createBinaryCodecFactory(
|
|
88
|
+
* (v) => new Uint8Array(encode(v)),
|
|
89
|
+
* decode,
|
|
90
|
+
* "msgpack"
|
|
91
|
+
* );
|
|
92
|
+
*
|
|
93
|
+
* const DataCodec = msgpackCodec(MySchema);
|
|
94
|
+
* const bytes = DataCodec.encode(data); // Uint8Array
|
|
95
|
+
* const data = DataCodec.decode(bytes); // validated
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
function createBinaryCodecFactory(serialize, deserialize, formatName) {
|
|
99
|
+
return (schema, options) => {
|
|
100
|
+
return z.codec(z.instanceof(Uint8Array), schema, {
|
|
101
|
+
decode: (bytes, ctx) => {
|
|
102
|
+
try {
|
|
103
|
+
return deserialize(bytes);
|
|
104
|
+
} catch (err) {
|
|
105
|
+
ctx.issues.push({
|
|
106
|
+
code: "invalid_format",
|
|
107
|
+
format: formatName,
|
|
108
|
+
input: String(bytes),
|
|
109
|
+
message: options?.errorMessage ?? (err instanceof Error ? err.message : `Invalid ${formatName}`)
|
|
110
|
+
});
|
|
111
|
+
return z.NEVER;
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
encode: (value) => serialize(value)
|
|
115
|
+
});
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Helper to check if a codec encodes to string
|
|
120
|
+
*/
|
|
121
|
+
function isStringCodec(codec) {
|
|
122
|
+
return codec._zod.def.in._zod.def.type === "string";
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Helper to check if a codec encodes to binary
|
|
126
|
+
*/
|
|
127
|
+
function isBinaryCodec(codec) {
|
|
128
|
+
return !isStringCodec(codec);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
//#endregion
|
|
132
|
+
export { isStringCodec as i, createStringCodecFactory as n, isBinaryCodec as r, createBinaryCodecFactory as t };
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { d as LiteralStringUnion } from "./schema-CN5HHHku.js";
|
|
2
|
+
import * as z from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/codecs/factory.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Type alias for a Zod codec that encodes to string
|
|
8
|
+
*/
|
|
9
|
+
type StringCodec<T extends z.ZodType = z.ZodType> = z.ZodCodec<z.ZodString, T>;
|
|
10
|
+
/**
|
|
11
|
+
* Type alias for a Zod codec that encodes to Uint8Array
|
|
12
|
+
*/
|
|
13
|
+
type BinaryCodec<T extends z.ZodType = z.ZodType> = z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>>, T>;
|
|
14
|
+
/**
|
|
15
|
+
* Options for codec factories
|
|
16
|
+
*/
|
|
17
|
+
interface CodecOptions {
|
|
18
|
+
/** Custom error message for parse failures */
|
|
19
|
+
errorMessage?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Codec factory signature for custom serialization libraries
|
|
23
|
+
*
|
|
24
|
+
* Implement this interface to create codecs using libraries like
|
|
25
|
+
* superjson, devalue, or MessagePack.
|
|
26
|
+
*/
|
|
27
|
+
interface CodecFactory<TEncoded> {
|
|
28
|
+
<T extends z.ZodType>(schema: T, options?: CodecOptions): z.ZodCodec<string extends TEncoded ? z.ZodString : z.ZodCustom<TEncoded>, T>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Create a custom string codec factory
|
|
32
|
+
*
|
|
33
|
+
* Use this to integrate custom serialization libraries that encode to strings.
|
|
34
|
+
*
|
|
35
|
+
* @param serialize - Function to serialize a value to string
|
|
36
|
+
* @param deserialize - Function to deserialize a string to a value
|
|
37
|
+
* @param formatName - Name of the format for error messages
|
|
38
|
+
* @returns A codec factory function
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* import superjson from "superjson";
|
|
43
|
+
*
|
|
44
|
+
* const superJsonCodec = createStringCodecFactory(
|
|
45
|
+
* superjson.stringify,
|
|
46
|
+
* superjson.parse,
|
|
47
|
+
* "superjson"
|
|
48
|
+
* );
|
|
49
|
+
*
|
|
50
|
+
* // Now supports Date, Map, Set, BigInt, etc.
|
|
51
|
+
* const DataCodec = superJsonCodec(z.object({
|
|
52
|
+
* timestamp: z.date(),
|
|
53
|
+
* values: z.map(z.string(), z.number()),
|
|
54
|
+
* }));
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
declare function createStringCodecFactory(serialize: (value: unknown) => string, deserialize: (text: string) => unknown, formatName: LiteralStringUnion<z.core.$ZodStringFormats>): CodecFactory<string>;
|
|
58
|
+
/**
|
|
59
|
+
* Create a custom binary codec factory
|
|
60
|
+
*
|
|
61
|
+
* Use this to integrate binary serialization libraries like MessagePack or CBOR.
|
|
62
|
+
*
|
|
63
|
+
* @param serialize - Function to serialize a value to Uint8Array
|
|
64
|
+
* @param deserialize - Function to deserialize a Uint8Array to a value
|
|
65
|
+
* @param formatName - Name of the format for error messages
|
|
66
|
+
* @returns A codec factory function
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```ts
|
|
70
|
+
* import { encode, decode } from "@msgpack/msgpack";
|
|
71
|
+
*
|
|
72
|
+
* const msgpackCodec = createBinaryCodecFactory(
|
|
73
|
+
* (v) => new Uint8Array(encode(v)),
|
|
74
|
+
* decode,
|
|
75
|
+
* "msgpack"
|
|
76
|
+
* );
|
|
77
|
+
*
|
|
78
|
+
* const DataCodec = msgpackCodec(MySchema);
|
|
79
|
+
* const bytes = DataCodec.encode(data); // Uint8Array
|
|
80
|
+
* const data = DataCodec.decode(bytes); // validated
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
declare function createBinaryCodecFactory(serialize: (value: unknown) => Uint8Array<ArrayBuffer>, deserialize: (bytes: Uint8Array<ArrayBuffer>) => unknown, formatName: string): CodecFactory<Uint8Array<ArrayBuffer>>;
|
|
84
|
+
/**
|
|
85
|
+
* Wire codec - either string or binary
|
|
86
|
+
*/
|
|
87
|
+
type WireCodec<T extends z.ZodType = z.ZodType> = StringCodec<T> | BinaryCodec<T>;
|
|
88
|
+
/**
|
|
89
|
+
* Wire data - what gets sent over WebSocket
|
|
90
|
+
*/
|
|
91
|
+
type WireData = string | Uint8Array<ArrayBuffer>;
|
|
92
|
+
/**
|
|
93
|
+
* Helper to check if a codec encodes to string
|
|
94
|
+
*/
|
|
95
|
+
declare function isStringCodec(codec: z.ZodCodec<z.ZodType, z.ZodType>): codec is StringCodec;
|
|
96
|
+
/**
|
|
97
|
+
* Helper to check if a codec encodes to binary
|
|
98
|
+
*/
|
|
99
|
+
declare function isBinaryCodec(codec: z.ZodCodec<z.ZodType, z.ZodType>): codec is BinaryCodec;
|
|
100
|
+
//#endregion
|
|
101
|
+
export { WireCodec as a, createStringCodecFactory as c, StringCodec as i, isBinaryCodec as l, CodecFactory as n, WireData as o, CodecOptions as r, createBinaryCodecFactory as s, BinaryCodec as t, isStringCodec as u };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { _ as method, a as InferEventData, c as InferMethods, f as MethodDef, g as event, i as EventHandler, l as InferOutput, m as RpcSchema, n as EventDef, o as InferEvents, p as Provider, s as InferInput, t as Driver } from "./schema-CN5HHHku.js";
|
|
2
|
+
import "./factory-C1v0AEHY.js";
|
|
3
|
+
import "./json-54Z2bIIs.js";
|
|
4
|
+
import "./index-Be7jjS77.js";
|
|
5
|
+
import { _ as createProtocol, a as RpcEvent, c as RpcMessageCodec, d as RpcRequest, f as RpcRequestSchema, h as RpcWireCodec, i as RpcErrorSchema, l as RpcMessageSchema, m as RpcResponseSchema, n as RpcError$1, o as RpcEventSchema, p as RpcResponse, r as RpcErrorCodes, s as RpcMessage, t as JsonProtocol, u as RpcProtocol } from "./protocol-DA84zrc2.js";
|
|
6
|
+
import { a as IRpcOptions, c as WebSocketOptions, i as IRpcConnection, l as WebSocketReadyState, n as IMethodController, o as IWebSocket, r as IMinWebSocket, s as IWebSocketServer, t as IEventController, u as WebSocketServerOptions } from "./types-Be-qmQu0.js";
|
|
7
|
+
import { n as calculateReconnectDelay, r as defaultReconnectOptions, t as ReconnectOptions } from "./reconnect-DbcN0R_1.js";
|
|
8
|
+
import { RpcConnectionClosed, RpcError, RpcMethodNotFoundError, RpcRemoteError, RpcTimeoutError, RpcValidationError } from "./errors.js";
|
|
9
|
+
import { a as PendingCallStorage, i as PendingCall, o as StorageMode, r as MaybePromise, s as SyncPendingCallStorage, t as AsyncPendingCallStorage } from "./interface-C4S-WCqW.js";
|
|
10
|
+
import { t as MemoryPendingCallStorage } from "./memory-D1nGjzzH.js";
|
|
11
|
+
import { t as SqlPendingCallStorage } from "./sql-DPmHOeZy.js";
|
|
12
|
+
import "./storage/index.js";
|
|
13
|
+
import "./utils/index.js";
|
|
14
|
+
export { type AsyncPendingCallStorage, type Driver, type EventDef, type EventHandler, type IEventController, type IMethodController, type IMinWebSocket, type IRpcConnection, type IRpcOptions, type IWebSocket, type IWebSocketServer, type InferEventData, type InferEvents, type InferInput, type InferMethods, type InferOutput, JsonProtocol, type MaybePromise, MemoryPendingCallStorage, type MethodDef, type PendingCall, type PendingCallStorage, type Provider, type ReconnectOptions, RpcConnectionClosed, RpcError, RpcErrorCodes, type RpcError$1 as RpcErrorMessage, RpcErrorSchema, type RpcEvent, RpcEventSchema, type RpcMessage, RpcMessageCodec, RpcMessageSchema, RpcMethodNotFoundError, type RpcProtocol, RpcRemoteError, type RpcRequest, RpcRequestSchema, type RpcResponse, RpcResponseSchema, type RpcSchema, RpcTimeoutError, RpcValidationError, type RpcWireCodec, SqlPendingCallStorage, type StorageMode, type SyncPendingCallStorage, type WebSocketOptions, WebSocketReadyState, type WebSocketServerOptions, calculateReconnectDelay, createProtocol, defaultReconnectOptions, event, method };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import "./factory-3ziwTuZe.js";
|
|
2
|
+
import "./json-Bshec-bZ.js";
|
|
3
|
+
import "./codecs-BmYG2d_U.js";
|
|
4
|
+
import { a as RpcMessageCodec, c as RpcResponseSchema, i as RpcEventSchema, l as createProtocol, n as RpcErrorCodes, o as RpcMessageSchema, r as RpcErrorSchema, s as RpcRequestSchema, t as JsonProtocol } from "./protocol-_mpoOPp6.js";
|
|
5
|
+
import { a as RpcTimeoutError, i as RpcRemoteError, n as RpcError, o as RpcValidationError, r as RpcMethodNotFoundError, t as RpcConnectionClosed } from "./errors-5BfreE63.js";
|
|
6
|
+
import { event, method } from "./schema.js";
|
|
7
|
+
import { t as MemoryPendingCallStorage } from "./memory-Bqb3KEVr.js";
|
|
8
|
+
import { t as SqlPendingCallStorage } from "./sql-CCjc6Bid.js";
|
|
9
|
+
import "./storage/index.js";
|
|
10
|
+
import { t as WebSocketReadyState } from "./types-D_psiH09.js";
|
|
11
|
+
import { n as defaultReconnectOptions, t as calculateReconnectDelay } from "./reconnect-CGAA_1Gf.js";
|
|
12
|
+
import "./utils/index.js";
|
|
13
|
+
|
|
14
|
+
export { JsonProtocol, MemoryPendingCallStorage, RpcConnectionClosed, RpcError, RpcErrorCodes, RpcErrorSchema, RpcEventSchema, RpcMessageCodec, RpcMessageSchema, RpcMethodNotFoundError, RpcRemoteError, RpcRequestSchema, RpcResponseSchema, RpcTimeoutError, RpcValidationError, SqlPendingCallStorage, WebSocketReadyState, calculateReconnectDelay, createProtocol, defaultReconnectOptions, event, method };
|