@irpclib/irpc 1.0.0-beta.22 → 1.0.0-beta.24
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/call.d.ts +7 -4
- package/dist/call.js +25 -7
- package/dist/context.d.ts +6 -16
- package/dist/context.js +12 -23
- package/dist/credential.d.ts +9 -0
- package/dist/credential.js +16 -0
- package/dist/enum.d.ts +20 -12
- package/dist/enum.js +21 -13
- package/dist/error.d.ts +6 -0
- package/dist/error.js +6 -0
- package/dist/file.d.ts +37 -0
- package/dist/file.js +86 -0
- package/dist/index.d.ts +12 -6
- package/dist/index.js +12 -6
- package/dist/module.d.ts +41 -9
- package/dist/module.js +183 -12
- package/dist/packet.d.ts +32 -0
- package/dist/packet.js +100 -0
- package/dist/reader.d.ts +17 -3
- package/dist/reader.js +23 -4
- package/dist/resolver.d.ts +1 -1
- package/dist/resolver.js +25 -2
- package/dist/router.d.ts +53 -0
- package/dist/router.js +81 -0
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +15 -0
- package/dist/state.d.ts +18 -17
- package/dist/state.js +96 -23
- package/dist/store.d.ts +44 -0
- package/dist/store.js +76 -0
- package/dist/stream.d.ts +13 -2
- package/dist/stream.js +77 -17
- package/dist/transport.d.ts +18 -2
- package/dist/transport.js +46 -5
- package/dist/types.d.ts +103 -17
- package/package.json +9 -7
- package/readme.md +8 -3
- package/dist/uuid.d.ts +0 -21
- package/dist/uuid.js +0 -45
package/dist/router.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { IRPC_BASE_CONTEXT, IRPC_PACKET_TYPE, IRPC_STATUS } from "./enum.js";
|
|
2
|
+
import { ERROR_CODE, ERROR_MESSAGE } from "./error.js";
|
|
3
|
+
import { createContextStore, withContext } from "./context.js";
|
|
4
|
+
import { IRPC_STORE } from "./store.js";
|
|
5
|
+
|
|
6
|
+
//#region src/router.ts
|
|
7
|
+
var IRPCRouter = class {
|
|
8
|
+
/** Array of middleware functions to be executed */
|
|
9
|
+
hooks = [];
|
|
10
|
+
/**
|
|
11
|
+
* Creates a new Router instance
|
|
12
|
+
* @param {IRPCPackage} module - The IRPC package module to resolve requests against
|
|
13
|
+
* @param {IRPCTransport} transport - The transport mechanism to use for resolving requests
|
|
14
|
+
*/
|
|
15
|
+
constructor(module, transport) {
|
|
16
|
+
this.module = module;
|
|
17
|
+
this.transport = transport;
|
|
18
|
+
IRPC_STORE.route(this);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Adds a hook function to the router
|
|
22
|
+
* @param hook - The hook function to add
|
|
23
|
+
* @returns The current Router instance for chaining
|
|
24
|
+
*/
|
|
25
|
+
use(hook) {
|
|
26
|
+
if (typeof hook !== "function") {
|
|
27
|
+
const error = new Error(ERROR_MESSAGE[ERROR_CODE.INVALID_HOOK]);
|
|
28
|
+
IRPC_STORE.error(error);
|
|
29
|
+
return this;
|
|
30
|
+
}
|
|
31
|
+
this.hooks.push(hook);
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Run a function within an isolated IRPC Router context.
|
|
36
|
+
* This make sure any subsequent RPC calls will be seeded with the hooks added to the router.
|
|
37
|
+
*
|
|
38
|
+
* @param handler - The handler function to isolate
|
|
39
|
+
* @param controller - The AbortController to use for cancellation
|
|
40
|
+
* @param context - Additional context to pass to the handler
|
|
41
|
+
* @param preHook - A hook function to run before the router hooks
|
|
42
|
+
* @returns The result of the isolated handler function
|
|
43
|
+
*/
|
|
44
|
+
isolate(handler, controller, context = [], preHook) {
|
|
45
|
+
return withContext(createContextStore([
|
|
46
|
+
[IRPC_BASE_CONTEXT.ABORT_SIGNAL, controller.signal],
|
|
47
|
+
[IRPC_BASE_CONTEXT.ABORT_CONTROLLER, controller],
|
|
48
|
+
...context
|
|
49
|
+
]), async () => {
|
|
50
|
+
await preHook?.();
|
|
51
|
+
for (const hook of this.hooks) await hook();
|
|
52
|
+
return handler();
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Resolves hook functions for a given request
|
|
57
|
+
* @param req - The IRPC request to process hook for
|
|
58
|
+
* @returns An error response if hook fails, undefined otherwise
|
|
59
|
+
*/
|
|
60
|
+
async resolveHooks(req) {
|
|
61
|
+
for (const hook of this.hooks) try {
|
|
62
|
+
await hook();
|
|
63
|
+
} catch (error) {
|
|
64
|
+
IRPC_STORE.error(error, [req.id, req.name]);
|
|
65
|
+
return {
|
|
66
|
+
id: req.id,
|
|
67
|
+
name: req.name,
|
|
68
|
+
type: IRPC_PACKET_TYPE.CLOSE,
|
|
69
|
+
status: IRPC_STATUS.ERROR,
|
|
70
|
+
error: {
|
|
71
|
+
code: ERROR_CODE.UNKNOWN,
|
|
72
|
+
message: ERROR_MESSAGE[ERROR_CODE.UNKNOWN]
|
|
73
|
+
},
|
|
74
|
+
createdAt: Date.now()
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
//#endregion
|
|
81
|
+
export { IRPCRouter };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { setAsyncScope, setReactive } from "@anchorlib/core";
|
|
2
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
3
|
+
|
|
4
|
+
//#region src/server/index.ts
|
|
5
|
+
var AnchorASL = class extends AsyncLocalStorage {
|
|
6
|
+
store = /* @__PURE__ */ new Map();
|
|
7
|
+
getStore() {
|
|
8
|
+
return super.getStore() ?? this.store;
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
setAsyncScope(new AnchorASL());
|
|
12
|
+
setReactive(false);
|
|
13
|
+
|
|
14
|
+
//#endregion
|
|
15
|
+
export { };
|
package/dist/state.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IRPCReadable, IRPCStatus } from "./types.js";
|
|
1
|
+
import { IRPCReadable, IRPCStatus, StreamConstructor } from "./types.js";
|
|
2
2
|
import * as _anchorlib_core0 from "@anchorlib/core";
|
|
3
3
|
import { StateSubscriber } from "@anchorlib/core";
|
|
4
4
|
|
|
@@ -14,9 +14,9 @@ import { StateSubscriber } from "@anchorlib/core";
|
|
|
14
14
|
* @template T - The type of data held by the state.
|
|
15
15
|
*/
|
|
16
16
|
declare class RemoteState<T> extends Promise<T> {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
#private;
|
|
18
|
+
private resumable?;
|
|
19
|
+
get state(): IRPCReadable<T>;
|
|
20
20
|
/**
|
|
21
21
|
* The current data payload of the state.
|
|
22
22
|
*/
|
|
@@ -37,8 +37,13 @@ declare class RemoteState<T> extends Promise<T> {
|
|
|
37
37
|
* Initializes a new RemoteState with an optional initial payload.
|
|
38
38
|
*
|
|
39
39
|
* @param init - An optional starting value for the data payload.
|
|
40
|
+
* @param status - The initial status of the state (PENDING, SUCCESS, ERROR).
|
|
41
|
+
* @param resumable - Whether the state should be resumable after being closed.
|
|
40
42
|
*/
|
|
41
|
-
constructor(init?: T);
|
|
43
|
+
constructor(init?: T, status?: IRPCStatus, resumable?: boolean | undefined);
|
|
44
|
+
accept(value?: T): void;
|
|
45
|
+
reject(error?: Error): void;
|
|
46
|
+
abort(): void;
|
|
42
47
|
/**
|
|
43
48
|
* Subscribes to changes emitted by the internal state.
|
|
44
49
|
*
|
|
@@ -46,6 +51,13 @@ declare class RemoteState<T> extends Promise<T> {
|
|
|
46
51
|
* @returns An unsubscribe function to terminate the listener.
|
|
47
52
|
*/
|
|
48
53
|
subscribe(handler: StateSubscriber<IRPCReadable<T>>): _anchorlib_core0.StateUnsubscribe;
|
|
54
|
+
/**
|
|
55
|
+
* Closes the reactive state and terminates the underlying Promise.
|
|
56
|
+
*/
|
|
57
|
+
close(): void;
|
|
58
|
+
protected resume(): void;
|
|
59
|
+
pipe(): this;
|
|
60
|
+
unpipe(): this;
|
|
49
61
|
/**
|
|
50
62
|
* Destroys the reactive state bindings.
|
|
51
63
|
*/
|
|
@@ -56,17 +68,6 @@ declare class RemoteState<T> extends Promise<T> {
|
|
|
56
68
|
*/
|
|
57
69
|
static get [Symbol.species](): PromiseConstructor;
|
|
58
70
|
}
|
|
59
|
-
/**
|
|
60
|
-
* A callback function type used to natively construct and drive a reactive stream.
|
|
61
|
-
* It provides the initial reactive data reference and terminal resolution hooks
|
|
62
|
-
* without forcing strict async/await boundaries, securely yielding stream operations.
|
|
63
|
-
*
|
|
64
|
-
* @template T - The type of data yielded globally by the stream.
|
|
65
|
-
* @param data - The mutable data payload natively tracked by RemoteState.
|
|
66
|
-
* @param resolve - Callback to statically mark the stream as successfully completed, optionally with a resolved value.
|
|
67
|
-
* @param reject - Callback to forcefully throw a runtime error into the stream structure.
|
|
68
|
-
*/
|
|
69
|
-
type StreamConstructor<T> = (data: T, resolve: (value?: T) => void, reject: (error: Error) => void) => void | Promise<void>;
|
|
70
71
|
/**
|
|
71
72
|
* A utility factory to structurally instantiate an active `RemoteState` pipeline natively
|
|
72
73
|
* decoupled from standard Promise chains. This elegantly captures constructor functions
|
|
@@ -79,4 +80,4 @@ type StreamConstructor<T> = (data: T, resolve: (value?: T) => void, reject: (err
|
|
|
79
80
|
*/
|
|
80
81
|
declare function stream<T>(construct: StreamConstructor<T>, init?: T): RemoteState<T>;
|
|
81
82
|
//#endregion
|
|
82
|
-
export { RemoteState,
|
|
83
|
+
export { RemoteState, stream };
|
package/dist/state.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { IRPC_STATUS } from "./enum.js";
|
|
2
|
-
import {
|
|
2
|
+
import { ERROR_CODE, ERROR_MESSAGE } from "./error.js";
|
|
3
|
+
import { getAbortSignal } from "./context.js";
|
|
4
|
+
import { $do, anchor, mutable, onCleanup, subscribe } from "@anchorlib/core";
|
|
3
5
|
|
|
4
6
|
//#region src/state.ts
|
|
5
7
|
/**
|
|
@@ -12,62 +14,99 @@ import { anchor, mutable, subscribe } from "@anchorlib/core";
|
|
|
12
14
|
* @template T - The type of data held by the state.
|
|
13
15
|
*/
|
|
14
16
|
var RemoteState = class extends Promise {
|
|
15
|
-
state;
|
|
16
|
-
accept;
|
|
17
|
-
reject;
|
|
17
|
+
#state;
|
|
18
|
+
#accept;
|
|
19
|
+
#reject;
|
|
20
|
+
#closed = false;
|
|
21
|
+
#locked;
|
|
22
|
+
get state() {
|
|
23
|
+
return this.#state;
|
|
24
|
+
}
|
|
18
25
|
/**
|
|
19
26
|
* The current data payload of the state.
|
|
20
27
|
*/
|
|
21
28
|
get data() {
|
|
22
|
-
return this
|
|
29
|
+
return this.#state.data;
|
|
23
30
|
}
|
|
24
31
|
set data(data) {
|
|
25
|
-
this
|
|
32
|
+
if (this.#closed) return;
|
|
33
|
+
this.#state.data = data;
|
|
26
34
|
}
|
|
27
35
|
/**
|
|
28
36
|
* The current error encountered by the state, if any.
|
|
29
37
|
*/
|
|
30
38
|
get error() {
|
|
31
|
-
return this
|
|
39
|
+
return this.#state.error;
|
|
32
40
|
}
|
|
33
41
|
set error(error) {
|
|
34
|
-
this
|
|
42
|
+
if (this.#closed) return;
|
|
43
|
+
this.#state.error = error;
|
|
35
44
|
}
|
|
36
45
|
/**
|
|
37
46
|
* The execution status of the state (PENDING, SUCCESS, ERROR).
|
|
38
47
|
* Transitioning to a terminal status (SUCCESS or ERROR) will automatically resolve or reject the underlying Promise.
|
|
39
48
|
*/
|
|
40
49
|
get status() {
|
|
41
|
-
return this
|
|
50
|
+
return this.#state.status;
|
|
42
51
|
}
|
|
43
52
|
set status(status) {
|
|
53
|
+
if (this.#closed) return;
|
|
44
54
|
this.state.status = status;
|
|
45
|
-
if (
|
|
46
|
-
|
|
47
|
-
this.destroy();
|
|
48
|
-
} else if (this.status === IRPC_STATUS.SUCCESS) {
|
|
49
|
-
this.accept(this.data);
|
|
50
|
-
this.destroy();
|
|
51
|
-
}
|
|
55
|
+
if (status === IRPC_STATUS.ERROR) this.reject();
|
|
56
|
+
else if (status === IRPC_STATUS.SUCCESS) this.accept();
|
|
52
57
|
}
|
|
53
58
|
/**
|
|
54
59
|
* Initializes a new RemoteState with an optional initial payload.
|
|
55
60
|
*
|
|
56
61
|
* @param init - An optional starting value for the data payload.
|
|
62
|
+
* @param status - The initial status of the state (PENDING, SUCCESS, ERROR).
|
|
63
|
+
* @param resumable - Whether the state should be resumable after being closed.
|
|
57
64
|
*/
|
|
58
|
-
constructor(init) {
|
|
65
|
+
constructor(init, status = IRPC_STATUS.PENDING, resumable) {
|
|
59
66
|
let acceptFn;
|
|
60
67
|
let rejectFn;
|
|
61
68
|
super((resolve, reject) => {
|
|
69
|
+
if (resumable) resolve(init);
|
|
62
70
|
acceptFn = resolve;
|
|
63
71
|
rejectFn = reject;
|
|
64
72
|
});
|
|
65
|
-
this.
|
|
66
|
-
this
|
|
67
|
-
this
|
|
73
|
+
this.resumable = resumable;
|
|
74
|
+
this.#accept = acceptFn;
|
|
75
|
+
this.#reject = rejectFn;
|
|
76
|
+
this.#state = mutable({
|
|
68
77
|
data: init,
|
|
69
78
|
error: void 0,
|
|
70
|
-
status
|
|
79
|
+
status
|
|
80
|
+
});
|
|
81
|
+
onCleanup(() => this.close());
|
|
82
|
+
}
|
|
83
|
+
accept(...args) {
|
|
84
|
+
$do(() => {
|
|
85
|
+
if (this.#closed) return;
|
|
86
|
+
const value = args.length ? args[0] : this.data;
|
|
87
|
+
this.#closed = true;
|
|
88
|
+
this.#state.status = IRPC_STATUS.SUCCESS;
|
|
89
|
+
this.#state.data = value;
|
|
90
|
+
this.#accept(value);
|
|
91
|
+
this.destroy();
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
reject(...args) {
|
|
95
|
+
$do(() => {
|
|
96
|
+
if (this.#closed) return;
|
|
97
|
+
if (args.length) this.#state.error = args[0];
|
|
98
|
+
this.#closed = true;
|
|
99
|
+
this.#state.status = IRPC_STATUS.ERROR;
|
|
100
|
+
this.#reject(this.error ?? new Error(ERROR_MESSAGE[ERROR_CODE.UNKNOWN]));
|
|
101
|
+
this.destroy();
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
abort() {
|
|
105
|
+
$do(() => {
|
|
106
|
+
this.#closed = true;
|
|
107
|
+
this.#state.status = IRPC_STATUS.ABORTED;
|
|
108
|
+
this.#accept(this.data);
|
|
109
|
+
this.destroy();
|
|
71
110
|
});
|
|
72
111
|
}
|
|
73
112
|
/**
|
|
@@ -80,9 +119,33 @@ var RemoteState = class extends Promise {
|
|
|
80
119
|
return subscribe(this.state, handler);
|
|
81
120
|
}
|
|
82
121
|
/**
|
|
122
|
+
* Closes the reactive state and terminates the underlying Promise.
|
|
123
|
+
*/
|
|
124
|
+
close() {
|
|
125
|
+
if (this.#closed) return;
|
|
126
|
+
this.#closed = true;
|
|
127
|
+
this.#accept(this.data);
|
|
128
|
+
this.destroy();
|
|
129
|
+
}
|
|
130
|
+
resume() {
|
|
131
|
+
this.#closed = false;
|
|
132
|
+
}
|
|
133
|
+
pipe() {
|
|
134
|
+
this.#locked = this.then;
|
|
135
|
+
this.then = void 0;
|
|
136
|
+
return this;
|
|
137
|
+
}
|
|
138
|
+
unpipe() {
|
|
139
|
+
if (!this.#locked) return this;
|
|
140
|
+
this.then = this.#locked;
|
|
141
|
+
this.#locked = void 0;
|
|
142
|
+
return this;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
83
145
|
* Destroys the reactive state bindings.
|
|
84
146
|
*/
|
|
85
147
|
destroy() {
|
|
148
|
+
if (this.resumable) return;
|
|
86
149
|
anchor.destroy(this.state);
|
|
87
150
|
}
|
|
88
151
|
/**
|
|
@@ -105,17 +168,27 @@ var RemoteState = class extends Promise {
|
|
|
105
168
|
*/
|
|
106
169
|
function stream(construct, init) {
|
|
107
170
|
const state = new RemoteState(init);
|
|
171
|
+
const abortSignal = getAbortSignal();
|
|
108
172
|
const accept = ((...values) => {
|
|
109
173
|
if (values.length > 0) state.data = values[0];
|
|
110
174
|
state.status = IRPC_STATUS.SUCCESS;
|
|
175
|
+
abortSignal?.removeEventListener("abort", abort);
|
|
111
176
|
});
|
|
112
177
|
const reject = (error) => {
|
|
113
178
|
state.error = error;
|
|
114
179
|
state.status = IRPC_STATUS.ERROR;
|
|
180
|
+
abortSignal?.removeEventListener("abort", abort);
|
|
115
181
|
};
|
|
182
|
+
const abort = () => state.abort();
|
|
183
|
+
abortSignal?.addEventListener("abort", abort, { once: true });
|
|
116
184
|
try {
|
|
117
|
-
const
|
|
118
|
-
if (
|
|
185
|
+
const cleanup = construct(state, accept, reject);
|
|
186
|
+
if (cleanup instanceof Promise) cleanup.then((futureCleanup) => {
|
|
187
|
+
if (typeof futureCleanup === "function") if (abortSignal?.aborted || state.status !== IRPC_STATUS.PENDING) $do(futureCleanup);
|
|
188
|
+
else abortSignal?.addEventListener("abort", () => $do(futureCleanup), { once: true });
|
|
189
|
+
}).catch(reject);
|
|
190
|
+
else if (typeof cleanup === "function") if (abortSignal?.aborted || state.status !== IRPC_STATUS.PENDING) $do(cleanup);
|
|
191
|
+
else abortSignal?.addEventListener("abort", () => $do(cleanup), { once: true });
|
|
119
192
|
} catch (error) {
|
|
120
193
|
reject(error);
|
|
121
194
|
}
|
package/dist/store.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { IRPC_STORE_EVENT } from "./enum.js";
|
|
2
|
+
import { IRPCPackage } from "./module.js";
|
|
3
|
+
import { IRPCData } from "./types.js";
|
|
4
|
+
import { IRPCRouter } from "./router.js";
|
|
5
|
+
import { IRPCStream } from "./stream.js";
|
|
6
|
+
|
|
7
|
+
//#region src/store.d.ts
|
|
8
|
+
type IRPCStoreEvent = {
|
|
9
|
+
type: typeof IRPC_STORE_EVENT.REGISTER;
|
|
10
|
+
data: IRPCPackage;
|
|
11
|
+
} | {
|
|
12
|
+
type: typeof IRPC_STORE_EVENT.ROUTE;
|
|
13
|
+
data: IRPCRouter;
|
|
14
|
+
} | {
|
|
15
|
+
type: typeof IRPC_STORE_EVENT.QUEUE;
|
|
16
|
+
data: IRPCStream<IRPCData>;
|
|
17
|
+
} | {
|
|
18
|
+
type: typeof IRPC_STORE_EVENT.DEQUEUE;
|
|
19
|
+
data: IRPCStream<IRPCData>;
|
|
20
|
+
} | {
|
|
21
|
+
type: typeof IRPC_STORE_EVENT.ERROR;
|
|
22
|
+
error: Error;
|
|
23
|
+
data?: unknown[];
|
|
24
|
+
};
|
|
25
|
+
type IRPCStoreSubscriber = (event: IRPCStoreEvent) => void;
|
|
26
|
+
declare class IRPCStore {
|
|
27
|
+
#private;
|
|
28
|
+
calls: Set<IRPCStream<IRPCData>>;
|
|
29
|
+
routers: Set<IRPCRouter>;
|
|
30
|
+
packages: Set<IRPCPackage>;
|
|
31
|
+
callCount: number;
|
|
32
|
+
errorCount: number;
|
|
33
|
+
register(pkg: IRPCPackage): void;
|
|
34
|
+
route(router: IRPCRouter): void;
|
|
35
|
+
queue(call: IRPCStream<IRPCData>): void;
|
|
36
|
+
dequeue(call: IRPCStream<IRPCData>): void;
|
|
37
|
+
error(error: Error, data?: unknown[]): void;
|
|
38
|
+
print(): void;
|
|
39
|
+
subscribe(handler: IRPCStoreSubscriber): () => boolean;
|
|
40
|
+
private broadcast;
|
|
41
|
+
}
|
|
42
|
+
declare const IRPC_STORE: IRPCStore;
|
|
43
|
+
//#endregion
|
|
44
|
+
export { IRPCStore, IRPCStoreEvent, IRPCStoreSubscriber, IRPC_STORE };
|
package/dist/store.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { IRPC_STORE_EVENT } from "./enum.js";
|
|
2
|
+
import { IRPCPackage } from "./module.js";
|
|
3
|
+
import { IRPCRouter } from "./router.js";
|
|
4
|
+
import { IRPCStream } from "./stream.js";
|
|
5
|
+
|
|
6
|
+
//#region src/store.ts
|
|
7
|
+
var IRPCStore = class {
|
|
8
|
+
#subscribers = /* @__PURE__ */ new Set();
|
|
9
|
+
calls = /* @__PURE__ */ new Set();
|
|
10
|
+
routers = /* @__PURE__ */ new Set();
|
|
11
|
+
packages = /* @__PURE__ */ new Set();
|
|
12
|
+
callCount = 0;
|
|
13
|
+
errorCount = 0;
|
|
14
|
+
register(pkg) {
|
|
15
|
+
if (!(pkg instanceof IRPCPackage)) throw new Error("Invalid package: package must be an instance of IRPCPackage.");
|
|
16
|
+
this.packages.add(pkg);
|
|
17
|
+
this.broadcast({
|
|
18
|
+
type: IRPC_STORE_EVENT.REGISTER,
|
|
19
|
+
data: pkg
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
route(router) {
|
|
23
|
+
if (!(router instanceof IRPCRouter)) throw new Error("Invalid router: router must be an instance of IRPCRouter.");
|
|
24
|
+
this.routers.add(router);
|
|
25
|
+
this.broadcast({
|
|
26
|
+
type: IRPC_STORE_EVENT.ROUTE,
|
|
27
|
+
data: router
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
queue(call) {
|
|
31
|
+
if (!(call instanceof IRPCStream)) throw new Error("Invalid call: call must be an instance of IRPCStream.");
|
|
32
|
+
this.calls.add(call);
|
|
33
|
+
this.callCount += 1;
|
|
34
|
+
this.broadcast({
|
|
35
|
+
type: IRPC_STORE_EVENT.QUEUE,
|
|
36
|
+
data: call
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
dequeue(call) {
|
|
40
|
+
if (!(call instanceof IRPCStream)) throw new Error("Invalid call: call must be an instance of IRPCStream.");
|
|
41
|
+
this.calls.delete(call);
|
|
42
|
+
this.broadcast({
|
|
43
|
+
type: IRPC_STORE_EVENT.DEQUEUE,
|
|
44
|
+
data: call
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
error(error, data) {
|
|
48
|
+
this.errorCount += 1;
|
|
49
|
+
this.broadcast({
|
|
50
|
+
type: IRPC_STORE_EVENT.ERROR,
|
|
51
|
+
error,
|
|
52
|
+
data
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
print() {
|
|
56
|
+
console.table([{
|
|
57
|
+
Packages: this.packages.size,
|
|
58
|
+
Routers: this.routers.size,
|
|
59
|
+
Running: this.calls.size,
|
|
60
|
+
Calls: this.callCount,
|
|
61
|
+
Errors: this.errorCount
|
|
62
|
+
}]);
|
|
63
|
+
}
|
|
64
|
+
subscribe(handler) {
|
|
65
|
+
if (typeof handler !== "function") throw new Error("Invalid handler: handler must be a function.");
|
|
66
|
+
this.#subscribers.add(handler);
|
|
67
|
+
return () => this.#subscribers.delete(handler);
|
|
68
|
+
}
|
|
69
|
+
broadcast(event) {
|
|
70
|
+
for (const subscriber of this.#subscribers) subscriber(event);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
const IRPC_STORE = new IRPCStore();
|
|
74
|
+
|
|
75
|
+
//#endregion
|
|
76
|
+
export { IRPCStore, IRPC_STORE };
|
package/dist/stream.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { IRPCData, IRPCError, IRPCPacketStream, IRPCResponse, IRPCStatus } from "./types.js";
|
|
1
|
+
import { IRPCData, IRPCDataSchema, IRPCError, IRPCInputs, IRPCPacketStream, IRPCResponse, IRPCSpec, IRPCStatus } from "./types.js";
|
|
2
|
+
import { IRPCRouter } from "./router.js";
|
|
2
3
|
|
|
3
4
|
//#region src/stream.d.ts
|
|
4
5
|
|
|
@@ -14,20 +15,29 @@ declare class IRPCStream<T extends IRPCData> {
|
|
|
14
15
|
private id;
|
|
15
16
|
private name;
|
|
16
17
|
private initializer;
|
|
18
|
+
spec?: IRPCSpec<IRPCInputs, IRPCDataSchema> | undefined;
|
|
19
|
+
router?: IRPCRouter | undefined;
|
|
17
20
|
private pipeHandlers;
|
|
18
21
|
private closeHandlers;
|
|
19
22
|
private errorHandlers;
|
|
20
23
|
value?: T;
|
|
21
24
|
error?: IRPCError;
|
|
22
25
|
status: IRPCStatus;
|
|
26
|
+
closed: boolean;
|
|
27
|
+
createdAt: number;
|
|
28
|
+
startedAt?: number;
|
|
29
|
+
updatedAt?: number;
|
|
30
|
+
controller?: AbortController;
|
|
23
31
|
/**
|
|
24
32
|
* Initializes a stream wrapping an asynchronous RPC execution.
|
|
25
33
|
*
|
|
26
34
|
* @param id - The unique identifier of the RPC request.
|
|
27
35
|
* @param name - The name of the specification processing the execution.
|
|
28
36
|
* @param initializer - An execution callback that yields an IRPCResponse.
|
|
37
|
+
* @param spec - The specification for the RPC execution.
|
|
38
|
+
* @param router - The router instance managing the stream.
|
|
29
39
|
*/
|
|
30
|
-
constructor(id: string, name: string, initializer: () => Promise<IRPCResponse>);
|
|
40
|
+
constructor(id: string, name: string, initializer: () => Promise<IRPCResponse>, spec?: IRPCSpec<IRPCInputs, IRPCDataSchema> | undefined, router?: IRPCRouter | undefined);
|
|
31
41
|
/**
|
|
32
42
|
* Evaluates the underlying initializer and propagates standard transport packets
|
|
33
43
|
* to all bound pipe handlers based on the output lifecycle.
|
|
@@ -52,6 +62,7 @@ declare class IRPCStream<T extends IRPCData> {
|
|
|
52
62
|
* @param handler - A callback function invoked at stream completion.
|
|
53
63
|
*/
|
|
54
64
|
close(handler: () => void): void;
|
|
65
|
+
private finish;
|
|
55
66
|
}
|
|
56
67
|
//#endregion
|
|
57
68
|
export { IRPCStream };
|