@ereo/server 0.2.4 → 0.2.7
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/bun-server.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +115 -63
- package/dist/streaming.d.ts +7 -8
- package/dist/streaming.d.ts.map +1 -1
- package/package.json +5 -5
package/dist/bun-server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bun-server.d.ts","sourceRoot":"","sources":["../src/bun-server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAClC,OAAO,KAAK,EAAmE,iBAAiB,EAA0C,MAAM,YAAY,CAAC;AAC7J,OAAO,EAAiC,OAAO,EAAiB,MAAM,YAAY,CAAC;AACnF,OAAO,EAAE,UAAU,EAAwD,MAAM,cAAc,CAAC;AAChG,OAAO,EAIL,IAAI,EACJ,eAAe,EAChB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAe,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAC3D,OAAO,EAA+C,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"bun-server.d.ts","sourceRoot":"","sources":["../src/bun-server.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,6 @@ export type { MiddlewareHandler, NextFunction, Middleware, AppContext, } from '@
|
|
|
11
11
|
export { enforceAuthConfig, resolveAuthDenial, resolveCheckResult, } from './auth-enforcement';
|
|
12
12
|
export { serveStatic, staticMiddleware, getMimeType, } from './static';
|
|
13
13
|
export type { StaticOptions } from './static';
|
|
14
|
-
export { createShell, renderToStream, renderToString, createResponse,
|
|
14
|
+
export { createShell, renderToStream, renderToString, createResponse, } from './streaming';
|
|
15
15
|
export type { RenderOptions, ShellTemplate, RenderResult, } from './streaming';
|
|
16
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,SAAS,EACT,YAAY,EACZ,KAAK,GACN,MAAM,cAAc,CAAC;AAEtB,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGpE,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,MAAM,EACN,IAAI,EACJ,eAAe,EACf,QAAQ,EACR,SAAS,GACV,MAAM,cAAc,CAAC;AAEtB,YAAY,EACV,oBAAoB,EACpB,WAAW,EACX,sBAAsB,EACtB,gBAAgB,GACjB,MAAM,cAAc,CAAC;AAItB,YAAY,EACV,iBAAiB,EACjB,YAAY,EACZ,UAAU,EACV,UAAU,GACX,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,WAAW,GACZ,MAAM,UAAU,CAAC;AAElB,YAAY,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAG9C,OAAO,EACL,WAAW,EACX,cAAc,EACd,cAAc,EACd,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,SAAS,EACT,YAAY,EACZ,KAAK,GACN,MAAM,cAAc,CAAC;AAEtB,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGpE,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,MAAM,EACN,IAAI,EACJ,eAAe,EACf,QAAQ,EACR,SAAS,GACV,MAAM,cAAc,CAAC;AAEtB,YAAY,EACV,oBAAoB,EACpB,WAAW,EACX,sBAAsB,EACtB,gBAAgB,GACjB,MAAM,cAAc,CAAC;AAItB,YAAY,EACV,iBAAiB,EACjB,YAAY,EACZ,UAAU,EACV,UAAU,GACX,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,WAAW,GACZ,MAAM,UAAU,CAAC;AAElB,YAAY,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAG9C,OAAO,EACL,WAAW,EACX,cAAc,EACd,cAAc,EACd,cAAc,GACf,MAAM,aAAa,CAAC;AAErB,YAAY,EACV,aAAa,EACb,aAAa,EACb,YAAY,GACb,MAAM,aAAa,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -484,40 +484,85 @@ async function renderToStream(element, options) {
|
|
|
484
484
|
context: options.context
|
|
485
485
|
});
|
|
486
486
|
}
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
487
|
+
const hasDeferred = hasDeferredData(loaderData);
|
|
488
|
+
const { head, tail } = createShell({
|
|
489
|
+
shell,
|
|
490
|
+
scripts: [],
|
|
491
|
+
styles,
|
|
492
|
+
loaderData: hasDeferred ? null : loaderData
|
|
493
|
+
});
|
|
491
494
|
return new Promise((resolve2, reject) => {
|
|
492
495
|
const { PassThrough } = __require("stream");
|
|
496
|
+
const DEFERRED_TIMEOUT_MS = 1e4;
|
|
497
|
+
const RENDER_TIMEOUT_MS = 1e4;
|
|
498
|
+
const timeoutId = setTimeout(() => {
|
|
499
|
+
abort();
|
|
500
|
+
}, RENDER_TIMEOUT_MS);
|
|
493
501
|
const { pipe, abort } = renderToPipeableStream(element, {
|
|
494
|
-
|
|
502
|
+
bootstrapModules: scripts,
|
|
495
503
|
onShellReady() {
|
|
496
504
|
const passThrough = new PassThrough;
|
|
497
|
-
const
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
505
|
+
const encoder = new TextEncoder;
|
|
506
|
+
const stream = new ReadableStream({
|
|
507
|
+
start(controller) {
|
|
508
|
+
controller.enqueue(encoder.encode(head));
|
|
509
|
+
passThrough.on("data", (chunk) => {
|
|
510
|
+
controller.enqueue(new Uint8Array(chunk));
|
|
511
|
+
});
|
|
512
|
+
passThrough.on("end", () => {
|
|
513
|
+
(async () => {
|
|
514
|
+
if (hasDeferred) {
|
|
515
|
+
let resolvedData;
|
|
516
|
+
try {
|
|
517
|
+
resolvedData = await Promise.race([
|
|
518
|
+
resolveAllDeferred(loaderData),
|
|
519
|
+
new Promise((_, rejectTimeout) => setTimeout(() => rejectTimeout(new Error("Deferred data resolution timed out")), DEFERRED_TIMEOUT_MS))
|
|
520
|
+
]);
|
|
521
|
+
} catch (error) {
|
|
522
|
+
console.error("Deferred data resolution failed:", error);
|
|
523
|
+
resolvedData = null;
|
|
524
|
+
}
|
|
525
|
+
const loaderScript = `<script>window.__EREO_DATA__=${serializeLoaderData(resolvedData)}</script>`;
|
|
526
|
+
const resolvedTail = `</div>
|
|
527
|
+
${loaderScript}
|
|
528
|
+
</body>
|
|
529
|
+
</html>`;
|
|
530
|
+
controller.enqueue(encoder.encode(resolvedTail));
|
|
531
|
+
} else {
|
|
532
|
+
controller.enqueue(encoder.encode(tail));
|
|
533
|
+
}
|
|
534
|
+
controller.close();
|
|
535
|
+
})().catch((error) => {
|
|
536
|
+
console.error("Stream finalization error:", error);
|
|
537
|
+
try {
|
|
538
|
+
controller.error(error);
|
|
539
|
+
} catch {}
|
|
540
|
+
}).finally(() => {
|
|
541
|
+
clearTimeout(timeoutId);
|
|
542
|
+
});
|
|
543
|
+
});
|
|
544
|
+
passThrough.on("error", (error) => {
|
|
545
|
+
clearTimeout(timeoutId);
|
|
546
|
+
console.error("Stream error:", error);
|
|
547
|
+
controller.error(error);
|
|
548
|
+
});
|
|
549
|
+
},
|
|
550
|
+
cancel() {
|
|
551
|
+
clearTimeout(timeoutId);
|
|
552
|
+
passThrough.destroy();
|
|
553
|
+
}
|
|
513
554
|
});
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
555
|
+
resolve2({
|
|
556
|
+
body: stream,
|
|
557
|
+
headers: new Headers({
|
|
558
|
+
"Content-Type": "text/html; charset=utf-8"
|
|
559
|
+
}),
|
|
560
|
+
status: 200
|
|
517
561
|
});
|
|
518
562
|
pipe(passThrough);
|
|
519
563
|
},
|
|
520
564
|
onShellError(error) {
|
|
565
|
+
clearTimeout(timeoutId);
|
|
521
566
|
console.error("Shell render error:", error);
|
|
522
567
|
reject(error);
|
|
523
568
|
},
|
|
@@ -525,9 +570,6 @@ async function renderToStream(element, options) {
|
|
|
525
570
|
console.error("Render error:", error);
|
|
526
571
|
}
|
|
527
572
|
});
|
|
528
|
-
setTimeout(() => {
|
|
529
|
-
abort();
|
|
530
|
-
}, 1e4);
|
|
531
573
|
});
|
|
532
574
|
}
|
|
533
575
|
async function renderToString(element, options) {
|
|
@@ -562,24 +604,6 @@ function createResponse(result) {
|
|
|
562
604
|
headers: result.headers
|
|
563
605
|
});
|
|
564
606
|
}
|
|
565
|
-
function createSuspenseStream() {
|
|
566
|
-
const encoder = new TextEncoder;
|
|
567
|
-
let controller;
|
|
568
|
-
const stream = new ReadableStream({
|
|
569
|
-
start(c) {
|
|
570
|
-
controller = c;
|
|
571
|
-
}
|
|
572
|
-
});
|
|
573
|
-
return {
|
|
574
|
-
stream,
|
|
575
|
-
push: (chunk) => {
|
|
576
|
-
controller.enqueue(encoder.encode(chunk));
|
|
577
|
-
},
|
|
578
|
-
close: () => {
|
|
579
|
-
controller.close();
|
|
580
|
-
}
|
|
581
|
-
};
|
|
582
|
-
}
|
|
583
607
|
|
|
584
608
|
// src/bun-server.ts
|
|
585
609
|
import { serializeLoaderData as serializeLoaderData2, hasDeferredData as hasDeferredData2, resolveAllDeferred as resolveAllDeferred2 } from "@ereo/data";
|
|
@@ -1000,27 +1024,31 @@ class BunServer {
|
|
|
1000
1024
|
}
|
|
1001
1025
|
}
|
|
1002
1026
|
async renderStreamingPage(element, shell, loaderData) {
|
|
1027
|
+
let timeoutId;
|
|
1003
1028
|
try {
|
|
1004
1029
|
const { renderToReadableStream } = await getStreamingRenderer();
|
|
1005
1030
|
if (!renderToReadableStream) {
|
|
1006
1031
|
return this.renderStringPage(element, shell, loaderData);
|
|
1007
1032
|
}
|
|
1008
1033
|
const hasDeferred = hasDeferredData2(loaderData);
|
|
1009
|
-
const
|
|
1034
|
+
const clientEntry = this.options.clientEntry;
|
|
1010
1035
|
const { head, tail } = createShell({
|
|
1011
1036
|
shell,
|
|
1012
|
-
scripts,
|
|
1037
|
+
scripts: [],
|
|
1013
1038
|
loaderData: hasDeferred ? null : loaderData
|
|
1014
1039
|
});
|
|
1015
1040
|
const encoder = new TextEncoder;
|
|
1016
1041
|
const headBytes = encoder.encode(head);
|
|
1017
1042
|
const tailBytes = hasDeferred ? null : encoder.encode(tail);
|
|
1043
|
+
const abortController = new AbortController;
|
|
1044
|
+
timeoutId = setTimeout(() => abortController.abort(), 1e4);
|
|
1018
1045
|
const reactStream = await renderToReadableStream(element, {
|
|
1046
|
+
bootstrapModules: [clientEntry],
|
|
1047
|
+
signal: abortController.signal,
|
|
1019
1048
|
onError(error) {
|
|
1020
1049
|
console.error("Streaming render error:", error);
|
|
1021
1050
|
}
|
|
1022
1051
|
});
|
|
1023
|
-
const clientEntry = this.options.clientEntry;
|
|
1024
1052
|
const reader = reactStream.getReader();
|
|
1025
1053
|
let phase = "head";
|
|
1026
1054
|
const stream = new ReadableStream({
|
|
@@ -1034,18 +1062,26 @@ class BunServer {
|
|
|
1034
1062
|
const { done, value } = await reader.read();
|
|
1035
1063
|
if (done) {
|
|
1036
1064
|
if (hasDeferred) {
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1065
|
+
let resolvedData;
|
|
1066
|
+
try {
|
|
1067
|
+
resolvedData = await Promise.race([
|
|
1068
|
+
resolveAllDeferred2(loaderData),
|
|
1069
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error("Deferred data resolution timed out")), 1e4))
|
|
1070
|
+
]);
|
|
1071
|
+
} catch (error) {
|
|
1072
|
+
console.error("Deferred data resolution failed:", error);
|
|
1073
|
+
resolvedData = null;
|
|
1074
|
+
}
|
|
1075
|
+
const loaderScript = `<script>window.__EREO_DATA__=${serializeLoaderData2(resolvedData)}</script>`;
|
|
1040
1076
|
const resolvedTail = `</div>
|
|
1041
1077
|
${loaderScript}
|
|
1042
|
-
${scriptTag}
|
|
1043
1078
|
</body>
|
|
1044
1079
|
</html>`;
|
|
1045
1080
|
controller.enqueue(encoder.encode(resolvedTail));
|
|
1046
1081
|
} else {
|
|
1047
1082
|
controller.enqueue(tailBytes);
|
|
1048
1083
|
}
|
|
1084
|
+
clearTimeout(timeoutId);
|
|
1049
1085
|
controller.close();
|
|
1050
1086
|
phase = "done";
|
|
1051
1087
|
} else {
|
|
@@ -1057,6 +1093,7 @@ class BunServer {
|
|
|
1057
1093
|
},
|
|
1058
1094
|
cancel() {
|
|
1059
1095
|
reader.cancel();
|
|
1096
|
+
clearTimeout(timeoutId);
|
|
1060
1097
|
}
|
|
1061
1098
|
});
|
|
1062
1099
|
return new Response(stream, {
|
|
@@ -1066,6 +1103,7 @@ class BunServer {
|
|
|
1066
1103
|
}
|
|
1067
1104
|
});
|
|
1068
1105
|
} catch (error) {
|
|
1106
|
+
clearTimeout(timeoutId);
|
|
1069
1107
|
console.error("Streaming render failed:", error);
|
|
1070
1108
|
return this.renderStringPage(element, shell, loaderData);
|
|
1071
1109
|
}
|
|
@@ -1093,20 +1131,25 @@ class BunServer {
|
|
|
1093
1131
|
}
|
|
1094
1132
|
}
|
|
1095
1133
|
async renderStreamingPageDirect(element, loaderData) {
|
|
1134
|
+
let timeoutId;
|
|
1096
1135
|
try {
|
|
1097
1136
|
const { renderToReadableStream } = await getStreamingRenderer();
|
|
1098
1137
|
if (!renderToReadableStream) {
|
|
1099
1138
|
return this.renderStringPageDirect(element, loaderData);
|
|
1100
1139
|
}
|
|
1140
|
+
const hasDeferred = hasDeferredData2(loaderData);
|
|
1141
|
+
const clientEntry = this.options.clientEntry;
|
|
1142
|
+
const encoder = new TextEncoder;
|
|
1143
|
+
const abortController = new AbortController;
|
|
1144
|
+
timeoutId = setTimeout(() => abortController.abort(), 1e4);
|
|
1101
1145
|
const reactStream = await renderToReadableStream(element, {
|
|
1146
|
+
bootstrapModules: [clientEntry],
|
|
1147
|
+
signal: abortController.signal,
|
|
1102
1148
|
onError(error) {
|
|
1103
1149
|
console.error("Streaming render error:", error);
|
|
1104
1150
|
}
|
|
1105
1151
|
});
|
|
1106
|
-
const
|
|
1107
|
-
const hasDeferred = hasDeferredData2(loaderData);
|
|
1108
|
-
const clientEntry = this.options.clientEntry;
|
|
1109
|
-
const injectedScripts = hasDeferred ? null : encoder.encode((loaderData ? `<script>window.__EREO_DATA__=${serializeLoaderData2(loaderData)}</script>` : "") + `<script type="module" src="${clientEntry}"></script>`);
|
|
1152
|
+
const loaderScript = !hasDeferred && loaderData ? encoder.encode(`<script>window.__EREO_DATA__=${serializeLoaderData2(loaderData)}</script>`) : null;
|
|
1110
1153
|
const reader = reactStream.getReader();
|
|
1111
1154
|
let done = false;
|
|
1112
1155
|
const stream = new ReadableStream({
|
|
@@ -1116,13 +1159,21 @@ class BunServer {
|
|
|
1116
1159
|
const result = await reader.read();
|
|
1117
1160
|
if (result.done) {
|
|
1118
1161
|
if (hasDeferred) {
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1162
|
+
let resolvedData;
|
|
1163
|
+
try {
|
|
1164
|
+
resolvedData = await Promise.race([
|
|
1165
|
+
resolveAllDeferred2(loaderData),
|
|
1166
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error("Deferred data resolution timed out")), 1e4))
|
|
1167
|
+
]);
|
|
1168
|
+
} catch (error) {
|
|
1169
|
+
console.error("Deferred data resolution failed:", error);
|
|
1170
|
+
resolvedData = null;
|
|
1171
|
+
}
|
|
1172
|
+
controller.enqueue(encoder.encode(`<script>window.__EREO_DATA__=${serializeLoaderData2(resolvedData)}</script>`));
|
|
1173
|
+
} else if (loaderScript) {
|
|
1174
|
+
controller.enqueue(loaderScript);
|
|
1125
1175
|
}
|
|
1176
|
+
clearTimeout(timeoutId);
|
|
1126
1177
|
controller.close();
|
|
1127
1178
|
done = true;
|
|
1128
1179
|
} else {
|
|
@@ -1131,6 +1182,7 @@ class BunServer {
|
|
|
1131
1182
|
},
|
|
1132
1183
|
cancel() {
|
|
1133
1184
|
reader.cancel();
|
|
1185
|
+
clearTimeout(timeoutId);
|
|
1134
1186
|
}
|
|
1135
1187
|
});
|
|
1136
1188
|
return new Response(stream, {
|
|
@@ -1140,6 +1192,7 @@ class BunServer {
|
|
|
1140
1192
|
}
|
|
1141
1193
|
});
|
|
1142
1194
|
} catch (error) {
|
|
1195
|
+
clearTimeout(timeoutId);
|
|
1143
1196
|
console.error("Streaming render failed:", error);
|
|
1144
1197
|
return this.renderStringPageDirect(element, loaderData);
|
|
1145
1198
|
}
|
|
@@ -1443,7 +1496,6 @@ export {
|
|
|
1443
1496
|
logger,
|
|
1444
1497
|
getMimeType,
|
|
1445
1498
|
enforceAuthConfig,
|
|
1446
|
-
createSuspenseStream,
|
|
1447
1499
|
createShell,
|
|
1448
1500
|
createServer,
|
|
1449
1501
|
createResponse,
|
package/dist/streaming.d.ts
CHANGED
|
@@ -69,6 +69,13 @@ export declare function createShell(options: {
|
|
|
69
69
|
/**
|
|
70
70
|
* Render a route to a streaming response.
|
|
71
71
|
* Uses renderToPipeableStream for Node.js/Bun environments.
|
|
72
|
+
*
|
|
73
|
+
* Returns a ReadableStream body that progressively sends:
|
|
74
|
+
* shell head → React content (with $RC scripts for Suspense) → tail
|
|
75
|
+
*
|
|
76
|
+
* Deferred data is NOT resolved upfront — React streams Suspense fallbacks
|
|
77
|
+
* and resolves them out-of-order via inline $RC scripts. Loader data is
|
|
78
|
+
* serialized into the tail only after all Suspense boundaries resolve.
|
|
72
79
|
*/
|
|
73
80
|
export declare function renderToStream(element: ReactElement, options: RenderOptions): Promise<RenderResult>;
|
|
74
81
|
/**
|
|
@@ -79,12 +86,4 @@ export declare function renderToString(element: ReactElement, options: RenderOpt
|
|
|
79
86
|
* Create a Response from render result.
|
|
80
87
|
*/
|
|
81
88
|
export declare function createResponse(result: RenderResult): Response;
|
|
82
|
-
/**
|
|
83
|
-
* Stream helper for sending chunks with delays (Suspense boundaries).
|
|
84
|
-
*/
|
|
85
|
-
export declare function createSuspenseStream(): {
|
|
86
|
-
stream: ReadableStream<Uint8Array>;
|
|
87
|
-
push: (chunk: string) => void;
|
|
88
|
-
close: () => void;
|
|
89
|
-
};
|
|
90
89
|
//# sourceMappingURL=streaming.d.ts.map
|
package/dist/streaming.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"streaming.d.ts","sourceRoot":"","sources":["../src/streaming.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,KAAK,EAAS,UAAU,EAAE,UAAU,EAAkB,cAAc,EAAE,MAAM,YAAY,CAAC;AAGhG;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,kBAAkB;IAClB,KAAK,EAAE,UAAU,CAAC;IAClB,sBAAsB;IACtB,OAAO,EAAE,UAAU,CAAC;IACpB,qBAAqB;IACrB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,uBAAuB;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,wBAAwB;IACxB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,kBAAkB;IAClB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB;IAChB,IAAI,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpE,uDAAuD;IACvD,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IACzB,mBAAmB;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,sBAAsB;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,6BAA6B;IAC7B,IAAI,EAAE,MAAM,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IAC1C,uBAAuB;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE;IACnC,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CA8DjC;AAED
|
|
1
|
+
{"version":3,"file":"streaming.d.ts","sourceRoot":"","sources":["../src/streaming.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,KAAK,EAAS,UAAU,EAAE,UAAU,EAAkB,cAAc,EAAE,MAAM,YAAY,CAAC;AAGhG;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,kBAAkB;IAClB,KAAK,EAAE,UAAU,CAAC;IAClB,sBAAsB;IACtB,OAAO,EAAE,UAAU,CAAC;IACpB,qBAAqB;IACrB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,uBAAuB;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,wBAAwB;IACxB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,kBAAkB;IAClB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB;IAChB,IAAI,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpE,uDAAuD;IACvD,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IACzB,mBAAmB;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,sBAAsB;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,6BAA6B;IAC7B,IAAI,EAAE,MAAM,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IAC1C,uBAAuB;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE;IACnC,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CA8DjC;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,YAAY,CAAC,CAuHvB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,YAAY,CAAC,CAgCvB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,QAAQ,CAK7D"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ereo/server",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Ereo Team",
|
|
6
6
|
"homepage": "https://ereojs.github.io/ereoJS",
|
|
@@ -32,10 +32,10 @@
|
|
|
32
32
|
"typecheck": "tsc --noEmit"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@ereo/core": "^0.2.
|
|
36
|
-
"@ereo/client": "^0.2.
|
|
37
|
-
"@ereo/router": "^0.2.
|
|
38
|
-
"@ereo/data": "^0.2.
|
|
35
|
+
"@ereo/core": "^0.2.7",
|
|
36
|
+
"@ereo/client": "^0.2.7",
|
|
37
|
+
"@ereo/router": "^0.2.7",
|
|
38
|
+
"@ereo/data": "^0.2.7"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/bun": "^1.1.0",
|