@irpclib/irpc 1.0.0-beta.20 → 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 +19 -12
- package/dist/call.js +58 -16
- package/dist/enum.d.ts +1 -0
- package/dist/enum.js +1 -0
- package/dist/error.d.ts +5 -0
- package/dist/error.js +7 -2
- package/dist/index.d.ts +6 -3
- package/dist/index.js +6 -3
- package/dist/module.d.ts +5 -4
- package/dist/module.js +26 -18
- 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 +68 -5
- package/dist/state.js +99 -14
- package/dist/stream.d.ts +57 -0
- package/dist/stream.js +204 -0
- package/dist/transport.d.ts +5 -4
- package/dist/transport.js +28 -18
- package/dist/types.d.ts +47 -21
- package/package.json +2 -2
- package/readme.md +99 -30
package/dist/call.d.ts
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IRPCTransport } from "./transport.js";
|
|
2
|
+
import { IRPCCallConfig, IRPCData, IRPCPacketStream, IRPCPayload, IRPCStatus } from "./types.js";
|
|
3
|
+
import { IRPCReader } from "./reader.js";
|
|
2
4
|
|
|
3
5
|
//#region src/call.d.ts
|
|
4
|
-
|
|
6
|
+
declare const DEFAULT_RETRY_MODE = "exponential";
|
|
7
|
+
declare const DEFAULT_RETRY_DELAY = 1000;
|
|
5
8
|
/**
|
|
6
9
|
* Represents an RPC call with promise-like behavior for handling asynchronous operations.
|
|
7
10
|
* Each call has a unique identifier and manages its own resolution state.
|
|
8
11
|
*/
|
|
9
12
|
declare class IRPCCall {
|
|
13
|
+
transport: IRPCTransport;
|
|
10
14
|
payload: IRPCPayload;
|
|
11
|
-
|
|
12
|
-
private rejector;
|
|
13
|
-
timeout?: number | undefined;
|
|
15
|
+
options: IRPCCallConfig;
|
|
14
16
|
/**
|
|
15
17
|
* Unique identifier for this RPC call, generated using shortId().
|
|
16
18
|
*/
|
|
@@ -37,26 +39,31 @@ declare class IRPCCall {
|
|
|
37
39
|
*/
|
|
38
40
|
value?: unknown;
|
|
39
41
|
error?: Error;
|
|
42
|
+
private readonly timerId?;
|
|
43
|
+
private retries;
|
|
44
|
+
private retryReasons;
|
|
45
|
+
reader: IRPCReader<IRPCData>;
|
|
40
46
|
/**
|
|
41
47
|
* Creates a new IRPCCall instance.
|
|
48
|
+
* @param transport
|
|
42
49
|
* @param payload - The RPC payload containing method and parameters
|
|
43
|
-
* @param
|
|
44
|
-
* @param rejector - Function to reject the associated promise with an error
|
|
45
|
-
* @param timeout - Optional timeout value in milliseconds
|
|
50
|
+
* @param options - Options for the call, such as timeout, maxRetries, etc.
|
|
46
51
|
*/
|
|
47
|
-
constructor(
|
|
52
|
+
constructor(transport: IRPCTransport, payload: IRPCPayload, options: IRPCCallConfig);
|
|
53
|
+
enqueue(packet: IRPCPacketStream<IRPCData>): void;
|
|
48
54
|
/**
|
|
49
55
|
* Resolves the RPC call with the provided value.
|
|
50
56
|
* If the call is already resolved, this method does nothing.
|
|
51
57
|
* @param value - The value to resolve the promise with
|
|
52
58
|
*/
|
|
53
|
-
resolve(value:
|
|
59
|
+
resolve(value: IRPCData): void;
|
|
54
60
|
/**
|
|
55
61
|
* Rejects the RPC call with the provided reason.
|
|
56
62
|
* If the call is already resolved, this method does nothing.
|
|
57
63
|
* @param reason - Optional error reason for rejecting the promise
|
|
64
|
+
* @param retriable - Flag indicating whether to retry the call
|
|
58
65
|
*/
|
|
59
|
-
reject(reason?: Error): void;
|
|
66
|
+
reject(reason?: Error, retriable?: boolean): void;
|
|
60
67
|
}
|
|
61
68
|
//#endregion
|
|
62
|
-
export { IRPCCall };
|
|
69
|
+
export { DEFAULT_RETRY_DELAY, DEFAULT_RETRY_MODE, IRPCCall };
|
package/dist/call.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import { IRPC_STATUS } from "./enum.js";
|
|
1
|
+
import { IRPC_PACKET_TYPE, IRPC_STATUS } from "./enum.js";
|
|
2
|
+
import { ERROR_CODE, ERROR_MESSAGE } from "./error.js";
|
|
3
|
+
import { IRPCReader } from "./reader.js";
|
|
2
4
|
import { uuid } from "./uuid.js";
|
|
3
5
|
|
|
4
6
|
//#region src/call.ts
|
|
7
|
+
const DEFAULT_RETRY_MODE = "exponential";
|
|
8
|
+
const DEFAULT_RETRY_DELAY = 1e3;
|
|
5
9
|
/**
|
|
6
10
|
* Represents an RPC call with promise-like behavior for handling asynchronous operations.
|
|
7
11
|
* Each call has a unique identifier and manages its own resolution state.
|
|
@@ -33,18 +37,40 @@ var IRPCCall = class {
|
|
|
33
37
|
*/
|
|
34
38
|
value;
|
|
35
39
|
error;
|
|
40
|
+
timerId;
|
|
41
|
+
retries = 0;
|
|
42
|
+
retryReasons = /* @__PURE__ */ new Set();
|
|
43
|
+
reader;
|
|
36
44
|
/**
|
|
37
45
|
* Creates a new IRPCCall instance.
|
|
46
|
+
* @param transport
|
|
38
47
|
* @param payload - The RPC payload containing method and parameters
|
|
39
|
-
* @param
|
|
40
|
-
* @param rejector - Function to reject the associated promise with an error
|
|
41
|
-
* @param timeout - Optional timeout value in milliseconds
|
|
48
|
+
* @param options - Options for the call, such as timeout, maxRetries, etc.
|
|
42
49
|
*/
|
|
43
|
-
constructor(
|
|
50
|
+
constructor(transport, payload, options) {
|
|
51
|
+
this.transport = transport;
|
|
44
52
|
this.payload = payload;
|
|
45
|
-
this.
|
|
46
|
-
this.
|
|
47
|
-
|
|
53
|
+
this.options = options;
|
|
54
|
+
if (options.timeout) this.timerId = setTimeout(() => {
|
|
55
|
+
this.reader.push({
|
|
56
|
+
id: this.id,
|
|
57
|
+
name: this.payload.name,
|
|
58
|
+
type: IRPC_PACKET_TYPE.CLOSE,
|
|
59
|
+
status: IRPC_STATUS.ERROR,
|
|
60
|
+
error: {
|
|
61
|
+
code: ERROR_CODE.TIMEOUT,
|
|
62
|
+
message: ERROR_MESSAGE[ERROR_CODE.TIMEOUT]
|
|
63
|
+
},
|
|
64
|
+
createdAt: Date.now()
|
|
65
|
+
});
|
|
66
|
+
this.reject(new Error(ERROR_MESSAGE[ERROR_CODE.TIMEOUT]), false);
|
|
67
|
+
}, options.timeout);
|
|
68
|
+
this.reader = new IRPCReader(this.id);
|
|
69
|
+
}
|
|
70
|
+
enqueue(packet) {
|
|
71
|
+
this.reader.push(packet);
|
|
72
|
+
if (this.reader.status === IRPC_STATUS.SUCCESS) this.resolve(this.reader.data);
|
|
73
|
+
else if (this.reader.status === IRPC_STATUS.ERROR) this.reject(this.reader.error);
|
|
48
74
|
}
|
|
49
75
|
/**
|
|
50
76
|
* Resolves the RPC call with the provided value.
|
|
@@ -57,22 +83,38 @@ var IRPCCall = class {
|
|
|
57
83
|
this.status = IRPC_STATUS.SUCCESS;
|
|
58
84
|
this.resolved = true;
|
|
59
85
|
this.finishedAt = Date.now();
|
|
60
|
-
this.
|
|
86
|
+
clearTimeout(this.timerId);
|
|
61
87
|
}
|
|
62
88
|
/**
|
|
63
89
|
* Rejects the RPC call with the provided reason.
|
|
64
90
|
* If the call is already resolved, this method does nothing.
|
|
65
91
|
* @param reason - Optional error reason for rejecting the promise
|
|
92
|
+
* @param retriable - Flag indicating whether to retry the call
|
|
66
93
|
*/
|
|
67
|
-
reject(reason) {
|
|
94
|
+
reject(reason, retriable = true) {
|
|
68
95
|
if (this.resolved) return;
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
96
|
+
const { maxRetries, retryMode = DEFAULT_RETRY_MODE, retryDelay = DEFAULT_RETRY_DELAY } = this.options;
|
|
97
|
+
if (maxRetries && retriable) {
|
|
98
|
+
if (reason) this.retryReasons.add(reason);
|
|
99
|
+
if (this.retries >= maxRetries) {
|
|
100
|
+
console.error(ERROR_MESSAGE[ERROR_CODE.CALL_MAX_RETRIES_REACHED], this.retryReasons);
|
|
101
|
+
this.reject(reason, false);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const delay = retryMode === "linear" ? retryDelay : retryDelay * 2 ** this.retries;
|
|
105
|
+
setTimeout(() => {
|
|
106
|
+
this.retries++;
|
|
107
|
+
this.transport.schedule(this);
|
|
108
|
+
}, delay);
|
|
109
|
+
} else {
|
|
110
|
+
this.error = reason;
|
|
111
|
+
this.status = IRPC_STATUS.ERROR;
|
|
112
|
+
this.resolved = true;
|
|
113
|
+
this.finishedAt = Date.now();
|
|
114
|
+
clearTimeout(this.timerId);
|
|
115
|
+
}
|
|
74
116
|
}
|
|
75
117
|
};
|
|
76
118
|
|
|
77
119
|
//#endregion
|
|
78
|
-
export { IRPCCall };
|
|
120
|
+
export { DEFAULT_RETRY_DELAY, DEFAULT_RETRY_MODE, IRPCCall };
|
package/dist/enum.d.ts
CHANGED
package/dist/enum.js
CHANGED
package/dist/error.d.ts
CHANGED
|
@@ -22,6 +22,8 @@ declare const ERROR_CODE: {
|
|
|
22
22
|
RESOLVER_NOT_IMPLEMENTED: string;
|
|
23
23
|
RESOLVER_NOT_FOUND: string;
|
|
24
24
|
RESOLVER_NOT_SUPPORTED: string;
|
|
25
|
+
STREAM_ERROR: string;
|
|
26
|
+
CALL_MAX_RETRIES_REACHED: string;
|
|
25
27
|
};
|
|
26
28
|
type ErrorCode = (typeof ERROR_CODE)[keyof typeof ERROR_CODE];
|
|
27
29
|
declare const ERROR_MESSAGE: {
|
|
@@ -41,10 +43,13 @@ declare const ERROR_MESSAGE: {
|
|
|
41
43
|
[ERROR_CODE.TRANSPORT_INVALID]: string;
|
|
42
44
|
[ERROR_CODE.TRANSPORT_NOT_IMPLEMENTED]: string;
|
|
43
45
|
[ERROR_CODE.STUB_INVALID]: string;
|
|
46
|
+
[ERROR_CODE.STREAM_ERROR]: string;
|
|
44
47
|
[ERROR_CODE.STUB_NOT_IMPLEMENTED]: string;
|
|
45
48
|
[ERROR_CODE.RESOLVER_MISSING]: string;
|
|
46
49
|
[ERROR_CODE.RESOLVER_NOT_IMPLEMENTED]: string;
|
|
47
50
|
[ERROR_CODE.RESOLVER_NOT_FOUND]: string;
|
|
51
|
+
[ERROR_CODE.RESOLVER_NOT_SUPPORTED]: string;
|
|
52
|
+
[ERROR_CODE.CALL_MAX_RETRIES_REACHED]: string;
|
|
48
53
|
};
|
|
49
54
|
//#endregion
|
|
50
55
|
export { ERROR_CODE, ERROR_MESSAGE, ErrorCode };
|
package/dist/error.js
CHANGED
|
@@ -21,7 +21,9 @@ const ERROR_CODE = {
|
|
|
21
21
|
RESOLVER_MISSING: "resolver_missing",
|
|
22
22
|
RESOLVER_NOT_IMPLEMENTED: "resolver_not_implemented",
|
|
23
23
|
RESOLVER_NOT_FOUND: "resolver_not_found",
|
|
24
|
-
RESOLVER_NOT_SUPPORTED: "resolver_not_supported"
|
|
24
|
+
RESOLVER_NOT_SUPPORTED: "resolver_not_supported",
|
|
25
|
+
STREAM_ERROR: "stream_error",
|
|
26
|
+
CALL_MAX_RETRIES_REACHED: "call_max_retries_reached"
|
|
25
27
|
};
|
|
26
28
|
const ERROR_MESSAGE = {
|
|
27
29
|
[ERROR_CODE.UNKNOWN]: "IRPC: Unknown error",
|
|
@@ -40,10 +42,13 @@ const ERROR_MESSAGE = {
|
|
|
40
42
|
[ERROR_CODE.TRANSPORT_INVALID]: "IRPC: Transport invalid error",
|
|
41
43
|
[ERROR_CODE.TRANSPORT_NOT_IMPLEMENTED]: "IRPC: Transport not implemented error",
|
|
42
44
|
[ERROR_CODE.STUB_INVALID]: "IRPC: Stub invalid error",
|
|
45
|
+
[ERROR_CODE.STREAM_ERROR]: "IRPC: Stream error",
|
|
43
46
|
[ERROR_CODE.STUB_NOT_IMPLEMENTED]: "IRPC: Stub not implemented error",
|
|
44
47
|
[ERROR_CODE.RESOLVER_MISSING]: "IRPC: Resolver missing error",
|
|
45
48
|
[ERROR_CODE.RESOLVER_NOT_IMPLEMENTED]: "IRPC: Resolver not implemented error",
|
|
46
|
-
[ERROR_CODE.RESOLVER_NOT_FOUND]: "IRPC: Resolver not found error"
|
|
49
|
+
[ERROR_CODE.RESOLVER_NOT_FOUND]: "IRPC: Resolver not found error",
|
|
50
|
+
[ERROR_CODE.RESOLVER_NOT_SUPPORTED]: "IRPC: Resolver not supported error",
|
|
51
|
+
[ERROR_CODE.CALL_MAX_RETRIES_REACHED]: "IRPC: Call max retries reached error"
|
|
47
52
|
};
|
|
48
53
|
|
|
49
54
|
//#endregion
|
package/dist/index.d.ts
CHANGED
|
@@ -2,9 +2,12 @@ import { IRPCCacheEntry, IRPCCacher } from "./cache.js";
|
|
|
2
2
|
import { IRPC_DATA_TYPE, IRPC_EVENT_TYPE, IRPC_PACKET_TYPE, IRPC_STATUS } from "./enum.js";
|
|
3
3
|
import { ERROR_CODE, ERROR_MESSAGE, ErrorCode } from "./error.js";
|
|
4
4
|
import { IRPCTransport } from "./transport.js";
|
|
5
|
-
import { IRPCArraySchema,
|
|
6
|
-
import {
|
|
5
|
+
import { IRPCArraySchema, IRPCCallConfig, IRPCContext, IRPCContextProvider, IRPCData, IRPCDataSchema, IRPCDataType, IRPCDeclareInit, IRPCError, IRPCEventType, IRPCHandler, IRPCInit, IRPCInputs, IRPCObject, IRPCObjectSchema, IRPCOutput, IRPCPackageConfig, IRPCPackageInfo, IRPCPacketAnswer, IRPCPacketBase, IRPCPacketCall, IRPCPacketClose, IRPCPacketData, IRPCPacketEvent, IRPCPacketStream, IRPCPacketType, IRPCParseResult, IRPCPayload, IRPCPrimitive, IRPCPrimitiveSchema, IRPCReadable, IRPCRequest, IRPCResponse, IRPCSchema, IRPCSpec, IRPCSpecStore, IRPCStatus, IRPCStubStore, TransportConfig } from "./types.js";
|
|
6
|
+
import { RemoteState, StreamConstructor, stream } from "./state.js";
|
|
7
|
+
import { IRPCReader } from "./reader.js";
|
|
8
|
+
import { DEFAULT_RETRY_DELAY, DEFAULT_RETRY_MODE, IRPCCall } from "./call.js";
|
|
7
9
|
import { createContext, getContext, setContext, setContextProvider, withContext } from "./context.js";
|
|
8
10
|
import { IRPCPackage, createPackage } from "./module.js";
|
|
9
11
|
import { IRPCResolver } from "./resolver.js";
|
|
10
|
-
|
|
12
|
+
import { IRPCStream } from "./stream.js";
|
|
13
|
+
export { DEFAULT_RETRY_DELAY, DEFAULT_RETRY_MODE, ERROR_CODE, ERROR_MESSAGE, ErrorCode, IRPCArraySchema, IRPCCacheEntry, IRPCCacher, IRPCCall, IRPCCallConfig, IRPCContext, IRPCContextProvider, IRPCData, IRPCDataSchema, IRPCDataType, IRPCDeclareInit, IRPCError, IRPCEventType, IRPCHandler, IRPCInit, IRPCInputs, IRPCObject, IRPCObjectSchema, IRPCOutput, IRPCPackage, IRPCPackageConfig, IRPCPackageInfo, IRPCPacketAnswer, IRPCPacketBase, IRPCPacketCall, IRPCPacketClose, IRPCPacketData, IRPCPacketEvent, IRPCPacketStream, IRPCPacketType, IRPCParseResult, IRPCPayload, IRPCPrimitive, IRPCPrimitiveSchema, IRPCReadable, IRPCReader, IRPCRequest, IRPCResolver, IRPCResponse, IRPCSchema, IRPCSpec, IRPCSpecStore, IRPCStatus, IRPCStream, IRPCStubStore, IRPCTransport, IRPC_DATA_TYPE, IRPC_EVENT_TYPE, IRPC_PACKET_TYPE, IRPC_STATUS, RemoteState, StreamConstructor, TransportConfig, createContext, createPackage, getContext, setContext, setContextProvider, stream, withContext };
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { IRPCCacher } from "./cache.js";
|
|
2
2
|
import { IRPC_DATA_TYPE, IRPC_EVENT_TYPE, IRPC_PACKET_TYPE, IRPC_STATUS } from "./enum.js";
|
|
3
|
-
import { IRPCCall } from "./call.js";
|
|
4
|
-
import { createContext, getContext, setContext, setContextProvider, withContext } from "./context.js";
|
|
5
3
|
import { ERROR_CODE, ERROR_MESSAGE } from "./error.js";
|
|
4
|
+
import { RemoteState, stream } from "./state.js";
|
|
5
|
+
import { IRPCReader } from "./reader.js";
|
|
6
|
+
import { DEFAULT_RETRY_DELAY, DEFAULT_RETRY_MODE, IRPCCall } from "./call.js";
|
|
7
|
+
import { createContext, getContext, setContext, setContextProvider, withContext } from "./context.js";
|
|
6
8
|
import { IRPCTransport } from "./transport.js";
|
|
7
9
|
import { IRPCPackage, createPackage } from "./module.js";
|
|
8
10
|
import { IRPCResolver } from "./resolver.js";
|
|
11
|
+
import { IRPCStream } from "./stream.js";
|
|
9
12
|
|
|
10
|
-
export { ERROR_CODE, ERROR_MESSAGE, IRPCCacher, IRPCCall, IRPCPackage, IRPCResolver, IRPCTransport, IRPC_DATA_TYPE, IRPC_EVENT_TYPE, IRPC_PACKET_TYPE, IRPC_STATUS, createContext, createPackage, getContext, setContext, setContextProvider, withContext };
|
|
13
|
+
export { DEFAULT_RETRY_DELAY, DEFAULT_RETRY_MODE, ERROR_CODE, ERROR_MESSAGE, IRPCCacher, IRPCCall, IRPCPackage, IRPCReader, IRPCResolver, IRPCStream, IRPCTransport, IRPC_DATA_TYPE, IRPC_EVENT_TYPE, IRPC_PACKET_TYPE, IRPC_STATUS, RemoteState, createContext, createPackage, getContext, setContext, setContextProvider, stream, withContext };
|
package/dist/module.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { IRPCCacher } from "./cache.js";
|
|
2
2
|
import { IRPCTransport } from "./transport.js";
|
|
3
|
-
import { IRPCData,
|
|
3
|
+
import { IRPCData, IRPCDeclareInit, IRPCHandler, IRPCInputs, IRPCOutput, IRPCPackageConfig, IRPCPackageInfo, IRPCRequest, IRPCSpec, IRPCSpecStore, IRPCStubStore } from "./types.js";
|
|
4
|
+
import { RemoteState } from "./state.js";
|
|
4
5
|
|
|
5
6
|
//#region src/module.d.ts
|
|
6
7
|
|
|
@@ -46,18 +47,18 @@ declare class IRPCPackage {
|
|
|
46
47
|
constructor(config?: Partial<IRPCPackageConfig>);
|
|
47
48
|
/**
|
|
48
49
|
* Declares a new IRPC specification and creates a corresponding stub function
|
|
49
|
-
* @param
|
|
50
|
+
* @param options - The initialization object containing the IRPC specification
|
|
50
51
|
* @returns A stub function that can be used to call the IRPC
|
|
51
52
|
* @throws Error if an IRPC with the same name already exists
|
|
52
53
|
*/
|
|
53
|
-
declare<F, I extends IRPCInputs = IRPCInputs, O extends IRPCOutput = IRPCOutput>(
|
|
54
|
+
declare<F, I extends IRPCInputs = IRPCInputs, O extends IRPCOutput = IRPCOutput>(options: IRPCDeclareInit<F, I, O>): F;
|
|
54
55
|
/**
|
|
55
56
|
* Resolves and executes an IRPC call based on a request object
|
|
56
57
|
* @param req - The request containing the IRPC name and arguments
|
|
57
58
|
* @returns The result of the IRPC execution
|
|
58
59
|
* @throws Error if the IRPC doesn't exist or doesn't have an implementation
|
|
59
60
|
*/
|
|
60
|
-
resolve(req: IRPCRequest): Promise<IRPCData>;
|
|
61
|
+
resolve(req: IRPCRequest): IRPCData | Promise<IRPCData> | RemoteState<IRPCData>;
|
|
61
62
|
/**
|
|
62
63
|
* Associates a handler function with a stub function
|
|
63
64
|
* @param stub - The stub function created by declare()
|
package/dist/module.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { IRPCCacher } from "./cache.js";
|
|
2
2
|
import { ERROR_CODE, ERROR_MESSAGE } from "./error.js";
|
|
3
|
+
import { RemoteState } from "./state.js";
|
|
3
4
|
import { IRPCTransport } from "./transport.js";
|
|
4
5
|
|
|
5
6
|
//#region src/module.ts
|
|
@@ -65,33 +66,40 @@ var IRPCPackage = class {
|
|
|
65
66
|
}
|
|
66
67
|
/**
|
|
67
68
|
* Declares a new IRPC specification and creates a corresponding stub function
|
|
68
|
-
* @param
|
|
69
|
+
* @param options - The initialization object containing the IRPC specification
|
|
69
70
|
* @returns A stub function that can be used to call the IRPC
|
|
70
71
|
* @throws Error if an IRPC with the same name already exists
|
|
71
72
|
*/
|
|
72
|
-
declare(
|
|
73
|
-
if (this.specs.has(
|
|
74
|
-
const spec = { ...
|
|
73
|
+
declare(options) {
|
|
74
|
+
if (this.specs.has(options.name)) throw new Error(`IRPC ${options.name} already exists.`);
|
|
75
|
+
const spec = { ...options };
|
|
75
76
|
const calls = /* @__PURE__ */ new Map();
|
|
76
77
|
const caches = new IRPCCacher();
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
if (!this.transport && typeof spec.handler !== "function") throw new Error(ERROR_MESSAGE[ERROR_CODE.TRANSPORT_MISSING]);
|
|
78
|
+
const stub = ((...args) => {
|
|
79
|
+
if (!this.transport && typeof spec.handler !== "function") return Promise.reject(new Error(ERROR_MESSAGE[ERROR_CODE.TRANSPORT_MISSING]));
|
|
80
80
|
const callKey = JSON.stringify(args);
|
|
81
81
|
const cached = caches.get(callKey);
|
|
82
82
|
if (cached) return cached.value;
|
|
83
83
|
if (spec.coalesce !== false && calls.has(callKey)) return calls.get(callKey);
|
|
84
|
-
const
|
|
84
|
+
const { timeout, maxRetries, retryDelay, retryMode } = {
|
|
85
|
+
...this.config,
|
|
86
|
+
...spec
|
|
87
|
+
};
|
|
88
|
+
const config = {
|
|
89
|
+
timeout,
|
|
90
|
+
maxRetries,
|
|
91
|
+
retryDelay,
|
|
92
|
+
retryMode
|
|
93
|
+
};
|
|
94
|
+
const call = typeof spec.handler === "function" ? spec.handler(...args) : this.transport.call(spec, args, config);
|
|
85
95
|
calls.set(callKey, call);
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
calls.delete(callKey);
|
|
92
|
-
}
|
|
96
|
+
if (spec.maxAge) caches.set(callKey, call, spec.maxAge);
|
|
97
|
+
if (typeof spec.init === "function" && call instanceof RemoteState && typeof call.data === "undefined") call.data = spec.init();
|
|
98
|
+
if (call instanceof Promise) call.finally(() => calls.delete(callKey)).catch(() => {});
|
|
99
|
+
else calls.delete(callKey);
|
|
100
|
+
return call;
|
|
93
101
|
});
|
|
94
|
-
this.specs.set(
|
|
102
|
+
this.specs.set(options.name, spec);
|
|
95
103
|
this.stubs.set(stub, spec);
|
|
96
104
|
this.cache.set(stub, caches);
|
|
97
105
|
return stub;
|
|
@@ -102,11 +110,11 @@ var IRPCPackage = class {
|
|
|
102
110
|
* @returns The result of the IRPC execution
|
|
103
111
|
* @throws Error if the IRPC doesn't exist or doesn't have an implementation
|
|
104
112
|
*/
|
|
105
|
-
|
|
113
|
+
resolve(req) {
|
|
106
114
|
const spec = this.specs.get(req.name);
|
|
107
115
|
if (!spec) return Promise.reject(/* @__PURE__ */ new Error(`IRPC ${req.name} does not exist.`));
|
|
108
116
|
if (typeof spec.handler !== "function") return Promise.reject(/* @__PURE__ */ new Error(`IRPC ${req.name} does not have an implementation.`));
|
|
109
|
-
return
|
|
117
|
+
return spec.handler(...req.args);
|
|
110
118
|
}
|
|
111
119
|
/**
|
|
112
120
|
* Associates a handler function with a stub function
|
package/dist/reader.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { IRPCData, IRPCPacketStream } from "./types.js";
|
|
2
|
+
import { RemoteState } from "./state.js";
|
|
3
|
+
|
|
4
|
+
//#region src/reader.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A client-side consumer that hydrates `RemoteState` instances from network stream packets.
|
|
8
|
+
*
|
|
9
|
+
* @template T - The type of data yielded by the stream.
|
|
10
|
+
*/
|
|
11
|
+
declare class IRPCReader<T extends IRPCData> extends RemoteState<T> {
|
|
12
|
+
id: string;
|
|
13
|
+
packets: Set<IRPCPacketStream<T>>;
|
|
14
|
+
constructor(id: string, init?: T);
|
|
15
|
+
/**
|
|
16
|
+
* Pushes incoming network packets into this reader, evaluating payload data
|
|
17
|
+
* and subsequently updating the core state values locally.
|
|
18
|
+
*
|
|
19
|
+
* @param packet - The incoming unified Stream Packet structure (`ANSWER`, `EVENT`, or `CLOSE`).
|
|
20
|
+
*/
|
|
21
|
+
push(packet: IRPCPacketStream<T>): void;
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
export { IRPCReader };
|
package/dist/reader.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { IRPC_PACKET_TYPE, IRPC_STATUS } from "./enum.js";
|
|
2
|
+
import { RemoteState } from "./state.js";
|
|
3
|
+
import { replay } from "@anchorlib/core";
|
|
4
|
+
|
|
5
|
+
//#region src/reader.ts
|
|
6
|
+
/**
|
|
7
|
+
* A client-side consumer that hydrates `RemoteState` instances from network stream packets.
|
|
8
|
+
*
|
|
9
|
+
* @template T - The type of data yielded by the stream.
|
|
10
|
+
*/
|
|
11
|
+
var IRPCReader = class extends RemoteState {
|
|
12
|
+
packets = /* @__PURE__ */ new Set();
|
|
13
|
+
constructor(id, init) {
|
|
14
|
+
super(init);
|
|
15
|
+
this.id = id;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Pushes incoming network packets into this reader, evaluating payload data
|
|
19
|
+
* and subsequently updating the core state values locally.
|
|
20
|
+
*
|
|
21
|
+
* @param packet - The incoming unified Stream Packet structure (`ANSWER`, `EVENT`, or `CLOSE`).
|
|
22
|
+
*/
|
|
23
|
+
push(packet) {
|
|
24
|
+
packet.arrivedAt = Date.now();
|
|
25
|
+
this.packets.add(packet);
|
|
26
|
+
if (packet.type === IRPC_PACKET_TYPE.ANSWER) if (packet.status === IRPC_STATUS.ERROR) this.error = new Error(packet.error.message);
|
|
27
|
+
else this.data = packet.data;
|
|
28
|
+
else if (packet.type === IRPC_PACKET_TYPE.EVENT) replay(this.state, packet.data);
|
|
29
|
+
else if (packet.type === IRPC_PACKET_TYPE.CLOSE) {
|
|
30
|
+
if (packet.error) this.error = new Error(packet.error.message);
|
|
31
|
+
}
|
|
32
|
+
this.status = packet.status;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
//#endregion
|
|
37
|
+
export { IRPCReader };
|
package/dist/resolver.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IRPCDataSchema,
|
|
1
|
+
import { IRPCDataSchema, IRPCInputs, IRPCOutput, IRPCRequest, IRPCResponse, IRPCSpec } from "./types.js";
|
|
2
2
|
import { IRPCPackage } from "./module.js";
|
|
3
3
|
|
|
4
4
|
//#region src/resolver.d.ts
|
|
@@ -45,17 +45,7 @@ declare class IRPCResolver {
|
|
|
45
45
|
id,
|
|
46
46
|
name,
|
|
47
47
|
args
|
|
48
|
-
}: IRPCRequest, schema?: IRPCOutput): Promise<
|
|
49
|
-
id: string;
|
|
50
|
-
name: string;
|
|
51
|
-
result: string | number | boolean | IRPCDataSchema | Record<string, unknown> | (string | number | boolean | Record<string, unknown> | null | undefined)[] | null | undefined;
|
|
52
|
-
error?: undefined;
|
|
53
|
-
} | {
|
|
54
|
-
id: string;
|
|
55
|
-
name: string;
|
|
56
|
-
error: IRPCError;
|
|
57
|
-
result?: undefined;
|
|
58
|
-
}>;
|
|
48
|
+
}: IRPCRequest, schema?: IRPCOutput): Promise<IRPCResponse>;
|
|
59
49
|
}
|
|
60
50
|
//#endregion
|
|
61
51
|
export { IRPCResolver };
|
package/dist/resolver.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ERROR_CODE } from "./error.js";
|
|
2
|
+
import { RemoteState } from "./state.js";
|
|
2
3
|
|
|
3
4
|
//#region src/resolver.ts
|
|
4
5
|
/**
|
|
@@ -69,11 +70,28 @@ var IRPCResolver = class {
|
|
|
69
70
|
*/
|
|
70
71
|
async forward({ id, name, args }, schema) {
|
|
71
72
|
try {
|
|
72
|
-
const
|
|
73
|
+
const result = this.module.resolve({
|
|
73
74
|
id,
|
|
74
75
|
name,
|
|
75
76
|
args
|
|
76
|
-
})
|
|
77
|
+
});
|
|
78
|
+
if (result instanceof RemoteState) {
|
|
79
|
+
const output$1 = parseOutput(result.data, schema);
|
|
80
|
+
if (!output$1.success) return {
|
|
81
|
+
id,
|
|
82
|
+
name,
|
|
83
|
+
error: {
|
|
84
|
+
code: ERROR_CODE.INVALID_OUTPUT,
|
|
85
|
+
message: output$1.error?.message
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
return {
|
|
89
|
+
id,
|
|
90
|
+
name,
|
|
91
|
+
result
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
const output = parseOutput(await result, schema);
|
|
77
95
|
if (output.success) return {
|
|
78
96
|
id,
|
|
79
97
|
name,
|
package/dist/state.d.ts
CHANGED
|
@@ -3,17 +3,80 @@ import * as _anchorlib_core0 from "@anchorlib/core";
|
|
|
3
3
|
import { StateSubscriber } from "@anchorlib/core";
|
|
4
4
|
|
|
5
5
|
//#region src/state.d.ts
|
|
6
|
-
|
|
7
|
-
|
|
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
|
+
*/
|
|
8
23
|
get data(): T;
|
|
9
24
|
set data(data: T);
|
|
25
|
+
/**
|
|
26
|
+
* The current error encountered by the state, if any.
|
|
27
|
+
*/
|
|
10
28
|
get error(): Error | undefined;
|
|
11
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
|
+
*/
|
|
12
34
|
get status(): IRPCStatus;
|
|
13
35
|
set status(status: IRPCStatus);
|
|
14
|
-
|
|
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
|
+
*/
|
|
15
48
|
subscribe(handler: StateSubscriber<IRPCReadable<T>>): _anchorlib_core0.StateUnsubscribe;
|
|
16
|
-
|
|
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;
|
|
17
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>;
|
|
18
81
|
//#endregion
|
|
19
|
-
export { RemoteState };
|
|
82
|
+
export { RemoteState, StreamConstructor, stream };
|