@irpclib/irpc 1.0.0-beta.24 → 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/dist/adapter.d.ts +76 -0
- package/dist/adapter.js +109 -0
- package/dist/call.d.ts +6 -2
- package/dist/call.js +5 -8
- package/dist/enum.d.ts +1 -10
- package/dist/enum.js +2 -11
- package/dist/error.d.ts +124 -58
- package/dist/error.js +224 -55
- package/dist/index.d.ts +8 -7
- package/dist/index.js +5 -3
- package/dist/module.d.ts +53 -12
- package/dist/module.js +91 -41
- package/dist/reader.js +3 -2
- package/dist/resolver.d.ts +1 -1
- package/dist/resolver.js +7 -25
- package/dist/router.d.ts +3 -6
- package/dist/router.js +3 -6
- package/dist/state.d.ts +37 -5
- package/dist/state.js +44 -7
- package/dist/store.d.ts +2 -2
- package/dist/stream.d.ts +3 -3
- package/dist/stream.js +4 -13
- package/dist/transport.d.ts +3 -3
- package/dist/transport.js +2 -5
- package/dist/types.d.ts +101 -17
- package/dist/types.js +8 -1
- package/package.json +6 -4
package/dist/module.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { HandlerError, ResolveError, StubError, TransportError } from "./error.js";
|
|
1
2
|
import { IRPCCacher } from "./cache.js";
|
|
2
3
|
import { IRPC_STATUS } from "./enum.js";
|
|
3
|
-
import { ERROR_CODE, ERROR_MESSAGE } from "./error.js";
|
|
4
4
|
import { getAbortSignal } from "./context.js";
|
|
5
5
|
import { RemoteState } from "./state.js";
|
|
6
6
|
import { IRPCReader } from "./reader.js";
|
|
@@ -37,6 +37,7 @@ var IRPCPackage = class {
|
|
|
37
37
|
config = {
|
|
38
38
|
name: "global",
|
|
39
39
|
version: "1.0.0",
|
|
40
|
+
key: "id",
|
|
40
41
|
timeout: DEFAULT_TIMEOUT
|
|
41
42
|
};
|
|
42
43
|
/**
|
|
@@ -71,23 +72,29 @@ var IRPCPackage = class {
|
|
|
71
72
|
this.configure(config ?? {});
|
|
72
73
|
IRPC_STORE.register(this);
|
|
73
74
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
75
|
+
declare(nameOrOptions, seedOrConfig, config) {
|
|
76
|
+
let options;
|
|
77
|
+
if (typeof nameOrOptions === "string") if (typeof seedOrConfig === "function") options = {
|
|
78
|
+
name: nameOrOptions,
|
|
79
|
+
seed: seedOrConfig,
|
|
80
|
+
...config
|
|
81
|
+
};
|
|
82
|
+
else options = {
|
|
83
|
+
name: nameOrOptions,
|
|
84
|
+
...seedOrConfig
|
|
85
|
+
};
|
|
86
|
+
else options = nameOrOptions;
|
|
81
87
|
const $options = options;
|
|
82
|
-
if (this.specs.has($options.name)) throw
|
|
88
|
+
if (this.specs.has($options.name)) throw StubError.duplicate($options.name);
|
|
89
|
+
if ($options.init && !$options.seed) $options.seed = $options.init;
|
|
83
90
|
const spec = {
|
|
84
|
-
|
|
91
|
+
seed: () => void 0,
|
|
85
92
|
...$options
|
|
86
93
|
};
|
|
87
94
|
const calls = /* @__PURE__ */ new Map();
|
|
88
95
|
const caches = new IRPCCacher();
|
|
89
96
|
const stub = ((...args) => {
|
|
90
|
-
return execute(args, new IRPCReader(uuid(), spec.
|
|
97
|
+
return execute(args, new IRPCReader(uuid(), spec.seed()));
|
|
91
98
|
});
|
|
92
99
|
/** Browser only stub for single immediate execution **/
|
|
93
100
|
stub.once = (...args) => {
|
|
@@ -100,7 +107,7 @@ var IRPCPackage = class {
|
|
|
100
107
|
return prepare(typeof getArgs === "function" ? getArgs : () => getArgs, true, debounce);
|
|
101
108
|
};
|
|
102
109
|
stub.later = (debounce) => {
|
|
103
|
-
const reader = new IRPCReader(uuid(), spec.
|
|
110
|
+
const reader = new IRPCReader(uuid(), spec.seed(), IRPC_STATUS.IDLE, true);
|
|
104
111
|
if (debounce) {
|
|
105
112
|
const [schedule, cancel] = microtask(debounce);
|
|
106
113
|
reader.dispatch = (...args) => schedule(() => {
|
|
@@ -125,7 +132,7 @@ var IRPCPackage = class {
|
|
|
125
132
|
* @returns {IRPCReader<IRPCData>} - The reader for the call.
|
|
126
133
|
*/
|
|
127
134
|
function prepare(getArgs, deferred, debounce = 0) {
|
|
128
|
-
const reader = new IRPCReader(uuid(), spec.
|
|
135
|
+
const reader = new IRPCReader(uuid(), spec.seed(), deferred ? IRPC_STATUS.IDLE : IRPC_STATUS.PENDING);
|
|
129
136
|
if (isBrowser()) {
|
|
130
137
|
const observer = createObserver(() => {
|
|
131
138
|
observer.reset();
|
|
@@ -149,29 +156,28 @@ var IRPCPackage = class {
|
|
|
149
156
|
return reader;
|
|
150
157
|
}
|
|
151
158
|
const execute = (args, reader) => {
|
|
152
|
-
if (!this.transport && typeof spec.handler !== "function") return Promise.reject(
|
|
159
|
+
if (!this.transport && typeof spec.handler !== "function") return Promise.reject(TransportError.missing());
|
|
153
160
|
reader.status = IRPC_STATUS.PENDING;
|
|
154
161
|
const callKey = JSON.stringify(args);
|
|
155
162
|
const cached = caches.get(callKey);
|
|
156
163
|
if (cached) return cached.value;
|
|
157
164
|
if (spec.coalesce !== false && calls.has(callKey)) return calls.get(callKey);
|
|
158
|
-
const { timeout, maxRetries, retryDelay, retryMode
|
|
165
|
+
const { timeout, maxRetries, retryDelay, retryMode } = {
|
|
159
166
|
...this.config,
|
|
160
167
|
...spec
|
|
161
168
|
};
|
|
162
|
-
const config = {
|
|
169
|
+
const config$1 = {
|
|
163
170
|
timeout,
|
|
164
171
|
maxRetries,
|
|
165
172
|
retryDelay,
|
|
166
|
-
retryMode
|
|
167
|
-
init
|
|
173
|
+
retryMode
|
|
168
174
|
};
|
|
169
175
|
const hooks = this.hooks.get(spec);
|
|
170
176
|
if (hooks) hooks.forEach((hook) => hook({
|
|
171
177
|
name: spec.name,
|
|
172
178
|
args
|
|
173
179
|
}));
|
|
174
|
-
const call = typeof spec.handler === "function" ? intercept(spec, args, reader) : this.transport.call(spec, args, config, reader);
|
|
180
|
+
const call = typeof spec.handler === "function" ? intercept(spec, args, reader) : this.transport.call(spec, args, config$1, reader);
|
|
175
181
|
calls.set(callKey, call);
|
|
176
182
|
if (spec.maxAge) caches.set(callKey, call, spec.maxAge);
|
|
177
183
|
onCleanup(() => call.close());
|
|
@@ -185,6 +191,50 @@ var IRPCPackage = class {
|
|
|
185
191
|
return stub;
|
|
186
192
|
}
|
|
187
193
|
/**
|
|
194
|
+
* Declares CRUD stubs (get, create, update, delete) for an entity
|
|
195
|
+
* @param name - The entity name used as prefix for stub names
|
|
196
|
+
* @param seed - Factory function returning a default entity instance
|
|
197
|
+
* @param options - Optional configuration for caching, schemas, and call behavior
|
|
198
|
+
* @returns An object containing the four CRUD stub functions
|
|
199
|
+
*/
|
|
200
|
+
crud(name, seed, options) {
|
|
201
|
+
const { description, schema, maxAge, coalesce,...callConfig } = options ?? {};
|
|
202
|
+
const desc = (method) => typeof description === "string" ? description : description?.[method];
|
|
203
|
+
const init = (method) => ({
|
|
204
|
+
...callConfig,
|
|
205
|
+
name: `${name}.${method}`,
|
|
206
|
+
seed,
|
|
207
|
+
description: desc(method),
|
|
208
|
+
schema: schema?.[method],
|
|
209
|
+
...method === "get" ? { maxAge } : {},
|
|
210
|
+
coalesce
|
|
211
|
+
});
|
|
212
|
+
return {
|
|
213
|
+
get: this.declare(init("get")),
|
|
214
|
+
create: this.declare(init("create")),
|
|
215
|
+
update: this.declare(init("update")),
|
|
216
|
+
delete: this.declare(init("delete"))
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Removes CRUD methods from a stubs object and unregisters their specs
|
|
221
|
+
* @param stubs - The CRUD stubs object to modify
|
|
222
|
+
* @param keys - The method names to remove
|
|
223
|
+
* @returns The stubs object without the excluded methods
|
|
224
|
+
*/
|
|
225
|
+
exclude(stubs, keys) {
|
|
226
|
+
for (const key of keys) {
|
|
227
|
+
const stub = stubs[key];
|
|
228
|
+
if (stub) {
|
|
229
|
+
const spec = this.stubs.get(stub);
|
|
230
|
+
if (spec) this.specs.delete(spec.name);
|
|
231
|
+
this.stubs.delete(stub);
|
|
232
|
+
}
|
|
233
|
+
delete stubs[key];
|
|
234
|
+
}
|
|
235
|
+
return stubs;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
188
238
|
* Resolves and executes an IRPC call based on a request object
|
|
189
239
|
* @param req - The request containing the IRPC name and arguments
|
|
190
240
|
* @returns The result of the IRPC execution
|
|
@@ -192,8 +242,8 @@ var IRPCPackage = class {
|
|
|
192
242
|
*/
|
|
193
243
|
resolve(req) {
|
|
194
244
|
const spec = this.specs.get(req.name);
|
|
195
|
-
if (!spec) return Promise.reject(
|
|
196
|
-
if (typeof spec.handler !== "function") return Promise.reject(
|
|
245
|
+
if (!spec) return Promise.reject(ResolveError.notFound(req.name));
|
|
246
|
+
if (typeof spec.handler !== "function") return Promise.reject(HandlerError.missing(req.name));
|
|
197
247
|
return spec.handler(...req.args);
|
|
198
248
|
}
|
|
199
249
|
/**
|
|
@@ -204,28 +254,28 @@ var IRPCPackage = class {
|
|
|
204
254
|
* @throws Error if the stub or handler is invalid, or if no IRPC exists for the stub
|
|
205
255
|
*/
|
|
206
256
|
construct(stub, handler) {
|
|
207
|
-
if (typeof stub !== "function") throw
|
|
208
|
-
if (typeof handler !== "function") throw
|
|
257
|
+
if (typeof stub !== "function") throw StubError.invalid();
|
|
258
|
+
if (typeof handler !== "function") throw HandlerError.invalid();
|
|
209
259
|
const spec = this.stubs.get(stub);
|
|
210
|
-
if (!spec?.name) throw
|
|
260
|
+
if (!spec?.name) throw StubError.notFound();
|
|
211
261
|
spec.handler = handler;
|
|
212
262
|
return this;
|
|
213
263
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
const error = new Error(ERROR_MESSAGE[ERROR_CODE.NOT_FOUND]);
|
|
224
|
-
IRPC_STORE.error(error);
|
|
264
|
+
hook(stubOrGroup, handler) {
|
|
265
|
+
if (typeof stubOrGroup === "function") {
|
|
266
|
+
if (!this.stubs.has(stubOrGroup)) {
|
|
267
|
+
const error = StubError.notFound();
|
|
268
|
+
IRPC_STORE.error(error);
|
|
269
|
+
return this;
|
|
270
|
+
}
|
|
271
|
+
const spec = this.stubs.get(stubOrGroup);
|
|
272
|
+
this.hooks.get(spec).add(handler);
|
|
225
273
|
return this;
|
|
226
274
|
}
|
|
227
|
-
const
|
|
228
|
-
|
|
275
|
+
for (const stub of Object.values(stubOrGroup)) if (typeof stub === "function" && this.stubs.has(stub)) {
|
|
276
|
+
const spec = this.stubs.get(stub);
|
|
277
|
+
this.hooks.get(spec).add(handler);
|
|
278
|
+
}
|
|
229
279
|
return this;
|
|
230
280
|
}
|
|
231
281
|
/**
|
|
@@ -236,7 +286,7 @@ var IRPCPackage = class {
|
|
|
236
286
|
*/
|
|
237
287
|
async resolveHooks(req) {
|
|
238
288
|
const spec = this.specs.get(req.name);
|
|
239
|
-
if (!spec || !this.hooks.has(spec)) throw
|
|
289
|
+
if (!spec || !this.hooks.has(spec)) throw StubError.notFound();
|
|
240
290
|
const hooks = this.hooks.get(spec);
|
|
241
291
|
for (const hook of hooks) await hook(req);
|
|
242
292
|
}
|
|
@@ -247,7 +297,7 @@ var IRPCPackage = class {
|
|
|
247
297
|
* @throws Error if the transport is not a valid Transport instance
|
|
248
298
|
*/
|
|
249
299
|
use(transport) {
|
|
250
|
-
if (!(transport instanceof IRPCTransport)) throw
|
|
300
|
+
if (!(transport instanceof IRPCTransport)) throw TransportError.invalid();
|
|
251
301
|
if (this.transport) this.transport.modules.delete(this);
|
|
252
302
|
transport.modules.add(this);
|
|
253
303
|
this.config.transport = transport;
|
|
@@ -269,8 +319,8 @@ var IRPCPackage = class {
|
|
|
269
319
|
* @throws Error if the provided name or version is invalid
|
|
270
320
|
*/
|
|
271
321
|
configure(config) {
|
|
272
|
-
if (config.name && !NAME_CONSTRAINT.test(config.name)) throw
|
|
273
|
-
if (config.version && !VERSION_CONSTRAINT.test(config.version)) throw
|
|
322
|
+
if (config.name && !NAME_CONSTRAINT.test(config.name)) throw StubError.invalidName(config.name);
|
|
323
|
+
if (config.version && !VERSION_CONSTRAINT.test(config.version)) throw StubError.invalidVersion(config.version);
|
|
274
324
|
Object.assign(this.config, config);
|
|
275
325
|
return this;
|
|
276
326
|
}
|
package/dist/reader.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { IRPCError } from "./error.js";
|
|
1
2
|
import { IRPC_PACKET_TYPE, IRPC_STATUS } from "./enum.js";
|
|
2
3
|
import { RemoteState } from "./state.js";
|
|
3
4
|
import { replay } from "@anchorlib/core";
|
|
@@ -30,11 +31,11 @@ var IRPCReader = class extends RemoteState {
|
|
|
30
31
|
*/
|
|
31
32
|
push(packet) {
|
|
32
33
|
packet.arrivedAt = Date.now();
|
|
33
|
-
if (packet.type === IRPC_PACKET_TYPE.ANSWER) if (packet.status === IRPC_STATUS.ERROR) this.error =
|
|
34
|
+
if (packet.type === IRPC_PACKET_TYPE.ANSWER) if (packet.status === IRPC_STATUS.ERROR) this.error = IRPCError.from(packet.error);
|
|
34
35
|
else this.data = packet.data;
|
|
35
36
|
else if (packet.type === IRPC_PACKET_TYPE.EVENT) replay(this.state, packet.data);
|
|
36
37
|
else if (packet.type === IRPC_PACKET_TYPE.CLOSE) {
|
|
37
|
-
if (packet.error) this.error =
|
|
38
|
+
if (packet.error) this.error = IRPCError.from(packet.error);
|
|
38
39
|
}
|
|
39
40
|
this.status = packet.status;
|
|
40
41
|
}
|
package/dist/resolver.d.ts
CHANGED
package/dist/resolver.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { HandlerError, ResolveError } from "./error.js";
|
|
2
2
|
import { RemoteState } from "./state.js";
|
|
3
3
|
|
|
4
4
|
//#region src/resolver.ts
|
|
@@ -40,20 +40,14 @@ var IRPCResolver = class {
|
|
|
40
40
|
if (!this.spec) return {
|
|
41
41
|
id,
|
|
42
42
|
name,
|
|
43
|
-
error:
|
|
44
|
-
code: ERROR_CODE.NOT_FOUND,
|
|
45
|
-
message: `IRPC "${name}" does not exist.`
|
|
46
|
-
}
|
|
43
|
+
error: ResolveError.notFound(name).json()
|
|
47
44
|
};
|
|
48
45
|
const { schema } = this.spec;
|
|
49
46
|
const inputs = parseInput(args, schema?.input);
|
|
50
47
|
if (!inputs.success) return {
|
|
51
48
|
id,
|
|
52
49
|
name,
|
|
53
|
-
error:
|
|
54
|
-
code: ERROR_CODE.INVALID_INPUT,
|
|
55
|
-
message: inputs.error
|
|
56
|
-
}
|
|
50
|
+
error: ResolveError.invalidInput(inputs.error).json()
|
|
57
51
|
};
|
|
58
52
|
return this.forward({
|
|
59
53
|
id,
|
|
@@ -85,10 +79,7 @@ var IRPCResolver = class {
|
|
|
85
79
|
if (!output$1.success) return {
|
|
86
80
|
id,
|
|
87
81
|
name,
|
|
88
|
-
error:
|
|
89
|
-
code: ERROR_CODE.INVALID_OUTPUT,
|
|
90
|
-
message: output$1.error?.message
|
|
91
|
-
}
|
|
82
|
+
error: ResolveError.invalidOutput(output$1.error).json()
|
|
92
83
|
};
|
|
93
84
|
return {
|
|
94
85
|
id,
|
|
@@ -103,10 +94,7 @@ var IRPCResolver = class {
|
|
|
103
94
|
if (!output$1.success) return {
|
|
104
95
|
id,
|
|
105
96
|
name,
|
|
106
|
-
error:
|
|
107
|
-
code: ERROR_CODE.INVALID_OUTPUT,
|
|
108
|
-
message: output$1.error?.message
|
|
109
|
-
}
|
|
97
|
+
error: ResolveError.invalidOutput(output$1.error).json()
|
|
110
98
|
};
|
|
111
99
|
return {
|
|
112
100
|
id,
|
|
@@ -123,19 +111,13 @@ var IRPCResolver = class {
|
|
|
123
111
|
else return {
|
|
124
112
|
id,
|
|
125
113
|
name,
|
|
126
|
-
error:
|
|
127
|
-
code: ERROR_CODE.INVALID_OUTPUT,
|
|
128
|
-
message: output.error?.message
|
|
129
|
-
}
|
|
114
|
+
error: ResolveError.invalidOutput(output.error).json()
|
|
130
115
|
};
|
|
131
116
|
} catch (error) {
|
|
132
117
|
return {
|
|
133
118
|
id,
|
|
134
119
|
name,
|
|
135
|
-
error:
|
|
136
|
-
code: ERROR_CODE.HANDLER_ERROR,
|
|
137
|
-
message: error.message
|
|
138
|
-
}
|
|
120
|
+
error: HandlerError.failed(error).json()
|
|
139
121
|
};
|
|
140
122
|
}
|
|
141
123
|
}
|
package/dist/router.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { IRPCPackage } from "./module.js";
|
|
2
1
|
import { IRPCTransport } from "./transport.js";
|
|
3
|
-
import { IRPCRequest } from "./types.js";
|
|
2
|
+
import { IRPCPacketError, IRPCRequest } from "./types.js";
|
|
3
|
+
import { IRPCPackage } from "./module.js";
|
|
4
4
|
|
|
5
5
|
//#region src/router.d.ts
|
|
6
6
|
type IRPCHook = () => void | Promise<void>;
|
|
@@ -42,10 +42,7 @@ declare class IRPCRouter {
|
|
|
42
42
|
name: string;
|
|
43
43
|
type: "close";
|
|
44
44
|
status: "error";
|
|
45
|
-
error:
|
|
46
|
-
code: string;
|
|
47
|
-
message: string;
|
|
48
|
-
};
|
|
45
|
+
error: IRPCPacketError;
|
|
49
46
|
createdAt: number;
|
|
50
47
|
} | undefined>;
|
|
51
48
|
}
|
package/dist/router.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { HookError } from "./error.js";
|
|
1
2
|
import { IRPC_BASE_CONTEXT, IRPC_PACKET_TYPE, IRPC_STATUS } from "./enum.js";
|
|
2
|
-
import { ERROR_CODE, ERROR_MESSAGE } from "./error.js";
|
|
3
3
|
import { createContextStore, withContext } from "./context.js";
|
|
4
4
|
import { IRPC_STORE } from "./store.js";
|
|
5
5
|
|
|
@@ -24,7 +24,7 @@ var IRPCRouter = class {
|
|
|
24
24
|
*/
|
|
25
25
|
use(hook) {
|
|
26
26
|
if (typeof hook !== "function") {
|
|
27
|
-
const error =
|
|
27
|
+
const error = HookError.invalid();
|
|
28
28
|
IRPC_STORE.error(error);
|
|
29
29
|
return this;
|
|
30
30
|
}
|
|
@@ -67,10 +67,7 @@ var IRPCRouter = class {
|
|
|
67
67
|
name: req.name,
|
|
68
68
|
type: IRPC_PACKET_TYPE.CLOSE,
|
|
69
69
|
status: IRPC_STATUS.ERROR,
|
|
70
|
-
error:
|
|
71
|
-
code: ERROR_CODE.UNKNOWN,
|
|
72
|
-
message: ERROR_MESSAGE[ERROR_CODE.UNKNOWN]
|
|
73
|
-
},
|
|
70
|
+
error: HookError.failed(error).json(),
|
|
74
71
|
createdAt: Date.now()
|
|
75
72
|
};
|
|
76
73
|
}
|
package/dist/state.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { IRPCReadable, IRPCStatus, StreamConstructor } from "./types.js";
|
|
2
|
-
import
|
|
3
|
-
import { StateSubscriber } from "@anchorlib/core";
|
|
2
|
+
import { StateSubscriber, StateUnsubscribe } from "@anchorlib/core";
|
|
4
3
|
|
|
5
4
|
//#region src/state.d.ts
|
|
6
5
|
|
|
@@ -41,8 +40,21 @@ declare class RemoteState<T> extends Promise<T> {
|
|
|
41
40
|
* @param resumable - Whether the state should be resumable after being closed.
|
|
42
41
|
*/
|
|
43
42
|
constructor(init?: T, status?: IRPCStatus, resumable?: boolean | undefined);
|
|
43
|
+
/**
|
|
44
|
+
* Transitions the state to SUCCESS and resolves the underlying Promise.
|
|
45
|
+
*
|
|
46
|
+
* @param value - Optional final value to resolve with.
|
|
47
|
+
*/
|
|
44
48
|
accept(value?: T): void;
|
|
49
|
+
/**
|
|
50
|
+
* Transitions the state to ERROR and rejects the underlying Promise.
|
|
51
|
+
*
|
|
52
|
+
* @param error - Optional error to reject with.
|
|
53
|
+
*/
|
|
45
54
|
reject(error?: Error): void;
|
|
55
|
+
/**
|
|
56
|
+
* Aborts the current execution, transitioning the status to ABORTED.
|
|
57
|
+
*/
|
|
46
58
|
abort(): void;
|
|
47
59
|
/**
|
|
48
60
|
* Subscribes to changes emitted by the internal state.
|
|
@@ -50,14 +62,34 @@ declare class RemoteState<T> extends Promise<T> {
|
|
|
50
62
|
* @param handler - A callback function invoked whenever the state mutates.
|
|
51
63
|
* @returns An unsubscribe function to terminate the listener.
|
|
52
64
|
*/
|
|
53
|
-
subscribe(handler: StateSubscriber<IRPCReadable<T>>):
|
|
65
|
+
subscribe(handler: StateSubscriber<IRPCReadable<T>>): StateUnsubscribe;
|
|
54
66
|
/**
|
|
55
67
|
* Closes the reactive state and terminates the underlying Promise.
|
|
56
68
|
*/
|
|
57
69
|
close(): void;
|
|
70
|
+
/**
|
|
71
|
+
* Resumes a closed state if it was marked as resumable.
|
|
72
|
+
*/
|
|
58
73
|
protected resume(): void;
|
|
74
|
+
/**
|
|
75
|
+
* Temporarily disables the `.then()` method to prevent automatic Promise chaining.
|
|
76
|
+
*
|
|
77
|
+
* @returns The current instance for chaining.
|
|
78
|
+
*/
|
|
59
79
|
pipe(): this;
|
|
80
|
+
/**
|
|
81
|
+
* Restores the `.then()` method if it was previously locked via `.pipe()`.
|
|
82
|
+
*
|
|
83
|
+
* @returns The current instance for chaining.
|
|
84
|
+
*/
|
|
60
85
|
unpipe(): this;
|
|
86
|
+
/**
|
|
87
|
+
* Pipes all state mutations from this instance to a target RemoteState.
|
|
88
|
+
*
|
|
89
|
+
* @param target - The destination RemoteState to receive the updates.
|
|
90
|
+
* @returns The current instance for chaining.
|
|
91
|
+
*/
|
|
92
|
+
pipeTo(target: RemoteState<T>): this;
|
|
61
93
|
/**
|
|
62
94
|
* Destroys the reactive state bindings.
|
|
63
95
|
*/
|
|
@@ -75,9 +107,9 @@ declare class RemoteState<T> extends Promise<T> {
|
|
|
75
107
|
*
|
|
76
108
|
* @template T - The type of the streamed payload data.
|
|
77
109
|
* @param construct - The isolated stream constructor callback that natively operates the pipeline.
|
|
78
|
-
* @param
|
|
110
|
+
* @param seed - An optional initial value to prime the state payload inherently.
|
|
79
111
|
* @returns A fully active RemoteState inherently bound to the callbacks executing natively.
|
|
80
112
|
*/
|
|
81
|
-
declare function stream<T>(construct: StreamConstructor<T>,
|
|
113
|
+
declare function stream<T>(construct: StreamConstructor<T>, seed?: T): RemoteState<T>;
|
|
82
114
|
//#endregion
|
|
83
115
|
export { RemoteState, stream };
|
package/dist/state.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { IRPCError, IRPC_ERROR_TYPE } from "./error.js";
|
|
1
2
|
import { IRPC_STATUS } from "./enum.js";
|
|
2
|
-
import { ERROR_CODE, ERROR_MESSAGE } from "./error.js";
|
|
3
3
|
import { getAbortSignal } from "./context.js";
|
|
4
|
-
import { $do, anchor, mutable, onCleanup, subscribe } from "@anchorlib/core";
|
|
4
|
+
import { $do, anchor, mutable, onCleanup, replay, subscribe } from "@anchorlib/core";
|
|
5
5
|
|
|
6
6
|
//#region src/state.ts
|
|
7
7
|
/**
|
|
@@ -17,6 +17,7 @@ var RemoteState = class extends Promise {
|
|
|
17
17
|
#state;
|
|
18
18
|
#accept;
|
|
19
19
|
#reject;
|
|
20
|
+
#pipes = /* @__PURE__ */ new Set();
|
|
20
21
|
#closed = false;
|
|
21
22
|
#locked;
|
|
22
23
|
get state() {
|
|
@@ -97,10 +98,13 @@ var RemoteState = class extends Promise {
|
|
|
97
98
|
if (args.length) this.#state.error = args[0];
|
|
98
99
|
this.#closed = true;
|
|
99
100
|
this.#state.status = IRPC_STATUS.ERROR;
|
|
100
|
-
this.#reject(this.error ?? new
|
|
101
|
+
this.#reject(this.error ?? new IRPCError(IRPC_ERROR_TYPE.CALL, "unknown", "Unknown error."));
|
|
101
102
|
this.destroy();
|
|
102
103
|
});
|
|
103
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* Aborts the current execution, transitioning the status to ABORTED.
|
|
107
|
+
*/
|
|
104
108
|
abort() {
|
|
105
109
|
$do(() => {
|
|
106
110
|
this.#closed = true;
|
|
@@ -116,7 +120,9 @@ var RemoteState = class extends Promise {
|
|
|
116
120
|
* @returns An unsubscribe function to terminate the listener.
|
|
117
121
|
*/
|
|
118
122
|
subscribe(handler) {
|
|
119
|
-
|
|
123
|
+
const unsubscribe = subscribe(this.state, handler);
|
|
124
|
+
this.#pipes.add(unsubscribe);
|
|
125
|
+
return unsubscribe;
|
|
120
126
|
}
|
|
121
127
|
/**
|
|
122
128
|
* Closes the reactive state and terminates the underlying Promise.
|
|
@@ -127,14 +133,27 @@ var RemoteState = class extends Promise {
|
|
|
127
133
|
this.#accept(this.data);
|
|
128
134
|
this.destroy();
|
|
129
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* Resumes a closed state if it was marked as resumable.
|
|
138
|
+
*/
|
|
130
139
|
resume() {
|
|
131
140
|
this.#closed = false;
|
|
132
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* Temporarily disables the `.then()` method to prevent automatic Promise chaining.
|
|
144
|
+
*
|
|
145
|
+
* @returns The current instance for chaining.
|
|
146
|
+
*/
|
|
133
147
|
pipe() {
|
|
134
148
|
this.#locked = this.then;
|
|
135
149
|
this.then = void 0;
|
|
136
150
|
return this;
|
|
137
151
|
}
|
|
152
|
+
/**
|
|
153
|
+
* Restores the `.then()` method if it was previously locked via `.pipe()`.
|
|
154
|
+
*
|
|
155
|
+
* @returns The current instance for chaining.
|
|
156
|
+
*/
|
|
138
157
|
unpipe() {
|
|
139
158
|
if (!this.#locked) return this;
|
|
140
159
|
this.then = this.#locked;
|
|
@@ -142,10 +161,28 @@ var RemoteState = class extends Promise {
|
|
|
142
161
|
return this;
|
|
143
162
|
}
|
|
144
163
|
/**
|
|
164
|
+
* Pipes all state mutations from this instance to a target RemoteState.
|
|
165
|
+
*
|
|
166
|
+
* @param target - The destination RemoteState to receive the updates.
|
|
167
|
+
* @returns The current instance for chaining.
|
|
168
|
+
*/
|
|
169
|
+
pipeTo(target) {
|
|
170
|
+
this.subscribe((_, event) => {
|
|
171
|
+
if (event.type === "init") {
|
|
172
|
+
anchor.assign(target.state, this.state);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
replay(target.state, event);
|
|
176
|
+
});
|
|
177
|
+
return this;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
145
180
|
* Destroys the reactive state bindings.
|
|
146
181
|
*/
|
|
147
182
|
destroy() {
|
|
148
183
|
if (this.resumable) return;
|
|
184
|
+
for (const unsubscribe of this.#pipes) unsubscribe();
|
|
185
|
+
this.#pipes.clear();
|
|
149
186
|
anchor.destroy(this.state);
|
|
150
187
|
}
|
|
151
188
|
/**
|
|
@@ -163,11 +200,11 @@ var RemoteState = class extends Promise {
|
|
|
163
200
|
*
|
|
164
201
|
* @template T - The type of the streamed payload data.
|
|
165
202
|
* @param construct - The isolated stream constructor callback that natively operates the pipeline.
|
|
166
|
-
* @param
|
|
203
|
+
* @param seed - An optional initial value to prime the state payload inherently.
|
|
167
204
|
* @returns A fully active RemoteState inherently bound to the callbacks executing natively.
|
|
168
205
|
*/
|
|
169
|
-
function stream(construct,
|
|
170
|
-
const state = new RemoteState(
|
|
206
|
+
function stream(construct, seed) {
|
|
207
|
+
const state = new RemoteState(seed);
|
|
171
208
|
const abortSignal = getAbortSignal();
|
|
172
209
|
const accept = ((...values) => {
|
|
173
210
|
if (values.length > 0) state.data = values[0];
|
package/dist/store.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IRPC_STORE_EVENT } from "./enum.js";
|
|
2
|
-
import { IRPCPackage } from "./module.js";
|
|
3
2
|
import { IRPCData } from "./types.js";
|
|
3
|
+
import { IRPCPackage } from "./module.js";
|
|
4
4
|
import { IRPCRouter } from "./router.js";
|
|
5
5
|
import { IRPCStream } from "./stream.js";
|
|
6
6
|
|
|
@@ -27,7 +27,7 @@ declare class IRPCStore {
|
|
|
27
27
|
#private;
|
|
28
28
|
calls: Set<IRPCStream<IRPCData>>;
|
|
29
29
|
routers: Set<IRPCRouter>;
|
|
30
|
-
packages: Set<IRPCPackage
|
|
30
|
+
packages: Set<IRPCPackage<"id">>;
|
|
31
31
|
callCount: number;
|
|
32
32
|
errorCount: number;
|
|
33
33
|
register(pkg: IRPCPackage): void;
|
package/dist/stream.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IRPCData, IRPCDataSchema,
|
|
1
|
+
import { IRPCData, IRPCDataSchema, IRPCInputs, IRPCPacketError, IRPCPacketStream, IRPCResponse, IRPCSpec, IRPCStatus } from "./types.js";
|
|
2
2
|
import { IRPCRouter } from "./router.js";
|
|
3
3
|
|
|
4
4
|
//#region src/stream.d.ts
|
|
@@ -21,7 +21,7 @@ declare class IRPCStream<T extends IRPCData> {
|
|
|
21
21
|
private closeHandlers;
|
|
22
22
|
private errorHandlers;
|
|
23
23
|
value?: T;
|
|
24
|
-
error?:
|
|
24
|
+
error?: IRPCPacketError;
|
|
25
25
|
status: IRPCStatus;
|
|
26
26
|
closed: boolean;
|
|
27
27
|
createdAt: number;
|
|
@@ -55,7 +55,7 @@ declare class IRPCStream<T extends IRPCData> {
|
|
|
55
55
|
*
|
|
56
56
|
* @param handler - A callback function to receive stream errors.
|
|
57
57
|
*/
|
|
58
|
-
catch(handler: (error:
|
|
58
|
+
catch(handler: (error: IRPCPacketError) => void): void;
|
|
59
59
|
/**
|
|
60
60
|
* Binds a handler triggered upon terminal completion of the stream process (success or error).
|
|
61
61
|
*
|
package/dist/stream.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { CallError, HandlerError, ResolveError } from "./error.js";
|
|
1
2
|
import { IRPC_PACKET_TYPE, IRPC_STATUS } from "./enum.js";
|
|
2
|
-
import { ERROR_CODE } from "./error.js";
|
|
3
3
|
import { getAbortController, getAbortSignal } from "./context.js";
|
|
4
4
|
import { RemoteState } from "./state.js";
|
|
5
5
|
import { IRPC_STORE } from "./store.js";
|
|
@@ -68,10 +68,7 @@ var IRPCStream = class {
|
|
|
68
68
|
this.value = result.data;
|
|
69
69
|
if (result.status === IRPC_STATUS.SUCCESS || result.status === IRPC_STATUS.ERROR) {
|
|
70
70
|
if (result.status === IRPC_STATUS.ERROR) {
|
|
71
|
-
this.error =
|
|
72
|
-
code: ERROR_CODE.HANDLER_ERROR,
|
|
73
|
-
message: result.error.message
|
|
74
|
-
};
|
|
71
|
+
this.error = HandlerError.failed(result.error).json();
|
|
75
72
|
this.status = IRPC_STATUS.ERROR;
|
|
76
73
|
} else this.status = IRPC_STATUS.SUCCESS;
|
|
77
74
|
const packet = {
|
|
@@ -119,10 +116,7 @@ var IRPCStream = class {
|
|
|
119
116
|
if (state.status !== IRPC_STATUS.SUCCESS && state.status !== IRPC_STATUS.ERROR) return;
|
|
120
117
|
this.status = state.status;
|
|
121
118
|
if (state.status === IRPC_STATUS.ERROR) {
|
|
122
|
-
this.error =
|
|
123
|
-
code: ERROR_CODE.STREAM_ERROR,
|
|
124
|
-
message: state.error.message
|
|
125
|
-
};
|
|
119
|
+
this.error = CallError.streamError(state.error).json();
|
|
126
120
|
this.errorHandlers.forEach((handler) => handler(this.error));
|
|
127
121
|
}
|
|
128
122
|
this.pipeHandlers.forEach((handler) => {
|
|
@@ -169,10 +163,7 @@ var IRPCStream = class {
|
|
|
169
163
|
id: this.id,
|
|
170
164
|
name: this.name
|
|
171
165
|
}]);
|
|
172
|
-
this.error =
|
|
173
|
-
code: ERROR_CODE.RESOLVE_ERROR,
|
|
174
|
-
message: error.message
|
|
175
|
-
};
|
|
166
|
+
this.error = ResolveError.failed(error).json();
|
|
176
167
|
this.status = IRPC_STATUS.ERROR;
|
|
177
168
|
this.pipeHandlers.forEach((handler) => {
|
|
178
169
|
handler({
|