@irpclib/irpc 1.0.0-beta.19 → 1.0.0-beta.21
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 +36 -11
- package/dist/call.js +78 -11
- package/dist/enum.d.ts +35 -0
- package/dist/enum.js +36 -0
- package/dist/error.d.ts +5 -0
- package/dist/error.js +7 -2
- package/dist/index.d.ts +7 -3
- package/dist/index.js +7 -3
- package/dist/module.d.ts +5 -4
- package/dist/module.js +32 -20
- package/dist/reader.d.ts +24 -0
- package/dist/reader.js +37 -0
- package/dist/resolver.d.ts +2 -12
- package/dist/resolver.js +20 -2
- package/dist/state.d.ts +82 -0
- package/dist/state.js +126 -0
- package/dist/stream.d.ts +57 -0
- package/dist/stream.js +204 -0
- package/dist/transport.d.ts +5 -4
- package/dist/transport.js +37 -19
- package/dist/types.d.ts +80 -28
- package/package.json +7 -4
- package/readme.md +99 -30
package/dist/state.d.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { IRPCReadable, IRPCStatus } from "./types.js";
|
|
2
|
+
import * as _anchorlib_core0 from "@anchorlib/core";
|
|
3
|
+
import { StateSubscriber } from "@anchorlib/core";
|
|
4
|
+
|
|
5
|
+
//#region src/state.d.ts
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A reactive state wrapper that implements the standard Promise interface.
|
|
9
|
+
*
|
|
10
|
+
* RemoteState acts as a dual-layer abstraction:
|
|
11
|
+
* 1. For asynchronous execution, it operates as a `Promise<T>` that resolves upon completion or rejects upon failure.
|
|
12
|
+
* 2. For reactive environments, it exposes an `.subscribe()` method to react to intermediate data mutations.
|
|
13
|
+
*
|
|
14
|
+
* @template T - The type of data held by the state.
|
|
15
|
+
*/
|
|
16
|
+
declare class RemoteState<T> extends Promise<T> {
|
|
17
|
+
protected readonly state: IRPCReadable<T>;
|
|
18
|
+
protected readonly accept: (value: T) => void;
|
|
19
|
+
protected readonly reject: (error: Error) => void;
|
|
20
|
+
/**
|
|
21
|
+
* The current data payload of the state.
|
|
22
|
+
*/
|
|
23
|
+
get data(): T;
|
|
24
|
+
set data(data: T);
|
|
25
|
+
/**
|
|
26
|
+
* The current error encountered by the state, if any.
|
|
27
|
+
*/
|
|
28
|
+
get error(): Error | undefined;
|
|
29
|
+
set error(error: Error | undefined);
|
|
30
|
+
/**
|
|
31
|
+
* The execution status of the state (PENDING, SUCCESS, ERROR).
|
|
32
|
+
* Transitioning to a terminal status (SUCCESS or ERROR) will automatically resolve or reject the underlying Promise.
|
|
33
|
+
*/
|
|
34
|
+
get status(): IRPCStatus;
|
|
35
|
+
set status(status: IRPCStatus);
|
|
36
|
+
/**
|
|
37
|
+
* Initializes a new RemoteState with an optional initial payload.
|
|
38
|
+
*
|
|
39
|
+
* @param init - An optional starting value for the data payload.
|
|
40
|
+
*/
|
|
41
|
+
constructor(init?: T);
|
|
42
|
+
/**
|
|
43
|
+
* Subscribes to changes emitted by the internal state.
|
|
44
|
+
*
|
|
45
|
+
* @param handler - A callback function invoked whenever the state mutates.
|
|
46
|
+
* @returns An unsubscribe function to terminate the listener.
|
|
47
|
+
*/
|
|
48
|
+
subscribe(handler: StateSubscriber<IRPCReadable<T>>): _anchorlib_core0.StateUnsubscribe;
|
|
49
|
+
/**
|
|
50
|
+
* Destroys the reactive state bindings.
|
|
51
|
+
*/
|
|
52
|
+
protected destroy(): void;
|
|
53
|
+
/**
|
|
54
|
+
* Ensures that chained Promise operations return standard Promises
|
|
55
|
+
* rather than instantiating new RemoteState subclasses.
|
|
56
|
+
*/
|
|
57
|
+
static get [Symbol.species](): PromiseConstructor;
|
|
58
|
+
}
|
|
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
|
+
* A utility factory to structurally instantiate an active `RemoteState` pipeline natively
|
|
72
|
+
* decoupled from standard Promise chains. This elegantly captures constructor functions
|
|
73
|
+
* pushing events into the state before terminating mechanically via secure internal hooks.
|
|
74
|
+
*
|
|
75
|
+
* @template T - The type of the streamed payload data.
|
|
76
|
+
* @param construct - The isolated stream constructor callback that natively operates the pipeline.
|
|
77
|
+
* @param init - An optional initial value to prime the state payload inherently.
|
|
78
|
+
* @returns A fully active RemoteState inherently bound to the callbacks executing natively.
|
|
79
|
+
*/
|
|
80
|
+
declare function stream<T>(construct: StreamConstructor<T>, init?: T): RemoteState<T>;
|
|
81
|
+
//#endregion
|
|
82
|
+
export { RemoteState, StreamConstructor, stream };
|
package/dist/state.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { IRPC_STATUS } from "./enum.js";
|
|
2
|
+
import { anchor, mutable, subscribe } from "@anchorlib/core";
|
|
3
|
+
|
|
4
|
+
//#region src/state.ts
|
|
5
|
+
/**
|
|
6
|
+
* A reactive state wrapper that implements the standard Promise interface.
|
|
7
|
+
*
|
|
8
|
+
* RemoteState acts as a dual-layer abstraction:
|
|
9
|
+
* 1. For asynchronous execution, it operates as a `Promise<T>` that resolves upon completion or rejects upon failure.
|
|
10
|
+
* 2. For reactive environments, it exposes an `.subscribe()` method to react to intermediate data mutations.
|
|
11
|
+
*
|
|
12
|
+
* @template T - The type of data held by the state.
|
|
13
|
+
*/
|
|
14
|
+
var RemoteState = class extends Promise {
|
|
15
|
+
state;
|
|
16
|
+
accept;
|
|
17
|
+
reject;
|
|
18
|
+
/**
|
|
19
|
+
* The current data payload of the state.
|
|
20
|
+
*/
|
|
21
|
+
get data() {
|
|
22
|
+
return this.state.data;
|
|
23
|
+
}
|
|
24
|
+
set data(data) {
|
|
25
|
+
this.state.data = data;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The current error encountered by the state, if any.
|
|
29
|
+
*/
|
|
30
|
+
get error() {
|
|
31
|
+
return this.state.error;
|
|
32
|
+
}
|
|
33
|
+
set error(error) {
|
|
34
|
+
this.state.error = error;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The execution status of the state (PENDING, SUCCESS, ERROR).
|
|
38
|
+
* Transitioning to a terminal status (SUCCESS or ERROR) will automatically resolve or reject the underlying Promise.
|
|
39
|
+
*/
|
|
40
|
+
get status() {
|
|
41
|
+
return this.state.status;
|
|
42
|
+
}
|
|
43
|
+
set status(status) {
|
|
44
|
+
this.state.status = status;
|
|
45
|
+
if (this.status === IRPC_STATUS.ERROR) {
|
|
46
|
+
this.reject(new Error(this.error.message));
|
|
47
|
+
this.destroy();
|
|
48
|
+
} else if (this.status === IRPC_STATUS.SUCCESS) {
|
|
49
|
+
this.accept(this.data);
|
|
50
|
+
this.destroy();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Initializes a new RemoteState with an optional initial payload.
|
|
55
|
+
*
|
|
56
|
+
* @param init - An optional starting value for the data payload.
|
|
57
|
+
*/
|
|
58
|
+
constructor(init) {
|
|
59
|
+
let acceptFn;
|
|
60
|
+
let rejectFn;
|
|
61
|
+
super((resolve, reject) => {
|
|
62
|
+
acceptFn = resolve;
|
|
63
|
+
rejectFn = reject;
|
|
64
|
+
});
|
|
65
|
+
this.accept = acceptFn;
|
|
66
|
+
this.reject = rejectFn;
|
|
67
|
+
this.state = mutable({
|
|
68
|
+
data: init,
|
|
69
|
+
error: void 0,
|
|
70
|
+
status: IRPC_STATUS.PENDING
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Subscribes to changes emitted by the internal state.
|
|
75
|
+
*
|
|
76
|
+
* @param handler - A callback function invoked whenever the state mutates.
|
|
77
|
+
* @returns An unsubscribe function to terminate the listener.
|
|
78
|
+
*/
|
|
79
|
+
subscribe(handler) {
|
|
80
|
+
return subscribe(this.state, handler);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Destroys the reactive state bindings.
|
|
84
|
+
*/
|
|
85
|
+
destroy() {
|
|
86
|
+
anchor.destroy(this.state);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Ensures that chained Promise operations return standard Promises
|
|
90
|
+
* rather than instantiating new RemoteState subclasses.
|
|
91
|
+
*/
|
|
92
|
+
static get [Symbol.species]() {
|
|
93
|
+
return Promise;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* A utility factory to structurally instantiate an active `RemoteState` pipeline natively
|
|
98
|
+
* decoupled from standard Promise chains. This elegantly captures constructor functions
|
|
99
|
+
* pushing events into the state before terminating mechanically via secure internal hooks.
|
|
100
|
+
*
|
|
101
|
+
* @template T - The type of the streamed payload data.
|
|
102
|
+
* @param construct - The isolated stream constructor callback that natively operates the pipeline.
|
|
103
|
+
* @param init - An optional initial value to prime the state payload inherently.
|
|
104
|
+
* @returns A fully active RemoteState inherently bound to the callbacks executing natively.
|
|
105
|
+
*/
|
|
106
|
+
function stream(construct, init) {
|
|
107
|
+
const state = new RemoteState(init);
|
|
108
|
+
const accept = ((...values) => {
|
|
109
|
+
if (values.length > 0) state.data = values[0];
|
|
110
|
+
state.status = IRPC_STATUS.SUCCESS;
|
|
111
|
+
});
|
|
112
|
+
const reject = (error) => {
|
|
113
|
+
state.error = error;
|
|
114
|
+
state.status = IRPC_STATUS.ERROR;
|
|
115
|
+
};
|
|
116
|
+
try {
|
|
117
|
+
const result = construct(state.data, accept, reject);
|
|
118
|
+
if (result instanceof Promise) result.catch(reject);
|
|
119
|
+
} catch (error) {
|
|
120
|
+
reject(error);
|
|
121
|
+
}
|
|
122
|
+
return state;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
//#endregion
|
|
126
|
+
export { RemoteState, stream };
|
package/dist/stream.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { IRPCData, IRPCError, IRPCPacketStream, IRPCResponse, IRPCStatus } from "./types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/stream.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A server-side producer that normalizes and serializes RPC outputs into standard transport packets.
|
|
7
|
+
*
|
|
8
|
+
* Supports both standard asynchronous responses and reactive streams. When handling a continuous stream,
|
|
9
|
+
* it intercepts state mutations and emits sequential network packets (`ANSWER`, `EVENT`, `CLOSE`).
|
|
10
|
+
*
|
|
11
|
+
* @template T - The type of data yielded by the stream.
|
|
12
|
+
*/
|
|
13
|
+
declare class IRPCStream<T extends IRPCData> {
|
|
14
|
+
private id;
|
|
15
|
+
private name;
|
|
16
|
+
private initializer;
|
|
17
|
+
private pipeHandlers;
|
|
18
|
+
private closeHandlers;
|
|
19
|
+
private errorHandlers;
|
|
20
|
+
value?: T;
|
|
21
|
+
error?: IRPCError;
|
|
22
|
+
status: IRPCStatus;
|
|
23
|
+
/**
|
|
24
|
+
* Initializes a stream wrapping an asynchronous RPC execution.
|
|
25
|
+
*
|
|
26
|
+
* @param id - The unique identifier of the RPC request.
|
|
27
|
+
* @param name - The name of the specification processing the execution.
|
|
28
|
+
* @param initializer - An execution callback that yields an IRPCResponse.
|
|
29
|
+
*/
|
|
30
|
+
constructor(id: string, name: string, initializer: () => Promise<IRPCResponse>);
|
|
31
|
+
/**
|
|
32
|
+
* Evaluates the underlying initializer and propagates standard transport packets
|
|
33
|
+
* to all bound pipe handlers based on the output lifecycle.
|
|
34
|
+
*/
|
|
35
|
+
private start;
|
|
36
|
+
/**
|
|
37
|
+
* Binds a handler to receive the outbound stream packets.
|
|
38
|
+
* If invoked after the stream has fulfilled or rejected natively, it automatically plays back the conclusive packet.
|
|
39
|
+
*
|
|
40
|
+
* @param handler - A callback function to receive packets.
|
|
41
|
+
*/
|
|
42
|
+
pipe(handler: (event: IRPCPacketStream<T>) => void): void;
|
|
43
|
+
/**
|
|
44
|
+
* Binds a handler to trap any internal runtime failures independently.
|
|
45
|
+
*
|
|
46
|
+
* @param handler - A callback function to receive stream errors.
|
|
47
|
+
*/
|
|
48
|
+
catch(handler: (error: IRPCError) => void): void;
|
|
49
|
+
/**
|
|
50
|
+
* Binds a handler triggered upon terminal completion of the stream process (success or error).
|
|
51
|
+
*
|
|
52
|
+
* @param handler - A callback function invoked at stream completion.
|
|
53
|
+
*/
|
|
54
|
+
close(handler: () => void): void;
|
|
55
|
+
}
|
|
56
|
+
//#endregion
|
|
57
|
+
export { IRPCStream };
|
package/dist/stream.js
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { IRPC_PACKET_TYPE, IRPC_STATUS } from "./enum.js";
|
|
2
|
+
import { ERROR_CODE } from "./error.js";
|
|
3
|
+
import { RemoteState } from "./state.js";
|
|
4
|
+
|
|
5
|
+
//#region src/stream.ts
|
|
6
|
+
/**
|
|
7
|
+
* A server-side producer that normalizes and serializes RPC outputs into standard transport packets.
|
|
8
|
+
*
|
|
9
|
+
* Supports both standard asynchronous responses and reactive streams. When handling a continuous stream,
|
|
10
|
+
* it intercepts state mutations and emits sequential network packets (`ANSWER`, `EVENT`, `CLOSE`).
|
|
11
|
+
*
|
|
12
|
+
* @template T - The type of data yielded by the stream.
|
|
13
|
+
*/
|
|
14
|
+
var IRPCStream = class {
|
|
15
|
+
pipeHandlers = /* @__PURE__ */ new Set();
|
|
16
|
+
closeHandlers = /* @__PURE__ */ new Set();
|
|
17
|
+
errorHandlers = /* @__PURE__ */ new Set();
|
|
18
|
+
value;
|
|
19
|
+
error;
|
|
20
|
+
status = IRPC_STATUS.IDLE;
|
|
21
|
+
/**
|
|
22
|
+
* Initializes a stream wrapping an asynchronous RPC execution.
|
|
23
|
+
*
|
|
24
|
+
* @param id - The unique identifier of the RPC request.
|
|
25
|
+
* @param name - The name of the specification processing the execution.
|
|
26
|
+
* @param initializer - An execution callback that yields an IRPCResponse.
|
|
27
|
+
*/
|
|
28
|
+
constructor(id, name, initializer) {
|
|
29
|
+
this.id = id;
|
|
30
|
+
this.name = name;
|
|
31
|
+
this.initializer = initializer;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Evaluates the underlying initializer and propagates standard transport packets
|
|
35
|
+
* to all bound pipe handlers based on the output lifecycle.
|
|
36
|
+
*/
|
|
37
|
+
async start() {
|
|
38
|
+
if (this.status !== IRPC_STATUS.IDLE) return;
|
|
39
|
+
this.status = IRPC_STATUS.PENDING;
|
|
40
|
+
const { id, name } = this;
|
|
41
|
+
try {
|
|
42
|
+
const { result } = await this.initializer();
|
|
43
|
+
if (result instanceof RemoteState) {
|
|
44
|
+
this.value = result.data;
|
|
45
|
+
if (result.status === IRPC_STATUS.SUCCESS || result.status === IRPC_STATUS.ERROR) {
|
|
46
|
+
if (result.status === IRPC_STATUS.ERROR) {
|
|
47
|
+
this.error = {
|
|
48
|
+
code: ERROR_CODE.STREAM_ERROR,
|
|
49
|
+
message: result.error.message
|
|
50
|
+
};
|
|
51
|
+
this.status = IRPC_STATUS.ERROR;
|
|
52
|
+
} else this.status = IRPC_STATUS.SUCCESS;
|
|
53
|
+
const packet = {
|
|
54
|
+
id,
|
|
55
|
+
name,
|
|
56
|
+
type: IRPC_PACKET_TYPE.ANSWER,
|
|
57
|
+
data: this.value,
|
|
58
|
+
error: this.error,
|
|
59
|
+
status: this.status,
|
|
60
|
+
createdAt: Date.now()
|
|
61
|
+
};
|
|
62
|
+
this.pipeHandlers.forEach((handler) => handler(packet));
|
|
63
|
+
this.errorHandlers.forEach((handler) => handler(this.error));
|
|
64
|
+
this.closeHandlers.forEach((handler) => handler());
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
this.pipeHandlers.forEach((handler) => {
|
|
68
|
+
handler({
|
|
69
|
+
id,
|
|
70
|
+
name,
|
|
71
|
+
type: IRPC_PACKET_TYPE.ANSWER,
|
|
72
|
+
data: result.data,
|
|
73
|
+
status: result.status,
|
|
74
|
+
createdAt: Date.now()
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
const unsubscribe = result.subscribe((state, { type, keys, value }) => {
|
|
78
|
+
if (type === "init") return;
|
|
79
|
+
const [rootKey] = keys;
|
|
80
|
+
if (rootKey === "data") this.pipeHandlers.forEach((handler) => {
|
|
81
|
+
handler({
|
|
82
|
+
id,
|
|
83
|
+
name,
|
|
84
|
+
type: IRPC_PACKET_TYPE.EVENT,
|
|
85
|
+
status: state.status,
|
|
86
|
+
data: {
|
|
87
|
+
type,
|
|
88
|
+
keys,
|
|
89
|
+
value
|
|
90
|
+
},
|
|
91
|
+
createdAt: Date.now()
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
else if (rootKey === "status") {
|
|
95
|
+
if (state.status !== IRPC_STATUS.SUCCESS && state.status !== IRPC_STATUS.ERROR) return;
|
|
96
|
+
this.status = state.status;
|
|
97
|
+
if (state.status === IRPC_STATUS.ERROR) {
|
|
98
|
+
this.error = {
|
|
99
|
+
code: ERROR_CODE.STREAM_ERROR,
|
|
100
|
+
message: state.error.message
|
|
101
|
+
};
|
|
102
|
+
this.errorHandlers.forEach((handler) => handler(this.error));
|
|
103
|
+
}
|
|
104
|
+
this.pipeHandlers.forEach((handler) => {
|
|
105
|
+
handler({
|
|
106
|
+
id,
|
|
107
|
+
name,
|
|
108
|
+
type: IRPC_PACKET_TYPE.CLOSE,
|
|
109
|
+
error: this.error,
|
|
110
|
+
status: this.status,
|
|
111
|
+
createdAt: Date.now()
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
this.closeHandlers.forEach((handler) => handler());
|
|
115
|
+
unsubscribe();
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
} else {
|
|
119
|
+
this.value = result;
|
|
120
|
+
this.status = IRPC_STATUS.SUCCESS;
|
|
121
|
+
const packet = {
|
|
122
|
+
id,
|
|
123
|
+
name,
|
|
124
|
+
type: IRPC_PACKET_TYPE.ANSWER,
|
|
125
|
+
status: IRPC_STATUS.SUCCESS,
|
|
126
|
+
data: this.value,
|
|
127
|
+
createdAt: Date.now()
|
|
128
|
+
};
|
|
129
|
+
this.pipeHandlers.forEach((handler) => handler(packet));
|
|
130
|
+
this.closeHandlers.forEach((handler) => handler());
|
|
131
|
+
}
|
|
132
|
+
} catch (error) {
|
|
133
|
+
this.error = {
|
|
134
|
+
code: ERROR_CODE.STREAM_ERROR,
|
|
135
|
+
message: error.message
|
|
136
|
+
};
|
|
137
|
+
this.status = IRPC_STATUS.ERROR;
|
|
138
|
+
this.pipeHandlers.forEach((handler) => {
|
|
139
|
+
handler({
|
|
140
|
+
id,
|
|
141
|
+
name,
|
|
142
|
+
type: IRPC_PACKET_TYPE.ANSWER,
|
|
143
|
+
status: IRPC_STATUS.ERROR,
|
|
144
|
+
error,
|
|
145
|
+
createdAt: Date.now()
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
this.errorHandlers.forEach((handler) => handler(this.error));
|
|
149
|
+
this.closeHandlers.forEach((handler) => handler());
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Binds a handler to receive the outbound stream packets.
|
|
155
|
+
* If invoked after the stream has fulfilled or rejected natively, it automatically plays back the conclusive packet.
|
|
156
|
+
*
|
|
157
|
+
* @param handler - A callback function to receive packets.
|
|
158
|
+
*/
|
|
159
|
+
pipe(handler) {
|
|
160
|
+
if (this.status === IRPC_STATUS.SUCCESS || this.status === IRPC_STATUS.ERROR) {
|
|
161
|
+
handler({
|
|
162
|
+
id: this.id,
|
|
163
|
+
name: this.name,
|
|
164
|
+
type: IRPC_PACKET_TYPE.ANSWER,
|
|
165
|
+
data: this.value,
|
|
166
|
+
error: this.error,
|
|
167
|
+
status: this.status,
|
|
168
|
+
createdAt: Date.now()
|
|
169
|
+
});
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
this.pipeHandlers.add(handler);
|
|
173
|
+
this.start().catch(() => {});
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Binds a handler to trap any internal runtime failures independently.
|
|
177
|
+
*
|
|
178
|
+
* @param handler - A callback function to receive stream errors.
|
|
179
|
+
*/
|
|
180
|
+
catch(handler) {
|
|
181
|
+
if (this.status === IRPC_STATUS.ERROR) {
|
|
182
|
+
handler(this.error);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
this.errorHandlers.add(handler);
|
|
186
|
+
this.start().catch(() => {});
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Binds a handler triggered upon terminal completion of the stream process (success or error).
|
|
190
|
+
*
|
|
191
|
+
* @param handler - A callback function invoked at stream completion.
|
|
192
|
+
*/
|
|
193
|
+
close(handler) {
|
|
194
|
+
if (this.status === IRPC_STATUS.SUCCESS || this.status === IRPC_STATUS.ERROR) {
|
|
195
|
+
handler();
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
this.closeHandlers.add(handler);
|
|
199
|
+
this.start().catch(() => {});
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
//#endregion
|
|
204
|
+
export { IRPCStream };
|
package/dist/transport.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { IRPCData, IRPCInputs, IRPCOutput, IRPCSpec, TransportConfig } from "./types.js";
|
|
1
|
+
import { IRPCCallConfig, IRPCData, IRPCInputs, IRPCOutput, IRPCSpec, TransportConfig } from "./types.js";
|
|
2
|
+
import { IRPCReader } from "./reader.js";
|
|
2
3
|
import { IRPCCall } from "./call.js";
|
|
3
4
|
|
|
4
5
|
//#region src/transport.d.ts
|
|
@@ -22,16 +23,16 @@ declare class IRPCTransport {
|
|
|
22
23
|
* Initiates an RPC call with the given specification and arguments.
|
|
23
24
|
* @param spec - The RPC specification defining the method to call.
|
|
24
25
|
* @param args - An array of arguments to pass to the RPC method.
|
|
25
|
-
* @param
|
|
26
|
+
* @param config - Optional call configuration, including timeout, retry settings, and more.
|
|
26
27
|
* @returns A promise that resolves with the RPC response data or rejects with an error.
|
|
27
28
|
*/
|
|
28
|
-
call(spec: IRPCSpec<IRPCInputs, IRPCOutput>, args: IRPCData[],
|
|
29
|
+
call(spec: IRPCSpec<IRPCInputs, IRPCOutput>, args: IRPCData[], config?: IRPCCallConfig): IRPCReader<IRPCData>;
|
|
29
30
|
/**
|
|
30
31
|
* Schedules an RPC call for execution, implementing debouncing logic.
|
|
31
32
|
* Queued calls will be dispatched after the configured debounce delay.
|
|
32
33
|
* @param call - The RPC call to schedule.
|
|
33
34
|
*/
|
|
34
|
-
|
|
35
|
+
schedule(call: IRPCCall): void;
|
|
35
36
|
/**
|
|
36
37
|
* Dispatches a batch of RPC calls. This base implementation rejects all calls
|
|
37
38
|
* with a "not implemented" error. Subclasses should override this method to
|
package/dist/transport.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IRPC_PACKET_TYPE, IRPC_STATUS } from "./enum.js";
|
|
2
2
|
import { ERROR_CODE, ERROR_MESSAGE } from "./error.js";
|
|
3
|
+
import { IRPCCall } from "./call.js";
|
|
3
4
|
|
|
4
5
|
//#region src/transport.ts
|
|
5
6
|
/**
|
|
@@ -22,27 +23,26 @@ var IRPCTransport = class {
|
|
|
22
23
|
* Initiates an RPC call with the given specification and arguments.
|
|
23
24
|
* @param spec - The RPC specification defining the method to call.
|
|
24
25
|
* @param args - An array of arguments to pass to the RPC method.
|
|
25
|
-
* @param
|
|
26
|
+
* @param config - Optional call configuration, including timeout, retry settings, and more.
|
|
26
27
|
* @returns A promise that resolves with the RPC response data or rejects with an error.
|
|
27
28
|
*/
|
|
28
|
-
call(spec, args,
|
|
29
|
+
call(spec, args, config) {
|
|
29
30
|
const payload = {
|
|
30
31
|
name: spec.name,
|
|
31
32
|
args
|
|
32
33
|
};
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
clearTimeout(timer);
|
|
43
|
-
}, timeout);
|
|
44
|
-
this.schedule(call);
|
|
34
|
+
const { timeout, maxRetries, retryMode, retryDelay } = {
|
|
35
|
+
...this.config,
|
|
36
|
+
...config
|
|
37
|
+
};
|
|
38
|
+
const call = new IRPCCall(this, payload, {
|
|
39
|
+
timeout,
|
|
40
|
+
maxRetries,
|
|
41
|
+
retryMode,
|
|
42
|
+
retryDelay
|
|
45
43
|
});
|
|
44
|
+
this.schedule(call);
|
|
45
|
+
return call.reader;
|
|
46
46
|
}
|
|
47
47
|
/**
|
|
48
48
|
* Schedules an RPC call for execution, implementing debouncing logic.
|
|
@@ -50,10 +50,18 @@ var IRPCTransport = class {
|
|
|
50
50
|
* @param call - The RPC call to schedule.
|
|
51
51
|
*/
|
|
52
52
|
schedule(call) {
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
const { debounce } = this.config ?? {};
|
|
54
|
+
if (debounce === false) {
|
|
55
|
+
this.dispatch([call]).finally(() => {}).catch(() => {});
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const timeout = typeof debounce === "number" && !Number.isNaN(debounce) ? debounce : 0;
|
|
59
|
+
const dispatch = () => {
|
|
60
|
+
this.dispatch(Array.from(this.queue)).finally(() => {}).catch(() => {});
|
|
55
61
|
this.queue.clear();
|
|
56
|
-
}
|
|
62
|
+
};
|
|
63
|
+
if (!this.queue.size) if (timeout === 0) queueMicrotask(dispatch);
|
|
64
|
+
else setTimeout(dispatch, timeout);
|
|
57
65
|
this.queue.add(call);
|
|
58
66
|
}
|
|
59
67
|
/**
|
|
@@ -65,7 +73,17 @@ var IRPCTransport = class {
|
|
|
65
73
|
*/
|
|
66
74
|
async dispatch(calls) {
|
|
67
75
|
calls.forEach((call) => {
|
|
68
|
-
call.
|
|
76
|
+
call.enqueue({
|
|
77
|
+
id: call.id,
|
|
78
|
+
name: call.payload.name,
|
|
79
|
+
type: IRPC_PACKET_TYPE.CLOSE,
|
|
80
|
+
status: IRPC_STATUS.ERROR,
|
|
81
|
+
error: {
|
|
82
|
+
code: ERROR_CODE.TRANSPORT_NOT_IMPLEMENTED,
|
|
83
|
+
message: ERROR_MESSAGE[ERROR_CODE.TRANSPORT_NOT_IMPLEMENTED]
|
|
84
|
+
},
|
|
85
|
+
createdAt: Date.now()
|
|
86
|
+
});
|
|
69
87
|
});
|
|
70
88
|
}
|
|
71
89
|
};
|