@absolutejs/absolute 0.19.0-beta.808 → 0.19.0-beta.809
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/angular/browser.js +9801 -57
- package/dist/angular/browser.js.map +246 -4
- package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
- package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
- package/dist/angular/index.js +14877 -60
- package/dist/angular/index.js.map +281 -4
- package/dist/angular/server.js +5610 -45
- package/dist/angular/server.js.map +51 -3
- package/dist/build.js +18092 -45
- package/dist/build.js.map +99 -3
- package/dist/cli/index.js +317 -86
- package/dist/client/index.js +1100 -40
- package/dist/client/index.js.map +24 -4
- package/dist/core/streamingSlotRegistrar.js +108 -11
- package/dist/core/streamingSlotRegistrar.js.map +4 -3
- package/dist/core/streamingSlotRegistry.js +169 -7
- package/dist/core/streamingSlotRegistry.js.map +5 -3
- package/dist/index.js +19957 -547
- package/dist/index.js.map +116 -3
- package/dist/islands/browser.js +228 -9
- package/dist/islands/browser.js.map +9 -4
- package/dist/islands/index.js +1908 -17
- package/dist/islands/index.js.map +27 -3
- package/dist/react/browser.js +328 -12
- package/dist/react/browser.js.map +12 -4
- package/dist/react/components/index.js +167 -16
- package/dist/react/components/index.js.map +6 -3
- package/dist/react/hooks/index.js +183 -8
- package/dist/react/hooks/index.js.map +7 -3
- package/dist/react/index.js +3627 -36
- package/dist/react/index.js.map +45 -4
- package/dist/react/jsxDevRuntimeCompat.js +61 -2
- package/dist/react/jsxDevRuntimeCompat.js.map +2 -2
- package/dist/react/server.js +1789 -18
- package/dist/react/server.js.map +21 -3
- package/dist/src/angular/injectorPatch.d.ts +1 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/svelte/browser.js +247 -12
- package/dist/svelte/browser.js.map +10 -3
- package/dist/svelte/index.js +3732 -37
- package/dist/svelte/index.js.map +47 -4
- package/dist/svelte/server.js +2794 -21
- package/dist/svelte/server.js.map +27 -3
- package/dist/vue/browser.js +348 -12
- package/dist/vue/browser.js.map +12 -4
- package/dist/vue/components/Image.js +240 -7
- package/dist/vue/components/Image.js.map +6 -3
- package/dist/vue/components/index.js +544 -11
- package/dist/vue/components/index.js.map +9 -3
- package/dist/vue/index.js +4212 -52
- package/dist/vue/index.js.map +50 -4
- package/dist/vue/server.js +1849 -18
- package/dist/vue/server.js.map +21 -3
- package/package.json +1 -1
- package/dist/chunk-0867j0r0.js +0 -136
- package/dist/chunk-0867j0r0.js.map +0 -10
- package/dist/chunk-0kdc6r16.js +0 -20
- package/dist/chunk-0kdc6r16.js.map +0 -10
- package/dist/chunk-102fp7xe.js +0 -63
- package/dist/chunk-102fp7xe.js.map +0 -10
- package/dist/chunk-11zpfqz6.js +0 -19
- package/dist/chunk-11zpfqz6.js.map +0 -10
- package/dist/chunk-1rfh7hw9.js +0 -319
- package/dist/chunk-1rfh7hw9.js.map +0 -11
- package/dist/chunk-25v9t56f.js +0 -29
- package/dist/chunk-25v9t56f.js.map +0 -11
- package/dist/chunk-2f21eenc.js +0 -21
- package/dist/chunk-2f21eenc.js.map +0 -10
- package/dist/chunk-2ga2znex.js +0 -13
- package/dist/chunk-2ga2znex.js.map +0 -9
- package/dist/chunk-30yrw0f6.js +0 -33
- package/dist/chunk-30yrw0f6.js.map +0 -10
- package/dist/chunk-38jwhqcw.js +0 -4410
- package/dist/chunk-38jwhqcw.js.map +0 -28
- package/dist/chunk-3g91wb4f.js +0 -358
- package/dist/chunk-3g91wb4f.js.map +0 -10
- package/dist/chunk-3yjzpcne.js +0 -34
- package/dist/chunk-3yjzpcne.js.map +0 -10
- package/dist/chunk-41bf6aqt.js +0 -17
- package/dist/chunk-41bf6aqt.js.map +0 -9
- package/dist/chunk-4d39r92n.js +0 -81
- package/dist/chunk-4d39r92n.js.map +0 -10
- package/dist/chunk-5003emhv.js +0 -17
- package/dist/chunk-5003emhv.js.map +0 -10
- package/dist/chunk-5f67rsed.js +0 -466
- package/dist/chunk-5f67rsed.js.map +0 -10
- package/dist/chunk-5fhp1jap.js +0 -9169
- package/dist/chunk-5fhp1jap.js.map +0 -236
- package/dist/chunk-6pdj08z3.js +0 -73
- package/dist/chunk-6pdj08z3.js.map +0 -12
- package/dist/chunk-6qjbrt0k.js +0 -13
- package/dist/chunk-6qjbrt0k.js.map +0 -9
- package/dist/chunk-6sccb4jr.js +0 -14
- package/dist/chunk-6sccb4jr.js.map +0 -9
- package/dist/chunk-798spvzv.js +0 -50
- package/dist/chunk-798spvzv.js.map +0 -10
- package/dist/chunk-7fw6x3js.js +0 -131
- package/dist/chunk-7fw6x3js.js.map +0 -11
- package/dist/chunk-7kjj42xm.js +0 -11
- package/dist/chunk-7kjj42xm.js.map +0 -10
- package/dist/chunk-7mtstdqn.js +0 -90
- package/dist/chunk-7mtstdqn.js.map +0 -10
- package/dist/chunk-851whwc7.js +0 -17
- package/dist/chunk-851whwc7.js.map +0 -10
- package/dist/chunk-85n68sy6.js +0 -103
- package/dist/chunk-85n68sy6.js.map +0 -10
- package/dist/chunk-8kcfffry.js +0 -35
- package/dist/chunk-8kcfffry.js.map +0 -10
- package/dist/chunk-8qqxc1h2.js +0 -426
- package/dist/chunk-8qqxc1h2.js.map +0 -14
- package/dist/chunk-92fsjfpp.js +0 -1731
- package/dist/chunk-92fsjfpp.js.map +0 -11
- package/dist/chunk-93sqk7be.js +0 -139
- package/dist/chunk-93sqk7be.js.map +0 -12
- package/dist/chunk-94gvx0hg.js +0 -28
- package/dist/chunk-94gvx0hg.js.map +0 -10
- package/dist/chunk-9c5tj4k3.js +0 -130
- package/dist/chunk-9c5tj4k3.js.map +0 -10
- package/dist/chunk-9ve9jq72.js +0 -203
- package/dist/chunk-9ve9jq72.js.map +0 -10
- package/dist/chunk-9xrsjeem.js +0 -12
- package/dist/chunk-9xrsjeem.js.map +0 -9
- package/dist/chunk-a9mvyp04.js +0 -87
- package/dist/chunk-a9mvyp04.js.map +0 -10
- package/dist/chunk-b3gbnrwe.js +0 -21
- package/dist/chunk-b3gbnrwe.js.map +0 -10
- package/dist/chunk-bmgqm774.js +0 -65
- package/dist/chunk-bmgqm774.js.map +0 -9
- package/dist/chunk-bxfghpma.js +0 -69
- package/dist/chunk-bxfghpma.js.map +0 -10
- package/dist/chunk-c1jfjnka.js +0 -74
- package/dist/chunk-c1jfjnka.js.map +0 -10
- package/dist/chunk-cbkrwmvh.js +0 -80
- package/dist/chunk-cbkrwmvh.js.map +0 -10
- package/dist/chunk-cdxd7sy2.js +0 -71
- package/dist/chunk-cdxd7sy2.js.map +0 -10
- package/dist/chunk-cg95827x.js +0 -21
- package/dist/chunk-cg95827x.js.map +0 -10
- package/dist/chunk-cm0g4q6w.js +0 -149
- package/dist/chunk-cm0g4q6w.js.map +0 -10
- package/dist/chunk-cwfy538a.js +0 -51
- package/dist/chunk-cwfy538a.js.map +0 -9
- package/dist/chunk-d7mwkzry.js +0 -261
- package/dist/chunk-d7mwkzry.js.map +0 -10
- package/dist/chunk-d8w0qm28.js +0 -184
- package/dist/chunk-d8w0qm28.js.map +0 -11
- package/dist/chunk-d9c0am65.js +0 -12
- package/dist/chunk-d9c0am65.js.map +0 -10
- package/dist/chunk-daqghmg8.js +0 -12
- package/dist/chunk-daqghmg8.js.map +0 -9
- package/dist/chunk-e3r9fxaa.js +0 -149
- package/dist/chunk-e3r9fxaa.js.map +0 -10
- package/dist/chunk-e8eecyrq.js +0 -244
- package/dist/chunk-e8eecyrq.js.map +0 -10
- package/dist/chunk-ex2hxe0v.js +0 -160
- package/dist/chunk-ex2hxe0v.js.map +0 -11
- package/dist/chunk-fak944et.js +0 -91
- package/dist/chunk-fak944et.js.map +0 -10
- package/dist/chunk-ff70rnhd.js +0 -672
- package/dist/chunk-ff70rnhd.js.map +0 -15
- package/dist/chunk-fygx2ymm.js +0 -118
- package/dist/chunk-fygx2ymm.js.map +0 -12
- package/dist/chunk-g15qj669.js +0 -271
- package/dist/chunk-g15qj669.js.map +0 -11
- package/dist/chunk-gd6wmknh.js +0 -121
- package/dist/chunk-gd6wmknh.js.map +0 -11
- package/dist/chunk-gf0ygptk.js +0 -85
- package/dist/chunk-gf0ygptk.js.map +0 -11
- package/dist/chunk-gytkmthr.js +0 -220
- package/dist/chunk-gytkmthr.js.map +0 -10
- package/dist/chunk-h5bbfn3n.js +0 -28
- package/dist/chunk-h5bbfn3n.js.map +0 -11
- package/dist/chunk-h6mye9r3.js +0 -93
- package/dist/chunk-h6mye9r3.js.map +0 -10
- package/dist/chunk-hcsmxw1v.js +0 -85
- package/dist/chunk-hcsmxw1v.js.map +0 -10
- package/dist/chunk-hyjs4bqs.js +0 -8
- package/dist/chunk-hyjs4bqs.js.map +0 -10
- package/dist/chunk-j88z31ep.js +0 -25
- package/dist/chunk-j88z31ep.js.map +0 -10
- package/dist/chunk-jn91vzkh.js +0 -66
- package/dist/chunk-jn91vzkh.js.map +0 -10
- package/dist/chunk-jpkjdgsk.js +0 -167
- package/dist/chunk-jpkjdgsk.js.map +0 -11
- package/dist/chunk-jwxt8gnp.js +0 -13
- package/dist/chunk-jwxt8gnp.js.map +0 -9
- package/dist/chunk-kk8w9rh5.js +0 -195
- package/dist/chunk-kk8w9rh5.js.map +0 -10
- package/dist/chunk-m97ze5hz.js +0 -46
- package/dist/chunk-m97ze5hz.js.map +0 -10
- package/dist/chunk-mbazhahf.js +0 -60
- package/dist/chunk-mbazhahf.js.map +0 -10
- package/dist/chunk-mgfwq18r.js +0 -15
- package/dist/chunk-mgfwq18r.js.map +0 -9
- package/dist/chunk-mtgf69xn.js +0 -88
- package/dist/chunk-mtgf69xn.js.map +0 -10
- package/dist/chunk-mtxzyxpg.js +0 -102
- package/dist/chunk-mtxzyxpg.js.map +0 -10
- package/dist/chunk-nehhtthw.js +0 -225
- package/dist/chunk-nehhtthw.js.map +0 -10
- package/dist/chunk-p5504p14.js +0 -16
- package/dist/chunk-p5504p14.js.map +0 -10
- package/dist/chunk-pnscgw95.js +0 -90
- package/dist/chunk-pnscgw95.js.map +0 -10
- package/dist/chunk-pvpp4pvs.js +0 -17
- package/dist/chunk-pvpp4pvs.js.map +0 -10
- package/dist/chunk-qh75agse.js +0 -95
- package/dist/chunk-qh75agse.js.map +0 -10
- package/dist/chunk-qxq2zcty.js +0 -52
- package/dist/chunk-qxq2zcty.js.map +0 -10
- package/dist/chunk-r6e8pytx.js +0 -22
- package/dist/chunk-r6e8pytx.js.map +0 -9
- package/dist/chunk-r7jmgqnw.js +0 -114
- package/dist/chunk-r7jmgqnw.js.map +0 -10
- package/dist/chunk-s6defjk2.js +0 -116
- package/dist/chunk-s6defjk2.js.map +0 -10
- package/dist/chunk-sd39p726.js +0 -619
- package/dist/chunk-sd39p726.js.map +0 -10
- package/dist/chunk-swrnzs4c.js +0 -63
- package/dist/chunk-swrnzs4c.js.map +0 -10
- package/dist/chunk-tfe3sb44.js +0 -33
- package/dist/chunk-tfe3sb44.js.map +0 -10
- package/dist/chunk-tjr0kcev.js +0 -41
- package/dist/chunk-tjr0kcev.js.map +0 -9
- package/dist/chunk-tx9edm1x.js +0 -34
- package/dist/chunk-tx9edm1x.js.map +0 -10
- package/dist/chunk-txhm2vb5.js +0 -18
- package/dist/chunk-txhm2vb5.js.map +0 -9
- package/dist/chunk-v5vmsxmy.js +0 -526
- package/dist/chunk-v5vmsxmy.js.map +0 -12
- package/dist/chunk-vjhxm8n2.js +0 -29
- package/dist/chunk-vjhxm8n2.js.map +0 -9
- package/dist/chunk-vkrpm7kc.js +0 -247
- package/dist/chunk-vkrpm7kc.js.map +0 -12
- package/dist/chunk-w3m4m5we.js +0 -4925
- package/dist/chunk-w3m4m5we.js.map +0 -12
- package/dist/chunk-wrxtn9ve.js +0 -18
- package/dist/chunk-wrxtn9ve.js.map +0 -10
- package/dist/chunk-wwzvp0zn.js +0 -192
- package/dist/chunk-wwzvp0zn.js.map +0 -10
- package/dist/chunk-x09cskqd.js +0 -377
- package/dist/chunk-x09cskqd.js.map +0 -10
- package/dist/chunk-xnt8c6h2.js +0 -576
- package/dist/chunk-xnt8c6h2.js.map +0 -10
- package/dist/chunk-xw0tx842.js +0 -13
- package/dist/chunk-xw0tx842.js.map +0 -9
- package/dist/chunk-xx5b6b9m.js +0 -69
- package/dist/chunk-xx5b6b9m.js.map +0 -10
- package/dist/chunk-xz1kdswj.js +0 -21
- package/dist/chunk-xz1kdswj.js.map +0 -9
- package/dist/chunk-y84qnsd3.js +0 -32
- package/dist/chunk-y84qnsd3.js.map +0 -10
- package/dist/chunk-ywjn0rad.js +0 -14
- package/dist/chunk-ywjn0rad.js.map +0 -9
- package/dist/chunk-z9nvhm6r.js +0 -13
- package/dist/chunk-z9nvhm6r.js.map +0 -9
- package/dist/chunk-zhmvdpk6.js +0 -15
- package/dist/chunk-zhmvdpk6.js.map +0 -9
- package/dist/chunk-zrg9d4zw.js +0 -784
- package/dist/chunk-zrg9d4zw.js.map +0 -10
package/dist/vue/server.js
CHANGED
|
@@ -1,24 +1,1855 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
function __accessProp(key) {
|
|
8
|
+
return this[key];
|
|
9
|
+
}
|
|
10
|
+
var __toESMCache_node;
|
|
11
|
+
var __toESMCache_esm;
|
|
12
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
13
|
+
var canCache = mod != null && typeof mod === "object";
|
|
14
|
+
if (canCache) {
|
|
15
|
+
var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
|
|
16
|
+
var cached = cache.get(mod);
|
|
17
|
+
if (cached)
|
|
18
|
+
return cached;
|
|
19
|
+
}
|
|
20
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
21
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
22
|
+
for (let key of __getOwnPropNames(mod))
|
|
23
|
+
if (!__hasOwnProp.call(to, key))
|
|
24
|
+
__defProp(to, key, {
|
|
25
|
+
get: __accessProp.bind(mod, key),
|
|
26
|
+
enumerable: true
|
|
27
|
+
});
|
|
28
|
+
if (canCache)
|
|
29
|
+
cache.set(mod, to);
|
|
30
|
+
return to;
|
|
31
|
+
};
|
|
32
|
+
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
33
|
+
var __returnValue = (v) => v;
|
|
34
|
+
function __exportSetter(name, newValue) {
|
|
35
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
36
|
+
}
|
|
37
|
+
var __export = (target, all) => {
|
|
38
|
+
for (var name in all)
|
|
39
|
+
__defProp(target, name, {
|
|
40
|
+
get: all[name],
|
|
41
|
+
enumerable: true,
|
|
42
|
+
configurable: true,
|
|
43
|
+
set: __exportSetter.bind(all, name)
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
var __legacyDecorateClassTS = function(decorators, target, key, desc) {
|
|
47
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
48
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
49
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
50
|
+
else
|
|
51
|
+
for (var i = decorators.length - 1;i >= 0; i--)
|
|
52
|
+
if (d = decorators[i])
|
|
53
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
54
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
55
|
+
};
|
|
56
|
+
var __legacyMetadataTS = (k, v) => {
|
|
57
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
|
|
58
|
+
return Reflect.metadata(k, v);
|
|
59
|
+
};
|
|
60
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
61
|
+
var __require = import.meta.require;
|
|
62
|
+
|
|
63
|
+
// src/constants.ts
|
|
64
|
+
var ANGULAR_INIT_TIMEOUT_MS = 500, ANSI_ESCAPE_CODE = 27, ANSI_ESCAPE_LENGTH = 3, ASCII_SPACE = 32, BASE_36_RADIX = 36, BUN_BUILD_WARNING_SUPPRESSION = "wildcard sideEffects are not supported yet", BODY_SLICE_LENGTH = 2000, BYTES_PER_KILOBYTE = 1024, CLI_ARGS_OFFSET = 3, CSS_ERROR_RESOLVE_DELAY_MS = 50, CSS_MAX_CHECK_ATTEMPTS = 10, CSS_MAX_PARSE_TIMEOUT_MS = 500, CSS_SHEET_READY_TIMEOUT_MS = 100, DEFAULT_CHUNK_SIZE = 16384, DEFAULT_DEBOUNCE_MS = 15, DEFAULT_PORT = 3000, DEV_SERVER_RESTART_DEBOUNCE_MS = 100, DOM_UPDATE_DELAY_MS = 50, FILE_PROTOCOL_PREFIX_LENGTH = 7, FOCUS_ID_PREFIX_LENGTH = 3, FOCUS_IDX_PREFIX_LENGTH = 4, FOCUS_NAME_PREFIX_LENGTH = 5, HMR_UPDATE_TIMEOUT_MS = 2000, HOOK_SIGNATURE_LENGTH = 12, EXCLUDE_LAST_OFFSET = -1, HTTP_STATUS_OK = 200, HTTP_STATUS_BAD_REQUEST = 400, HTTP_STATUS_NOT_FOUND = 404, HOURS_IN_DAY = 24, HOURS_IN_HALF_DAY = 12, IMAGE_DEFAULT_DEVICE_SIZES, IMAGE_DEFAULT_IMAGE_SIZES, IMAGE_DEFAULT_QUALITY = 75, IMAGE_GLOB_SUFFIX_LENGTH = 2, MAX_ERROR_LENGTH = 200, MAX_RECONNECT_ATTEMPTS = 60, MILLISECONDS_IN_A_SECOND = 1000, MINUTES_IN_AN_HOUR = 60, SECONDS_IN_A_MINUTE = 60, MILLISECONDS_IN_A_MINUTE, MILLISECONDS_IN_A_DAY, OVERLAY_FADE_DURATION_MS = 150, PING_INTERVAL_MS = 30000, RAF_BATCH_COUNT = 3, RANDOM_ID_END_INDEX = 11, REBUILD_BATCH_DELAY_MS = 10, REBUILD_RELOAD_DELAY_MS = 200, RECONNECT_INITIAL_DELAY_MS = 500, RECONNECT_POLL_INTERVAL_MS = 300, REACT_STREAM_SLOT_FAST_DELAY_MS = 5, REACT_STREAM_SLOT_SLOW_DELAY_MS = 20, SIGINT_EXIT_CODE = 130, SIGTERM_EXIT_CODE = 143, SVELTE_CSS_LOAD_TIMEOUT_MS = 500, TIME_PRECISION = 2, TWO_THIRDS, UNFOUND_INDEX = -1, WEBSOCKET_NORMAL_CLOSURE = 1000, WORKSPACE_COMMAND_ARGS_OFFSET = 3, WORKSPACE_FAILURE_LOG_PRINT_LIMIT = 30, WORKSPACE_FAILURE_RECENT_LOG_LIMIT = 60, WORKSPACE_READY_ATTEMPT_TIMEOUT_MS = 5000, WORKSPACE_READY_PROBE_INTERVAL_MS = 250, WORKSPACE_READY_TIMEOUT_MS = 30000, WORKSPACE_SHUTDOWN_TIMEOUT_MS = 1e4, WORKSPACE_TUI_DEFAULT_HEIGHT = 28, WORKSPACE_TUI_DEFAULT_WIDTH = 100, WORKSPACE_TUI_ESCAPE_SEQUENCE_TIMEOUT_MS = 30, WORKSPACE_TUI_FOOTER_LINE_COUNT = 3, WORKSPACE_TUI_MIN_LOG_HEIGHT = 3, WORKSPACE_TUI_MIN_SERVICE_NAME_WIDTH = 7, WORKSPACE_TUI_MIN_TARGET_WIDTH = 8, WORKSPACE_TUI_MIN_WRAP_WIDTH = 12, WORKSPACE_TUI_PROMPT_CURSOR_OFFSET = 3, WORKSPACE_TUI_RECENT_LOG_LIMIT = 40, WORKSPACE_TUI_RENDER_DEBOUNCE_MS = 16, WORKSPACE_TUI_STATUS_WIDTH = 10, WORKSPACE_TUI_TARGET_PADDING_WIDTH = 6, WORKSPACE_TUI_VISIBILITY_WIDTH = 8;
|
|
65
|
+
var init_constants = __esm(() => {
|
|
66
|
+
IMAGE_DEFAULT_DEVICE_SIZES = [
|
|
67
|
+
640,
|
|
68
|
+
750,
|
|
69
|
+
828,
|
|
70
|
+
1080,
|
|
71
|
+
1200,
|
|
72
|
+
1920,
|
|
73
|
+
2048,
|
|
74
|
+
3840
|
|
75
|
+
];
|
|
76
|
+
IMAGE_DEFAULT_IMAGE_SIZES = [16, 32, 48, 64, 96, 128, 256, 384];
|
|
77
|
+
MILLISECONDS_IN_A_MINUTE = MILLISECONDS_IN_A_SECOND * SECONDS_IN_A_MINUTE;
|
|
78
|
+
MILLISECONDS_IN_A_DAY = MILLISECONDS_IN_A_SECOND * SECONDS_IN_A_MINUTE * MINUTES_IN_AN_HOUR * HOURS_IN_DAY;
|
|
79
|
+
TWO_THIRDS = 2 / 3;
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// src/core/devRouteRegistrationCallsite.ts
|
|
83
|
+
var exports_devRouteRegistrationCallsite = {};
|
|
84
|
+
__export(exports_devRouteRegistrationCallsite, {
|
|
85
|
+
patchElysiaRouteRegistrationCallsites: () => patchElysiaRouteRegistrationCallsites,
|
|
86
|
+
getCurrentRouteRegistrationCallsite: () => getCurrentRouteRegistrationCallsite
|
|
87
|
+
});
|
|
88
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
89
|
+
import { Elysia } from "elysia";
|
|
90
|
+
var ROUTE_CALLSITE_STORAGE_KEY, ROUTE_CALLSITE_PATCHED_KEY, ROUTE_METHOD_NAMES, isObjectRecord3 = (value) => Boolean(value) && typeof value === "object", isAsyncLocalStorage2 = (value) => isObjectRecord3(value) && ("getStore" in value) && typeof value.getStore === "function" && ("run" in value) && typeof value.run === "function", isRouteMethod = (value) => typeof value === "function", getRouteCallsiteStorage = () => {
|
|
91
|
+
const value = Reflect.get(globalThis, ROUTE_CALLSITE_STORAGE_KEY);
|
|
92
|
+
if (value === null || typeof value === "undefined") {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
return isAsyncLocalStorage2(value) ? value : undefined;
|
|
96
|
+
}, ensureRouteCallsiteStorage = () => {
|
|
97
|
+
const existing = getRouteCallsiteStorage();
|
|
98
|
+
if (existing) {
|
|
99
|
+
return existing;
|
|
100
|
+
}
|
|
101
|
+
const storage = new AsyncLocalStorage;
|
|
102
|
+
Reflect.set(globalThis, ROUTE_CALLSITE_STORAGE_KEY, storage);
|
|
103
|
+
return storage;
|
|
104
|
+
}, normalizeCallsitePath = (value) => value.replace(`${process.cwd()}/`, "").replace(process.cwd(), "").replace(/^\.\/+/, ""), shouldIgnoreRouteCallsiteFrame = (frame) => frame.includes("/node_modules/") || frame.includes("/dist/") || frame.includes("/src/core/devRouteRegistrationCallsite."), getRouteCallsiteLocation = (frame) => frame.match(/\((\/[^)]+:\d+:\d+)\)$/)?.[1] ?? frame.match(/at (\/[^ ]+:\d+:\d+)$/)?.[1], extractRouteRegistrationCallsite = (stack) => {
|
|
105
|
+
const location = stack.split(`
|
|
106
|
+
`).slice(1).map((line) => line.trim()).filter((frame) => !shouldIgnoreRouteCallsiteFrame(frame)).map((frame) => getRouteCallsiteLocation(frame)).find((frameLocation) => frameLocation !== undefined);
|
|
107
|
+
return location ? normalizeCallsitePath(location) : undefined;
|
|
108
|
+
}, captureRouteRegistrationCallsite = () => {
|
|
109
|
+
const { stack } = new Error;
|
|
110
|
+
if (!stack) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
return extractRouteRegistrationCallsite(stack);
|
|
114
|
+
}, wrapRouteHandlerWithCallsite = (handler, callsite) => {
|
|
115
|
+
if (typeof handler !== "function" || !callsite) {
|
|
116
|
+
return handler;
|
|
117
|
+
}
|
|
118
|
+
const storage = ensureRouteCallsiteStorage();
|
|
119
|
+
const routeHandler = handler;
|
|
120
|
+
return function wrappedRouteHandler(...args) {
|
|
121
|
+
return storage.run({ callsite }, () => Reflect.apply(routeHandler, this, args));
|
|
122
|
+
};
|
|
123
|
+
}, createPatchedRouteMethod = (originalMethod) => function patchedRouteMethod(path, handler, ...rest) {
|
|
124
|
+
const callsite = captureRouteRegistrationCallsite();
|
|
125
|
+
return Reflect.apply(originalMethod, this, [
|
|
126
|
+
path,
|
|
127
|
+
wrapRouteHandlerWithCallsite(handler, callsite),
|
|
128
|
+
...rest
|
|
129
|
+
]);
|
|
130
|
+
}, getCurrentRouteRegistrationCallsite = () => getRouteCallsiteStorage()?.getStore()?.callsite, patchElysiaRouteRegistrationCallsites = () => {
|
|
131
|
+
if (false) {}
|
|
132
|
+
if (Reflect.get(globalThis, ROUTE_CALLSITE_PATCHED_KEY) === true) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const { prototype } = Elysia;
|
|
136
|
+
ROUTE_METHOD_NAMES.forEach((methodName) => {
|
|
137
|
+
const originalMethod = Reflect.get(prototype, methodName);
|
|
138
|
+
if (!isRouteMethod(originalMethod))
|
|
139
|
+
return;
|
|
140
|
+
Reflect.set(prototype, methodName, createPatchedRouteMethod(originalMethod));
|
|
141
|
+
});
|
|
142
|
+
Reflect.set(globalThis, ROUTE_CALLSITE_PATCHED_KEY, true);
|
|
143
|
+
};
|
|
144
|
+
var init_devRouteRegistrationCallsite = __esm(() => {
|
|
145
|
+
ROUTE_CALLSITE_STORAGE_KEY = Symbol.for("absolutejs.devRouteRegistrationCallsiteStorage");
|
|
146
|
+
ROUTE_CALLSITE_PATCHED_KEY = Symbol.for("absolutejs.devRouteRegistrationCallsitePatched");
|
|
147
|
+
ROUTE_METHOD_NAMES = [
|
|
148
|
+
"all",
|
|
149
|
+
"delete",
|
|
150
|
+
"get",
|
|
151
|
+
"head",
|
|
152
|
+
"options",
|
|
153
|
+
"patch",
|
|
154
|
+
"post",
|
|
155
|
+
"put"
|
|
156
|
+
];
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// src/client/streamSwap.ts
|
|
160
|
+
var streamSwapRuntime = () => {
|
|
161
|
+
const absoluteWindow = window;
|
|
162
|
+
const SLOT_PATCH_EVENT = "absolutejs:slot-patch";
|
|
163
|
+
if (absoluteWindow.__ABS_SLOT_RUNTIME__ === true)
|
|
164
|
+
return;
|
|
165
|
+
absoluteWindow.__ABS_SLOT_RUNTIME__ = true;
|
|
166
|
+
absoluteWindow.__ABS_SLOT_CONSUMERS__ = absoluteWindow.__ABS_SLOT_CONSUMERS__ ?? {};
|
|
167
|
+
absoluteWindow.__ABS_SLOT_PENDING__ = absoluteWindow.__ABS_SLOT_PENDING__ ?? {};
|
|
168
|
+
const consumers = absoluteWindow.__ABS_SLOT_CONSUMERS__;
|
|
169
|
+
const pending = absoluteWindow.__ABS_SLOT_PENDING__;
|
|
170
|
+
const isObjectRecord4 = (value) => Boolean(value) && typeof value === "object";
|
|
171
|
+
const isPatchedPendingEntry = (value) => {
|
|
172
|
+
if (!isObjectRecord4(value))
|
|
173
|
+
return false;
|
|
174
|
+
return value.domPatched === true && "payload" in value;
|
|
175
|
+
};
|
|
176
|
+
const unwrapPendingPayload = (value) => isPatchedPendingEntry(value) ? value.payload : value;
|
|
177
|
+
const canApplyImmediately = () => absoluteWindow.__ABS_SLOT_HYDRATION_PENDING__ !== true;
|
|
178
|
+
const isAngularDeferPayload = (payload) => {
|
|
179
|
+
if (!isObjectRecord4(payload))
|
|
180
|
+
return false;
|
|
181
|
+
return payload.kind === "angular-defer";
|
|
182
|
+
};
|
|
183
|
+
const isVueSuspensePayload = (payload) => {
|
|
184
|
+
if (!isObjectRecord4(payload))
|
|
185
|
+
return false;
|
|
186
|
+
return payload.kind === "vue-suspense";
|
|
187
|
+
};
|
|
188
|
+
const resolveHtml = (payload) => {
|
|
189
|
+
if (!isObjectRecord4(payload)) {
|
|
190
|
+
return typeof payload === "string" ? payload : "";
|
|
191
|
+
}
|
|
192
|
+
if (typeof payload.html === "string") {
|
|
193
|
+
return payload.html;
|
|
194
|
+
}
|
|
195
|
+
return "";
|
|
196
|
+
};
|
|
197
|
+
const apply = (id, pendingEntry) => {
|
|
198
|
+
const payload = unwrapPendingPayload(pendingEntry);
|
|
199
|
+
if (!canApplyImmediately()) {
|
|
200
|
+
pending[id] = payload;
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const consumer = consumers[id];
|
|
204
|
+
if (typeof consumer !== "function") {
|
|
205
|
+
applyToDom(id, payload, pendingEntry);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
const handled = consumer(payload);
|
|
209
|
+
if (handled !== false) {
|
|
210
|
+
delete pending[id];
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
applyToDom(id, payload, pendingEntry);
|
|
214
|
+
};
|
|
215
|
+
const applyToDom = (id, payload, pendingEntry) => {
|
|
216
|
+
if (isAngularDeferPayload(payload)) {
|
|
217
|
+
pending[id] = payload;
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const node = document.getElementById(id);
|
|
221
|
+
if (!node) {
|
|
222
|
+
pending[id] = payload;
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
const html = resolveHtml(payload);
|
|
226
|
+
if (isVueSuspensePayload(payload) && isPatchedPendingEntry(pendingEntry)) {
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
node.innerHTML = html;
|
|
230
|
+
node.setAttribute("data-absolute-slot-state", "resolved");
|
|
231
|
+
window.dispatchEvent(new CustomEvent(SLOT_PATCH_EVENT, {
|
|
232
|
+
detail: { html, id, payload }
|
|
233
|
+
}));
|
|
234
|
+
if (isVueSuspensePayload(payload)) {
|
|
235
|
+
pending[id] = { domPatched: true, payload };
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
delete pending[id];
|
|
239
|
+
};
|
|
240
|
+
const flush = () => {
|
|
241
|
+
for (const id in pending) {
|
|
242
|
+
if (!Object.prototype.hasOwnProperty.call(pending, id))
|
|
243
|
+
continue;
|
|
244
|
+
apply(id, pending[id] ?? "");
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
absoluteWindow.__ABS_SLOT_FLUSH__ = flush;
|
|
248
|
+
absoluteWindow.__ABS_SLOT_ENQUEUE__ = (id, payload) => {
|
|
249
|
+
apply(id, payload);
|
|
250
|
+
};
|
|
251
|
+
if (typeof MutationObserver === "function") {
|
|
252
|
+
const observer = new MutationObserver(flush);
|
|
253
|
+
const root = document.documentElement ?? document.body ?? document;
|
|
254
|
+
observer.observe(root, { childList: true, subtree: true });
|
|
255
|
+
}
|
|
256
|
+
if (document.readyState === "loading") {
|
|
257
|
+
document.addEventListener("DOMContentLoaded", flush, { once: true });
|
|
258
|
+
}
|
|
259
|
+
flush();
|
|
260
|
+
}, stripFunctionWrapper = (value) => {
|
|
261
|
+
const start = value.indexOf("{");
|
|
262
|
+
const end = value.lastIndexOf("}");
|
|
263
|
+
if (start < 0 || end <= start)
|
|
264
|
+
return "";
|
|
265
|
+
return value.slice(start + 1, end);
|
|
266
|
+
}, getStreamSwapRuntimeScript = () => `(function(){${stripFunctionWrapper(streamSwapRuntime.toString())}})();`;
|
|
267
|
+
|
|
268
|
+
// src/utils/escapeScriptContent.ts
|
|
269
|
+
var ESCAPE_LOOKUP, ESCAPE_REGEX, escapeScriptContent = (content) => content.replace(ESCAPE_REGEX, (char) => {
|
|
270
|
+
const escaped = ESCAPE_LOOKUP[char];
|
|
271
|
+
return escaped !== undefined ? escaped : char;
|
|
272
|
+
});
|
|
273
|
+
var init_escapeScriptContent = __esm(() => {
|
|
274
|
+
ESCAPE_LOOKUP = {
|
|
275
|
+
"\u2028": "\\u2028",
|
|
276
|
+
"\u2029": "\\u2029",
|
|
277
|
+
"<": "\\u003C"
|
|
278
|
+
};
|
|
279
|
+
ESCAPE_REGEX = /[<\u2028\u2029]/g;
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
// src/utils/streamingSlots.ts
|
|
283
|
+
var SLOT_ID_PREFIX = "abs-slot-", CLOSING_BODY_TAG = "</body>", CLOSING_HEAD_TAG2 = "</head>", CLOSING_BODY_TAG_LENGTH, CLOSING_HEAD_TAG_LENGTH, CLOSING_PAGE_TAG_REGEX, STREAMING_RUNTIME_GLOBAL = "__ABS_SLOT_ENQUEUE__", STREAMING_PENDING_GLOBAL = "__ABS_SLOT_PENDING__", STREAM_TAIL_LOOKBEHIND = 128, STREAMING_SLOT_TIMEOUT_MS = 5000, STREAMING_SLOT_MAX_PER_RESPONSE = 128, STREAMING_SLOT_MAX_HTML_BYTES = 64000, createSlotPatchStatement = (id, payload) => `(window.${STREAMING_RUNTIME_GLOBAL}||function(i,p){window.${STREAMING_PENDING_GLOBAL}=window.${STREAMING_PENDING_GLOBAL}||{};window.${STREAMING_PENDING_GLOBAL}[i]=p;})(${JSON.stringify(id)},${JSON.stringify(payload)});`, createNonceAttr = (nonce) => nonce ? ` nonce="${nonce}"` : "", createStreamingSlotId = () => `${SLOT_ID_PREFIX}${Math.random().toString(BASE_36_RADIX).slice(2, RANDOM_ID_END_INDEX)}`, getStreamingSlotsRuntimeScript = () => getStreamSwapRuntimeScript(), injectHtmlIntoBody = (html, injection) => {
|
|
284
|
+
const closingBodyIndex = html.indexOf(CLOSING_BODY_TAG);
|
|
285
|
+
if (closingBodyIndex >= 0) {
|
|
286
|
+
return `${html.slice(0, closingBodyIndex)}${injection}${html.slice(closingBodyIndex)}`;
|
|
287
|
+
}
|
|
288
|
+
return `${html}${injection}`;
|
|
289
|
+
}, injectHtmlIntoHead = (html, injection) => {
|
|
290
|
+
const closingHeadIndex = html.indexOf(CLOSING_HEAD_TAG2);
|
|
291
|
+
if (closingHeadIndex >= 0) {
|
|
292
|
+
return `${html.slice(0, closingHeadIndex)}${injection}${html.slice(closingHeadIndex)}`;
|
|
293
|
+
}
|
|
294
|
+
return `${html}${injection}`;
|
|
295
|
+
}, renderStreamingSlotPatchTag = (id, payload, nonce) => `<script${createNonceAttr(nonce)}>${escapeScriptContent(createSlotPatchStatement(id, payload))}</script>`, renderStreamingSlotPlaceholder = (id, fallbackHtml = "") => `<div id="${id}" data-absolute-slot="true" data-absolute-slot-state="fallback">${fallbackHtml}</div>`, renderStreamingSlotsRuntimeTag = (nonce, runtimePreludeScript) => {
|
|
296
|
+
const runtimeBody = [
|
|
297
|
+
runtimePreludeScript?.trim() ? runtimePreludeScript.trim() : "",
|
|
298
|
+
getStreamingSlotsRuntimeScript()
|
|
299
|
+
].filter(Boolean).join(";");
|
|
300
|
+
return `<script${createNonceAttr(nonce)}>${escapeScriptContent(runtimeBody)}</script>`;
|
|
301
|
+
}, toUint8 = (value, encoder) => encoder.encode(value), isRecord = (value) => Boolean(value) && typeof value === "object", isSafeHtmlLike = (value) => isRecord(value) && typeof value.changingThisBreaksApplicationSecurity === "string", normalizeSafeHtml = (value) => {
|
|
302
|
+
if (isSafeHtmlLike(value)) {
|
|
303
|
+
return value.changingThisBreaksApplicationSecurity;
|
|
304
|
+
}
|
|
305
|
+
return value;
|
|
306
|
+
}, currentStreamingSlotPolicy, clonePolicy = (policy) => ({
|
|
307
|
+
...policy
|
|
308
|
+
}), normalizeSlotBytes = (value, fallback) => {
|
|
309
|
+
if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
|
|
310
|
+
return Math.floor(value);
|
|
311
|
+
}
|
|
312
|
+
return fallback;
|
|
313
|
+
}, normalizeSlotText = (value, fallback) => {
|
|
314
|
+
const normalizedValue = normalizeSafeHtml(value);
|
|
315
|
+
return typeof normalizedValue === "string" ? normalizedValue : fallback;
|
|
316
|
+
}, normalizeSlotError = (value, fallback = undefined) => {
|
|
317
|
+
const safeValue = normalizeSafeHtml(value);
|
|
318
|
+
if (typeof safeValue === "string")
|
|
319
|
+
return safeValue;
|
|
320
|
+
return fallback;
|
|
321
|
+
}, hasPolicyValue = (policy, key) => Object.prototype.hasOwnProperty.call(policy, key), applyStreamingSlotPolicyOverrides = (base, overridePolicy = {}) => ({
|
|
322
|
+
errorHtml: hasPolicyValue(overridePolicy, "errorHtml") ? normalizeSlotError(overridePolicy.errorHtml) : base.errorHtml,
|
|
323
|
+
fallbackHtml: hasPolicyValue(overridePolicy, "fallbackHtml") ? normalizeSlotText(overridePolicy.fallbackHtml, "") : base.fallbackHtml,
|
|
324
|
+
maxSlotHtmlSizeBytes: hasPolicyValue(overridePolicy, "maxSlotHtmlSizeBytes") ? normalizeSlotBytes(overridePolicy.maxSlotHtmlSizeBytes, base.maxSlotHtmlSizeBytes) : base.maxSlotHtmlSizeBytes,
|
|
325
|
+
maxSlotsPerResponse: hasPolicyValue(overridePolicy, "maxSlotsPerResponse") ? normalizeSlotBytes(overridePolicy.maxSlotsPerResponse, base.maxSlotsPerResponse) : base.maxSlotsPerResponse,
|
|
326
|
+
onError: hasPolicyValue(overridePolicy, "onError") ? overridePolicy.onError : base.onError,
|
|
327
|
+
onSlotMetric: hasPolicyValue(overridePolicy, "onSlotMetric") ? overridePolicy.onSlotMetric : base.onSlotMetric,
|
|
328
|
+
timeoutMs: hasPolicyValue(overridePolicy, "timeoutMs") ? normalizeSlotBytes(overridePolicy.timeoutMs, base.timeoutMs) : base.timeoutMs
|
|
329
|
+
}), createCombinedSlotErrorHandler = (policyOnError, enhancerOnError) => {
|
|
330
|
+
if (!policyOnError && !enhancerOnError)
|
|
331
|
+
return;
|
|
332
|
+
return (error, slot) => {
|
|
333
|
+
policyOnError?.(error, slot);
|
|
334
|
+
enhancerOnError?.(error, slot);
|
|
335
|
+
};
|
|
336
|
+
}, createCombinedSlotMetricHandler = (policyOnSlotMetric, callOnSlotMetric) => {
|
|
337
|
+
if (!policyOnSlotMetric && !callOnSlotMetric)
|
|
338
|
+
return;
|
|
339
|
+
return (metric) => {
|
|
340
|
+
policyOnSlotMetric?.(metric);
|
|
341
|
+
callOnSlotMetric?.(metric);
|
|
342
|
+
};
|
|
343
|
+
}, resolveStreamingSlotPolicy = (overridePolicy = {}) => {
|
|
344
|
+
const base = getStreamingSlotPolicy();
|
|
345
|
+
return applyStreamingSlotPolicyOverrides(base, overridePolicy);
|
|
346
|
+
}, getStreamingSlotPolicy = () => clonePolicy(currentStreamingSlotPolicy), setStreamingSlotPolicy = (policy = {}) => {
|
|
347
|
+
const base = getStreamingSlotPolicy();
|
|
348
|
+
currentStreamingSlotPolicy = applyStreamingSlotPolicyOverrides(base, policy);
|
|
349
|
+
}, withStreamingSlotPolicy = async (policy, callback) => {
|
|
350
|
+
const previous = getStreamingSlotPolicy();
|
|
351
|
+
setStreamingSlotPolicy(policy);
|
|
352
|
+
try {
|
|
353
|
+
return await callback();
|
|
354
|
+
} finally {
|
|
355
|
+
currentStreamingSlotPolicy = previous;
|
|
356
|
+
}
|
|
357
|
+
}, emitSlotMetric = (metric, onSlotMetric) => {
|
|
358
|
+
onSlotMetric?.(metric);
|
|
359
|
+
}, createTimeoutError = (slot, timeoutMs) => {
|
|
360
|
+
const error = Object.assign(new Error(`Streaming slot "${slot.id}" timed out after ${timeoutMs}ms`), { __absTimeout: true });
|
|
361
|
+
return error;
|
|
362
|
+
}, isSlotPatchPayloadObject = (value) => isRecord(value) && ("html" in value), isTimeoutError = (error) => isRecord(error) && error.__absTimeout === true, toStreamingSlot = (slot, policy) => ({
|
|
363
|
+
errorHtml: slot.errorHtml === undefined ? policy.errorHtml : slot.errorHtml,
|
|
364
|
+
fallbackHtml: normalizeSlotText(slot.fallbackHtml, policy.fallbackHtml),
|
|
365
|
+
id: slot.id ?? createStreamingSlotId(),
|
|
366
|
+
resolve: slot.resolve,
|
|
367
|
+
timeoutMs: normalizeSlotBytes(slot.timeoutMs, policy.timeoutMs)
|
|
368
|
+
}), prepareSlots = ({
|
|
369
|
+
policy,
|
|
370
|
+
slots,
|
|
371
|
+
onError,
|
|
372
|
+
onSlotMetric
|
|
373
|
+
}) => {
|
|
374
|
+
const preparedSlots = slots.map((slot) => toStreamingSlot(slot, policy));
|
|
375
|
+
const emitPreparedSlotMetric = (slot) => {
|
|
376
|
+
emitSlotMetric({
|
|
377
|
+
slotId: slot.id,
|
|
378
|
+
type: "prepared"
|
|
379
|
+
}, onSlotMetric);
|
|
380
|
+
};
|
|
381
|
+
const dropPreparedSlot = (slot, reason) => {
|
|
382
|
+
onError?.(new Error(reason), slot);
|
|
383
|
+
emitSlotMetric({
|
|
384
|
+
reason,
|
|
385
|
+
slotId: slot.id,
|
|
386
|
+
type: "dropped"
|
|
387
|
+
}, onSlotMetric);
|
|
388
|
+
};
|
|
389
|
+
const { maxSlotsPerResponse } = policy;
|
|
390
|
+
if (maxSlotsPerResponse === 0) {
|
|
391
|
+
preparedSlots.forEach((slot) => dropPreparedSlot(slot, "maxSlotsPerResponse is 0"));
|
|
392
|
+
return [];
|
|
393
|
+
}
|
|
394
|
+
if (preparedSlots.length <= maxSlotsPerResponse) {
|
|
395
|
+
preparedSlots.forEach(emitPreparedSlotMetric);
|
|
396
|
+
return preparedSlots;
|
|
397
|
+
}
|
|
398
|
+
const keptSlots = preparedSlots.slice(0, maxSlotsPerResponse);
|
|
399
|
+
const droppedSlots = preparedSlots.slice(maxSlotsPerResponse);
|
|
400
|
+
droppedSlots.forEach((slot) => {
|
|
401
|
+
dropPreparedSlot(slot, `Streaming slot "${slot.id}" dropped because ${maxSlotsPerResponse} slots is the configured maximum`);
|
|
402
|
+
});
|
|
403
|
+
keptSlots.forEach(emitPreparedSlotMetric);
|
|
404
|
+
return keptSlots;
|
|
405
|
+
}, htmlByteLength = (value, encoder) => encoder.encode(value).length, normalizeSlotPatchPayload = (value) => {
|
|
406
|
+
const safeValue = normalizeSafeHtml(value);
|
|
407
|
+
if (isSlotPatchPayloadObject(safeValue) && typeof safeValue.html === "string") {
|
|
408
|
+
return {
|
|
409
|
+
...safeValue,
|
|
410
|
+
html: normalizeSlotText(safeValue.html, "")
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
return typeof safeValue === "string" ? safeValue : `${safeValue}`;
|
|
414
|
+
}, getPayloadHtml = (payload) => typeof payload === "string" ? payload : payload.html, enqueueEncodedText = (controller, encoder, value) => {
|
|
415
|
+
if (value.length === 0) {
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
controller.enqueue(encoder.encode(value));
|
|
419
|
+
}, readStreamingRuntimeChunk = async (reader) => {
|
|
420
|
+
const { done, value } = await reader.read();
|
|
421
|
+
if (done || !value) {
|
|
422
|
+
return { done, value: undefined };
|
|
423
|
+
}
|
|
424
|
+
return { done, value };
|
|
425
|
+
}, applyBaseWinnerState = (state, winner, handleResolved) => {
|
|
426
|
+
if (!state.handled && winner.kind === "slot") {
|
|
427
|
+
handleResolved(winner);
|
|
428
|
+
}
|
|
429
|
+
return state;
|
|
430
|
+
}, resolveOversizedSlotPayload = (input) => {
|
|
431
|
+
const {
|
|
432
|
+
encoder,
|
|
433
|
+
html,
|
|
434
|
+
maxSlotHtmlSizeBytes,
|
|
435
|
+
onError,
|
|
436
|
+
onSlotMetric,
|
|
437
|
+
slot,
|
|
438
|
+
start
|
|
439
|
+
} = input;
|
|
440
|
+
const bytes = htmlByteLength(html, encoder);
|
|
441
|
+
if (bytes <= maxSlotHtmlSizeBytes) {
|
|
442
|
+
return null;
|
|
443
|
+
}
|
|
444
|
+
const error = new Error(`Streaming slot "${slot.id}" exceeded max payload size of ${maxSlotHtmlSizeBytes} bytes`);
|
|
445
|
+
const durationMs = Date.now() - start;
|
|
446
|
+
onError?.(error, slot);
|
|
447
|
+
emitSlotMetric({
|
|
448
|
+
bytes,
|
|
449
|
+
durationMs,
|
|
450
|
+
error,
|
|
451
|
+
slotId: slot.id,
|
|
452
|
+
type: "size_exceeded"
|
|
453
|
+
}, onSlotMetric);
|
|
454
|
+
const fallbackHtml = normalizeSlotError(slot.errorHtml, undefined);
|
|
455
|
+
return {
|
|
456
|
+
bytes: fallbackHtml === undefined ? 0 : htmlByteLength(fallbackHtml, encoder),
|
|
457
|
+
durationMs,
|
|
458
|
+
id: slot.id,
|
|
459
|
+
payload: fallbackHtml === undefined ? null : fallbackHtml
|
|
460
|
+
};
|
|
461
|
+
}, raceWithTimeout = (promise, slot) => {
|
|
462
|
+
const { timeoutMs } = slot;
|
|
463
|
+
if (typeof timeoutMs !== "number" || timeoutMs <= 0) {
|
|
464
|
+
return promise;
|
|
465
|
+
}
|
|
466
|
+
const { promise: timeoutPromise, reject } = Promise.withResolvers();
|
|
467
|
+
setTimeout(() => {
|
|
468
|
+
reject(createTimeoutError(slot, timeoutMs));
|
|
469
|
+
}, timeoutMs);
|
|
470
|
+
return Promise.race([promise, timeoutPromise]);
|
|
471
|
+
}, resolveSlot = async (slot, onError, policy, onSlotMetric) => {
|
|
472
|
+
const safePolicy = policy ?? getStreamingSlotPolicy();
|
|
473
|
+
const encoder = new TextEncoder;
|
|
474
|
+
const start = Date.now();
|
|
475
|
+
try {
|
|
476
|
+
const maybeAsyncValue = Promise.resolve(slot.resolve());
|
|
477
|
+
const resolved = await raceWithTimeout(maybeAsyncValue, slot);
|
|
478
|
+
const payload = normalizeSlotPatchPayload(resolved);
|
|
479
|
+
const html = getPayloadHtml(payload);
|
|
480
|
+
const oversizedResult = safePolicy.maxSlotHtmlSizeBytes > 0 ? resolveOversizedSlotPayload({
|
|
481
|
+
encoder,
|
|
482
|
+
html,
|
|
483
|
+
maxSlotHtmlSizeBytes: safePolicy.maxSlotHtmlSizeBytes,
|
|
484
|
+
onError,
|
|
485
|
+
onSlotMetric,
|
|
486
|
+
slot,
|
|
487
|
+
start
|
|
488
|
+
}) : null;
|
|
489
|
+
if (oversizedResult) {
|
|
490
|
+
return oversizedResult;
|
|
491
|
+
}
|
|
492
|
+
const durationMs = Date.now() - start;
|
|
493
|
+
const bytes = htmlByteLength(html, encoder);
|
|
494
|
+
emitSlotMetric({
|
|
495
|
+
bytes,
|
|
496
|
+
durationMs,
|
|
497
|
+
slotId: slot.id,
|
|
498
|
+
type: "resolved"
|
|
499
|
+
}, onSlotMetric);
|
|
500
|
+
return {
|
|
501
|
+
bytes,
|
|
502
|
+
durationMs,
|
|
503
|
+
id: slot.id,
|
|
504
|
+
payload
|
|
505
|
+
};
|
|
506
|
+
} catch (error) {
|
|
507
|
+
const durationMs = Date.now() - start;
|
|
508
|
+
onError?.(error, slot);
|
|
509
|
+
emitSlotMetric({
|
|
510
|
+
durationMs,
|
|
511
|
+
error,
|
|
512
|
+
slotId: slot.id,
|
|
513
|
+
type: isTimeoutError(error) ? "timeout" : "error"
|
|
514
|
+
}, onSlotMetric);
|
|
515
|
+
const html = normalizeSlotError(slot.errorHtml, undefined);
|
|
516
|
+
if (html) {
|
|
517
|
+
return {
|
|
518
|
+
bytes: htmlByteLength(html, encoder),
|
|
519
|
+
durationMs,
|
|
520
|
+
id: slot.id,
|
|
521
|
+
payload: html
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
return {
|
|
525
|
+
bytes: 0,
|
|
526
|
+
durationMs,
|
|
527
|
+
id: slot.id,
|
|
528
|
+
payload: null
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
}, nextResolvedSlot = async (pending) => {
|
|
532
|
+
const wrapped = pending.map((promise) => promise.then((result) => ({
|
|
533
|
+
original: promise,
|
|
534
|
+
result
|
|
535
|
+
})));
|
|
536
|
+
return Promise.race(wrapped);
|
|
537
|
+
}, streamChunkToString2 = (value, decoder) => typeof value === "string" ? value : decoder.decode(value, { stream: true }), appendStreamingSlotPatchesToStream = (stream, slots = [], {
|
|
538
|
+
injectRuntime = true,
|
|
539
|
+
nonce,
|
|
540
|
+
onError,
|
|
541
|
+
onSlotMetric,
|
|
542
|
+
policy,
|
|
543
|
+
runtimePreludeScript,
|
|
544
|
+
runtimePlacement = "head"
|
|
545
|
+
} = {}) => {
|
|
546
|
+
const resolvedPolicy = resolveStreamingSlotPolicy(policy);
|
|
547
|
+
const combinedOnError = createCombinedSlotErrorHandler(resolvedPolicy.onError, onError);
|
|
548
|
+
const combinedOnSlotMetric = createCombinedSlotMetricHandler(resolvedPolicy.onSlotMetric, onSlotMetric);
|
|
549
|
+
const effectivePolicy = {
|
|
550
|
+
...resolvedPolicy,
|
|
551
|
+
onSlotMetric: combinedOnSlotMetric
|
|
552
|
+
};
|
|
553
|
+
const preparedSlots = prepareSlots({
|
|
554
|
+
onError: combinedOnError,
|
|
555
|
+
onSlotMetric: combinedOnSlotMetric,
|
|
556
|
+
policy: effectivePolicy,
|
|
557
|
+
slots
|
|
558
|
+
});
|
|
559
|
+
if (preparedSlots.length === 0)
|
|
560
|
+
return stream;
|
|
561
|
+
const source = injectRuntime ? injectStreamingRuntimeIntoStream(stream, nonce, runtimePlacement, runtimePreludeScript) : stream;
|
|
562
|
+
const encoder = new TextEncoder;
|
|
563
|
+
const decoder = new TextDecoder;
|
|
564
|
+
const reader = source.getReader();
|
|
565
|
+
const pending = preparedSlots.map((slot) => resolveSlot(slot, combinedOnError, effectivePolicy, combinedOnSlotMetric));
|
|
566
|
+
const createRaceCandidates = (baseDone, baseRead) => {
|
|
567
|
+
const racers = [];
|
|
568
|
+
if (!baseDone) {
|
|
569
|
+
racers.push(baseRead.then(({ done, value }) => ({
|
|
570
|
+
done,
|
|
571
|
+
kind: "base",
|
|
572
|
+
value
|
|
573
|
+
})));
|
|
574
|
+
}
|
|
575
|
+
if (pending.length > 0) {
|
|
576
|
+
racers.push(nextResolvedSlot(pending).then((resolved) => ({
|
|
577
|
+
kind: "slot",
|
|
578
|
+
...resolved
|
|
579
|
+
})));
|
|
580
|
+
}
|
|
581
|
+
return racers;
|
|
582
|
+
};
|
|
583
|
+
const flushTailLookbehind = (controller, tail) => {
|
|
584
|
+
if (tail.length <= STREAM_TAIL_LOOKBEHIND) {
|
|
585
|
+
return tail;
|
|
586
|
+
}
|
|
587
|
+
const content = tail.slice(0, tail.length - STREAM_TAIL_LOOKBEHIND);
|
|
588
|
+
controller.enqueue(encoder.encode(content));
|
|
589
|
+
return tail.slice(-STREAM_TAIL_LOOKBEHIND);
|
|
590
|
+
};
|
|
591
|
+
const finalizeCompletedBaseWinner = (controller, decodedTail, baseRead) => {
|
|
592
|
+
const footerStart = decodedTail.search(CLOSING_PAGE_TAG_REGEX);
|
|
593
|
+
if (footerStart < 0) {
|
|
594
|
+
enqueueEncodedText(controller, encoder, decodedTail);
|
|
595
|
+
return {
|
|
596
|
+
baseDone: true,
|
|
597
|
+
baseRead,
|
|
598
|
+
footer: "",
|
|
599
|
+
handled: true,
|
|
600
|
+
tail: ""
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
const content = decodedTail.slice(0, footerStart);
|
|
604
|
+
const nextFooter = decodedTail.slice(footerStart);
|
|
605
|
+
enqueueEncodedText(controller, encoder, content);
|
|
606
|
+
return {
|
|
607
|
+
baseDone: true,
|
|
608
|
+
baseRead,
|
|
609
|
+
footer: nextFooter,
|
|
610
|
+
handled: true,
|
|
611
|
+
tail: ""
|
|
612
|
+
};
|
|
613
|
+
};
|
|
614
|
+
const handleBaseWinner = (controller, winner, baseRead, tail, footer) => {
|
|
615
|
+
if (winner.kind !== "base") {
|
|
616
|
+
return { baseDone: false, baseRead, footer, handled: false, tail };
|
|
617
|
+
}
|
|
618
|
+
if (winner.done) {
|
|
619
|
+
return finalizeCompletedBaseWinner(controller, tail + decoder.decode(), baseRead);
|
|
620
|
+
}
|
|
621
|
+
if (!winner.value) {
|
|
622
|
+
return { baseDone: false, baseRead, footer, handled: true, tail };
|
|
623
|
+
}
|
|
624
|
+
const nextTail = flushTailLookbehind(controller, tail + streamChunkToString2(winner.value, decoder));
|
|
625
|
+
return {
|
|
626
|
+
baseDone: false,
|
|
627
|
+
baseRead: reader.read(),
|
|
628
|
+
footer,
|
|
629
|
+
handled: true,
|
|
630
|
+
tail: nextTail
|
|
631
|
+
};
|
|
632
|
+
};
|
|
633
|
+
const handleResolvedSlot = (controller, winner) => {
|
|
634
|
+
const index = pending.indexOf(winner.original);
|
|
635
|
+
if (index >= 0)
|
|
636
|
+
pending.splice(index, 1);
|
|
637
|
+
if (winner.result.payload === null) {
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
emitSlotMetric({
|
|
641
|
+
bytes: winner.result.bytes,
|
|
642
|
+
durationMs: winner.result.durationMs,
|
|
643
|
+
slotId: winner.result.id,
|
|
644
|
+
type: "patched"
|
|
645
|
+
}, combinedOnSlotMetric);
|
|
646
|
+
controller.enqueue(encoder.encode(renderStreamingSlotPatchTag(winner.result.id, winner.result.payload, nonce)));
|
|
647
|
+
};
|
|
648
|
+
const runPatchedStreamLoop = async (controller) => {
|
|
649
|
+
let baseDone = false;
|
|
650
|
+
let baseRead = reader.read();
|
|
651
|
+
let tail = "";
|
|
652
|
+
let footer = "";
|
|
653
|
+
const readNextRaceWinner = async () => {
|
|
654
|
+
const racers = createRaceCandidates(baseDone, baseRead);
|
|
655
|
+
if (racers.length === 0) {
|
|
656
|
+
return footer;
|
|
657
|
+
}
|
|
658
|
+
const winner = await Promise.race(racers);
|
|
659
|
+
const baseWinnerState = applyBaseWinnerState(handleBaseWinner(controller, winner, baseRead, tail, footer), winner, (slotWinner) => {
|
|
660
|
+
handleResolvedSlot(controller, slotWinner);
|
|
661
|
+
});
|
|
662
|
+
({ baseDone, baseRead, footer, tail } = baseWinnerState);
|
|
663
|
+
if (baseDone && pending.length === 0) {
|
|
664
|
+
return footer;
|
|
665
|
+
}
|
|
666
|
+
return readNextRaceWinner();
|
|
667
|
+
};
|
|
668
|
+
return readNextRaceWinner();
|
|
669
|
+
};
|
|
670
|
+
return new ReadableStream({
|
|
671
|
+
async start(controller) {
|
|
672
|
+
try {
|
|
673
|
+
const footer = await runPatchedStreamLoop(controller);
|
|
674
|
+
enqueueEncodedText(controller, encoder, footer);
|
|
675
|
+
controller.close();
|
|
676
|
+
} catch (error) {
|
|
677
|
+
controller.error(error);
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
});
|
|
681
|
+
}, injectStreamingRuntimeIntoStream = (stream, nonce, runtimePlacement = "head", runtimePreludeScript) => {
|
|
682
|
+
const runtimeTag = renderStreamingSlotsRuntimeTag(nonce, runtimePreludeScript);
|
|
683
|
+
const encoder = new TextEncoder;
|
|
684
|
+
const decoder = new TextDecoder;
|
|
685
|
+
const closingTag = runtimePlacement === "body" ? CLOSING_BODY_TAG : CLOSING_HEAD_TAG2;
|
|
686
|
+
const lookbehind = (runtimePlacement === "body" ? CLOSING_BODY_TAG_LENGTH : CLOSING_HEAD_TAG_LENGTH) - 1;
|
|
687
|
+
const flushRuntimeLookbehind = (controller, pending) => {
|
|
688
|
+
if (pending.length <= lookbehind) {
|
|
689
|
+
return pending;
|
|
690
|
+
}
|
|
691
|
+
const safeText = pending.slice(0, pending.length - lookbehind);
|
|
692
|
+
controller.enqueue(encoder.encode(safeText));
|
|
693
|
+
return pending.slice(-lookbehind);
|
|
694
|
+
};
|
|
695
|
+
const injectRuntimeIntoPending = (pending) => runtimePlacement === "body" ? injectHtmlIntoBody(pending, runtimeTag) : injectHtmlIntoHead(pending, runtimeTag);
|
|
696
|
+
const processRuntimePending = (controller, pending, injected) => {
|
|
697
|
+
if (injected) {
|
|
698
|
+
controller.enqueue(encoder.encode(pending));
|
|
699
|
+
return { injected, pending: "" };
|
|
700
|
+
}
|
|
701
|
+
const closingTagIndex = pending.indexOf(closingTag);
|
|
702
|
+
if (closingTagIndex >= 0) {
|
|
703
|
+
const withRuntime = `${pending.slice(0, closingTagIndex)}${runtimeTag}${pending.slice(closingTagIndex)}`;
|
|
704
|
+
controller.enqueue(encoder.encode(withRuntime));
|
|
705
|
+
return { injected: true, pending: "" };
|
|
706
|
+
}
|
|
707
|
+
return {
|
|
708
|
+
injected,
|
|
709
|
+
pending: flushRuntimeLookbehind(controller, pending)
|
|
710
|
+
};
|
|
711
|
+
};
|
|
712
|
+
return new ReadableStream({
|
|
713
|
+
async start(controller) {
|
|
714
|
+
const reader = stream.getReader();
|
|
715
|
+
let injected = false;
|
|
716
|
+
let pending = "";
|
|
717
|
+
const enqueuePending = () => enqueueEncodedText(controller, encoder, pending);
|
|
718
|
+
const consumeRuntimeChunk = async () => {
|
|
719
|
+
const { done, value } = await readStreamingRuntimeChunk(reader);
|
|
720
|
+
if (done || !value) {
|
|
721
|
+
return done;
|
|
722
|
+
}
|
|
723
|
+
pending += streamChunkToString2(value, decoder);
|
|
724
|
+
({ injected, pending } = processRuntimePending(controller, pending, injected));
|
|
725
|
+
return false;
|
|
726
|
+
};
|
|
727
|
+
const runRuntimeInjectionLoop = async () => {
|
|
728
|
+
const done = await consumeRuntimeChunk();
|
|
729
|
+
if (done) {
|
|
730
|
+
return;
|
|
731
|
+
}
|
|
732
|
+
await runRuntimeInjectionLoop();
|
|
733
|
+
};
|
|
734
|
+
try {
|
|
735
|
+
await runRuntimeInjectionLoop();
|
|
736
|
+
pending += decoder.decode();
|
|
737
|
+
pending = injected ? pending : injectRuntimeIntoPending(pending);
|
|
738
|
+
enqueuePending();
|
|
739
|
+
controller.close();
|
|
740
|
+
} catch (error) {
|
|
741
|
+
controller.error(error);
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
});
|
|
745
|
+
}, streamOutOfOrderSlots = ({
|
|
746
|
+
footerHtml = "",
|
|
747
|
+
headerHtml = "",
|
|
748
|
+
nonce,
|
|
749
|
+
policy,
|
|
750
|
+
onSlotMetric,
|
|
751
|
+
onError,
|
|
752
|
+
slots
|
|
753
|
+
}) => {
|
|
754
|
+
const resolvedPolicy = resolveStreamingSlotPolicy(policy);
|
|
755
|
+
const combinedOnError = createCombinedSlotErrorHandler(resolvedPolicy.onError, onError);
|
|
756
|
+
const combinedOnSlotMetric = createCombinedSlotMetricHandler(resolvedPolicy.onSlotMetric, onSlotMetric);
|
|
757
|
+
const effectivePolicy = {
|
|
758
|
+
...resolvedPolicy,
|
|
759
|
+
onSlotMetric: combinedOnSlotMetric
|
|
760
|
+
};
|
|
761
|
+
const preparedSlots = prepareSlots({
|
|
762
|
+
onError: combinedOnError,
|
|
763
|
+
onSlotMetric: combinedOnSlotMetric,
|
|
764
|
+
policy: effectivePolicy,
|
|
765
|
+
slots
|
|
766
|
+
});
|
|
767
|
+
const encoder = new TextEncoder;
|
|
768
|
+
const createPendingSlots = (controller) => preparedSlots.map((slot) => {
|
|
769
|
+
const fallback = renderStreamingSlotPlaceholder(slot.id, normalizeSlotText(slot.fallbackHtml, ""));
|
|
770
|
+
controller.enqueue(toUint8(fallback, encoder));
|
|
771
|
+
return resolveSlot(slot, combinedOnError, effectivePolicy, combinedOnSlotMetric);
|
|
772
|
+
});
|
|
773
|
+
const handleResolvedPreparedSlot = async (controller, pending) => {
|
|
774
|
+
const { original, result } = await nextResolvedSlot(pending);
|
|
775
|
+
const index = pending.indexOf(original);
|
|
776
|
+
if (index >= 0)
|
|
777
|
+
pending.splice(index, 1);
|
|
778
|
+
if (result.payload === null) {
|
|
779
|
+
return;
|
|
780
|
+
}
|
|
781
|
+
emitSlotMetric({
|
|
782
|
+
bytes: result.bytes,
|
|
783
|
+
durationMs: result.durationMs,
|
|
784
|
+
slotId: result.id,
|
|
785
|
+
type: "patched"
|
|
786
|
+
}, combinedOnSlotMetric);
|
|
787
|
+
controller.enqueue(toUint8(renderStreamingSlotPatchTag(result.id, result.payload, nonce), encoder));
|
|
788
|
+
};
|
|
789
|
+
const streamPreparedSlots = async (controller) => {
|
|
790
|
+
const pending = createPendingSlots(controller);
|
|
791
|
+
const streamNextPreparedSlot = async () => {
|
|
792
|
+
if (pending.length === 0) {
|
|
793
|
+
return;
|
|
794
|
+
}
|
|
795
|
+
await handleResolvedPreparedSlot(controller, pending);
|
|
796
|
+
await streamNextPreparedSlot();
|
|
797
|
+
};
|
|
798
|
+
await streamNextPreparedSlot();
|
|
799
|
+
};
|
|
800
|
+
const resolveHeaderHtml = () => {
|
|
801
|
+
const needsRuntimeTag = preparedSlots.length > 0 && !headerHtml.includes(STREAMING_RUNTIME_GLOBAL);
|
|
802
|
+
if (!needsRuntimeTag) {
|
|
803
|
+
return headerHtml;
|
|
804
|
+
}
|
|
805
|
+
return injectHtmlIntoHead(headerHtml, renderStreamingSlotsRuntimeTag(nonce));
|
|
806
|
+
};
|
|
807
|
+
return new ReadableStream({
|
|
808
|
+
async start(controller) {
|
|
809
|
+
try {
|
|
810
|
+
const header = resolveHeaderHtml();
|
|
811
|
+
controller.enqueue(toUint8(header, encoder));
|
|
812
|
+
await streamPreparedSlots(controller);
|
|
813
|
+
enqueueEncodedText(controller, encoder, footerHtml);
|
|
814
|
+
controller.close();
|
|
815
|
+
} catch (error) {
|
|
816
|
+
controller.error(error);
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
});
|
|
820
|
+
};
|
|
821
|
+
var init_streamingSlots = __esm(() => {
|
|
822
|
+
init_constants();
|
|
823
|
+
init_escapeScriptContent();
|
|
824
|
+
CLOSING_BODY_TAG_LENGTH = CLOSING_BODY_TAG.length;
|
|
825
|
+
CLOSING_HEAD_TAG_LENGTH = CLOSING_HEAD_TAG2.length;
|
|
826
|
+
CLOSING_PAGE_TAG_REGEX = /<\/body>\s*<\/html>\s*$/i;
|
|
827
|
+
currentStreamingSlotPolicy = {
|
|
828
|
+
errorHtml: undefined,
|
|
829
|
+
fallbackHtml: "",
|
|
830
|
+
maxSlotHtmlSizeBytes: STREAMING_SLOT_MAX_HTML_BYTES,
|
|
831
|
+
maxSlotsPerResponse: STREAMING_SLOT_MAX_PER_RESPONSE,
|
|
832
|
+
timeoutMs: STREAMING_SLOT_TIMEOUT_MS
|
|
833
|
+
};
|
|
834
|
+
});
|
|
835
|
+
|
|
836
|
+
// src/utils/getDurationString.ts
|
|
837
|
+
var getDurationString = (duration) => {
|
|
838
|
+
let durationString;
|
|
839
|
+
if (duration < MILLISECONDS_IN_A_SECOND) {
|
|
840
|
+
durationString = `${duration.toFixed(TIME_PRECISION)}ms`;
|
|
841
|
+
} else if (duration < MILLISECONDS_IN_A_MINUTE) {
|
|
842
|
+
durationString = `${(duration / MILLISECONDS_IN_A_SECOND).toFixed(TIME_PRECISION)}s`;
|
|
843
|
+
} else {
|
|
844
|
+
const totalSeconds = Math.round(duration / MILLISECONDS_IN_A_SECOND);
|
|
845
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
846
|
+
const seconds = totalSeconds % 60;
|
|
847
|
+
durationString = seconds === 0 ? `${minutes}m` : `${minutes}m ${seconds}s`;
|
|
848
|
+
}
|
|
849
|
+
return durationString;
|
|
850
|
+
};
|
|
851
|
+
var init_getDurationString = __esm(() => {
|
|
852
|
+
init_constants();
|
|
853
|
+
});
|
|
854
|
+
|
|
855
|
+
// src/utils/startupBanner.ts
|
|
856
|
+
var colors, MONTHS, formatTimestamp = () => {
|
|
857
|
+
const now = new Date;
|
|
858
|
+
const month = MONTHS[now.getMonth()];
|
|
859
|
+
const day = now.getDate().toString().padStart(2, "0");
|
|
860
|
+
let hours = now.getHours();
|
|
861
|
+
const minutes = now.getMinutes().toString().padStart(2, "0");
|
|
862
|
+
const seconds = now.getSeconds().toString().padStart(2, "0");
|
|
863
|
+
const ampm = hours >= HOURS_IN_HALF_DAY ? "PM" : "AM";
|
|
864
|
+
hours = hours % HOURS_IN_HALF_DAY || HOURS_IN_HALF_DAY;
|
|
865
|
+
return `${month} ${day} ${hours}:${minutes}:${seconds} ${ampm}`;
|
|
866
|
+
}, startupBanner = (options) => {
|
|
867
|
+
const {
|
|
868
|
+
version,
|
|
869
|
+
readyDuration,
|
|
870
|
+
buildDuration,
|
|
871
|
+
port,
|
|
872
|
+
host,
|
|
873
|
+
networkUrl,
|
|
874
|
+
protocol = "http"
|
|
875
|
+
} = options;
|
|
876
|
+
const name = `${colors.cyan}${colors.bold}ABSOLUTEJS${colors.reset}`;
|
|
877
|
+
const ver = `${colors.dim}v${version}${colors.reset}`;
|
|
878
|
+
const time = `${colors.dim}ready in${colors.reset} ${colors.bold}${getDurationString(readyDuration)}${colors.reset}`;
|
|
879
|
+
const build = typeof buildDuration === "number" && Number.isFinite(buildDuration) ? ` ${colors.dim}(build ${getDurationString(buildDuration)})${colors.reset}` : "";
|
|
880
|
+
console.log("");
|
|
881
|
+
console.log(` ${name} ${ver} ${time}${build}`);
|
|
882
|
+
console.log("");
|
|
883
|
+
console.log(` ${colors.green}\u279C${colors.reset} ${colors.bold}Local:${colors.reset} ${protocol}://${host === "0.0.0.0" ? "localhost" : host}:${port}/`);
|
|
884
|
+
if (networkUrl) {
|
|
885
|
+
console.log(` ${colors.green}\u279C${colors.reset} ${colors.bold}Network:${colors.reset} ${networkUrl}`);
|
|
886
|
+
}
|
|
887
|
+
console.log("");
|
|
888
|
+
};
|
|
889
|
+
var init_startupBanner = __esm(() => {
|
|
890
|
+
init_constants();
|
|
891
|
+
init_getDurationString();
|
|
892
|
+
colors = {
|
|
893
|
+
bold: "\x1B[1m",
|
|
894
|
+
cyan: "\x1B[36m",
|
|
895
|
+
dim: "\x1B[2m",
|
|
896
|
+
green: "\x1B[32m",
|
|
897
|
+
reset: "\x1B[0m"
|
|
898
|
+
};
|
|
899
|
+
MONTHS = [
|
|
900
|
+
"Jan",
|
|
901
|
+
"Feb",
|
|
902
|
+
"Mar",
|
|
903
|
+
"Apr",
|
|
904
|
+
"May",
|
|
905
|
+
"Jun",
|
|
906
|
+
"Jul",
|
|
907
|
+
"Aug",
|
|
908
|
+
"Sep",
|
|
909
|
+
"Oct",
|
|
910
|
+
"Nov",
|
|
911
|
+
"Dec"
|
|
912
|
+
];
|
|
913
|
+
});
|
|
914
|
+
|
|
915
|
+
// src/utils/logger.ts
|
|
916
|
+
var colors2, frameworkColors, formatPath = (filePath) => {
|
|
917
|
+
const cwd = process.cwd();
|
|
918
|
+
let relative = filePath.startsWith(cwd) ? filePath.slice(cwd.length + 1) : filePath;
|
|
919
|
+
relative = relative.replace(/\\/g, "/");
|
|
920
|
+
if (!relative.startsWith("/")) {
|
|
921
|
+
relative = `/${relative}`;
|
|
922
|
+
}
|
|
923
|
+
return relative;
|
|
924
|
+
}, getFrameworkColor = (framework) => frameworkColors[framework] || colors2.white, log = (action, options) => {
|
|
925
|
+
const timestamp = `${colors2.dim}${formatTimestamp()}${colors2.reset}`;
|
|
926
|
+
const tag = `${colors2.cyan}[hmr]${colors2.reset}`;
|
|
927
|
+
let message = action;
|
|
928
|
+
if (options?.path) {
|
|
929
|
+
const pathColor = options.framework ? getFrameworkColor(options.framework) : colors2.white;
|
|
930
|
+
message += ` ${pathColor}${formatPath(options.path)}${colors2.reset}`;
|
|
931
|
+
}
|
|
932
|
+
if (options?.duration !== undefined) {
|
|
933
|
+
message += ` ${colors2.dim}(${options.duration}ms)${colors2.reset}`;
|
|
934
|
+
}
|
|
935
|
+
console.log(`${timestamp} ${tag} ${message}`);
|
|
936
|
+
}, logCssUpdate = (path, framework, duration) => {
|
|
937
|
+
log("css update", { duration, framework: framework ?? "css", path });
|
|
938
|
+
}, logError = (message, error) => {
|
|
939
|
+
const timestamp = `${colors2.dim}${formatTimestamp()}${colors2.reset}`;
|
|
940
|
+
const tag = `${colors2.red}[hmr]${colors2.reset}`;
|
|
941
|
+
const errorMsg = error instanceof Error ? error.message : error;
|
|
942
|
+
const fullMessage = `${colors2.red}error${colors2.reset} ${message}${errorMsg ? `: ${errorMsg}` : ""}`;
|
|
943
|
+
console.error(`${timestamp} ${tag} ${fullMessage}`);
|
|
944
|
+
}, logHmrUpdate = (path, framework, duration) => {
|
|
945
|
+
log("hmr update", { duration, framework, path });
|
|
946
|
+
}, logScriptUpdate = (path, framework, duration) => {
|
|
947
|
+
log("script update", { duration, framework, path });
|
|
948
|
+
}, logServerReload = () => {
|
|
949
|
+
log(`${colors2.cyan}server module reloaded${colors2.reset}`);
|
|
950
|
+
}, logWarn = (message) => {
|
|
951
|
+
const timestamp = `${colors2.dim}${formatTimestamp()}${colors2.reset}`;
|
|
952
|
+
const tag = `${colors2.yellow}[hmr]${colors2.reset}`;
|
|
953
|
+
console.log(`${timestamp} ${tag} ${colors2.yellow}warning ${message}${colors2.reset}`);
|
|
954
|
+
};
|
|
955
|
+
var init_logger = __esm(() => {
|
|
956
|
+
init_startupBanner();
|
|
957
|
+
colors2 = {
|
|
958
|
+
blue: "\x1B[34m",
|
|
959
|
+
bold: "\x1B[1m",
|
|
960
|
+
cyan: "\x1B[36m",
|
|
961
|
+
dim: "\x1B[2m",
|
|
962
|
+
green: "\x1B[32m",
|
|
963
|
+
magenta: "\x1B[35m",
|
|
964
|
+
red: "\x1B[31m",
|
|
965
|
+
reset: "\x1B[0m",
|
|
966
|
+
white: "\x1B[37m",
|
|
967
|
+
yellow: "\x1B[33m"
|
|
968
|
+
};
|
|
969
|
+
frameworkColors = {
|
|
970
|
+
angular: colors2.magenta,
|
|
971
|
+
assets: colors2.dim,
|
|
972
|
+
css: colors2.cyan,
|
|
973
|
+
html: colors2.white,
|
|
974
|
+
htmx: colors2.white,
|
|
975
|
+
react: colors2.blue,
|
|
976
|
+
svelte: colors2.yellow,
|
|
977
|
+
vue: colors2.green
|
|
978
|
+
};
|
|
979
|
+
});
|
|
980
|
+
|
|
981
|
+
// src/core/ssrCache.ts
|
|
982
|
+
var dirtyFrameworks, isSsrCacheDirty = (framework) => dirtyFrameworks.has(framework), markSsrCacheDirty = (framework) => {
|
|
983
|
+
dirtyFrameworks.add(framework);
|
|
984
|
+
};
|
|
985
|
+
var init_ssrCache = __esm(() => {
|
|
986
|
+
dirtyFrameworks = new Set;
|
|
987
|
+
});
|
|
988
|
+
|
|
989
|
+
// src/utils/stringModifiers.ts
|
|
990
|
+
var normalizeSlug = (str) => str.trim().replace(/\s+/g, "-").replace(/[^A-Za-z0-9\-_]+/g, "").replace(/[-_]{2,}/g, "-"), toKebab = (str) => normalizeSlug(str).replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), toPascal = (str) => {
|
|
991
|
+
if (!str.includes("-") && !str.includes("_")) {
|
|
992
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
993
|
+
}
|
|
994
|
+
return normalizeSlug(str).split(/[-_]/).filter(Boolean).map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1).toLowerCase()).join("");
|
|
995
|
+
}, toScreamingSnake = (str) => str.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toUpperCase();
|
|
996
|
+
|
|
997
|
+
// src/core/streamingSlotRegistrar.ts
|
|
998
|
+
var STREAMING_SLOT_REGISTRAR_KEY = Symbol.for("absolutejs.streamingSlotRegistrar");
|
|
999
|
+
var STREAMING_SLOT_WARNING_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotWarningController");
|
|
1000
|
+
var STREAMING_SLOT_COLLECTION_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotCollectionController");
|
|
1001
|
+
var getRegisteredStreamingSlotRegistrar = () => {
|
|
1002
|
+
const value = Reflect.get(globalThis, STREAMING_SLOT_REGISTRAR_KEY);
|
|
1003
|
+
if (typeof value === "function" || value === null) {
|
|
1004
|
+
return value;
|
|
1005
|
+
}
|
|
1006
|
+
return;
|
|
1007
|
+
};
|
|
1008
|
+
var isObjectRecord = (value) => Boolean(value) && typeof value === "object";
|
|
1009
|
+
var isStreamingSlotWarningController = (value) => isObjectRecord(value) && ("maybeWarn" in value) && typeof value.maybeWarn === "function";
|
|
1010
|
+
var isStreamingSlotCollectionController = (value) => isObjectRecord(value) && ("isCollecting" in value) && typeof value.isCollecting === "function";
|
|
1011
|
+
var getWarningController = () => {
|
|
1012
|
+
const value = Reflect.get(globalThis, STREAMING_SLOT_WARNING_STORAGE_KEY);
|
|
1013
|
+
if (value === null || typeof value === "undefined")
|
|
1014
|
+
return;
|
|
1015
|
+
return isStreamingSlotWarningController(value) ? value : undefined;
|
|
1016
|
+
};
|
|
1017
|
+
var getCollectionController = () => {
|
|
1018
|
+
const value = Reflect.get(globalThis, STREAMING_SLOT_COLLECTION_STORAGE_KEY);
|
|
1019
|
+
if (value === null || typeof value === "undefined")
|
|
1020
|
+
return;
|
|
1021
|
+
return isStreamingSlotCollectionController(value) ? value : undefined;
|
|
1022
|
+
};
|
|
1023
|
+
var hasRegisteredStreamingSlotRegistrar = () => typeof getRegisteredStreamingSlotRegistrar() === "function";
|
|
1024
|
+
var isStreamingSlotCollectionActive = () => getCollectionController()?.isCollecting() === true;
|
|
1025
|
+
var registerStreamingSlot = (slot) => {
|
|
1026
|
+
getRegisteredStreamingSlotRegistrar()?.(slot);
|
|
1027
|
+
};
|
|
1028
|
+
var setStreamingSlotCollectionController = (controller) => {
|
|
1029
|
+
Reflect.set(globalThis, STREAMING_SLOT_COLLECTION_STORAGE_KEY, controller);
|
|
1030
|
+
};
|
|
1031
|
+
var setStreamingSlotRegistrar = (nextRegistrar) => {
|
|
1032
|
+
Reflect.set(globalThis, STREAMING_SLOT_REGISTRAR_KEY, nextRegistrar);
|
|
1033
|
+
};
|
|
1034
|
+
var setStreamingSlotWarningController = (controller) => {
|
|
1035
|
+
Reflect.set(globalThis, STREAMING_SLOT_WARNING_STORAGE_KEY, controller);
|
|
1036
|
+
};
|
|
1037
|
+
var warnMissingStreamingSlotCollector = (primitiveName) => {
|
|
1038
|
+
if (isStreamingSlotCollectionActive()) {
|
|
1039
|
+
return;
|
|
1040
|
+
}
|
|
1041
|
+
getWarningController()?.maybeWarn(primitiveName);
|
|
1042
|
+
};
|
|
1043
|
+
|
|
1044
|
+
// src/core/streamingSlotRegistry.ts
|
|
1045
|
+
var STREAMING_SLOT_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotAsyncLocalStorage");
|
|
1046
|
+
var isObjectRecord2 = (value) => Boolean(value) && typeof value === "object";
|
|
1047
|
+
var isAsyncLocalStorage = (value) => isObjectRecord2(value) && ("getStore" in value) && typeof value.getStore === "function" && ("run" in value) && typeof value.run === "function";
|
|
1048
|
+
var getStorageGlobal = () => {
|
|
1049
|
+
const value = Reflect.get(globalThis, STREAMING_SLOT_STORAGE_KEY);
|
|
1050
|
+
if (value === null || typeof value === "undefined") {
|
|
1051
|
+
return value;
|
|
1052
|
+
}
|
|
1053
|
+
return isAsyncLocalStorage(value) ? value : undefined;
|
|
1054
|
+
};
|
|
1055
|
+
var isServerRuntime = () => typeof process !== "undefined" && typeof process.versions?.node === "string";
|
|
1056
|
+
var ensureAsyncLocalStorage = async () => {
|
|
1057
|
+
const storage = getStorageGlobal();
|
|
1058
|
+
if (typeof storage !== "undefined") {
|
|
1059
|
+
return storage;
|
|
1060
|
+
}
|
|
1061
|
+
if (!isServerRuntime()) {
|
|
1062
|
+
Reflect.set(globalThis, STREAMING_SLOT_STORAGE_KEY, null);
|
|
1063
|
+
return getStorageGlobal();
|
|
1064
|
+
}
|
|
1065
|
+
const mod = await import("async_hooks");
|
|
1066
|
+
Reflect.set(globalThis, STREAMING_SLOT_STORAGE_KEY, new mod.AsyncLocalStorage);
|
|
1067
|
+
return getStorageGlobal();
|
|
1068
|
+
};
|
|
1069
|
+
var getActiveSlotStore = () => {
|
|
1070
|
+
const storage = getStorageGlobal();
|
|
1071
|
+
if (!storage)
|
|
1072
|
+
return;
|
|
1073
|
+
return storage.getStore();
|
|
1074
|
+
};
|
|
1075
|
+
var registerStreamingSlot2 = (slot) => {
|
|
1076
|
+
const store = getActiveSlotStore();
|
|
1077
|
+
if (!store)
|
|
1078
|
+
return;
|
|
1079
|
+
store.set(slot.id, slot);
|
|
1080
|
+
};
|
|
1081
|
+
setStreamingSlotRegistrar(registerStreamingSlot2);
|
|
1082
|
+
setStreamingSlotCollectionController({
|
|
1083
|
+
isCollecting: () => getActiveSlotStore() !== undefined
|
|
1084
|
+
});
|
|
1085
|
+
var hasActiveStreamingSlotRegistry = () => getActiveSlotStore() !== undefined;
|
|
1086
|
+
var runWithStreamingSlotRegistry = async (task) => {
|
|
1087
|
+
const storage = await ensureAsyncLocalStorage();
|
|
1088
|
+
if (!storage) {
|
|
1089
|
+
const slots = [];
|
|
1090
|
+
return {
|
|
1091
|
+
result: await task(),
|
|
1092
|
+
slots
|
|
1093
|
+
};
|
|
1094
|
+
}
|
|
1095
|
+
return storage.run(new Map, async () => {
|
|
1096
|
+
const result = await task();
|
|
1097
|
+
const store = storage.getStore();
|
|
1098
|
+
return {
|
|
1099
|
+
result,
|
|
1100
|
+
slots: store ? [...store.values()] : []
|
|
1101
|
+
};
|
|
1102
|
+
});
|
|
1103
|
+
};
|
|
1104
|
+
|
|
1105
|
+
// src/vue/pageHandler.ts
|
|
1106
|
+
init_constants();
|
|
1107
|
+
import { readdir } from "fs/promises";
|
|
1108
|
+
import { basename as basename2, dirname } from "path";
|
|
1109
|
+
|
|
1110
|
+
// src/core/islandPageContext.ts
|
|
1111
|
+
init_constants();
|
|
1112
|
+
var BOOTSTRAP_MANIFEST_KEY = "BootstrapClient";
|
|
1113
|
+
var ISLAND_MARKER = 'data-island="true"';
|
|
1114
|
+
var MANIFEST_MARKER = "__ABSOLUTE_MANIFEST__";
|
|
1115
|
+
var ISLAND_STATE_MARKER = "__ABS_ISLAND_STATE__";
|
|
1116
|
+
var CLOSING_HEAD_TAG = "</head>";
|
|
1117
|
+
var buildIslandsHeadMarkup = (manifest) => {
|
|
1118
|
+
const manifestScript = `<script>window.__ABSOLUTE_MANIFEST__ = ${JSON.stringify(manifest)}</script>`;
|
|
1119
|
+
const islandStateScript = `<script>window.__ABS_ISLAND_STATE__ = ${JSON.stringify(globalThis.__ABS_ISLAND_STATE__ ?? {})}</script>`;
|
|
1120
|
+
const bootstrapPath = manifest[BOOTSTRAP_MANIFEST_KEY];
|
|
1121
|
+
const bootstrapScript = bootstrapPath ? `<script type="module" src="${bootstrapPath}"></script>` : "";
|
|
1122
|
+
return `${manifestScript}${islandStateScript}${bootstrapScript}`;
|
|
1123
|
+
};
|
|
1124
|
+
var injectHeadMarkup = (html, markup) => {
|
|
1125
|
+
const closingHeadIndex = html.indexOf("</head>");
|
|
1126
|
+
if (closingHeadIndex >= 0) {
|
|
1127
|
+
return `${html.slice(0, closingHeadIndex)}${markup}${html.slice(closingHeadIndex)}`;
|
|
1128
|
+
}
|
|
1129
|
+
const openingBodyIndex = html.indexOf("<body");
|
|
1130
|
+
if (openingBodyIndex >= 0) {
|
|
1131
|
+
const bodyStart = html.indexOf(">", openingBodyIndex);
|
|
1132
|
+
if (bodyStart >= 0) {
|
|
1133
|
+
return `${html.slice(0, openingBodyIndex)}<head>${markup}</head>${html.slice(openingBodyIndex)}`;
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
return `<!DOCTYPE html><html><head>${markup}</head><body>${html}</body></html>`;
|
|
1137
|
+
};
|
|
1138
|
+
var streamChunkToString = (value, decoder) => typeof value === "string" ? value : decoder.decode(value, { stream: true });
|
|
1139
|
+
var flushSafePendingText = (controller, encoder, pending, lookbehind) => {
|
|
1140
|
+
if (pending.length <= lookbehind) {
|
|
1141
|
+
return pending;
|
|
1142
|
+
}
|
|
1143
|
+
const safeText = pending.slice(0, pending.length - lookbehind);
|
|
1144
|
+
controller.enqueue(encoder.encode(safeText));
|
|
1145
|
+
return pending.slice(-lookbehind);
|
|
1146
|
+
};
|
|
1147
|
+
var updateInjectedState = (consumed, injected, pending) => {
|
|
1148
|
+
if (consumed.done) {
|
|
1149
|
+
return { done: true, injected, pending };
|
|
1150
|
+
}
|
|
1151
|
+
return {
|
|
1152
|
+
done: false,
|
|
1153
|
+
injected: consumed.injected,
|
|
1154
|
+
pending: consumed.pending
|
|
1155
|
+
};
|
|
1156
|
+
};
|
|
1157
|
+
var readStreamChunk = async (reader) => {
|
|
1158
|
+
const { done, value } = await reader.read();
|
|
1159
|
+
if (done || !value) {
|
|
1160
|
+
return { done, value: undefined };
|
|
1161
|
+
}
|
|
1162
|
+
return { done, value };
|
|
1163
|
+
};
|
|
1164
|
+
var pipeStreamWithHeadInjection = (stream, markup) => {
|
|
1165
|
+
const encoder = new TextEncoder;
|
|
1166
|
+
const decoder = new TextDecoder;
|
|
1167
|
+
const lookbehind = CLOSING_HEAD_TAG.length - 1;
|
|
1168
|
+
const processPending = (controller, pending, injected) => {
|
|
1169
|
+
if (injected) {
|
|
1170
|
+
controller.enqueue(encoder.encode(pending));
|
|
1171
|
+
return { injected, pending: "" };
|
|
1172
|
+
}
|
|
1173
|
+
const headIndex = pending.indexOf(CLOSING_HEAD_TAG);
|
|
1174
|
+
if (headIndex >= 0) {
|
|
1175
|
+
const next = `${pending.slice(0, headIndex)}${markup}${pending.slice(headIndex)}`;
|
|
1176
|
+
controller.enqueue(encoder.encode(next));
|
|
1177
|
+
return { injected: true, pending: "" };
|
|
1178
|
+
}
|
|
1179
|
+
return {
|
|
1180
|
+
injected,
|
|
1181
|
+
pending: flushSafePendingText(controller, encoder, pending, lookbehind)
|
|
1182
|
+
};
|
|
1183
|
+
};
|
|
1184
|
+
const finishHeadInjectionStream = (controller, pending, injected) => {
|
|
1185
|
+
let finalPending = pending + decoder.decode();
|
|
1186
|
+
if (!injected) {
|
|
1187
|
+
finalPending = injectHeadMarkup(finalPending, markup);
|
|
1188
|
+
}
|
|
1189
|
+
if (finalPending.length > 0) {
|
|
1190
|
+
controller.enqueue(encoder.encode(finalPending));
|
|
1191
|
+
}
|
|
1192
|
+
controller.close();
|
|
1193
|
+
};
|
|
1194
|
+
const consumeHeadChunk = async (controller, reader, pending, injected) => {
|
|
1195
|
+
const { done, value } = await readStreamChunk(reader);
|
|
1196
|
+
if (done || !value) {
|
|
1197
|
+
return { done, injected, pending };
|
|
1198
|
+
}
|
|
1199
|
+
const processed = processPending(controller, pending + streamChunkToString(value, decoder), injected);
|
|
1200
|
+
return {
|
|
1201
|
+
done,
|
|
1202
|
+
injected: processed.injected,
|
|
1203
|
+
pending: processed.pending
|
|
1204
|
+
};
|
|
1205
|
+
};
|
|
1206
|
+
const runHeadInjectionLoop = async (controller, reader) => {
|
|
1207
|
+
const consumeNextHeadChunk = async (injected, pending) => {
|
|
1208
|
+
const consumed = await consumeHeadChunk(controller, reader, pending, injected);
|
|
1209
|
+
const nextState = updateInjectedState(consumed, injected, pending);
|
|
1210
|
+
if (nextState.done) {
|
|
1211
|
+
return { injected, pending };
|
|
1212
|
+
}
|
|
1213
|
+
return consumeNextHeadChunk(nextState.injected, nextState.pending);
|
|
1214
|
+
};
|
|
1215
|
+
return consumeNextHeadChunk(false, "");
|
|
1216
|
+
};
|
|
1217
|
+
return new ReadableStream({
|
|
1218
|
+
async start(controller) {
|
|
1219
|
+
const reader = stream.getReader();
|
|
1220
|
+
try {
|
|
1221
|
+
const { injected, pending } = await runHeadInjectionLoop(controller, reader);
|
|
1222
|
+
finishHeadInjectionStream(controller, pending, injected);
|
|
1223
|
+
} catch (error) {
|
|
1224
|
+
controller.error(error);
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
});
|
|
1228
|
+
};
|
|
1229
|
+
var pipeStreamWithIslandMarkerDetection = (stream, markup) => {
|
|
1230
|
+
const encoder = new TextEncoder;
|
|
1231
|
+
const decoder = new TextDecoder;
|
|
1232
|
+
const lookbehind = Math.max(ISLAND_MARKER.length, BYTES_PER_KILOBYTE);
|
|
1233
|
+
const processPending = (controller, pending, injected) => {
|
|
1234
|
+
if (injected) {
|
|
1235
|
+
controller.enqueue(encoder.encode(pending));
|
|
1236
|
+
return { injected, pending: "" };
|
|
1237
|
+
}
|
|
1238
|
+
const markerIndex = pending.indexOf(ISLAND_MARKER);
|
|
1239
|
+
if (markerIndex >= 0) {
|
|
1240
|
+
const tagStart = pending.lastIndexOf("<", markerIndex);
|
|
1241
|
+
const injectAt = tagStart >= 0 ? tagStart : markerIndex;
|
|
1242
|
+
const next = `${pending.slice(0, injectAt)}${markup}${pending.slice(injectAt)}`;
|
|
1243
|
+
controller.enqueue(encoder.encode(next));
|
|
1244
|
+
return { injected: true, pending: "" };
|
|
1245
|
+
}
|
|
1246
|
+
return {
|
|
1247
|
+
injected,
|
|
1248
|
+
pending: flushSafePendingText(controller, encoder, pending, lookbehind)
|
|
1249
|
+
};
|
|
1250
|
+
};
|
|
1251
|
+
const finishIslandMarkerStream = (controller, pending) => {
|
|
1252
|
+
const finalPending = pending + decoder.decode();
|
|
1253
|
+
if (finalPending.length > 0) {
|
|
1254
|
+
controller.enqueue(encoder.encode(finalPending));
|
|
1255
|
+
}
|
|
1256
|
+
controller.close();
|
|
1257
|
+
};
|
|
1258
|
+
const consumeIslandChunk = async (controller, reader, pending, injected) => {
|
|
1259
|
+
const { done, value } = await readStreamChunk(reader);
|
|
1260
|
+
if (done || !value) {
|
|
1261
|
+
return { done, injected, pending };
|
|
1262
|
+
}
|
|
1263
|
+
const processed = processPending(controller, pending + streamChunkToString(value, decoder), injected);
|
|
1264
|
+
return {
|
|
1265
|
+
done,
|
|
1266
|
+
injected: processed.injected,
|
|
1267
|
+
pending: processed.pending
|
|
1268
|
+
};
|
|
1269
|
+
};
|
|
1270
|
+
const runIslandMarkerLoop = async (controller, reader) => {
|
|
1271
|
+
const consumeNextIslandChunk = async (injected, pending) => {
|
|
1272
|
+
const consumed = await consumeIslandChunk(controller, reader, pending, injected);
|
|
1273
|
+
const nextState = updateInjectedState(consumed, injected, pending);
|
|
1274
|
+
if (nextState.done) {
|
|
1275
|
+
return { injected, pending };
|
|
1276
|
+
}
|
|
1277
|
+
return consumeNextIslandChunk(nextState.injected, nextState.pending);
|
|
1278
|
+
};
|
|
1279
|
+
return consumeNextIslandChunk(false, "");
|
|
1280
|
+
};
|
|
1281
|
+
return new ReadableStream({
|
|
1282
|
+
async start(controller) {
|
|
1283
|
+
const reader = stream.getReader();
|
|
1284
|
+
try {
|
|
1285
|
+
const { pending } = await runIslandMarkerLoop(controller, reader);
|
|
1286
|
+
finishIslandMarkerStream(controller, pending);
|
|
1287
|
+
} catch (error) {
|
|
1288
|
+
controller.error(error);
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
});
|
|
1292
|
+
};
|
|
1293
|
+
var htmlContainsIslands = (html) => html.includes(ISLAND_MARKER);
|
|
1294
|
+
var injectIslandPageContext = (html, options) => {
|
|
1295
|
+
const manifest = globalThis.__absoluteManifest;
|
|
1296
|
+
const hasIslands = options?.hasIslands ?? htmlContainsIslands(html);
|
|
1297
|
+
if (!manifest || !hasIslands) {
|
|
1298
|
+
return html;
|
|
1299
|
+
}
|
|
1300
|
+
if (html.includes(MANIFEST_MARKER) || html.includes(ISLAND_STATE_MARKER)) {
|
|
1301
|
+
return html;
|
|
1302
|
+
}
|
|
1303
|
+
return injectHeadMarkup(html, buildIslandsHeadMarkup(manifest));
|
|
1304
|
+
};
|
|
1305
|
+
var injectIslandPageContextStream = (stream, options) => {
|
|
1306
|
+
const manifest = globalThis.__absoluteManifest;
|
|
1307
|
+
if (!manifest)
|
|
1308
|
+
return stream;
|
|
1309
|
+
const markup = buildIslandsHeadMarkup(manifest);
|
|
1310
|
+
if (options?.hasIslands === true) {
|
|
1311
|
+
return pipeStreamWithHeadInjection(stream, markup);
|
|
1312
|
+
}
|
|
1313
|
+
if (options?.hasIslands === false) {
|
|
1314
|
+
return stream;
|
|
1315
|
+
}
|
|
1316
|
+
return pipeStreamWithIslandMarkerDetection(stream, markup);
|
|
1317
|
+
};
|
|
1318
|
+
var setCurrentIslandManifest = (manifest) => {
|
|
1319
|
+
globalThis.__absoluteManifest = manifest;
|
|
1320
|
+
};
|
|
1321
|
+
|
|
1322
|
+
// src/vue/pageHandler.ts
|
|
1323
|
+
init_devRouteRegistrationCallsite();
|
|
1324
|
+
|
|
1325
|
+
// src/core/responseEnhancers.ts
|
|
1326
|
+
init_streamingSlots();
|
|
1327
|
+
var toResponse = async (responseLike) => responseLike;
|
|
1328
|
+
var cloneHeaders = (response) => {
|
|
1329
|
+
const headers = new Headers(response.headers);
|
|
1330
|
+
return headers;
|
|
1331
|
+
};
|
|
1332
|
+
var enhanceHtmlResponseWithStreamingSlots = (response, {
|
|
1333
|
+
nonce,
|
|
1334
|
+
onError,
|
|
1335
|
+
runtimePlacement,
|
|
1336
|
+
runtimePreludeScript,
|
|
1337
|
+
streamingSlots = [],
|
|
1338
|
+
policy
|
|
1339
|
+
} = {}) => {
|
|
1340
|
+
if (!response.body || streamingSlots.length === 0) {
|
|
1341
|
+
return response;
|
|
1342
|
+
}
|
|
1343
|
+
const body = appendStreamingSlotPatchesToStream(response.body, streamingSlots, {
|
|
1344
|
+
nonce,
|
|
1345
|
+
onError,
|
|
1346
|
+
policy,
|
|
1347
|
+
runtimePlacement,
|
|
1348
|
+
runtimePreludeScript
|
|
1349
|
+
});
|
|
1350
|
+
return new Response(body, {
|
|
1351
|
+
headers: cloneHeaders(response),
|
|
1352
|
+
status: response.status,
|
|
1353
|
+
statusText: response.statusText
|
|
1354
|
+
});
|
|
1355
|
+
};
|
|
1356
|
+
var withStreamingSlots = async (responseLike, options = {}) => enhanceHtmlResponseWithStreamingSlots(await toResponse(responseLike), options);
|
|
1357
|
+
var mergeStreamingSlots = (registered, explicit) => {
|
|
1358
|
+
const merged = new Map;
|
|
1359
|
+
for (const slot of registered)
|
|
1360
|
+
merged.set(slot.id, slot);
|
|
1361
|
+
for (const slot of explicit)
|
|
1362
|
+
merged.set(slot.id, slot);
|
|
1363
|
+
return [...merged.values()];
|
|
1364
|
+
};
|
|
1365
|
+
var withRegisteredStreamingSlots = async (renderResponse, options = {}) => {
|
|
1366
|
+
const { result, slots } = await runWithStreamingSlotRegistry(renderResponse);
|
|
1367
|
+
const explicit = options.streamingSlots ?? [];
|
|
1368
|
+
return withStreamingSlots(result, {
|
|
1369
|
+
...options,
|
|
1370
|
+
streamingSlots: mergeStreamingSlots(slots, explicit)
|
|
1371
|
+
});
|
|
1372
|
+
};
|
|
1373
|
+
|
|
1374
|
+
// src/core/streamingSlotWarningScope.ts
|
|
1375
|
+
init_logger();
|
|
1376
|
+
import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
|
|
1377
|
+
var STREAMING_SLOT_WARNING_STORAGE_KEY2 = Symbol.for("absolutejs.streamingSlotWarningAsyncLocalStorage");
|
|
1378
|
+
var isObjectRecord4 = (value) => Boolean(value) && typeof value === "object";
|
|
1379
|
+
var isAsyncLocalStorage3 = (value) => isObjectRecord4(value) && ("getStore" in value) && typeof value.getStore === "function" && ("run" in value) && typeof value.run === "function";
|
|
1380
|
+
var getWarningStorage = () => {
|
|
1381
|
+
const value = Reflect.get(globalThis, STREAMING_SLOT_WARNING_STORAGE_KEY2);
|
|
1382
|
+
if (value === null || typeof value === "undefined") {
|
|
1383
|
+
return;
|
|
1384
|
+
}
|
|
1385
|
+
return isAsyncLocalStorage3(value) ? value : undefined;
|
|
1386
|
+
};
|
|
1387
|
+
var ensureWarningStorage = () => {
|
|
1388
|
+
const existing = getWarningStorage();
|
|
1389
|
+
if (existing) {
|
|
1390
|
+
return existing;
|
|
1391
|
+
}
|
|
1392
|
+
const storage = new AsyncLocalStorage2;
|
|
1393
|
+
Reflect.set(globalThis, STREAMING_SLOT_WARNING_STORAGE_KEY2, storage);
|
|
1394
|
+
return storage;
|
|
1395
|
+
};
|
|
1396
|
+
var normalizeCallsitePath2 = (value) => value.replace(`${process.cwd()}/`, "").replace(process.cwd(), "").replace(/^\.\/+/, "");
|
|
1397
|
+
var formatWarningCallsite = (callsite) => {
|
|
1398
|
+
const match = callsite.match(/^(.*?)(:\d+:\d+)$/);
|
|
1399
|
+
if (!match) {
|
|
1400
|
+
return `\x1B[36m${callsite}\x1B[0m`;
|
|
1401
|
+
}
|
|
1402
|
+
return `\x1B[36m${match[1]}\x1B[33m${match[2]}\x1B[0m`;
|
|
1403
|
+
};
|
|
1404
|
+
var shouldIgnoreWarningFrame = (frame) => frame.includes("/node_modules/") || frame.includes("/dist/") || frame.includes("/src/react/pageHandler.") || frame.includes("/src/vue/pageHandler.") || frame.includes("/src/svelte/pageHandler.") || frame.includes("/src/angular/pageHandler.") || frame.includes("/src/core/streamingSlotWarningScope.");
|
|
1405
|
+
var getWarningLocation = (frame) => frame.match(/\((\/[^)]+:\d+:\d+)\)$/)?.[1] ?? frame.match(/at (\/[^ ]+:\d+:\d+)$/)?.[1];
|
|
1406
|
+
var extractCallsiteFromStack = (stack) => {
|
|
1407
|
+
const location = stack.split(`
|
|
1408
|
+
`).slice(1).map((line) => line.trim()).filter((frame) => !shouldIgnoreWarningFrame(frame)).map((frame) => getWarningLocation(frame)).find((frameLocation) => frameLocation !== undefined);
|
|
1409
|
+
return location ? normalizeCallsitePath2(location) : undefined;
|
|
1410
|
+
};
|
|
1411
|
+
var buildMissingCollectorWarning = (primitiveName, handlerCallsite) => `${primitiveName} rendered during SSR without streaming slot collection enabled. Add { collectStreamingSlots: true } to this page handler to enable out-of-order streaming for this route.${handlerCallsite ? ` Update ${formatWarningCallsite(handlerCallsite)}.` : ""}`;
|
|
1412
|
+
setStreamingSlotWarningController({
|
|
1413
|
+
maybeWarn: (primitiveName) => {
|
|
1414
|
+
const store = getWarningStorage()?.getStore();
|
|
1415
|
+
if (!store || store.hasWarned) {
|
|
1416
|
+
return;
|
|
1417
|
+
}
|
|
1418
|
+
store.hasWarned = true;
|
|
1419
|
+
logWarn(buildMissingCollectorWarning(primitiveName, store.handlerCallsite));
|
|
1420
|
+
}
|
|
1421
|
+
});
|
|
1422
|
+
var captureStreamingSlotWarningCallsite = () => {
|
|
1423
|
+
if (false) {}
|
|
1424
|
+
const { stack } = new Error;
|
|
1425
|
+
if (!stack) {
|
|
1426
|
+
return;
|
|
1427
|
+
}
|
|
1428
|
+
return extractCallsiteFromStack(stack);
|
|
1429
|
+
};
|
|
1430
|
+
var runWithStreamingSlotWarningScope = (task, metadata) => ensureWarningStorage().run({ handlerCallsite: metadata?.handlerCallsite, hasWarned: false }, task);
|
|
1431
|
+
|
|
1432
|
+
// src/vue/pageHandler.ts
|
|
1433
|
+
init_ssrCache();
|
|
1434
|
+
|
|
1435
|
+
// src/utils/ssrErrorPage.ts
|
|
1436
|
+
var ssrErrorPage = (framework, error) => {
|
|
1437
|
+
const frameworkColors2 = {
|
|
1438
|
+
angular: "#dd0031",
|
|
1439
|
+
html: "#e34c26",
|
|
1440
|
+
htmx: "#1a365d",
|
|
1441
|
+
react: "#61dafb",
|
|
1442
|
+
svelte: "#ff3e00",
|
|
1443
|
+
vue: "#42b883"
|
|
1444
|
+
};
|
|
1445
|
+
const accent = frameworkColors2[framework] ?? "#94a3b8";
|
|
1446
|
+
const label = framework.charAt(0).toUpperCase() + framework.slice(1);
|
|
1447
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1448
|
+
return `<!DOCTYPE html>
|
|
1449
|
+
<html>
|
|
1450
|
+
<head>
|
|
1451
|
+
<meta charset="utf-8">
|
|
1452
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
1453
|
+
<title>SSR Error - AbsoluteJS</title>
|
|
1454
|
+
<style>
|
|
1455
|
+
*{margin:0;padding:0;box-sizing:border-box}
|
|
1456
|
+
body{min-height:100vh;background:linear-gradient(135deg,rgba(15,23,42,0.98) 0%,rgba(30,41,59,0.98) 100%);color:#e2e8f0;font-family:"JetBrains Mono","Fira Code",ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:14px;line-height:1.6;display:flex;align-items:flex-start;justify-content:center;padding:32px}
|
|
1457
|
+
.card{max-width:720px;width:100%;background:rgba(30,41,59,0.6);border:1px solid rgba(71,85,105,0.5);border-radius:16px;box-shadow:0 25px 50px -12px rgba(0,0,0,0.5),0 0 0 1px rgba(255,255,255,0.05);overflow:hidden}
|
|
1458
|
+
.header{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:20px 24px;background:rgba(15,23,42,0.5);border-bottom:1px solid rgba(71,85,105,0.4)}
|
|
1459
|
+
.brand{font-weight:700;font-size:20px;color:#fff;letter-spacing:-0.02em}
|
|
1460
|
+
.badge{padding:5px 10px;border-radius:8px;font-size:12px;font-weight:600;background:${accent};color:#fff;opacity:0.95;box-shadow:0 2px 4px rgba(0,0,0,0.2)}
|
|
1461
|
+
.kind{color:#94a3b8;font-size:13px;font-weight:500}
|
|
1462
|
+
.content{padding:24px}
|
|
1463
|
+
.label{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:0.08em;color:#94a3b8;margin-bottom:8px}
|
|
1464
|
+
.message{margin:0;padding:16px 20px;background:rgba(239,68,68,0.12);border:1px solid rgba(239,68,68,0.25);border-radius:10px;overflow-x:auto;white-space:pre-wrap;word-break:break-word;color:#fca5a5;font-size:13px;line-height:1.5}
|
|
1465
|
+
.hint{margin-top:20px;padding:12px 20px;background:rgba(71,85,105,0.3);border-radius:10px;border:1px solid rgba(71,85,105,0.4);color:#cbd5e1;font-size:13px}
|
|
1466
|
+
</style>
|
|
1467
|
+
</head>
|
|
1468
|
+
<body>
|
|
1469
|
+
<div class="card">
|
|
1470
|
+
<div class="header">
|
|
1471
|
+
<div style="display:flex;align-items:center;gap:12px">
|
|
1472
|
+
<span class="brand">AbsoluteJS</span>
|
|
1473
|
+
<span class="badge">${label}</span>
|
|
1474
|
+
</div>
|
|
1475
|
+
<span class="kind">Server Render Error</span>
|
|
1476
|
+
</div>
|
|
1477
|
+
<div class="content">
|
|
1478
|
+
<div class="label">What went wrong</div>
|
|
1479
|
+
<pre class="message">${message.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")}</pre>
|
|
1480
|
+
<div class="hint">A component threw during server-side rendering. Check the terminal for the full stack trace.</div>
|
|
1481
|
+
</div>
|
|
1482
|
+
</div>
|
|
1483
|
+
</body>
|
|
1484
|
+
</html>`;
|
|
1485
|
+
};
|
|
1486
|
+
|
|
1487
|
+
// src/utils/resolveConvention.ts
|
|
1488
|
+
import { basename } from "path";
|
|
1489
|
+
var CONVENTIONS_KEY = "__absoluteConventions";
|
|
1490
|
+
var isConventionsMap = (value) => Boolean(value) && typeof value === "object";
|
|
1491
|
+
var getMap = () => {
|
|
1492
|
+
const value = Reflect.get(globalThis, CONVENTIONS_KEY);
|
|
1493
|
+
if (isConventionsMap(value))
|
|
1494
|
+
return value;
|
|
1495
|
+
const empty = {};
|
|
1496
|
+
return empty;
|
|
1497
|
+
};
|
|
1498
|
+
var derivePageName = (pagePath) => {
|
|
1499
|
+
const base = basename(pagePath);
|
|
1500
|
+
const dotIndex = base.indexOf(".");
|
|
1501
|
+
const name = dotIndex > 0 ? base.slice(0, dotIndex) : base;
|
|
1502
|
+
return toPascal(name);
|
|
1503
|
+
};
|
|
1504
|
+
var normalizeConventionPageName = (name) => toPascal(name).replace(/\d+$/, "");
|
|
1505
|
+
var resolveErrorConventionPath = (framework, pageName) => {
|
|
1506
|
+
const conventions = getMap()[framework];
|
|
1507
|
+
if (!conventions)
|
|
1508
|
+
return;
|
|
1509
|
+
const exact = conventions.pages?.[pageName]?.error;
|
|
1510
|
+
if (exact)
|
|
1511
|
+
return exact;
|
|
1512
|
+
const normalizedPageName = normalizeConventionPageName(pageName);
|
|
1513
|
+
for (const [candidate, page] of Object.entries(conventions.pages ?? {})) {
|
|
1514
|
+
if (normalizeConventionPageName(candidate) === normalizedPageName) {
|
|
1515
|
+
return page.error ?? conventions.defaults?.error;
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
return conventions.defaults?.error;
|
|
1519
|
+
};
|
|
1520
|
+
var resolveNotFoundConventionPath = (framework) => getMap()[framework]?.defaults?.notFound;
|
|
1521
|
+
var hasErrorConvention = (framework) => {
|
|
1522
|
+
const conventions = getMap()[framework];
|
|
1523
|
+
if (!conventions)
|
|
1524
|
+
return false;
|
|
1525
|
+
if (conventions.defaults?.error)
|
|
1526
|
+
return true;
|
|
1527
|
+
return Object.values(conventions.pages ?? {}).some((page) => Boolean(page.error));
|
|
1528
|
+
};
|
|
1529
|
+
var setConventions = (map) => {
|
|
1530
|
+
Reflect.set(globalThis, CONVENTIONS_KEY, map);
|
|
1531
|
+
};
|
|
1532
|
+
var isDev = () => true;
|
|
1533
|
+
var buildErrorProps = (error) => {
|
|
1534
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1535
|
+
const stack = isDev() && error instanceof Error ? error.stack : undefined;
|
|
1536
|
+
return { error: { message, stack } };
|
|
1537
|
+
};
|
|
1538
|
+
var renderReactError = async (conventionPath, errorProps) => {
|
|
1539
|
+
const { createElement } = await import("react");
|
|
1540
|
+
const { renderToReadableStream } = await import("react-dom/server");
|
|
1541
|
+
const mod = await import(conventionPath);
|
|
1542
|
+
const [firstKey] = Object.keys(mod);
|
|
1543
|
+
const ErrorComponent = mod.default ?? (firstKey ? mod[firstKey] : undefined);
|
|
1544
|
+
const element = createElement(ErrorComponent, errorProps);
|
|
1545
|
+
const stream = await renderToReadableStream(element);
|
|
1546
|
+
return new Response(stream, {
|
|
1547
|
+
headers: { "Content-Type": "text/html" },
|
|
1548
|
+
status: 500
|
|
1549
|
+
});
|
|
1550
|
+
};
|
|
1551
|
+
var renderSvelteError = async (conventionPath, errorProps) => {
|
|
1552
|
+
const { render } = await import("svelte/server");
|
|
1553
|
+
const mod = await import(conventionPath);
|
|
1554
|
+
const ErrorComponent = mod.default;
|
|
1555
|
+
const { head, body } = render(ErrorComponent, {
|
|
1556
|
+
props: errorProps
|
|
1557
|
+
});
|
|
1558
|
+
const html = `<!DOCTYPE html><html><head>${head}</head><body>${body}</body></html>`;
|
|
1559
|
+
return new Response(html, {
|
|
1560
|
+
headers: { "Content-Type": "text/html" },
|
|
1561
|
+
status: 500
|
|
1562
|
+
});
|
|
1563
|
+
};
|
|
1564
|
+
var unescapeVueStyles = (ssrBody) => {
|
|
1565
|
+
let styles = "";
|
|
1566
|
+
const body = ssrBody.replace(/<style>([\s\S]*?)<\/style>/g, (_, css) => {
|
|
1567
|
+
styles += `<style>${css.replace(/"/g, '"').replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")}</style>`;
|
|
1568
|
+
return "";
|
|
1569
|
+
});
|
|
1570
|
+
return { body, styles };
|
|
1571
|
+
};
|
|
1572
|
+
var renderVueError = async (conventionPath, errorProps) => {
|
|
1573
|
+
const { createSSRApp, h } = await import("vue");
|
|
1574
|
+
const { renderToString } = await import("vue/server-renderer");
|
|
1575
|
+
const mod = await import(conventionPath);
|
|
1576
|
+
const ErrorComponent = mod.default;
|
|
1577
|
+
const app = createSSRApp({
|
|
1578
|
+
render: () => h(ErrorComponent, errorProps)
|
|
1579
|
+
});
|
|
1580
|
+
const rawBody = await renderToString(app);
|
|
1581
|
+
const { styles, body } = unescapeVueStyles(rawBody);
|
|
1582
|
+
const html = `<!DOCTYPE html><html><head>${styles}</head><body><div id="root">${body}</div></body></html>`;
|
|
1583
|
+
return new Response(html, {
|
|
1584
|
+
headers: { "Content-Type": "text/html" },
|
|
1585
|
+
status: 500
|
|
1586
|
+
});
|
|
1587
|
+
};
|
|
1588
|
+
var renderAngularError = async (conventionPath, errorProps) => {
|
|
1589
|
+
const mod = await import(conventionPath);
|
|
1590
|
+
const renderError = mod.default ?? mod.renderError;
|
|
1591
|
+
if (typeof renderError !== "function")
|
|
1592
|
+
return null;
|
|
1593
|
+
const html = renderError(errorProps);
|
|
1594
|
+
return new Response(html, {
|
|
1595
|
+
headers: { "Content-Type": "text/html" },
|
|
1596
|
+
status: 500
|
|
1597
|
+
});
|
|
1598
|
+
};
|
|
1599
|
+
var logConventionRenderError = (framework, label, renderError) => {
|
|
1600
|
+
const message = renderError instanceof Error ? renderError.message : "";
|
|
1601
|
+
if (message.includes("Cannot find module") || message.includes("Cannot find package") || message.includes("not found in module")) {
|
|
1602
|
+
console.error(`[SSR] Convention ${label} page for ${framework} failed: missing framework package. Ensure the ${framework} runtime is installed (e.g. bun add ${framework === "react" ? "react react-dom" : framework}).`);
|
|
1603
|
+
return;
|
|
1604
|
+
}
|
|
1605
|
+
console.error(`[SSR] Failed to render ${framework} convention ${label} page:`, renderError);
|
|
1606
|
+
};
|
|
1607
|
+
var ERROR_RENDERERS = {
|
|
1608
|
+
angular: renderAngularError,
|
|
1609
|
+
react: renderReactError,
|
|
1610
|
+
svelte: renderSvelteError,
|
|
1611
|
+
vue: renderVueError
|
|
1612
|
+
};
|
|
1613
|
+
var renderConventionError = async (framework, pageName, error) => {
|
|
1614
|
+
let conventionPath = resolveErrorConventionPath(framework, pageName);
|
|
1615
|
+
if (!conventionPath && error instanceof Error && error.stack) {
|
|
1616
|
+
for (const match of error.stack.matchAll(/^\s*at\s+([A-Za-z_$][\w$]*)/gm)) {
|
|
1617
|
+
const candidate = match[1];
|
|
1618
|
+
if (!candidate)
|
|
1619
|
+
continue;
|
|
1620
|
+
conventionPath = resolveErrorConventionPath(framework, candidate);
|
|
1621
|
+
if (conventionPath)
|
|
1622
|
+
break;
|
|
1623
|
+
}
|
|
1624
|
+
}
|
|
1625
|
+
if (!conventionPath)
|
|
1626
|
+
return null;
|
|
1627
|
+
const errorProps = buildErrorProps(error);
|
|
1628
|
+
const renderer = ERROR_RENDERERS[framework];
|
|
1629
|
+
if (!renderer)
|
|
1630
|
+
return null;
|
|
1631
|
+
try {
|
|
1632
|
+
return await renderer(conventionPath, errorProps);
|
|
1633
|
+
} catch (renderError) {
|
|
1634
|
+
logConventionRenderError(framework, "error", renderError);
|
|
1635
|
+
}
|
|
1636
|
+
return null;
|
|
1637
|
+
};
|
|
1638
|
+
var renderReactNotFound = async (conventionPath) => {
|
|
1639
|
+
const { createElement } = await import("react");
|
|
1640
|
+
const { renderToReadableStream } = await import("react-dom/server");
|
|
1641
|
+
const mod = await import(conventionPath);
|
|
1642
|
+
const [nfKey] = Object.keys(mod);
|
|
1643
|
+
const NotFoundComponent = mod.default ?? (nfKey ? mod[nfKey] : undefined);
|
|
1644
|
+
const element = createElement(NotFoundComponent);
|
|
1645
|
+
const stream = await renderToReadableStream(element);
|
|
1646
|
+
return new Response(stream, {
|
|
1647
|
+
headers: { "Content-Type": "text/html" },
|
|
1648
|
+
status: 404
|
|
1649
|
+
});
|
|
1650
|
+
};
|
|
1651
|
+
var renderSvelteNotFound = async (conventionPath) => {
|
|
1652
|
+
const { render } = await import("svelte/server");
|
|
1653
|
+
const mod = await import(conventionPath);
|
|
1654
|
+
const NotFoundComponent = mod.default;
|
|
1655
|
+
const { head, body } = render(NotFoundComponent);
|
|
1656
|
+
const html = `<!DOCTYPE html><html><head>${head}</head><body>${body}</body></html>`;
|
|
1657
|
+
return new Response(html, {
|
|
1658
|
+
headers: { "Content-Type": "text/html" },
|
|
1659
|
+
status: 404
|
|
1660
|
+
});
|
|
1661
|
+
};
|
|
1662
|
+
var renderVueNotFound = async (conventionPath) => {
|
|
1663
|
+
const { createSSRApp, h } = await import("vue");
|
|
1664
|
+
const { renderToString } = await import("vue/server-renderer");
|
|
1665
|
+
const mod = await import(conventionPath);
|
|
1666
|
+
const NotFoundComponent = mod.default;
|
|
1667
|
+
const app = createSSRApp({
|
|
1668
|
+
render: () => h(NotFoundComponent)
|
|
1669
|
+
});
|
|
1670
|
+
const rawBody = await renderToString(app);
|
|
1671
|
+
const { styles, body } = unescapeVueStyles(rawBody);
|
|
1672
|
+
const html = `<!DOCTYPE html><html><head>${styles}</head><body><div id="root">${body}</div></body></html>`;
|
|
1673
|
+
return new Response(html, {
|
|
1674
|
+
headers: { "Content-Type": "text/html" },
|
|
1675
|
+
status: 404
|
|
1676
|
+
});
|
|
1677
|
+
};
|
|
1678
|
+
var renderAngularNotFound = async (conventionPath) => {
|
|
1679
|
+
const mod = await import(conventionPath);
|
|
1680
|
+
const renderNotFound = mod.default ?? mod.renderNotFound;
|
|
1681
|
+
if (typeof renderNotFound !== "function")
|
|
1682
|
+
return null;
|
|
1683
|
+
const html = renderNotFound();
|
|
1684
|
+
return new Response(html, {
|
|
1685
|
+
headers: { "Content-Type": "text/html" },
|
|
1686
|
+
status: 404
|
|
1687
|
+
});
|
|
1688
|
+
};
|
|
1689
|
+
var NOT_FOUND_RENDERERS = {
|
|
1690
|
+
angular: renderAngularNotFound,
|
|
1691
|
+
react: renderReactNotFound,
|
|
1692
|
+
svelte: renderSvelteNotFound,
|
|
1693
|
+
vue: renderVueNotFound
|
|
1694
|
+
};
|
|
1695
|
+
var renderConventionNotFound = async (framework) => {
|
|
1696
|
+
const conventionPath = resolveNotFoundConventionPath(framework);
|
|
1697
|
+
if (!conventionPath)
|
|
1698
|
+
return null;
|
|
1699
|
+
const renderer = NOT_FOUND_RENDERERS[framework];
|
|
1700
|
+
if (!renderer)
|
|
1701
|
+
return null;
|
|
1702
|
+
try {
|
|
1703
|
+
return await renderer(conventionPath);
|
|
1704
|
+
} catch (renderError) {
|
|
1705
|
+
logConventionRenderError(framework, "not-found", renderError);
|
|
1706
|
+
}
|
|
1707
|
+
return null;
|
|
1708
|
+
};
|
|
1709
|
+
var NOT_FOUND_PRIORITY = [
|
|
1710
|
+
"react",
|
|
1711
|
+
"svelte",
|
|
1712
|
+
"vue",
|
|
1713
|
+
"angular"
|
|
1714
|
+
];
|
|
1715
|
+
var renderFirstNotFound = async () => {
|
|
1716
|
+
const renderNext = async (frameworks) => {
|
|
1717
|
+
const [framework, ...remaining] = frameworks;
|
|
1718
|
+
if (!framework) {
|
|
1719
|
+
return null;
|
|
1720
|
+
}
|
|
1721
|
+
if (!getMap()[framework]?.defaults?.notFound) {
|
|
1722
|
+
return renderNext(remaining);
|
|
1723
|
+
}
|
|
1724
|
+
const response = await renderConventionNotFound(framework);
|
|
1725
|
+
if (response) {
|
|
1726
|
+
return response;
|
|
1727
|
+
}
|
|
1728
|
+
return renderNext(remaining);
|
|
1729
|
+
};
|
|
1730
|
+
return renderNext(NOT_FOUND_PRIORITY);
|
|
1731
|
+
};
|
|
1732
|
+
|
|
1733
|
+
// src/vue/pageHandler.ts
|
|
1734
|
+
var isRecord2 = (value) => typeof value === "object" && value !== null;
|
|
1735
|
+
var isGenericVueComponent = (value) => typeof value === "function" || isRecord2(value);
|
|
1736
|
+
var readHasIslands = (value) => {
|
|
1737
|
+
if (!isRecord2(value))
|
|
1738
|
+
return false;
|
|
1739
|
+
const hasIslands = value["__ABSOLUTE_PAGE_HAS_ISLANDS__"];
|
|
1740
|
+
return typeof hasIslands === "boolean" ? hasIslands : false;
|
|
1741
|
+
};
|
|
1742
|
+
var readDefaultExport = (value) => isRecord2(value) ? value.default : undefined;
|
|
1743
|
+
var resolveCurrentGeneratedVueModulePath = async (pagePath) => {
|
|
1744
|
+
const pageDirectory = dirname(pagePath);
|
|
1745
|
+
const expectedPrefix = `${basename2(pagePath, ".js").split(".")[0]}.`;
|
|
1746
|
+
try {
|
|
1747
|
+
const pageEntries = await readdir(pageDirectory, {
|
|
1748
|
+
withFileTypes: true
|
|
1749
|
+
});
|
|
1750
|
+
const matchingEntry = pageEntries.find((entry) => entry.isFile() && entry.name.endsWith(".js") && (entry.name === `${expectedPrefix.slice(0, EXCLUDE_LAST_OFFSET)}.js` || entry.name.startsWith(expectedPrefix)));
|
|
1751
|
+
if (!matchingEntry) {
|
|
1752
|
+
return pagePath;
|
|
1753
|
+
}
|
|
1754
|
+
return `${pageDirectory}/${matchingEntry.name}`;
|
|
1755
|
+
} catch {
|
|
1756
|
+
return pagePath;
|
|
1757
|
+
}
|
|
1758
|
+
};
|
|
1759
|
+
var buildDirtyResponse = (headTag, indexPath, maybeProps) => {
|
|
1760
|
+
const propsScript = `window.__INITIAL_PROPS__=${JSON.stringify(maybeProps ?? {})};`;
|
|
1761
|
+
const dirtyFlag = "window.__SSR_DIRTY__=true;";
|
|
1762
|
+
const html = `<!DOCTYPE html><html>${headTag}<body><div id="root"></div>` + `<script>${propsScript}${dirtyFlag}</script>` + `<script type="module" src="${indexPath}"></script>` + `</body></html>`;
|
|
1763
|
+
return new Response(html, {
|
|
1764
|
+
headers: { "Content-Type": "text/html" }
|
|
1765
|
+
});
|
|
1766
|
+
};
|
|
1767
|
+
var primeVueStream = async (stream) => {
|
|
1768
|
+
const reader = stream.getReader();
|
|
1769
|
+
const firstChunk = await reader.read();
|
|
1770
|
+
return { firstChunk, reader };
|
|
1771
|
+
};
|
|
1772
|
+
var handleVuePageRequest = async (input) => {
|
|
1773
|
+
const passedPageComponent = input.Page;
|
|
1774
|
+
const resolvedHeadTag = input.headTag ?? "<head></head>";
|
|
1775
|
+
const resolvedIndexPath = input.indexPath;
|
|
1776
|
+
const resolvedOptions = input;
|
|
1777
|
+
const resolvedPagePath = input.pagePath;
|
|
1778
|
+
const maybeProps = input.props;
|
|
1779
|
+
if (isSsrCacheDirty("vue")) {
|
|
1780
|
+
return buildDirtyResponse(resolvedHeadTag, resolvedIndexPath, maybeProps);
|
|
1781
|
+
}
|
|
1782
|
+
try {
|
|
1783
|
+
const handlerCallsite = resolvedOptions?.collectStreamingSlots === true ? undefined : getCurrentRouteRegistrationCallsite() ?? captureStreamingSlotWarningCallsite();
|
|
1784
|
+
const renderPageResponse = async () => {
|
|
1785
|
+
const resolvePageComponent = async () => {
|
|
1786
|
+
if (isGenericVueComponent(passedPageComponent)) {
|
|
1787
|
+
return {
|
|
1788
|
+
component: passedPageComponent,
|
|
1789
|
+
hasIslands: readHasIslands(passedPageComponent)
|
|
1790
|
+
};
|
|
1791
|
+
}
|
|
1792
|
+
const generatedPagePath = await resolveCurrentGeneratedVueModulePath(resolvedPagePath);
|
|
1793
|
+
const importedPageModule = await import(generatedPagePath);
|
|
1794
|
+
const importedPageComponent = readDefaultExport(importedPageModule) ?? importedPageModule;
|
|
1795
|
+
if (!isGenericVueComponent(importedPageComponent)) {
|
|
1796
|
+
throw new Error(`Invalid Vue page module: ${generatedPagePath}`);
|
|
1797
|
+
}
|
|
1798
|
+
return {
|
|
1799
|
+
component: importedPageComponent,
|
|
1800
|
+
hasIslands: readHasIslands(importedPageModule)
|
|
1801
|
+
};
|
|
1802
|
+
};
|
|
1803
|
+
const resolvedPage = await resolvePageComponent();
|
|
1804
|
+
const { createSSRApp, h } = await import("vue");
|
|
1805
|
+
const { renderToWebStream } = await import("vue/server-renderer");
|
|
1806
|
+
const app = createSSRApp({
|
|
1807
|
+
render: () => h(resolvedPage.component, maybeProps ?? null)
|
|
1808
|
+
});
|
|
1809
|
+
const bodyStream = renderToWebStream(app);
|
|
1810
|
+
const { firstChunk, reader } = await primeVueStream(bodyStream);
|
|
1811
|
+
const head = `<!DOCTYPE html><html>${resolvedHeadTag}<body><div id="root">`;
|
|
1812
|
+
const tail = `</div><script>window.__INITIAL_PROPS__=${JSON.stringify(maybeProps ?? {})}</script><script type="module" src="${resolvedIndexPath}"></script></body></html>`;
|
|
1813
|
+
const stream = new ReadableStream({
|
|
1814
|
+
start(controller) {
|
|
1815
|
+
controller.enqueue(head);
|
|
1816
|
+
if (!firstChunk.done) {
|
|
1817
|
+
controller.enqueue(firstChunk.value);
|
|
1818
|
+
}
|
|
1819
|
+
if (firstChunk.done) {
|
|
1820
|
+
controller.enqueue(tail);
|
|
1821
|
+
controller.close();
|
|
1822
|
+
return;
|
|
1823
|
+
}
|
|
1824
|
+
const pumpLoop = () => {
|
|
1825
|
+
reader.read().then(({ done, value }) => done ? (controller.enqueue(tail), controller.close()) : (controller.enqueue(value), pumpLoop())).catch((err) => controller.error(err));
|
|
1826
|
+
};
|
|
1827
|
+
pumpLoop();
|
|
1828
|
+
}
|
|
1829
|
+
});
|
|
1830
|
+
const htmlStream = injectIslandPageContextStream(stream, {
|
|
1831
|
+
hasIslands: resolvedPage.hasIslands
|
|
1832
|
+
});
|
|
1833
|
+
return new Response(htmlStream, {
|
|
1834
|
+
headers: { "Content-Type": "text/html" }
|
|
1835
|
+
});
|
|
1836
|
+
};
|
|
1837
|
+
return await runWithStreamingSlotWarningScope(() => resolvedOptions?.collectStreamingSlots === true ? withRegisteredStreamingSlots(renderPageResponse, resolvedOptions) : renderPageResponse(), { handlerCallsite });
|
|
1838
|
+
} catch (error) {
|
|
1839
|
+
console.error("[SSR] Vue render error:", error);
|
|
1840
|
+
const pageName = derivePageName(resolvedPagePath);
|
|
1841
|
+
const conventionResponse = await renderConventionError("vue", pageName, error);
|
|
1842
|
+
if (conventionResponse)
|
|
1843
|
+
return conventionResponse;
|
|
1844
|
+
return new Response(ssrErrorPage("vue", error), {
|
|
1845
|
+
headers: { "Content-Type": "text/html" },
|
|
1846
|
+
status: 500
|
|
1847
|
+
});
|
|
1848
|
+
}
|
|
1849
|
+
};
|
|
19
1850
|
export {
|
|
20
1851
|
handleVuePageRequest
|
|
21
1852
|
};
|
|
22
1853
|
|
|
23
|
-
//# debugId=
|
|
1854
|
+
//# debugId=6176FCA802F5452A64756E2164756E21
|
|
24
1855
|
//# sourceMappingURL=server.js.map
|