@irpclib/irpc 1.0.0-beta.22 → 1.0.0-beta.23

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/module.js CHANGED
@@ -1,7 +1,11 @@
1
1
  import { IRPCCacher } from "./cache.js";
2
+ import { IRPC_STATUS } from "./enum.js";
2
3
  import { ERROR_CODE, ERROR_MESSAGE } from "./error.js";
3
4
  import { RemoteState } from "./state.js";
5
+ import { IRPCReader } from "./reader.js";
4
6
  import { IRPCTransport } from "./transport.js";
7
+ import { IRPC_STORE } from "./store.js";
8
+ import { anchor, createObserver, isBrowser, microtask, onCleanup, replay, uuid } from "@anchorlib/core";
5
9
 
6
10
  //#region src/module.ts
7
11
  const DEFAULT_TIMEOUT = 2e4;
@@ -17,6 +21,7 @@ var IRPCPackage = class {
17
21
  * A map storing all IRPC specifications by their names
18
22
  */
19
23
  specs = /* @__PURE__ */ new Map();
24
+ hooks = /* @__PURE__ */ new Map();
20
25
  /**
21
26
  * A weak map linking stub functions to their corresponding specifications
22
27
  */
@@ -63,6 +68,7 @@ var IRPCPackage = class {
63
68
  */
64
69
  constructor(config) {
65
70
  this.configure(config ?? {});
71
+ IRPC_STORE.register(this);
66
72
  }
67
73
  /**
68
74
  * Declares a new IRPC specification and creates a corresponding stub function
@@ -71,17 +77,67 @@ var IRPCPackage = class {
71
77
  * @throws Error if an IRPC with the same name already exists
72
78
  */
73
79
  declare(options) {
74
- if (this.specs.has(options.name)) throw new Error(`IRPC ${options.name} already exists.`);
75
- const spec = { ...options };
80
+ const $options = options;
81
+ if (this.specs.has($options.name)) throw new Error(`IRPC ${$options.name} already exists.`);
82
+ const spec = {
83
+ init: () => void 0,
84
+ ...$options
85
+ };
76
86
  const calls = /* @__PURE__ */ new Map();
77
87
  const caches = new IRPCCacher();
78
88
  const stub = ((...args) => {
89
+ return execute(args, new IRPCReader(uuid(), spec.init()));
90
+ });
91
+ /** Browser only stub for single immediate execution **/
92
+ stub.once = (...args) => {
93
+ return prepare(() => args);
94
+ };
95
+ stub.with = (getArgs, debounce) => {
96
+ return prepare(typeof getArgs === "function" ? getArgs : () => getArgs, false, debounce);
97
+ };
98
+ stub.when = (getArgs, debounce) => {
99
+ return prepare(typeof getArgs === "function" ? getArgs : () => getArgs, true, debounce);
100
+ };
101
+ /**
102
+ * A preparation utility to generate and schedule call on the browser environment.
103
+ *
104
+ * @param getArgs - A function that returns the arguments for the call.
105
+ * @param deferred - A flag indicating whether the call should be deferred.
106
+ * @param debounce - The debounce time in milliseconds.
107
+ * @returns {IRPCReader<IRPCData>} - The reader for the call.
108
+ */
109
+ function prepare(getArgs, deferred, debounce = 0) {
110
+ const reader = new IRPCReader(uuid(), spec.init(), deferred ? IRPC_STATUS.IDLE : IRPC_STATUS.PENDING);
111
+ if (isBrowser()) {
112
+ const observer = createObserver(() => {
113
+ observer.reset();
114
+ dispatch();
115
+ });
116
+ const [schedule, cancel] = microtask(debounce);
117
+ const dispatch = (coalesce = true) => {
118
+ const args = observer.run(getArgs);
119
+ if (!coalesce) return execute(args, reader);
120
+ schedule(() => {
121
+ execute(args, reader);
122
+ });
123
+ };
124
+ if (deferred) observer.run(getArgs);
125
+ else dispatch(false);
126
+ onCleanup(() => {
127
+ cancel();
128
+ observer.destroy();
129
+ });
130
+ }
131
+ return reader;
132
+ }
133
+ const execute = (args, reader) => {
79
134
  if (!this.transport && typeof spec.handler !== "function") return Promise.reject(new Error(ERROR_MESSAGE[ERROR_CODE.TRANSPORT_MISSING]));
135
+ reader.status = IRPC_STATUS.PENDING;
80
136
  const callKey = JSON.stringify(args);
81
137
  const cached = caches.get(callKey);
82
138
  if (cached) return cached.value;
83
139
  if (spec.coalesce !== false && calls.has(callKey)) return calls.get(callKey);
84
- const { timeout, maxRetries, retryDelay, retryMode } = {
140
+ const { timeout, maxRetries, retryDelay, retryMode, init } = {
85
141
  ...this.config,
86
142
  ...spec
87
143
  };
@@ -89,19 +145,25 @@ var IRPCPackage = class {
89
145
  timeout,
90
146
  maxRetries,
91
147
  retryDelay,
92
- retryMode
148
+ retryMode,
149
+ init
93
150
  };
94
- const call = typeof spec.handler === "function" ? spec.handler(...args) : this.transport.call(spec, args, config);
151
+ const hooks = this.hooks.get(spec);
152
+ if (hooks) hooks.forEach((hook) => hook({
153
+ name: spec.name,
154
+ args
155
+ }));
156
+ const call = typeof spec.handler === "function" ? intercept(spec, args, reader) : this.transport.call(spec, args, config, reader);
95
157
  calls.set(callKey, call);
96
158
  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;
101
- });
102
- this.specs.set(options.name, spec);
159
+ onCleanup(() => call.close());
160
+ call.finally(() => calls.delete(callKey)).catch((err) => IRPC_STORE.error(err, [{ name: spec.name }]));
161
+ return reader;
162
+ };
163
+ this.specs.set($options.name, spec);
103
164
  this.stubs.set(stub, spec);
104
165
  this.cache.set(stub, caches);
166
+ this.hooks.set(spec, /* @__PURE__ */ new Set());
105
167
  return stub;
106
168
  }
107
169
  /**
@@ -132,6 +194,35 @@ var IRPCPackage = class {
132
194
  return this;
133
195
  }
134
196
  /**
197
+ * Registers a hook function for a specific stub function
198
+ * @param stub - The stub function created by declare()
199
+ * @param handler - The hook function to register
200
+ * @returns This IRPCPackage instance for chaining
201
+ * @throws Error if the stub is invalid or if no IRPC exists for the stub
202
+ */
203
+ hook(stub, handler) {
204
+ if (!this.stubs.has(stub)) {
205
+ const error = new Error(ERROR_MESSAGE[ERROR_CODE.NOT_FOUND]);
206
+ IRPC_STORE.error(error);
207
+ return this;
208
+ }
209
+ const spec = this.stubs.get(stub);
210
+ this.hooks.get(spec).add(handler);
211
+ return this;
212
+ }
213
+ /**
214
+ * Resolves and executes all registered hooks for a given request
215
+ * @param req - The request containing the IRPC name and arguments
216
+ * @returns A promise that resolves when all hooks have been executed
217
+ * @throws Error if no IRPC exists for the request or if the hooks are not registered
218
+ */
219
+ async resolveHooks(req) {
220
+ const spec = this.specs.get(req.name);
221
+ if (!spec || !this.hooks.has(spec)) throw new Error(ERROR_MESSAGE[ERROR_CODE.NOT_FOUND]);
222
+ const hooks = this.hooks.get(spec);
223
+ for (const hook of hooks) await hook(req);
224
+ }
225
+ /**
135
226
  * Sets the transport mechanism for this package
136
227
  * @param transport - The transport instance to use for remote calls
137
228
  * @returns This IRPCPackage instance for chaining
@@ -183,6 +274,45 @@ var IRPCPackage = class {
183
274
  function createPackage(config) {
184
275
  return new IRPCPackage(config);
185
276
  }
277
+ /**
278
+ * Intercepts local function call to get an instant response without remote execution.
279
+ *
280
+ * @param reader - The reader object to intercept.
281
+ * @param spec - The IRPC specification for the function call.
282
+ * @param args - The arguments to be passed to the function.
283
+ * @returns {IRPCReader<IRPCData>} - The IRPCReader object for consumer.
284
+ */
285
+ function intercept(spec, args, reader) {
286
+ try {
287
+ const result = spec.handler(...args);
288
+ if (!(result instanceof Promise)) {
289
+ reader.accept(result);
290
+ return reader;
291
+ }
292
+ if (!(result instanceof RemoteState)) {
293
+ result.then((value) => {
294
+ reader.accept(value);
295
+ }).catch((err) => {
296
+ reader.reject(err);
297
+ });
298
+ return reader;
299
+ }
300
+ anchor.assign(reader.state, result.state);
301
+ const unsubscribe = result.subscribe((_, event) => {
302
+ if (event.type === "init") return;
303
+ const [rootKey] = event.keys;
304
+ if (rootKey === "status") {
305
+ reader.status = event.value;
306
+ if (reader.status === IRPC_STATUS.SUCCESS) unsubscribe();
307
+ return;
308
+ }
309
+ replay(reader.state, event);
310
+ });
311
+ } catch (error) {
312
+ reader.reject(error);
313
+ }
314
+ return reader;
315
+ }
186
316
 
187
317
  //#endregion
188
- export { IRPCPackage, createPackage };
318
+ export { IRPCPackage, createPackage, intercept };
@@ -0,0 +1,32 @@
1
+ import { IRPCFileMeta, IRPCFileStream } from "./file.js";
2
+ import { IRPCData } from "./types.js";
3
+
4
+ //#region src/packet.d.ts
5
+ declare const IRPC_FILE_IDENTIFIER: "IRPC_PACKET_FILE";
6
+ type IRPCFilePointer = {
7
+ id: string;
8
+ type: typeof IRPC_FILE_IDENTIFIER;
9
+ meta: IRPCFileMeta;
10
+ };
11
+ type IRPCFileQueue = {
12
+ file: IRPCFilePointer;
13
+ data: Blob;
14
+ };
15
+ type IRPCPacketJson = {
16
+ data: IRPCData;
17
+ files: IRPCFilePointer[];
18
+ };
19
+ type IRPCPacketQueues = {
20
+ json: IRPCPacketJson;
21
+ queues: IRPCFileQueue[];
22
+ };
23
+ type PacketStream = {
24
+ data: IRPCData;
25
+ files: Map<string, IRPCFileStream>;
26
+ resolved: number;
27
+ };
28
+ declare function isFilePointer(data: IRPCData): boolean;
29
+ declare function encode(data: IRPCData): IRPCPacketQueues;
30
+ declare function decode(packet: IRPCPacketJson): PacketStream;
31
+ //#endregion
32
+ export { IRPCFilePointer, IRPCFileQueue, IRPCPacketJson, IRPCPacketQueues, IRPC_FILE_IDENTIFIER, PacketStream, decode, encode, isFilePointer };
package/dist/packet.js ADDED
@@ -0,0 +1,100 @@
1
+ import { IRPCFile, IRPCFileStream } from "./file.js";
2
+ import { isArray, isObject, uuid } from "@anchorlib/core";
3
+
4
+ //#region src/packet.ts
5
+ const IRPC_FILE_IDENTIFIER = "IRPC_PACKET_FILE";
6
+ function isFilePointer(data) {
7
+ return isObject(data) && data.type === IRPC_FILE_IDENTIFIER;
8
+ }
9
+ function encode(data) {
10
+ const json = {
11
+ data,
12
+ files: []
13
+ };
14
+ const packet = {
15
+ json,
16
+ queues: []
17
+ };
18
+ if (data instanceof IRPCFile) {
19
+ const { pointer, queue } = createPointer(data);
20
+ json.data = pointer;
21
+ json.files.push(pointer);
22
+ packet.queues.push(queue);
23
+ } else if (isObject(data) || isArray(data)) encodePointers(data, json.files, packet.queues);
24
+ return packet;
25
+ }
26
+ function decode(packet) {
27
+ const files = packet.files.map((file) => {
28
+ return [file.id, new IRPCFileStream(file.meta)];
29
+ });
30
+ const stream = {
31
+ data: packet.data,
32
+ files: new Map(files),
33
+ resolved: 0
34
+ };
35
+ if (isFilePointer(packet.data)) {
36
+ const { id } = packet.data;
37
+ stream.data = stream.files.get(id);
38
+ } else if (isObject(packet.data) || isArray(packet.data)) decodePointers(packet.data, stream.files);
39
+ return stream;
40
+ }
41
+ function createPointer(file) {
42
+ const pointer = {
43
+ id: uuid(),
44
+ meta: file.meta,
45
+ type: IRPC_FILE_IDENTIFIER
46
+ };
47
+ return {
48
+ pointer,
49
+ queue: {
50
+ file: pointer,
51
+ data: file.data
52
+ }
53
+ };
54
+ }
55
+ /**
56
+ * Replace all IRPCFile inside an object with IRPCPacketFile.
57
+ * @param {Record<string, unknown> | unknown[]} data - The object to encode.
58
+ * @param {IRPCFilePointer[]} pointers - The array of IRPCPacketFile to replace.
59
+ * @param {IRPCFileQueue[]} queues - The array of IRPCPacketFileQueue to replace.
60
+ */
61
+ function encodePointers(data, pointers, queues) {
62
+ if (isArray(data)) data.forEach((item, i) => {
63
+ if (item instanceof IRPCFile) {
64
+ const { pointer, queue } = createPointer(item);
65
+ data[i] = pointer;
66
+ pointers.push(pointer);
67
+ queues.push(queue);
68
+ } else if (isObject(item) || isArray(item)) encodePointers(item, pointers, queues);
69
+ });
70
+ else if (isObject(data)) Object.entries(data).forEach(([key, value]) => {
71
+ if (value instanceof IRPCFile) {
72
+ const { pointer, queue } = createPointer(value);
73
+ data[key] = pointer;
74
+ pointers.push(pointer);
75
+ queues.push(queue);
76
+ } else if (isObject(value) || isArray(value)) encodePointers(value, pointers, queues);
77
+ });
78
+ }
79
+ /**
80
+ * Replace all IRPCPacketFile inside an object with IRPCFileStream.
81
+ * @param data - The object to decode.
82
+ * @param files - The map of IRPCFileStream to replace.
83
+ */
84
+ function decodePointers(data, files) {
85
+ if (isArray(data)) data.forEach((item, i) => {
86
+ if (isFilePointer(item)) {
87
+ const { id } = item;
88
+ data[i] = files.get(id);
89
+ } else if (isObject(item) || isArray(item)) decodePointers(item, files);
90
+ });
91
+ else if (isObject(data)) Object.entries(data).forEach(([key, value]) => {
92
+ if (isFilePointer(value)) {
93
+ const { id } = value;
94
+ data[key] = files.get(id);
95
+ } else if (isObject(value) || isArray(value)) decodePointers(value, files);
96
+ });
97
+ }
98
+
99
+ //#endregion
100
+ export { IRPC_FILE_IDENTIFIER, decode, encode, isFilePointer };
package/dist/reader.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { IRPCData, IRPCPacketStream } from "./types.js";
1
+ import { IRPCData, IRPCPacketStream, IRPCStatus } from "./types.js";
2
2
  import { RemoteState } from "./state.js";
3
3
 
4
4
  //#region src/reader.d.ts
@@ -10,8 +10,15 @@ import { RemoteState } from "./state.js";
10
10
  */
11
11
  declare class IRPCReader<T extends IRPCData> extends RemoteState<T> {
12
12
  id: string;
13
- packets: Set<IRPCPacketStream<T>>;
14
- constructor(id: string, init?: T);
13
+ onClose?: () => void;
14
+ /**
15
+ * Initializes a new RemoteState with an optional initial payload.
16
+ *
17
+ * @param id - The unique identifier for this state instance.
18
+ * @param init - An optional starting value for the data payload.
19
+ * @param status - The initial status of the state (PENDING, SUCCESS, ERROR).
20
+ */
21
+ constructor(id: string, init?: T, status?: IRPCStatus);
15
22
  /**
16
23
  * Pushes incoming network packets into this reader, evaluating payload data
17
24
  * and subsequently updating the core state values locally.
@@ -19,6 +26,12 @@ declare class IRPCReader<T extends IRPCData> extends RemoteState<T> {
19
26
  * @param packet - The incoming unified Stream Packet structure (`ANSWER`, `EVENT`, or `CLOSE`).
20
27
  */
21
28
  push(packet: IRPCPacketStream<T>): void;
29
+ close(): void;
30
+ /**
31
+ * Ensures that chained Promise operations return standard Promises
32
+ * rather than instantiating new RemoteState subclasses.
33
+ */
34
+ static get [Symbol.species](): PromiseConstructor;
22
35
  }
23
36
  //#endregion
24
37
  export { IRPCReader };
package/dist/reader.js CHANGED
@@ -9,9 +9,16 @@ import { replay } from "@anchorlib/core";
9
9
  * @template T - The type of data yielded by the stream.
10
10
  */
11
11
  var IRPCReader = class extends RemoteState {
12
- packets = /* @__PURE__ */ new Set();
13
- constructor(id, init) {
14
- super(init);
12
+ onClose;
13
+ /**
14
+ * Initializes a new RemoteState with an optional initial payload.
15
+ *
16
+ * @param id - The unique identifier for this state instance.
17
+ * @param init - An optional starting value for the data payload.
18
+ * @param status - The initial status of the state (PENDING, SUCCESS, ERROR).
19
+ */
20
+ constructor(id, init, status = IRPC_STATUS.PENDING) {
21
+ super(init, status);
15
22
  this.id = id;
16
23
  }
17
24
  /**
@@ -22,7 +29,6 @@ var IRPCReader = class extends RemoteState {
22
29
  */
23
30
  push(packet) {
24
31
  packet.arrivedAt = Date.now();
25
- this.packets.add(packet);
26
32
  if (packet.type === IRPC_PACKET_TYPE.ANSWER) if (packet.status === IRPC_STATUS.ERROR) this.error = new Error(packet.error.message);
27
33
  else this.data = packet.data;
28
34
  else if (packet.type === IRPC_PACKET_TYPE.EVENT) replay(this.state, packet.data);
@@ -31,6 +37,18 @@ var IRPCReader = class extends RemoteState {
31
37
  }
32
38
  this.status = packet.status;
33
39
  }
40
+ close() {
41
+ this.status = IRPC_STATUS.SUCCESS;
42
+ super.close();
43
+ this.onClose?.();
44
+ }
45
+ /**
46
+ * Ensures that chained Promise operations return standard Promises
47
+ * rather than instantiating new RemoteState subclasses.
48
+ */
49
+ static get [Symbol.species]() {
50
+ return Promise;
51
+ }
34
52
  };
35
53
 
36
54
  //#endregion
package/dist/resolver.js CHANGED
@@ -70,6 +70,11 @@ var IRPCResolver = class {
70
70
  */
71
71
  async forward({ id, name, args }, schema) {
72
72
  try {
73
+ await this.module.resolveHooks({
74
+ id,
75
+ name,
76
+ args
77
+ });
73
78
  const result = this.module.resolve({
74
79
  id,
75
80
  name,
@@ -0,0 +1,42 @@
1
+ import { IRPCTransport } from "./transport.js";
2
+ import { IRPCRequest } from "./types.js";
3
+ import { IRPCPackage } from "./module.js";
4
+
5
+ //#region src/router.d.ts
6
+ type IRPCHook = () => void | Promise<void>;
7
+ declare class IRPCRouter {
8
+ module: IRPCPackage;
9
+ transport: IRPCTransport;
10
+ /** Array of middleware functions to be executed */
11
+ hooks: IRPCHook[];
12
+ /**
13
+ * Creates a new Router instance
14
+ * @param {IRPCPackage} module - The IRPC package module to resolve requests against
15
+ * @param {IRPCTransport} transport - The transport mechanism to use for resolving requests
16
+ */
17
+ constructor(module: IRPCPackage, transport: IRPCTransport);
18
+ /**
19
+ * Adds a hook function to the router
20
+ * @param hook - The hook function to add
21
+ * @returns The current Router instance for chaining
22
+ */
23
+ use(hook: IRPCHook): this;
24
+ /**
25
+ * Resolves hook functions for a given request
26
+ * @param req - The IRPC request to process hook for
27
+ * @returns An error response if hook fails, undefined otherwise
28
+ */
29
+ protected resolveHooks(req: IRPCRequest): Promise<{
30
+ id: string;
31
+ name: string;
32
+ type: "close";
33
+ status: "error";
34
+ error: {
35
+ code: string;
36
+ message: string;
37
+ };
38
+ createdAt: number;
39
+ } | undefined>;
40
+ }
41
+ //#endregion
42
+ export { IRPCHook, IRPCRouter };
package/dist/router.js ADDED
@@ -0,0 +1,59 @@
1
+ import { IRPC_PACKET_TYPE, IRPC_STATUS } from "./enum.js";
2
+ import { ERROR_CODE, ERROR_MESSAGE } from "./error.js";
3
+ import { IRPC_STORE } from "./store.js";
4
+
5
+ //#region src/router.ts
6
+ var IRPCRouter = class {
7
+ /** Array of middleware functions to be executed */
8
+ hooks = [];
9
+ /**
10
+ * Creates a new Router instance
11
+ * @param {IRPCPackage} module - The IRPC package module to resolve requests against
12
+ * @param {IRPCTransport} transport - The transport mechanism to use for resolving requests
13
+ */
14
+ constructor(module, transport) {
15
+ this.module = module;
16
+ this.transport = transport;
17
+ IRPC_STORE.route(this);
18
+ }
19
+ /**
20
+ * Adds a hook function to the router
21
+ * @param hook - The hook function to add
22
+ * @returns The current Router instance for chaining
23
+ */
24
+ use(hook) {
25
+ if (typeof hook !== "function") {
26
+ const error = new Error(ERROR_MESSAGE[ERROR_CODE.INVALID_HOOK]);
27
+ IRPC_STORE.error(error);
28
+ return this;
29
+ }
30
+ this.hooks.push(hook);
31
+ return this;
32
+ }
33
+ /**
34
+ * Resolves hook functions for a given request
35
+ * @param req - The IRPC request to process hook for
36
+ * @returns An error response if hook fails, undefined otherwise
37
+ */
38
+ async resolveHooks(req) {
39
+ for (const hook of this.hooks) try {
40
+ await hook();
41
+ } catch (error) {
42
+ IRPC_STORE.error(error, [req.id, req.name]);
43
+ return {
44
+ id: req.id,
45
+ name: req.name,
46
+ type: IRPC_PACKET_TYPE.CLOSE,
47
+ status: IRPC_STATUS.ERROR,
48
+ error: {
49
+ code: ERROR_CODE.UNKNOWN,
50
+ message: ERROR_MESSAGE[ERROR_CODE.UNKNOWN]
51
+ },
52
+ createdAt: Date.now()
53
+ };
54
+ }
55
+ }
56
+ };
57
+
58
+ //#endregion
59
+ 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,8 @@ 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
- protected readonly state: IRPCReadable<T>;
18
- protected readonly accept: (value: T) => void;
19
- protected readonly reject: (error: Error) => void;
17
+ #private;
18
+ get state(): IRPCReadable<T>;
20
19
  /**
21
20
  * The current data payload of the state.
22
21
  */
@@ -37,8 +36,12 @@ declare class RemoteState<T> extends Promise<T> {
37
36
  * Initializes a new RemoteState with an optional initial payload.
38
37
  *
39
38
  * @param init - An optional starting value for the data payload.
39
+ * @param status - The initial status of the state (PENDING, SUCCESS, ERROR).
40
40
  */
41
- constructor(init?: T);
41
+ constructor(init?: T, status?: IRPCStatus);
42
+ accept(value?: T): void;
43
+ reject(error?: Error): void;
44
+ abort(): void;
42
45
  /**
43
46
  * Subscribes to changes emitted by the internal state.
44
47
  *
@@ -46,6 +49,10 @@ declare class RemoteState<T> extends Promise<T> {
46
49
  * @returns An unsubscribe function to terminate the listener.
47
50
  */
48
51
  subscribe(handler: StateSubscriber<IRPCReadable<T>>): _anchorlib_core0.StateUnsubscribe;
52
+ /**
53
+ * Closes the reactive state and terminates the underlying Promise.
54
+ */
55
+ close(): void;
49
56
  /**
50
57
  * Destroys the reactive state bindings.
51
58
  */
@@ -56,17 +63,6 @@ declare class RemoteState<T> extends Promise<T> {
56
63
  */
57
64
  static get [Symbol.species](): PromiseConstructor;
58
65
  }
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
66
  /**
71
67
  * A utility factory to structurally instantiate an active `RemoteState` pipeline natively
72
68
  * decoupled from standard Promise chains. This elegantly captures constructor functions
@@ -79,4 +75,4 @@ type StreamConstructor<T> = (data: T, resolve: (value?: T) => void, reject: (err
79
75
  */
80
76
  declare function stream<T>(construct: StreamConstructor<T>, init?: T): RemoteState<T>;
81
77
  //#endregion
82
- export { RemoteState, StreamConstructor, stream };
78
+ export { RemoteState, stream };