@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/stream.js CHANGED
@@ -1,6 +1,8 @@
1
1
  import { IRPC_PACKET_TYPE, IRPC_STATUS } from "./enum.js";
2
2
  import { ERROR_CODE } from "./error.js";
3
+ import { getAbortController, getAbortSignal } from "./context.js";
3
4
  import { RemoteState } from "./state.js";
5
+ import { IRPC_STORE } from "./store.js";
4
6
 
5
7
  //#region src/stream.ts
6
8
  /**
@@ -18,34 +20,56 @@ var IRPCStream = class {
18
20
  value;
19
21
  error;
20
22
  status = IRPC_STATUS.IDLE;
23
+ closed = false;
24
+ createdAt = Date.now();
25
+ startedAt;
26
+ updatedAt;
27
+ controller;
21
28
  /**
22
29
  * Initializes a stream wrapping an asynchronous RPC execution.
23
30
  *
24
31
  * @param id - The unique identifier of the RPC request.
25
32
  * @param name - The name of the specification processing the execution.
26
33
  * @param initializer - An execution callback that yields an IRPCResponse.
34
+ * @param spec - The specification for the RPC execution.
35
+ * @param router - The router instance managing the stream.
27
36
  */
28
- constructor(id, name, initializer) {
37
+ constructor(id, name, initializer, spec, router) {
29
38
  this.id = id;
30
39
  this.name = name;
31
40
  this.initializer = initializer;
41
+ this.spec = spec;
42
+ this.router = router;
43
+ IRPC_STORE.queue(this);
32
44
  }
33
45
  /**
34
46
  * Evaluates the underlying initializer and propagates standard transport packets
35
47
  * to all bound pipe handlers based on the output lifecycle.
36
48
  */
37
49
  async start() {
38
- if (this.status !== IRPC_STATUS.IDLE) return;
50
+ if (this.status !== IRPC_STATUS.IDLE || this.closed) return;
51
+ this.startedAt = Date.now();
52
+ this.controller = getAbortController();
53
+ const abortSignal = getAbortSignal();
54
+ if (abortSignal?.aborted) {
55
+ this.finish();
56
+ return;
57
+ }
39
58
  this.status = IRPC_STATUS.PENDING;
40
59
  const { id, name } = this;
41
60
  try {
42
- const { result } = await this.initializer();
61
+ const response = await this.initializer();
62
+ if (abortSignal?.aborted) {
63
+ this.finish();
64
+ return;
65
+ }
66
+ const { result } = response;
43
67
  if (result instanceof RemoteState) {
44
68
  this.value = result.data;
45
69
  if (result.status === IRPC_STATUS.SUCCESS || result.status === IRPC_STATUS.ERROR) {
46
70
  if (result.status === IRPC_STATUS.ERROR) {
47
71
  this.error = {
48
- code: ERROR_CODE.STREAM_ERROR,
72
+ code: ERROR_CODE.HANDLER_ERROR,
49
73
  message: result.error.message
50
74
  };
51
75
  this.status = IRPC_STATUS.ERROR;
@@ -60,8 +84,8 @@ var IRPCStream = class {
60
84
  createdAt: Date.now()
61
85
  };
62
86
  this.pipeHandlers.forEach((handler) => handler(packet));
63
- this.errorHandlers.forEach((handler) => handler(this.error));
64
- this.closeHandlers.forEach((handler) => handler());
87
+ if (this.error) this.errorHandlers.forEach((handler) => handler(this.error));
88
+ this.finish();
65
89
  return;
66
90
  }
67
91
  this.pipeHandlers.forEach((handler) => {
@@ -81,13 +105,13 @@ var IRPCStream = class {
81
105
  handler({
82
106
  id,
83
107
  name,
84
- type: IRPC_PACKET_TYPE.EVENT,
85
- status: state.status,
86
108
  data: {
87
109
  type,
88
110
  keys,
89
111
  value
90
112
  },
113
+ type: IRPC_PACKET_TYPE.EVENT,
114
+ status: state.status,
91
115
  createdAt: Date.now()
92
116
  });
93
117
  });
@@ -111,27 +135,42 @@ var IRPCStream = class {
111
135
  createdAt: Date.now()
112
136
  });
113
137
  });
114
- this.closeHandlers.forEach((handler) => handler());
138
+ abortSignal?.removeEventListener("abort", abortStream);
139
+ this.finish();
115
140
  unsubscribe();
116
141
  }
117
142
  });
143
+ const abortStream = () => {
144
+ unsubscribe();
145
+ this.finish();
146
+ };
147
+ abortSignal?.addEventListener("abort", abortStream, { once: true });
118
148
  } else {
119
149
  this.value = result;
120
- this.status = IRPC_STATUS.SUCCESS;
150
+ if (response.error) {
151
+ this.error = response.error;
152
+ this.status = IRPC_STATUS.ERROR;
153
+ this.errorHandlers.forEach((handler) => handler(this.error));
154
+ } else this.status = IRPC_STATUS.SUCCESS;
121
155
  const packet = {
122
156
  id,
123
157
  name,
124
158
  type: IRPC_PACKET_TYPE.ANSWER,
125
- status: IRPC_STATUS.SUCCESS,
126
159
  data: this.value,
160
+ error: this.error,
161
+ status: this.status,
127
162
  createdAt: Date.now()
128
163
  };
129
164
  this.pipeHandlers.forEach((handler) => handler(packet));
130
- this.closeHandlers.forEach((handler) => handler());
165
+ this.finish();
131
166
  }
132
167
  } catch (error) {
168
+ IRPC_STORE.error(error, [{
169
+ id: this.id,
170
+ name: this.name
171
+ }]);
133
172
  this.error = {
134
- code: ERROR_CODE.STREAM_ERROR,
173
+ code: ERROR_CODE.RESOLVE_ERROR,
135
174
  message: error.message
136
175
  };
137
176
  this.status = IRPC_STATUS.ERROR;
@@ -146,7 +185,7 @@ var IRPCStream = class {
146
185
  });
147
186
  });
148
187
  this.errorHandlers.forEach((handler) => handler(this.error));
149
- this.closeHandlers.forEach((handler) => handler());
188
+ this.finish();
150
189
  return;
151
190
  }
152
191
  }
@@ -169,8 +208,12 @@ var IRPCStream = class {
169
208
  });
170
209
  return;
171
210
  }
211
+ if (this.closed) return;
172
212
  this.pipeHandlers.add(handler);
173
- this.start().catch(() => {});
213
+ this.start().catch((err) => IRPC_STORE.error(err, [{
214
+ id: this.id,
215
+ name: this.name
216
+ }]));
174
217
  }
175
218
  /**
176
219
  * Binds a handler to trap any internal runtime failures independently.
@@ -182,8 +225,12 @@ var IRPCStream = class {
182
225
  handler(this.error);
183
226
  return;
184
227
  }
228
+ if (this.closed) return;
185
229
  this.errorHandlers.add(handler);
186
- this.start().catch(() => {});
230
+ this.start().catch((err) => IRPC_STORE.error(err, [{
231
+ id: this.id,
232
+ name: this.name
233
+ }]));
187
234
  }
188
235
  /**
189
236
  * Binds a handler triggered upon terminal completion of the stream process (success or error).
@@ -195,8 +242,21 @@ var IRPCStream = class {
195
242
  handler();
196
243
  return;
197
244
  }
245
+ if (this.closed) return;
198
246
  this.closeHandlers.add(handler);
199
- this.start().catch(() => {});
247
+ this.start().catch((err) => IRPC_STORE.error(err, [{
248
+ id: this.id,
249
+ name: this.name
250
+ }]));
251
+ }
252
+ finish() {
253
+ this.closed = true;
254
+ this.closeHandlers.forEach((handler) => handler());
255
+ this.pipeHandlers.clear();
256
+ this.errorHandlers.clear();
257
+ this.closeHandlers.clear();
258
+ this.updatedAt = Date.now();
259
+ IRPC_STORE.dequeue(this);
200
260
  }
201
261
  };
202
262
 
@@ -1,4 +1,5 @@
1
- import { IRPCCallConfig, IRPCData, IRPCInputs, IRPCOutput, IRPCSpec, TransportConfig } from "./types.js";
1
+ import { IRPCPackage } from "./module.js";
2
+ import { IRPCCallConfig, IRPCCredentials, IRPCCredentialsFactory, IRPCData, IRPCInputs, IRPCOutput, IRPCSpec, TransportConfig } from "./types.js";
2
3
  import { IRPCReader } from "./reader.js";
3
4
  import { IRPCCall } from "./call.js";
4
5
 
@@ -9,11 +10,14 @@ import { IRPCCall } from "./call.js";
9
10
  * It handles queuing, debouncing, and timeout management for RPC requests.
10
11
  */
11
12
  declare class IRPCTransport {
13
+ #private;
12
14
  config?: TransportConfig | undefined;
15
+ modules: Set<IRPCPackage>;
13
16
  /**
14
17
  * A set of pending RPC calls that are queued for execution.
15
18
  */
16
19
  queue: Set<IRPCCall>;
20
+ get credentials(): IRPCCredentials;
17
21
  /**
18
22
  * Creates a new IRPCTransport instance.
19
23
  * @param config - Optional transport configuration including timeout and debounce settings.
@@ -21,18 +25,30 @@ declare class IRPCTransport {
21
25
  constructor(config?: TransportConfig | undefined);
22
26
  /**
23
27
  * Initiates an RPC call with the given specification and arguments.
28
+ * @param reader - The reader instance to attach to the RPC call.
24
29
  * @param spec - The RPC specification defining the method to call.
25
30
  * @param args - An array of arguments to pass to the RPC method.
26
31
  * @param config - Optional call configuration, including timeout, retry settings, and more.
27
32
  * @returns A promise that resolves with the RPC response data or rejects with an error.
28
33
  */
29
- call(spec: IRPCSpec<IRPCInputs, IRPCOutput>, args: IRPCData[], config?: IRPCCallConfig): IRPCReader<IRPCData>;
34
+ call(spec: IRPCSpec<IRPCInputs, IRPCOutput>, args: IRPCData[], config?: IRPCCallConfig, reader?: IRPCReader<IRPCData>): IRPCReader<IRPCData>;
30
35
  /**
31
36
  * Schedules an RPC call for execution, implementing debouncing logic.
32
37
  * Queued calls will be dispatched after the configured debounce delay.
33
38
  * @param call - The RPC call to schedule.
34
39
  */
35
40
  schedule(call: IRPCCall): void;
41
+ /**
42
+ * Signs an RPC call with credentials.
43
+ * @param cred - The credentials to sign the call with.
44
+ */
45
+ sign(cred: IRPCCredentialsFactory): void;
46
+ /**
47
+ * Closes an RPC call. This base implementation does nothing.
48
+ * Subclasses should override this method to provide closing logic.
49
+ * @param call - The RPC call to cancel.
50
+ */
51
+ close(call: IRPCCall): void;
36
52
  /**
37
53
  * Dispatches a batch of RPC calls. This base implementation rejects all calls
38
54
  * with a "not implemented" error. Subclasses should override this method to
package/dist/transport.js CHANGED
@@ -1,6 +1,9 @@
1
1
  import { IRPC_PACKET_TYPE, IRPC_STATUS } from "./enum.js";
2
2
  import { ERROR_CODE, ERROR_MESSAGE } from "./error.js";
3
+ import { IRPCReader } from "./reader.js";
4
+ import { IRPC_STORE } from "./store.js";
3
5
  import { IRPCCall } from "./call.js";
6
+ import { onCleanup, uuid } from "@anchorlib/core";
4
7
 
5
8
  //#region src/transport.ts
6
9
  /**
@@ -8,10 +11,20 @@ import { IRPCCall } from "./call.js";
8
11
  * It handles queuing, debouncing, and timeout management for RPC requests.
9
12
  */
10
13
  var IRPCTransport = class {
14
+ #credentialFactory;
15
+ modules = /* @__PURE__ */ new Set();
11
16
  /**
12
17
  * A set of pending RPC calls that are queued for execution.
13
18
  */
14
19
  queue = /* @__PURE__ */ new Set();
20
+ get credentials() {
21
+ if (typeof this.#credentialFactory === "function") {
22
+ const cred = this.#credentialFactory();
23
+ if (cred === null || Array.isArray(cred) || typeof cred !== "object") return [];
24
+ return Object.entries(cred);
25
+ }
26
+ return Object.entries(this.#credentialFactory ?? {});
27
+ }
15
28
  /**
16
29
  * Creates a new IRPCTransport instance.
17
30
  * @param config - Optional transport configuration including timeout and debounce settings.
@@ -21,12 +34,13 @@ var IRPCTransport = class {
21
34
  }
22
35
  /**
23
36
  * Initiates an RPC call with the given specification and arguments.
37
+ * @param reader - The reader instance to attach to the RPC call.
24
38
  * @param spec - The RPC specification defining the method to call.
25
39
  * @param args - An array of arguments to pass to the RPC method.
26
40
  * @param config - Optional call configuration, including timeout, retry settings, and more.
27
41
  * @returns A promise that resolves with the RPC response data or rejects with an error.
28
42
  */
29
- call(spec, args, config) {
43
+ call(spec, args, config, reader = new IRPCReader(uuid())) {
30
44
  const payload = {
31
45
  name: spec.name,
32
46
  args
@@ -40,8 +54,15 @@ var IRPCTransport = class {
40
54
  maxRetries,
41
55
  retryMode,
42
56
  retryDelay
43
- });
44
- this.schedule(call);
57
+ }, reader);
58
+ if (spec.stream) {
59
+ this.dispatch([call]).finally(() => {}).catch((err) => IRPC_STORE.error(err, [{
60
+ id: call.id,
61
+ name: call.payload.name
62
+ }]));
63
+ return call.reader;
64
+ } else this.schedule(call);
65
+ onCleanup(() => this.close(call));
45
66
  return call.reader;
46
67
  }
47
68
  /**
@@ -52,12 +73,16 @@ var IRPCTransport = class {
52
73
  schedule(call) {
53
74
  const { debounce } = this.config ?? {};
54
75
  if (debounce === false) {
55
- this.dispatch([call]).finally(() => {}).catch(() => {});
76
+ this.dispatch([call]).finally(() => {}).catch((err) => IRPC_STORE.error(err, [{
77
+ id: call.id,
78
+ name: call.payload.name
79
+ }]));
56
80
  return;
57
81
  }
58
82
  const timeout = typeof debounce === "number" && !Number.isNaN(debounce) ? debounce : 0;
59
83
  const dispatch = () => {
60
- this.dispatch(Array.from(this.queue)).finally(() => {}).catch(() => {});
84
+ const pending = Array.from(this.queue);
85
+ this.dispatch(pending);
61
86
  this.queue.clear();
62
87
  };
63
88
  if (!this.queue.size) if (timeout === 0) queueMicrotask(dispatch);
@@ -65,6 +90,22 @@ var IRPCTransport = class {
65
90
  this.queue.add(call);
66
91
  }
67
92
  /**
93
+ * Signs an RPC call with credentials.
94
+ * @param cred - The credentials to sign the call with.
95
+ */
96
+ sign(cred) {
97
+ if (cred === null || Array.isArray(cred) || typeof cred !== "object" && typeof cred !== "function") return;
98
+ this.#credentialFactory = cred;
99
+ }
100
+ /**
101
+ * Closes an RPC call. This base implementation does nothing.
102
+ * Subclasses should override this method to provide closing logic.
103
+ * @param call - The RPC call to cancel.
104
+ */
105
+ close(call) {
106
+ console.log("[irpc] Closing call", call);
107
+ }
108
+ /**
68
109
  * Dispatches a batch of RPC calls. This base implementation rejects all calls
69
110
  * with a "not implemented" error. Subclasses should override this method to
70
111
  * provide actual transport mechanism.
package/dist/types.d.ts CHANGED
@@ -1,8 +1,11 @@
1
- import { IRPC_DATA_TYPE, IRPC_EVENT_TYPE, IRPC_PACKET_TYPE, IRPC_STATUS } from "./enum.js";
1
+ import { IRPC_BASE_CONTEXT, IRPC_DATA_TYPE, IRPC_PACKET_TYPE, IRPC_STATUS } from "./enum.js";
2
2
  import { ErrorCode } from "./error.js";
3
+ import { IRPCFile } from "./file.js";
4
+ import { IRPCFilePointer } from "./packet.js";
3
5
  import { IRPCTransport } from "./transport.js";
4
6
  import { RemoteState } from "./state.js";
5
- import { StateChange } from "@anchorlib/core";
7
+ import { IRPCReader } from "./reader.js";
8
+ import { AsyncValue, StateChange } from "@anchorlib/core";
6
9
  import { ZodArray, ZodBoolean, ZodNull, ZodNumber, ZodObject, ZodSafeParseResult, ZodString, ZodUndefined } from "zod/v4";
7
10
 
8
11
  //#region src/types.d.ts
@@ -20,7 +23,7 @@ type IRPCSpecStore = Map<string, IRPCSpec<IRPCInputs, IRPCOutput>>;
20
23
  type IRPCStatus = (typeof IRPC_STATUS)[keyof typeof IRPC_STATUS];
21
24
  type IRPCDataType = (typeof IRPC_DATA_TYPE)[keyof typeof IRPC_DATA_TYPE];
22
25
  type IRPCPacketType = (typeof IRPC_PACKET_TYPE)[keyof typeof IRPC_PACKET_TYPE];
23
- type IRPCEventType = (typeof IRPC_EVENT_TYPE)[keyof typeof IRPC_EVENT_TYPE];
26
+ type IRPCBaseContext = (typeof IRPC_BASE_CONTEXT)[keyof typeof IRPC_BASE_CONTEXT];
24
27
  type IRPCPacketBase = {
25
28
  id: string;
26
29
  name: string;
@@ -29,10 +32,6 @@ type IRPCPacketBase = {
29
32
  createdAt?: number;
30
33
  arrivedAt?: number;
31
34
  };
32
- type IRPCPacketData = {
33
- type: IRPCDataType;
34
- value: IRPCData;
35
- };
36
35
  type IRPCPacketCall = IRPCPacketBase & {
37
36
  args: IRPCData[];
38
37
  };
@@ -52,6 +51,56 @@ interface IRPCReadable<T> {
52
51
  error: Error | undefined;
53
52
  status: IRPCStatus;
54
53
  }
54
+ /**
55
+ * Represents a client-side stub for a remote function.
56
+ * When called, it returns an IRPCReader to handle the asynchronous result or stream.
57
+ *
58
+ * @template T - The original function type.
59
+ * @template A - The argument types of the function.
60
+ * @template R - The return data type.
61
+ */
62
+ interface IRPCStub<T, A$1 extends unknown[], R$1 extends IRPCData> {
63
+ (...args: A$1): IRPCReader<R$1>;
64
+ stub: T;
65
+ /**
66
+ * Creates a call that expect to run in browser environment.
67
+ * The function runs immediately on the browser and will not re-run.
68
+ *
69
+ * @param args - A factory function returning the argument array.
70
+ * @returns An IRPCReader instance for handling the asynchronous result or stream.
71
+ */
72
+ once(...args: A$1): IRPCReader<R$1>;
73
+ /**
74
+ * Creates a reactive call that expect to run in browser environment.
75
+ * The function runs immediately on the browser and will re-run when
76
+ * the reactive dependencies change.
77
+ *
78
+ * @param args - A factory function returning the argument array.
79
+ * @param debounce - The debounce time in milliseconds.
80
+ * @returns An IRPCReader instance for handling the asynchronous result or stream.
81
+ */
82
+ with(args: () => A$1, debounce?: number): IRPCReader<R$1>;
83
+ /**
84
+ * Creates a reactive call that expect to run in browser environment.
85
+ * The function only runs on the first dependency change and re-run
86
+ * when the reactive dependencies change.
87
+ *
88
+ * @param args - A factory function returning the argument array.
89
+ * @param debounce - The debounce time in milliseconds.
90
+ * @returns An IRPCReader instance for handling the asynchronous result or stream.
91
+ */
92
+ when(args: () => A$1, debounce?: number): IRPCReader<R$1>;
93
+ later(debounce?: number): IRPCReader<R$1> & {
94
+ dispatch: (...args: A$1) => void;
95
+ };
96
+ }
97
+ /**
98
+ * A utility type that transforms a standard function type into its corresponding IRPCStub.
99
+ * It automatically unwraps RemoteState types to determine the underlying data type.
100
+ *
101
+ * @template T - The function type to be transformed.
102
+ */
103
+ type IRPCFunction<T> = T extends ((...args: infer A) => infer R) ? R extends RemoteState<infer S> ? S extends IRPCData ? IRPCStub<T, A, S> : IRPCStub<T, A, IRPCData> : R extends Promise<infer O> ? O extends IRPCData ? IRPCStub<T, A, O> : IRPCStub<T, A, IRPCData> : R extends IRPCData ? IRPCStub<T, A, R> : IRPCStub<T, A, IRPCData> : IRPCStub<T, [], IRPCData>;
55
104
  /**
56
105
  * Represents primitive data types that can be used in IRPC communications.
57
106
  * Includes string, number, boolean, null, and undefined.
@@ -68,7 +117,7 @@ type IRPCObject = {
68
117
  * Represents all possible data types in IRPC, including primitives, objects, and arrays.
69
118
  * This is a recursive type that allows nested structures.
70
119
  */
71
- type IRPCData = IRPCPrimitive | IRPCObject | IRPCData[];
120
+ type IRPCData = IRPCPrimitive | IRPCObject | IRPCFile | IRPCData[];
72
121
  /**
73
122
  * Union type of all primitive Zod schema types used for validation.
74
123
  */
@@ -123,11 +172,11 @@ type IRPCPayload = {
123
172
  /**
124
173
  * Defines the schema for input and output validation of an RPC function.
125
174
  */
126
- type IRPCSchema<I extends IRPCInputs, O extends IRPCOutput> = {
175
+ type IRPCSchema<I extends IRPCInputs, O$1 extends IRPCOutput> = {
127
176
  /** Optional input validation schemas */
128
177
  input?: I;
129
178
  /** Optional output validation schema */
130
- output?: O;
179
+ output?: O$1;
131
180
  };
132
181
  /**
133
182
  * Type definition for an RPC handler function.
@@ -141,13 +190,13 @@ type IRPCHandler = Function;
141
190
  * @template I - Tuple of input validation schemas
142
191
  * @template O - Output validation schema
143
192
  */
144
- type IRPCInit<I extends IRPCInputs, O extends IRPCOutput> = {
193
+ type IRPCInit<R$1, I extends IRPCInputs, O$1 extends IRPCOutput> = {
145
194
  /** The name of the RPC function */
146
195
  name: string;
147
196
  /** Optional description of the RPC function */
148
197
  description?: string;
149
198
  /** Optional schema for input/output validation */
150
- schema?: IRPCSchema<I, O>;
199
+ schema?: IRPCSchema<I, O$1>;
151
200
  /** Optional maximum age of a call in milliseconds */
152
201
  maxAge?: number;
153
202
  /**
@@ -157,7 +206,20 @@ type IRPCInit<I extends IRPCInputs, O extends IRPCOutput> = {
157
206
  * This can help reduce the number of actual function executions.
158
207
  */
159
208
  coalesce?: boolean;
209
+ /** Optional initialization function to seed the data */
210
+ init?: () => R$1;
160
211
  } & IRPCCallConfig;
212
+ /**
213
+ * Configuration options for initializing an RPC stream function.
214
+ * Contains metadata and constraints for the RPC stream function.
215
+ *
216
+ * @template I - Tuple of input validation schemas
217
+ * @template O - Output validation schema
218
+ */
219
+ type IRPCStreamInit<I extends IRPCInputs, O$1 extends IRPCOutput, R$1> = IRPCInit<R$1, I, O$1> & {
220
+ stream: true;
221
+ ttl?: number;
222
+ };
161
223
  /**
162
224
  * Type definition for an RPC declaration.
163
225
  * Represents an RPC function with its name, description, and configuration.
@@ -166,9 +228,7 @@ type IRPCInit<I extends IRPCInputs, O extends IRPCOutput> = {
166
228
  * @template I - Tuple of input validation schemas
167
229
  * @template O - Output validation schema
168
230
  */
169
- type IRPCDeclareInit<F, I extends IRPCInputs, O extends IRPCOutput> = F extends ((...args: any[]) => RemoteState<infer R>) ? IRPCInit<I, IRPCOutput> & {
170
- init: () => R;
171
- } : IRPCInit<I, O>;
231
+ type IRPCDeclareInit<F, I extends IRPCInputs, O$1 extends IRPCOutput> = F extends ((...args: IRPCData[]) => infer R) ? R extends RemoteState<infer S> ? S extends IRPCData ? IRPCStreamInit<I, O$1, S> : IRPCInit<IRPCData, IRPCInputs, IRPCOutput> : R extends Promise<infer D> ? D extends IRPCData ? IRPCInit<D, I, O$1> : IRPCInit<IRPCData, IRPCInputs, IRPCOutput> : R extends IRPCData ? IRPCInit<R, I, O$1> : IRPCInit<IRPCData, IRPCInputs, IRPCOutput> : IRPCInit<IRPCData, IRPCInputs, IRPCOutput>;
172
232
  /**
173
233
  * Complete specification for an RPC function including its implementation.
174
234
  * Extends IRPCInit with the actual handler function.
@@ -176,9 +236,14 @@ type IRPCDeclareInit<F, I extends IRPCInputs, O extends IRPCOutput> = F extends
176
236
  * @template I - Tuple of input validation schemas
177
237
  * @template O - Output validation schema
178
238
  */
179
- type IRPCSpec<I extends IRPCInputs, O extends IRPCOutput> = IRPCInit<I, O> & {
239
+ type IRPCSpec<I extends IRPCInputs, O$1 extends IRPCOutput> = IRPCInit<IRPCData, I, O$1> & {
240
+ /** Optional time-to-live for a call in milliseconds */
241
+ ttl?: number;
242
+ /** Whether to stream the result of the RPC call */
243
+ stream?: boolean;
180
244
  /** The actual handler function that implements the RPC */
181
245
  handler: IRPCHandler;
246
+ /** Optional initialization function for a stream RPC */
182
247
  init?: () => unknown;
183
248
  };
184
249
  /**
@@ -191,6 +256,13 @@ type IRPCRequest = {
191
256
  name: string;
192
257
  /** Arguments for the RPC function */
193
258
  args: unknown[];
259
+ files?: IRPCFilePointer[];
260
+ };
261
+ type IRPCCredentials = Iterable<[string, AsyncValue]>;
262
+ type IRPCCredentialsFactory = Record<string, AsyncValue> | (() => Record<string, AsyncValue>);
263
+ type IRPCRequests = {
264
+ calls: IRPCRequest[];
265
+ credentials?: IRPCCredentials;
194
266
  };
195
267
  type IRPCError = {
196
268
  code: ErrorCode;
@@ -238,6 +310,8 @@ type IRPCCallConfig = {
238
310
  retryMode?: 'linear' | 'exponential';
239
311
  /** Base delay between retries in milliseconds */
240
312
  retryDelay?: number;
313
+ /** Optional initialization function for a stream RPC */
314
+ init?: () => unknown;
241
315
  };
242
316
  /**
243
317
  * Configuration for transport layer, extending call configuration with debounce settings.
@@ -246,5 +320,17 @@ type TransportConfig = IRPCCallConfig & {
246
320
  /** Debounce setting for transport - can be a boolean to enable/disable or a number for specific delay */
247
321
  debounce?: number | boolean;
248
322
  };
323
+ type StreamCleanup = () => void;
324
+ /**
325
+ * A callback function type used to natively construct and drive a reactive stream.
326
+ * It provides the initial reactive data reference and terminal resolution hooks
327
+ * without forcing strict async/await boundaries, securely yielding stream operations.
328
+ *
329
+ * @template T - The type of data yielded globally by the stream.
330
+ * @param state - The reactive state reference for the stream.
331
+ * @param resolve - Callback to statically mark the stream as successfully completed, optionally with a resolved value.
332
+ * @param reject - Callback to forcefully throw a runtime error into the stream structure.
333
+ */
334
+ type StreamConstructor<T> = (state: IRPCReadable<T>, resolve: (value?: T) => void, reject: (error: Error) => void) => StreamCleanup | void | Promise<StreamCleanup | void>;
249
335
  //#endregion
250
- export { 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 };
336
+ export { IRPCArraySchema, IRPCBaseContext, IRPCCallConfig, IRPCContext, IRPCContextProvider, IRPCCredentials, IRPCCredentialsFactory, IRPCData, IRPCDataSchema, IRPCDataType, IRPCDeclareInit, IRPCError, IRPCFunction, IRPCHandler, IRPCInit, IRPCInputs, IRPCObject, IRPCObjectSchema, IRPCOutput, IRPCPackageConfig, IRPCPackageInfo, IRPCPacketAnswer, IRPCPacketBase, IRPCPacketCall, IRPCPacketClose, IRPCPacketEvent, IRPCPacketStream, IRPCPacketType, IRPCParseResult, IRPCPayload, IRPCPrimitive, IRPCPrimitiveSchema, IRPCReadable, IRPCRequest, IRPCRequests, IRPCResponse, IRPCSchema, IRPCSpec, IRPCSpecStore, IRPCStatus, IRPCStreamInit, IRPCStub, IRPCStubStore, StreamCleanup, StreamConstructor, TransportConfig };
package/package.json CHANGED
@@ -1,18 +1,20 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@irpclib/irpc",
4
- "version": "1.0.0-beta.22",
4
+ "version": "1.0.0-beta.24",
5
5
  "types": "./dist/index.d.ts",
6
6
  "module": "./dist/index.js",
7
7
  "exports": {
8
8
  ".": {
9
9
  "types": "./dist/index.d.ts",
10
10
  "import": "./dist/index.js"
11
+ },
12
+ "./server": {
13
+ "types": "./dist/server/index.d.ts",
14
+ "import": "./dist/server/index.js"
11
15
  }
12
16
  },
13
- "files": [
14
- "dist"
15
- ],
17
+ "files": ["dist"],
16
18
  "directories": {
17
19
  "dist": "./dist"
18
20
  },
@@ -27,7 +29,7 @@
27
29
  "publint": "0.3.15",
28
30
  "rimraf": "6.0.1",
29
31
  "tsdown": "0.15.9",
30
- "vite": "7.1.12",
32
+ "vite": "8.0.10",
31
33
  "vitest": "^3.2.4",
32
34
  "zod": "^4.1.5"
33
35
  },
@@ -48,6 +50,6 @@
48
50
  },
49
51
  "license": "MIT",
50
52
  "dependencies": {
51
- "@anchorlib/core": "^1.0.0-beta.22"
53
+ "@anchorlib/core": "^1.0.0-beta.24"
52
54
  }
53
- }
55
+ }
package/readme.md CHANGED
@@ -120,7 +120,7 @@ import { loadDashboard } from './index.js';
120
120
  import { stream } from '@irpclib/irpc';
121
121
 
122
122
  irpc.construct(loadDashboard, (userId) => {
123
- return stream((data, resolve) => {
123
+ return stream(({ data }, resolve) => {
124
124
  const q1 = db.users.get(userId).then(res => data.user = res);
125
125
  const q2 = db.sales.aggregate(userId).then(res => data.sales = res);
126
126
 
@@ -131,6 +131,8 @@ irpc.construct(loadDashboard, (userId) => {
131
131
 
132
132
  ### 4. Setup Server
133
133
 
134
+ The integration point extracts application-level values from transport-specific objects and injects them as standardized context via `initContext`. This keeps middleware and handlers transport-agnostic.
135
+
134
136
  ```typescript
135
137
  // server.ts
136
138
  import { setContextProvider } from '@irpclib/irpc';
@@ -147,7 +149,10 @@ Bun.serve({
147
149
  port: 3000,
148
150
  routes: {
149
151
  [transport.endpoint]: {
150
- POST: (req) => router.resolve(req),
152
+ POST: (req) => router.resolve(req, [
153
+ ['token', req.headers.get('authorization')],
154
+ ['locale', req.headers.get('accept-language')],
155
+ ]),
151
156
  }
152
157
  },
153
158
  });
@@ -256,7 +261,7 @@ export const createUser = irpc.declare({
256
261
 
257
262
  ## Documentation
258
263
 
259
- For detailed documentation, visit [https://anchorlib.dev/docs/irpc](https://anchorlib.dev/docs/irpc)
264
+ For detailed documentation, visit [https://airlib.dev/irpc](https://airlib.dev/irpc)
260
265
 
261
266
  ## License
262
267
 
package/dist/uuid.d.ts DELETED
@@ -1,21 +0,0 @@
1
- //#region src/uuid.d.ts
2
- /**
3
- * A function that generates a random UUID string.
4
- *
5
- * @returns A UUID v4 string in the format xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
6
- */
7
- type UUIDProvider = () => string;
8
- /**
9
- * Generates a new UUID using the currently configured provider.
10
- *
11
- * @returns A UUID string generated by the current provider
12
- */
13
- declare function uuid(): string;
14
- /**
15
- * Sets a custom UUID provider function to be used by the uuid() function.
16
- *
17
- * @param provider - A function that returns a UUID string when called
18
- */
19
- declare function setUUIDProvider(provider: UUIDProvider): void;
20
- //#endregion
21
- export { UUIDProvider, setUUIDProvider, uuid };