@bigmistqke/rpc 0.1.0

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 ADDED
@@ -0,0 +1,601 @@
1
+ // ../../node_modules/.pnpm/valibot@1.0.0_typescript@5.7.2/node_modules/valibot/dist/index.js
2
+ var store;
3
+ function getGlobalConfig(config2) {
4
+ return {
5
+ lang: config2?.lang ?? store?.lang,
6
+ message: config2?.message,
7
+ abortEarly: config2?.abortEarly ?? store?.abortEarly,
8
+ abortPipeEarly: config2?.abortPipeEarly ?? store?.abortPipeEarly
9
+ };
10
+ }
11
+ var store2;
12
+ function getGlobalMessage(lang) {
13
+ return store2?.get(lang);
14
+ }
15
+ var store3;
16
+ function getSchemaMessage(lang) {
17
+ return store3?.get(lang);
18
+ }
19
+ var store4;
20
+ function getSpecificMessage(reference, lang) {
21
+ return store4?.get(reference)?.get(lang);
22
+ }
23
+ function _stringify(input) {
24
+ const type = typeof input;
25
+ if (type === "string") {
26
+ return `"${input}"`;
27
+ }
28
+ if (type === "number" || type === "bigint" || type === "boolean") {
29
+ return `${input}`;
30
+ }
31
+ if (type === "object" || type === "function") {
32
+ return (input && Object.getPrototypeOf(input)?.constructor?.name) ?? "null";
33
+ }
34
+ return type;
35
+ }
36
+ function _addIssue(context, label, dataset, config2, other) {
37
+ const input = other && "input" in other ? other.input : dataset.value;
38
+ const expected = other?.expected ?? context.expects ?? null;
39
+ const received = other?.received ?? _stringify(input);
40
+ const issue = {
41
+ kind: context.kind,
42
+ type: context.type,
43
+ input,
44
+ expected,
45
+ received,
46
+ message: `Invalid ${label}: ${expected ? `Expected ${expected} but r` : "R"}eceived ${received}`,
47
+ requirement: context.requirement,
48
+ path: other?.path,
49
+ issues: other?.issues,
50
+ lang: config2.lang,
51
+ abortEarly: config2.abortEarly,
52
+ abortPipeEarly: config2.abortPipeEarly
53
+ };
54
+ const isSchema = context.kind === "schema";
55
+ const message = other?.message ?? context.message ?? getSpecificMessage(context.reference, issue.lang) ?? (isSchema ? getSchemaMessage(issue.lang) : null) ?? config2.message ?? getGlobalMessage(issue.lang);
56
+ if (message !== void 0) {
57
+ issue.message = typeof message === "function" ? (
58
+ // @ts-expect-error
59
+ message(issue)
60
+ ) : message;
61
+ }
62
+ if (isSchema) {
63
+ dataset.typed = false;
64
+ }
65
+ if (dataset.issues) {
66
+ dataset.issues.push(issue);
67
+ } else {
68
+ dataset.issues = [issue];
69
+ }
70
+ }
71
+ function _getStandardProps(context) {
72
+ return {
73
+ version: 1,
74
+ vendor: "valibot",
75
+ validate(value2) {
76
+ return context["~run"]({ value: value2 }, getGlobalConfig());
77
+ }
78
+ };
79
+ }
80
+ function getFallback(schema, dataset, config2) {
81
+ return typeof schema.fallback === "function" ? (
82
+ // @ts-expect-error
83
+ schema.fallback(dataset, config2)
84
+ ) : (
85
+ // @ts-expect-error
86
+ schema.fallback
87
+ );
88
+ }
89
+ function getDefault(schema, dataset, config2) {
90
+ return typeof schema.default === "function" ? (
91
+ // @ts-expect-error
92
+ schema.default(dataset, config2)
93
+ ) : (
94
+ // @ts-expect-error
95
+ schema.default
96
+ );
97
+ }
98
+ function any() {
99
+ return {
100
+ kind: "schema",
101
+ type: "any",
102
+ reference: any,
103
+ expects: "any",
104
+ async: false,
105
+ get "~standard"() {
106
+ return _getStandardProps(this);
107
+ },
108
+ "~run"(dataset) {
109
+ dataset.typed = true;
110
+ return dataset;
111
+ }
112
+ };
113
+ }
114
+ function array(item, message) {
115
+ return {
116
+ kind: "schema",
117
+ type: "array",
118
+ reference: array,
119
+ expects: "Array",
120
+ async: false,
121
+ item,
122
+ message,
123
+ get "~standard"() {
124
+ return _getStandardProps(this);
125
+ },
126
+ "~run"(dataset, config2) {
127
+ const input = dataset.value;
128
+ if (Array.isArray(input)) {
129
+ dataset.typed = true;
130
+ dataset.value = [];
131
+ for (let key = 0; key < input.length; key++) {
132
+ const value2 = input[key];
133
+ const itemDataset = this.item["~run"]({ value: value2 }, config2);
134
+ if (itemDataset.issues) {
135
+ const pathItem = {
136
+ type: "array",
137
+ origin: "value",
138
+ input,
139
+ key,
140
+ value: value2
141
+ };
142
+ for (const issue of itemDataset.issues) {
143
+ if (issue.path) {
144
+ issue.path.unshift(pathItem);
145
+ } else {
146
+ issue.path = [pathItem];
147
+ }
148
+ dataset.issues?.push(issue);
149
+ }
150
+ if (!dataset.issues) {
151
+ dataset.issues = itemDataset.issues;
152
+ }
153
+ if (config2.abortEarly) {
154
+ dataset.typed = false;
155
+ break;
156
+ }
157
+ }
158
+ if (!itemDataset.typed) {
159
+ dataset.typed = false;
160
+ }
161
+ dataset.value.push(itemDataset.value);
162
+ }
163
+ } else {
164
+ _addIssue(this, "type", dataset, config2);
165
+ }
166
+ return dataset;
167
+ }
168
+ };
169
+ }
170
+ function boolean(message) {
171
+ return {
172
+ kind: "schema",
173
+ type: "boolean",
174
+ reference: boolean,
175
+ expects: "boolean",
176
+ async: false,
177
+ message,
178
+ get "~standard"() {
179
+ return _getStandardProps(this);
180
+ },
181
+ "~run"(dataset, config2) {
182
+ if (typeof dataset.value === "boolean") {
183
+ dataset.typed = true;
184
+ } else {
185
+ _addIssue(this, "type", dataset, config2);
186
+ }
187
+ return dataset;
188
+ }
189
+ };
190
+ }
191
+ function number(message) {
192
+ return {
193
+ kind: "schema",
194
+ type: "number",
195
+ reference: number,
196
+ expects: "number",
197
+ async: false,
198
+ message,
199
+ get "~standard"() {
200
+ return _getStandardProps(this);
201
+ },
202
+ "~run"(dataset, config2) {
203
+ if (typeof dataset.value === "number" && !isNaN(dataset.value)) {
204
+ dataset.typed = true;
205
+ } else {
206
+ _addIssue(this, "type", dataset, config2);
207
+ }
208
+ return dataset;
209
+ }
210
+ };
211
+ }
212
+ function object(entries, message) {
213
+ return {
214
+ kind: "schema",
215
+ type: "object",
216
+ reference: object,
217
+ expects: "Object",
218
+ async: false,
219
+ entries,
220
+ message,
221
+ get "~standard"() {
222
+ return _getStandardProps(this);
223
+ },
224
+ "~run"(dataset, config2) {
225
+ const input = dataset.value;
226
+ if (input && typeof input === "object") {
227
+ dataset.typed = true;
228
+ dataset.value = {};
229
+ for (const key in this.entries) {
230
+ const valueSchema = this.entries[key];
231
+ if (key in input || (valueSchema.type === "exact_optional" || valueSchema.type === "optional" || valueSchema.type === "nullish") && // @ts-expect-error
232
+ valueSchema.default !== void 0) {
233
+ const value2 = key in input ? (
234
+ // @ts-expect-error
235
+ input[key]
236
+ ) : getDefault(valueSchema);
237
+ const valueDataset = valueSchema["~run"]({ value: value2 }, config2);
238
+ if (valueDataset.issues) {
239
+ const pathItem = {
240
+ type: "object",
241
+ origin: "value",
242
+ input,
243
+ key,
244
+ value: value2
245
+ };
246
+ for (const issue of valueDataset.issues) {
247
+ if (issue.path) {
248
+ issue.path.unshift(pathItem);
249
+ } else {
250
+ issue.path = [pathItem];
251
+ }
252
+ dataset.issues?.push(issue);
253
+ }
254
+ if (!dataset.issues) {
255
+ dataset.issues = valueDataset.issues;
256
+ }
257
+ if (config2.abortEarly) {
258
+ dataset.typed = false;
259
+ break;
260
+ }
261
+ }
262
+ if (!valueDataset.typed) {
263
+ dataset.typed = false;
264
+ }
265
+ dataset.value[key] = valueDataset.value;
266
+ } else if (valueSchema.fallback !== void 0) {
267
+ dataset.value[key] = getFallback(valueSchema);
268
+ } else if (valueSchema.type !== "exact_optional" && valueSchema.type !== "optional" && valueSchema.type !== "nullish") {
269
+ _addIssue(this, "key", dataset, config2, {
270
+ input: void 0,
271
+ expected: `"${key}"`,
272
+ path: [
273
+ {
274
+ type: "object",
275
+ origin: "key",
276
+ input,
277
+ key,
278
+ // @ts-expect-error
279
+ value: input[key]
280
+ }
281
+ ]
282
+ });
283
+ if (config2.abortEarly) {
284
+ break;
285
+ }
286
+ }
287
+ }
288
+ } else {
289
+ _addIssue(this, "type", dataset, config2);
290
+ }
291
+ return dataset;
292
+ }
293
+ };
294
+ }
295
+ function string(message) {
296
+ return {
297
+ kind: "schema",
298
+ type: "string",
299
+ reference: string,
300
+ expects: "string",
301
+ async: false,
302
+ message,
303
+ get "~standard"() {
304
+ return _getStandardProps(this);
305
+ },
306
+ "~run"(dataset, config2) {
307
+ if (typeof dataset.value === "string") {
308
+ dataset.typed = true;
309
+ } else {
310
+ _addIssue(this, "type", dataset, config2);
311
+ }
312
+ return dataset;
313
+ }
314
+ };
315
+ }
316
+ function unknown() {
317
+ return {
318
+ kind: "schema",
319
+ type: "unknown",
320
+ reference: unknown,
321
+ expects: "unknown",
322
+ async: false,
323
+ get "~standard"() {
324
+ return _getStandardProps(this);
325
+ },
326
+ "~run"(dataset) {
327
+ dataset.typed = true;
328
+ return dataset;
329
+ }
330
+ };
331
+ }
332
+ function safeParse(schema, input, config2) {
333
+ const dataset = schema["~run"]({ value: input }, getGlobalConfig(config2));
334
+ return {
335
+ typed: dataset.typed,
336
+ success: !dataset.issues,
337
+ output: dataset.value,
338
+ issues: dataset.issues
339
+ };
340
+ }
341
+
342
+ // src/utils.ts
343
+ function createIdAllocator() {
344
+ const freeIds = new Array();
345
+ let id = 0;
346
+ return {
347
+ create() {
348
+ if (freeIds.length) {
349
+ return freeIds.pop();
350
+ }
351
+ return id++;
352
+ },
353
+ free(id2) {
354
+ freeIds.push(id2);
355
+ }
356
+ };
357
+ }
358
+ function createIdRegistry() {
359
+ const map = /* @__PURE__ */ new Map();
360
+ const idFactory = createIdAllocator();
361
+ return {
362
+ register(value) {
363
+ const id = idFactory.create();
364
+ map.set(id, value);
365
+ return id;
366
+ },
367
+ free(id) {
368
+ idFactory.free(id);
369
+ return map.get(id);
370
+ }
371
+ };
372
+ }
373
+ function createPromiseRegistry() {
374
+ return createIdRegistry();
375
+ }
376
+ function defer() {
377
+ let resolve = null;
378
+ let reject = null;
379
+ return {
380
+ promise: new Promise((_resolve, _reject) => (resolve = _resolve, reject = _reject)),
381
+ resolve,
382
+ reject
383
+ };
384
+ }
385
+ function createCommander(apply) {
386
+ function _createCommander(topics, apply2) {
387
+ return new Proxy(function() {
388
+ }, {
389
+ get(_, topic) {
390
+ if (typeof topic === "symbol")
391
+ return void 0;
392
+ return _createCommander([...topics, topic], apply2);
393
+ },
394
+ apply(_, __, args) {
395
+ return apply2(topics, args);
396
+ }
397
+ });
398
+ }
399
+ return _createCommander([], apply);
400
+ }
401
+ function createShape(schema, create) {
402
+ return {
403
+ validate: (value) => safeParse(schema, value).success,
404
+ create
405
+ };
406
+ }
407
+ function callMethod(methods, topics, args) {
408
+ const method = topics.reduce((acc, topic) => {
409
+ const result = acc?.[topic];
410
+ return result;
411
+ }, methods);
412
+ if (typeof method !== "function") {
413
+ throw new Error(`Topics did not resolve to a function: [${topics.join(",")}]`);
414
+ }
415
+ return method(...args);
416
+ }
417
+ function streamToAsyncIterable(stream) {
418
+ if (Symbol.asyncIterator in stream) {
419
+ return stream;
420
+ }
421
+ const reader = stream.getReader();
422
+ return {
423
+ [Symbol.asyncIterator]() {
424
+ return {
425
+ async next() {
426
+ const result = await reader.read();
427
+ return result;
428
+ },
429
+ async return() {
430
+ reader.releaseLock();
431
+ return { value: void 0, done: true };
432
+ }
433
+ };
434
+ }
435
+ };
436
+ }
437
+ function createReadableStream() {
438
+ const closeHandlers = /* @__PURE__ */ new Set();
439
+ let controller = null;
440
+ let closed = false;
441
+ const stream = new ReadableStream({
442
+ start(_controller) {
443
+ controller = _controller;
444
+ },
445
+ cancel() {
446
+ closeHandlers.forEach((handler) => handler());
447
+ closed = true;
448
+ }
449
+ });
450
+ return {
451
+ controller,
452
+ stream,
453
+ enqueue: controller.enqueue.bind(controller),
454
+ closed() {
455
+ return closed;
456
+ },
457
+ onClose(cb) {
458
+ closeHandlers.add(cb);
459
+ return () => closeHandlers.delete(cb);
460
+ }
461
+ };
462
+ }
463
+
464
+ // src/message-protocol.ts
465
+ var $MESSENGER_REQUEST = "RPC_PROXY_REQUEST";
466
+ var requestSchema = object({
467
+ [$MESSENGER_REQUEST]: number(),
468
+ payload: unknown()
469
+ });
470
+ var RequestShape = createShape(requestSchema, (id, payload) => ({
471
+ [$MESSENGER_REQUEST]: id,
472
+ payload
473
+ }));
474
+ var $MESSENGER_RESPONSE = "RPC_PROXY_RESPONSE";
475
+ var ResponseShape = createShape(
476
+ object({
477
+ [$MESSENGER_RESPONSE]: number(),
478
+ payload: unknown()
479
+ }),
480
+ (request, payload) => ({
481
+ [$MESSENGER_RESPONSE]: request[$MESSENGER_REQUEST],
482
+ payload
483
+ })
484
+ );
485
+ var $MESSENGER_ERROR = "RPC_PROXY_ERROR";
486
+ var ErrorShape = createShape(
487
+ object({
488
+ [$MESSENGER_ERROR]: number(),
489
+ error: unknown()
490
+ }),
491
+ (data, error) => ({
492
+ [$MESSENGER_ERROR]: data[$MESSENGER_REQUEST],
493
+ error
494
+ })
495
+ );
496
+ var $MESSENGER_RPC_REQUEST = "RPC_PROXY_RPC_REQUEST";
497
+ var RPCPayloadShape = createShape(
498
+ object({
499
+ [$MESSENGER_RPC_REQUEST]: boolean(),
500
+ topics: array(string()),
501
+ args: array(any())
502
+ }),
503
+ (topics, args) => ({ [$MESSENGER_RPC_REQUEST]: true, topics, args })
504
+ );
505
+
506
+ // src/stream/index.ts
507
+ var $STREAM_REQUEST_HEADER = "RPC_STREAM_REQUEST_HEADER";
508
+ var encoder = new TextEncoder();
509
+ var decoder = new TextDecoder();
510
+ var isStreamRequest = (event) => event.request.headers.has($STREAM_REQUEST_HEADER);
511
+ function rpc(reader, methods, codec = {
512
+ serialize(value, onChunk) {
513
+ onChunk(encoder.encode(`${JSON.stringify(value)}
514
+ `));
515
+ },
516
+ async deserialize(stream, onChunk) {
517
+ let buffer = "";
518
+ for await (const value of streamToAsyncIterable(stream)) {
519
+ buffer += decoder.decode(value, { stream: true });
520
+ let newlineIndex;
521
+ while ((newlineIndex = buffer.indexOf("\n")) !== -1) {
522
+ const line = buffer.slice(0, newlineIndex);
523
+ buffer = buffer.slice(newlineIndex + 1);
524
+ onChunk(JSON.parse(line));
525
+ }
526
+ }
527
+ }
528
+ }) {
529
+ const promiseRegistry = createPromiseRegistry();
530
+ const { stream, closed, onClose, enqueue } = createReadableStream();
531
+ (async () => {
532
+ const inputStream = await (typeof reader === "function" ? reader(stream) : reader);
533
+ codec.deserialize(inputStream, async (data) => {
534
+ if (methods && RequestShape.validate(data) && RPCPayloadShape.validate(data.payload)) {
535
+ const {
536
+ payload: { topics, args }
537
+ } = data;
538
+ codec.serialize(
539
+ ResponseShape.create(data, await callMethod(methods, topics, args)),
540
+ enqueue
541
+ );
542
+ } else if (ResponseShape.validate(data)) {
543
+ promiseRegistry.free(data[$MESSENGER_RESPONSE])?.resolve(data.payload);
544
+ }
545
+ });
546
+ })();
547
+ return {
548
+ proxy: createCommander(async (topics, args) => {
549
+ if (closed?.()) {
550
+ throw new Error(`[rpc/sse] Stream is closed.`);
551
+ }
552
+ const { promise, resolve, reject } = defer();
553
+ const id = promiseRegistry.register({ resolve, reject });
554
+ codec.serialize(RequestShape.create(id, RPCPayloadShape.create(topics, args)), enqueue);
555
+ return promise;
556
+ }),
557
+ closed,
558
+ onClose,
559
+ stream
560
+ };
561
+ }
562
+ function client(url, methods, codec) {
563
+ return rpc(
564
+ (stream) => fetch(url, {
565
+ method: "POST",
566
+ body: stream,
567
+ // @ts-expect-error
568
+ duplex: "half",
569
+ headers: {
570
+ "Content-Type": "text/event-stream",
571
+ "Cache-Control": "no-cache",
572
+ Connection: "keep-alive",
573
+ [$STREAM_REQUEST_HEADER]: "1"
574
+ }
575
+ }).then((response) => response.body),
576
+ methods,
577
+ codec
578
+ );
579
+ }
580
+ function server(reader, methods, codec) {
581
+ const { proxy, closed, onClose, stream } = rpc(reader, methods, codec);
582
+ return {
583
+ proxy,
584
+ closed,
585
+ onClose,
586
+ response: new Response(stream, {
587
+ headers: {
588
+ "Content-Type": "text/event-stream",
589
+ "Cache-Control": "no-cache",
590
+ Connection: "keep-alive"
591
+ }
592
+ })
593
+ };
594
+ }
595
+ export {
596
+ client,
597
+ isStreamRequest,
598
+ rpc,
599
+ server
600
+ };
601
+ //# sourceMappingURL=stream.js.map