@vesk/vesk-cli 0.2.58 → 0.2.60
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/cli.js +649 -50
- package/package.json +5 -5
package/dist/cli.js
CHANGED
|
@@ -889,6 +889,9 @@ function block(flags, fn, state = null, co) {
|
|
|
889
889
|
}
|
|
890
890
|
if (active_block !== null) {
|
|
891
891
|
push_block(newBlock, active_block);
|
|
892
|
+
} else {
|
|
893
|
+
newBlock.p = get_orphan_root();
|
|
894
|
+
push_block(newBlock, newBlock.p);
|
|
892
895
|
}
|
|
893
896
|
if ((flags & EFFECT_BLOCK) !== 0) {
|
|
894
897
|
schedule_update(newBlock);
|
|
@@ -978,6 +981,7 @@ function is_destroyed(target_block) {
|
|
|
978
981
|
}
|
|
979
982
|
function destroy_block(block2, remove_dom = true) {
|
|
980
983
|
block2.f ^= DESTROYED;
|
|
984
|
+
unsubscribe_reaction(block2);
|
|
981
985
|
let removed = false;
|
|
982
986
|
const f = block2.f;
|
|
983
987
|
if (remove_dom && (f & (BRANCH_BLOCK | ROOT_BLOCK)) !== 0 && (f & TRY_BLOCK) === 0 || (f & HEAD_BLOCK) !== 0) {
|
|
@@ -1013,6 +1017,28 @@ var init_ripple_utils = __esm({
|
|
|
1013
1017
|
});
|
|
1014
1018
|
|
|
1015
1019
|
// ../runtime/src/ripple-runtime.ts
|
|
1020
|
+
function get_orphan_root() {
|
|
1021
|
+
if (orphan_root === null) {
|
|
1022
|
+
orphan_root = {
|
|
1023
|
+
co: null,
|
|
1024
|
+
d: null,
|
|
1025
|
+
first: null,
|
|
1026
|
+
f: ROOT_BLOCK,
|
|
1027
|
+
fn: null,
|
|
1028
|
+
last: null,
|
|
1029
|
+
next: null,
|
|
1030
|
+
p: null,
|
|
1031
|
+
prev: null,
|
|
1032
|
+
s: null,
|
|
1033
|
+
t: null,
|
|
1034
|
+
tc: null
|
|
1035
|
+
};
|
|
1036
|
+
}
|
|
1037
|
+
return orphan_root;
|
|
1038
|
+
}
|
|
1039
|
+
function is_orphan(block2) {
|
|
1040
|
+
return block2 === null || block2 === void 0 || block2 === orphan_root;
|
|
1041
|
+
}
|
|
1016
1042
|
function increment_clock() {
|
|
1017
1043
|
return ++clock;
|
|
1018
1044
|
}
|
|
@@ -1138,6 +1164,7 @@ function run_block(block2) {
|
|
|
1138
1164
|
try {
|
|
1139
1165
|
active_block = block2;
|
|
1140
1166
|
active_reaction = block2;
|
|
1167
|
+
unsubscribe_reaction(block2);
|
|
1141
1168
|
active_component = block2.co;
|
|
1142
1169
|
destroy_non_branch_children(block2);
|
|
1143
1170
|
run_teardown(block2);
|
|
@@ -1167,10 +1194,10 @@ function run_block(block2) {
|
|
|
1167
1194
|
}
|
|
1168
1195
|
}
|
|
1169
1196
|
function tracked(v, block2, get2, set2) {
|
|
1170
|
-
return new TrackedValue(v, block2 || active_block, get2 || set2 ? { get: get2, set: set2 } : empty_get_set);
|
|
1197
|
+
return new TrackedValue(v, block2 || active_block || get_orphan_root(), get2 || set2 ? { get: get2, set: set2 } : empty_get_set);
|
|
1171
1198
|
}
|
|
1172
1199
|
function derived(fn, block2, get2, set2) {
|
|
1173
|
-
return new DerivedValue(fn, block2 || active_block, get2 || set2 ? { get: get2, set: set2 } : empty_get_set);
|
|
1200
|
+
return new DerivedValue(fn, block2 || active_block || get_orphan_root(), get2 || set2 ? { get: get2, set: set2 } : empty_get_set);
|
|
1174
1201
|
}
|
|
1175
1202
|
function track(v, b, get2, set2) {
|
|
1176
1203
|
if (is_ripple_object(v)) {
|
|
@@ -1193,6 +1220,9 @@ function track(v, b, get2, set2) {
|
|
|
1193
1220
|
}
|
|
1194
1221
|
function create_dependency(tracked2) {
|
|
1195
1222
|
const reaction = active_reaction;
|
|
1223
|
+
if (is_orphan(tracked2.b)) {
|
|
1224
|
+
(tracked2.r ??= /* @__PURE__ */ new Set()).add(reaction);
|
|
1225
|
+
}
|
|
1196
1226
|
const existing = reaction.d;
|
|
1197
1227
|
if (existing !== null) {
|
|
1198
1228
|
reaction.d = existing.n;
|
|
@@ -1367,6 +1397,7 @@ function queue_microtask(fn) {
|
|
|
1367
1397
|
}
|
|
1368
1398
|
function schedule_update(block2) {
|
|
1369
1399
|
if (block2 === null) return;
|
|
1400
|
+
if (block2.p === get_orphan_root() && globalThis.__vsk_ssr) return;
|
|
1370
1401
|
if (scheduler_mode === FLUSH_MICROTASK) {
|
|
1371
1402
|
queue_microtask();
|
|
1372
1403
|
}
|
|
@@ -1426,6 +1457,36 @@ function register_dependency(tracked2) {
|
|
|
1426
1457
|
current2.n = dependency;
|
|
1427
1458
|
}
|
|
1428
1459
|
}
|
|
1460
|
+
function unsubscribe_reaction(reaction) {
|
|
1461
|
+
if (reaction === null) return;
|
|
1462
|
+
let dep = reaction.d;
|
|
1463
|
+
while (dep !== null) {
|
|
1464
|
+
const t = dep.t;
|
|
1465
|
+
if (is_orphan(t.b) && t.r !== null) {
|
|
1466
|
+
t.r.delete(reaction);
|
|
1467
|
+
}
|
|
1468
|
+
dep = dep.n;
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
function schedule_ownerless_update(tracked2, visited) {
|
|
1472
|
+
const subscribers = tracked2.r;
|
|
1473
|
+
if (subscribers === null) return;
|
|
1474
|
+
for (const reaction of Array.from(subscribers)) {
|
|
1475
|
+
if (visited !== null) {
|
|
1476
|
+
if (visited.has(reaction)) continue;
|
|
1477
|
+
visited.add(reaction);
|
|
1478
|
+
}
|
|
1479
|
+
if (reaction.f & DESTROYED) {
|
|
1480
|
+
subscribers.delete(reaction);
|
|
1481
|
+
continue;
|
|
1482
|
+
}
|
|
1483
|
+
if ((reaction.f & DERIVED) !== 0) {
|
|
1484
|
+
schedule_ownerless_update(reaction, visited ?? /* @__PURE__ */ new Set());
|
|
1485
|
+
continue;
|
|
1486
|
+
}
|
|
1487
|
+
schedule_update(reaction);
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1429
1490
|
function get_derived(computed) {
|
|
1430
1491
|
update_derived(computed);
|
|
1431
1492
|
if (tracking) {
|
|
@@ -1493,7 +1554,11 @@ function set(tracked2, value) {
|
|
|
1493
1554
|
}
|
|
1494
1555
|
tracked2.__v = value;
|
|
1495
1556
|
tracked2.c = increment_clock();
|
|
1496
|
-
|
|
1557
|
+
if (!is_orphan(tracked_block)) {
|
|
1558
|
+
schedule_update(tracked_block);
|
|
1559
|
+
} else {
|
|
1560
|
+
schedule_ownerless_update(tracked2, null);
|
|
1561
|
+
}
|
|
1497
1562
|
}
|
|
1498
1563
|
}
|
|
1499
1564
|
function untrack2(fn) {
|
|
@@ -1590,7 +1655,7 @@ function pop_component() {
|
|
|
1590
1655
|
}
|
|
1591
1656
|
active_component = component.p;
|
|
1592
1657
|
}
|
|
1593
|
-
var FLUSH_MICROTASK, FLUSH_SYNC, active_block, active_reaction, active_scope, active_component, is_mutating_allowed, old_values, scheduler_mode, is_micro_task_queued, clock, queued_root_blocks, disable_scoped_flush, queued_microtasks, flush_count, queued_post_block_flush, active_dependency, tracking, teardown, empty_get_set, TrackedValue, DerivedValue;
|
|
1658
|
+
var FLUSH_MICROTASK, FLUSH_SYNC, active_block, active_reaction, active_scope, active_component, is_mutating_allowed, old_values, orphan_root, scheduler_mode, is_micro_task_queued, clock, queued_root_blocks, disable_scoped_flush, queued_microtasks, flush_count, queued_post_block_flush, active_dependency, tracking, teardown, empty_get_set, TrackedValue, DerivedValue;
|
|
1594
1659
|
var init_ripple_runtime = __esm({
|
|
1595
1660
|
"../runtime/src/ripple-runtime.ts"() {
|
|
1596
1661
|
"use strict";
|
|
@@ -1605,6 +1670,7 @@ var init_ripple_runtime = __esm({
|
|
|
1605
1670
|
active_component = null;
|
|
1606
1671
|
is_mutating_allowed = true;
|
|
1607
1672
|
old_values = /* @__PURE__ */ new Map();
|
|
1673
|
+
orphan_root = null;
|
|
1608
1674
|
scheduler_mode = FLUSH_MICROTASK;
|
|
1609
1675
|
is_micro_task_queued = false;
|
|
1610
1676
|
clock = 0;
|
|
@@ -1623,6 +1689,7 @@ var init_ripple_runtime = __esm({
|
|
|
1623
1689
|
c;
|
|
1624
1690
|
d;
|
|
1625
1691
|
f;
|
|
1692
|
+
r;
|
|
1626
1693
|
__v;
|
|
1627
1694
|
constructor(v, block2, a) {
|
|
1628
1695
|
this.a = a;
|
|
@@ -1630,6 +1697,7 @@ var init_ripple_runtime = __esm({
|
|
|
1630
1697
|
this.c = 0;
|
|
1631
1698
|
this.d = null;
|
|
1632
1699
|
this.f = TRACKED;
|
|
1700
|
+
this.r = null;
|
|
1633
1701
|
this.__v = v;
|
|
1634
1702
|
}
|
|
1635
1703
|
get() {
|
|
@@ -1670,6 +1738,7 @@ var init_ripple_runtime = __esm({
|
|
|
1670
1738
|
d;
|
|
1671
1739
|
f;
|
|
1672
1740
|
fn;
|
|
1741
|
+
r;
|
|
1673
1742
|
__v;
|
|
1674
1743
|
constructor(fn, block2, a) {
|
|
1675
1744
|
this.a = a;
|
|
@@ -1680,6 +1749,7 @@ var init_ripple_runtime = __esm({
|
|
|
1680
1749
|
this.d = null;
|
|
1681
1750
|
this.f = DERIVED;
|
|
1682
1751
|
this.fn = fn;
|
|
1752
|
+
this.r = null;
|
|
1683
1753
|
this.__v = UNINITIALIZED;
|
|
1684
1754
|
}
|
|
1685
1755
|
get() {
|
|
@@ -3369,6 +3439,17 @@ ${String(this.root.outerHTML).slice(0, 800)}` : ""),
|
|
|
3369
3439
|
// callee's first claim and resets the deposit so later claims stay
|
|
3370
3440
|
// positional against the advancing cursor. Consumed synchronously on the
|
|
3371
3441
|
// same walker reference the call was made through.
|
|
3442
|
+
//
|
|
3443
|
+
// The deposit is ALSO consumed implicitly by the next claim made through this
|
|
3444
|
+
// walker when the caller passed no explicit skipK. A component written in plain
|
|
3445
|
+
// JS (lucide-vesk icons are the common case) never calls `takeSkipK`, so
|
|
3446
|
+
// before this the deposit was silently dropped: the icon's `nextElement("svg")`
|
|
3447
|
+
// claimed the slot still holding the STATIC residue in front of it
|
|
3448
|
+
// (`<button><span>Apply Now</span><svg/></button>`), the descriptor missed on
|
|
3449
|
+
// `<span>`, and the walker detached server-rendered content that no client
|
|
3450
|
+
// program had any intention of replacing. Implicit consumption keeps static
|
|
3451
|
+
// residue out of the way for plain-JS components exactly as it is for
|
|
3452
|
+
// compiled ones.
|
|
3372
3453
|
inheritOffset = 0;
|
|
3373
3454
|
injectSkipK(n) {
|
|
3374
3455
|
this.inheritOffset = n;
|
|
@@ -3382,7 +3463,11 @@ ${String(this.root.outerHTML).slice(0, 800)}` : ""),
|
|
|
3382
3463
|
if (globalThis.__vesk_hydrate_debug) {
|
|
3383
3464
|
console.error("[hyd-dbg] claimAt", tag, "skip=", skipK, "idx=", this.idx, "els=", this.els.length);
|
|
3384
3465
|
}
|
|
3385
|
-
let
|
|
3466
|
+
let offset2 = skipK || 0;
|
|
3467
|
+
const inherited = this.inheritOffset;
|
|
3468
|
+
this.inheritOffset = 0;
|
|
3469
|
+
if (!offset2) offset2 = inherited;
|
|
3470
|
+
let target = this.advancePastSkippable(this.idx + offset2);
|
|
3386
3471
|
if (target > this.els.length) target = this.idx;
|
|
3387
3472
|
while (target < this.els.length) {
|
|
3388
3473
|
const el = this.els[target];
|
|
@@ -18305,6 +18390,20 @@ function tokenizeCode(code) {
|
|
|
18305
18390
|
}
|
|
18306
18391
|
});
|
|
18307
18392
|
}
|
|
18393
|
+
function collectStringDelimiters(code, tokens) {
|
|
18394
|
+
const t = tokens == null ? tokenizeCode(code) : tokens;
|
|
18395
|
+
if (t === null) return null;
|
|
18396
|
+
const starts = /* @__PURE__ */ new Set();
|
|
18397
|
+
let ti = 0;
|
|
18398
|
+
for (let i = 0; i < code.length; i++) {
|
|
18399
|
+
const c = code.charCodeAt(i);
|
|
18400
|
+
if (c !== 34 && c !== 39 && c !== 96) continue;
|
|
18401
|
+
while (ti < t.length && t[ti].end <= i) ti++;
|
|
18402
|
+
const covered = ti < t.length && t[ti].start <= i;
|
|
18403
|
+
if (!covered || QUOTED_LABELS.has(t[ti].label)) starts.add(i);
|
|
18404
|
+
}
|
|
18405
|
+
return starts;
|
|
18406
|
+
}
|
|
18308
18407
|
function containsIdentifier(code, name) {
|
|
18309
18408
|
const tokens = tokenizeCode(code);
|
|
18310
18409
|
if (tokens !== null) {
|
|
@@ -18496,33 +18595,33 @@ function manualExtractImportNames(importText) {
|
|
|
18496
18595
|
}
|
|
18497
18596
|
return names;
|
|
18498
18597
|
}
|
|
18499
|
-
function hasTopLevelValueDeclaration(code, name) {
|
|
18500
|
-
const
|
|
18501
|
-
if (
|
|
18598
|
+
function hasTopLevelValueDeclaration(code, name, tokens) {
|
|
18599
|
+
const t = tokens == null ? tokenizeCode(code) : tokens;
|
|
18600
|
+
if (t === null) return false;
|
|
18502
18601
|
const declWords = ["const", "let", "var", "function", "class"];
|
|
18503
|
-
for (let i = 1; i <
|
|
18504
|
-
if (
|
|
18505
|
-
const prev =
|
|
18602
|
+
for (let i = 1; i < t.length; i++) {
|
|
18603
|
+
if (t[i].label !== "name" || t[i].value !== name) continue;
|
|
18604
|
+
const prev = t[i - 1];
|
|
18506
18605
|
if (!prev || !declWords.includes(prev.value)) continue;
|
|
18507
18606
|
if (i >= 2) {
|
|
18508
|
-
const pp2 =
|
|
18607
|
+
const pp2 = t[i - 2];
|
|
18509
18608
|
if (pp2 && pp2.label === "name" && pp2.value === "export") continue;
|
|
18510
18609
|
}
|
|
18511
18610
|
return true;
|
|
18512
18611
|
}
|
|
18513
18612
|
return false;
|
|
18514
18613
|
}
|
|
18515
|
-
function findSpecifierExports(code) {
|
|
18516
|
-
const
|
|
18517
|
-
if (
|
|
18614
|
+
function findSpecifierExports(code, tokens) {
|
|
18615
|
+
const t = tokens == null ? tokenizeCode(code) : tokens;
|
|
18616
|
+
if (t === null) return [];
|
|
18518
18617
|
const out = [];
|
|
18519
|
-
for (let i = 0; i <
|
|
18520
|
-
if (
|
|
18521
|
-
if (!
|
|
18618
|
+
for (let i = 0; i < t.length; i++) {
|
|
18619
|
+
if (t[i].label !== "export") continue;
|
|
18620
|
+
if (!t[i + 1] || t[i + 1].label !== "{") continue;
|
|
18522
18621
|
let k = i + 2;
|
|
18523
18622
|
let depth = 1;
|
|
18524
|
-
for (; k <
|
|
18525
|
-
const lbl =
|
|
18623
|
+
for (; k < t.length; k++) {
|
|
18624
|
+
const lbl = t[k].label;
|
|
18526
18625
|
if (lbl === "string") {
|
|
18527
18626
|
continue;
|
|
18528
18627
|
}
|
|
@@ -18533,8 +18632,8 @@ function findSpecifierExports(code) {
|
|
|
18533
18632
|
}
|
|
18534
18633
|
}
|
|
18535
18634
|
let isReexport = false;
|
|
18536
|
-
for (let j = k + 1; j <
|
|
18537
|
-
const lbl =
|
|
18635
|
+
for (let j = k + 1; j < t.length; j++) {
|
|
18636
|
+
const lbl = t[j].label;
|
|
18538
18637
|
if (lbl === "string") {
|
|
18539
18638
|
isReexport = true;
|
|
18540
18639
|
break;
|
|
@@ -18542,10 +18641,10 @@ function findSpecifierExports(code) {
|
|
|
18542
18641
|
if (lbl === ";" || lbl === "export" || lbl === "import" || lbl === "}") break;
|
|
18543
18642
|
}
|
|
18544
18643
|
if (depth !== 0 || isReexport) continue;
|
|
18545
|
-
const pairs = readSpecifierPairs(code,
|
|
18644
|
+
const pairs = readSpecifierPairs(code, t[i + 1].end, t[k].end);
|
|
18546
18645
|
if (pairs === null) continue;
|
|
18547
|
-
const stmtEnd =
|
|
18548
|
-
for (const [local, exported] of pairs) out.push({ local, exported, start:
|
|
18646
|
+
const stmtEnd = t[k].end;
|
|
18647
|
+
for (const [local, exported] of pairs) out.push({ local, exported, start: t[i].start, end: stmtEnd });
|
|
18549
18648
|
i = k;
|
|
18550
18649
|
}
|
|
18551
18650
|
return out;
|
|
@@ -18605,12 +18704,14 @@ function stripTrackDeclMarkers(text, base, node) {
|
|
|
18605
18704
|
}
|
|
18606
18705
|
return out + text.slice(prev);
|
|
18607
18706
|
}
|
|
18707
|
+
var QUOTED_LABELS;
|
|
18608
18708
|
var init_tokens = __esm({
|
|
18609
18709
|
"../compiler/src/tokens.ts"() {
|
|
18610
18710
|
"use strict";
|
|
18611
18711
|
init_parser();
|
|
18612
18712
|
init_vesk_plugin();
|
|
18613
18713
|
init_scan();
|
|
18714
|
+
QUOTED_LABELS = /* @__PURE__ */ new Set(["string", "template", "`", "backQuote"]);
|
|
18614
18715
|
}
|
|
18615
18716
|
});
|
|
18616
18717
|
|
|
@@ -18634,7 +18735,7 @@ function offsetToLineCol(source, offset2) {
|
|
|
18634
18735
|
}
|
|
18635
18736
|
return { line, column };
|
|
18636
18737
|
}
|
|
18637
|
-
function preprocessForClauses(source) {
|
|
18738
|
+
function preprocessForClauses(source, delimiters) {
|
|
18638
18739
|
const annotations = [];
|
|
18639
18740
|
const chars = source.split("");
|
|
18640
18741
|
const isString = (ch) => ch === '"' || ch === "'" || ch === "`";
|
|
@@ -18642,6 +18743,10 @@ function preprocessForClauses(source) {
|
|
|
18642
18743
|
while (i < source.length) {
|
|
18643
18744
|
const ch = source[i];
|
|
18644
18745
|
if (isString(ch)) {
|
|
18746
|
+
if (delimiters && !delimiters.has(i)) {
|
|
18747
|
+
i++;
|
|
18748
|
+
continue;
|
|
18749
|
+
}
|
|
18645
18750
|
const quote = ch;
|
|
18646
18751
|
let j = i + 1;
|
|
18647
18752
|
let tplDepth = 0;
|
|
@@ -18996,9 +19101,11 @@ function parseGeneratedJs(source) {
|
|
|
18996
19101
|
}
|
|
18997
19102
|
function parse4(source, options = {}) {
|
|
18998
19103
|
const ParserClass = createBaseParser();
|
|
18999
|
-
const
|
|
19104
|
+
const sourceTokens = tokenizeCode(source);
|
|
19105
|
+
const delimiters = sourceTokens === null ? null : collectStringDelimiters(source, sourceTokens);
|
|
19106
|
+
const { code, annotations } = preprocessForClauses(blankGenericArrowTypeParams(blankComments(source)), delimiters);
|
|
19000
19107
|
const vskSource = !options.filename || String(options.filename).endsWith(".vsk");
|
|
19001
|
-
const specifierExports = vskSource ? findSpecifierExports(code).filter((e) => !hasTopLevelValueDeclaration(code, e.local)) : [];
|
|
19108
|
+
const specifierExports = vskSource && sourceTokens !== null ? findSpecifierExports(code, sourceTokens).filter((e) => !hasTopLevelValueDeclaration(code, e.local, sourceTokens)) : [];
|
|
19002
19109
|
let parseable = code;
|
|
19003
19110
|
if (specifierExports.length > 0) {
|
|
19004
19111
|
const edits = specifierExports.map((e) => code.slice(e.start, e.end)).map((text) => text.split("").map((ch) => ch === "\n" ? "\n" : " ").join(""));
|
|
@@ -21909,6 +22016,7 @@ function warnStaleConstBindings(comp, file) {
|
|
|
21909
22016
|
for (const d of st.declarations || []) {
|
|
21910
22017
|
if (d.id?.type !== "Identifier" || !d.init) continue;
|
|
21911
22018
|
if (reactive.has(d.id.name)) continue;
|
|
22019
|
+
if (d.init.type === "ArrowFunctionExpression" || d.init.type === "FunctionExpression") continue;
|
|
21912
22020
|
if (d.init.type === "Identifier" && reactive.has(d.init.name)) continue;
|
|
21913
22021
|
const seen = /* @__PURE__ */ new Set();
|
|
21914
22022
|
collectIdentifiers(d.init, seen);
|
|
@@ -30383,8 +30491,13 @@ function emitNode(ctx2, node, tracked2, effectsVar, parentVar, compPrefix = "__c
|
|
|
30383
30491
|
if (node instanceof SlotNode) {
|
|
30384
30492
|
if (!parentVar) {
|
|
30385
30493
|
if (ctx2.hydrate) {
|
|
30494
|
+
const promptExpr = ctx2.markerless && (regionBudget || skipK > 0) ? markerlessSkipExpr(regionBudget, skipK) : null;
|
|
30386
30495
|
ctx2.push(`if (props.children !== undefined && props.children !== null) {`);
|
|
30387
30496
|
ctx2.push(` if (typeof props.children === 'function') {`);
|
|
30497
|
+
if (promptExpr) {
|
|
30498
|
+
ctx2.push(` ${ctx2.walker}.injectSkipK(${promptExpr});`);
|
|
30499
|
+
if (regionBudget && ctx2.markerless) ctx2.push(` ${regionBudget} = 0;`);
|
|
30500
|
+
}
|
|
30388
30501
|
ctx2.push(` __pendingChild = props.children(__hydrate);`);
|
|
30389
30502
|
ctx2.push(` } else if (__hydrate && __hydrate.root) {`);
|
|
30390
30503
|
ctx2.push(` __hydrate.root.appendChild(toDomNode(props.children));`);
|
|
@@ -30704,6 +30817,9 @@ function isReactiveExpression(node, tracked2) {
|
|
|
30704
30817
|
if (!ast) return false;
|
|
30705
30818
|
let reactive = false;
|
|
30706
30819
|
walk4(ast, tracked2, {
|
|
30820
|
+
CallExpression() {
|
|
30821
|
+
reactive = true;
|
|
30822
|
+
},
|
|
30707
30823
|
Identifier(n, context) {
|
|
30708
30824
|
if (reactive) return;
|
|
30709
30825
|
const parent = context.path.at(-1);
|
|
@@ -30831,7 +30947,7 @@ function emitComponentCall(ctx2, node, tracked2, effectsVar, parentVar, compPref
|
|
|
30831
30947
|
ctx2.push(`return $f; })();`);
|
|
30832
30948
|
propsEntries.push(`children: ${frag}`);
|
|
30833
30949
|
}
|
|
30834
|
-
if (ctx2.markerless && promptExpr
|
|
30950
|
+
if (ctx2.markerless && promptExpr) {
|
|
30835
30951
|
ctx2.push(`${walkerArg}.injectSkipK(${promptExpr});`);
|
|
30836
30952
|
}
|
|
30837
30953
|
ctx2.push(`let ${v} = undefined;`);
|
|
@@ -35775,6 +35891,20 @@ ${serverStoreLine}
|
|
|
35775
35891
|
});
|
|
35776
35892
|
}
|
|
35777
35893
|
|
|
35894
|
+
// Persisted-store pre-paint payload (buildStorePrePaintPayload) \u2014 same
|
|
35895
|
+
// token-stash/consume contract as /ssr-data.js, own store so neither handoff
|
|
35896
|
+
// can eat the other.
|
|
35897
|
+
if (pathname === '/store-init.js') {
|
|
35898
|
+
const initToken = url.searchParams.get('t') || '';
|
|
35899
|
+
const initStore = (globalThis.__vsk_store_init_payload_store || {});
|
|
35900
|
+
const initPayload = initStore[initToken];
|
|
35901
|
+
if (initPayload !== undefined) delete initStore[initToken];
|
|
35902
|
+
return new Response(initPayload ?? '// no store init', {
|
|
35903
|
+
status: 200,
|
|
35904
|
+
headers: { 'Content-Type': 'application/javascript', 'Cache-Control': 'no-store' },
|
|
35905
|
+
});
|
|
35906
|
+
}
|
|
35907
|
+
|
|
35778
35908
|
${eventsStartLine}
|
|
35779
35909
|
let mwCtx = { params: {}, url, locals: ${localsSeed}, cookies: {}, request, resolveUrl(u) { return new URL(u, request.url).href; }, set() {}, get() { return undefined; } };
|
|
35780
35910
|
if (${hasMwLiteral}) {
|
|
@@ -46674,7 +46804,7 @@ function offsetToLineCol3(source, offset2) {
|
|
|
46674
46804
|
}
|
|
46675
46805
|
return { line, column };
|
|
46676
46806
|
}
|
|
46677
|
-
function preprocessForClauses2(source) {
|
|
46807
|
+
function preprocessForClauses2(source, delimiters) {
|
|
46678
46808
|
const annotations = [];
|
|
46679
46809
|
const chars = source.split("");
|
|
46680
46810
|
const isString = (ch) => ch === '"' || ch === "'" || ch === "`";
|
|
@@ -46682,6 +46812,10 @@ function preprocessForClauses2(source) {
|
|
|
46682
46812
|
while (i < source.length) {
|
|
46683
46813
|
const ch = source[i];
|
|
46684
46814
|
if (isString(ch)) {
|
|
46815
|
+
if (delimiters && !delimiters.has(i)) {
|
|
46816
|
+
i++;
|
|
46817
|
+
continue;
|
|
46818
|
+
}
|
|
46685
46819
|
const quote = ch;
|
|
46686
46820
|
let j = i + 1;
|
|
46687
46821
|
let tplDepth = 0;
|
|
@@ -47058,9 +47192,11 @@ function createBaseParser2() {
|
|
|
47058
47192
|
}
|
|
47059
47193
|
function parse5(source, options = {}) {
|
|
47060
47194
|
const ParserClass = createBaseParser2();
|
|
47061
|
-
const
|
|
47195
|
+
const sourceTokens = tokenizeCode(source);
|
|
47196
|
+
const delimiters = sourceTokens === null ? null : collectStringDelimiters(source, sourceTokens);
|
|
47197
|
+
const { code, annotations } = preprocessForClauses2(blankGenericArrowTypeParams2(blankComments(source)), delimiters);
|
|
47062
47198
|
const vskSource = !options.filename || String(options.filename).endsWith(".vsk");
|
|
47063
|
-
const specifierExports = vskSource ? findSpecifierExports(code).filter((e) => !hasTopLevelValueDeclaration(code, e.local)) : [];
|
|
47199
|
+
const specifierExports = vskSource && sourceTokens !== null ? findSpecifierExports(code, sourceTokens).filter((e) => !hasTopLevelValueDeclaration(code, e.local, sourceTokens)) : [];
|
|
47064
47200
|
let parseable = code;
|
|
47065
47201
|
if (specifierExports.length > 0) {
|
|
47066
47202
|
const edits = specifierExports.map((e) => code.slice(e.start, e.end)).map((text) => text.split("").map((ch) => ch === "\n" ? "\n" : " ").join(""));
|
|
@@ -48015,6 +48151,7 @@ async function bundleRuntime(appDir, outDir) {
|
|
|
48015
48151
|
`import { renderPage, renderFullPage, renderPageStream, compileFile, setRuntimeModule, setVskHydrate, hydratePrecompile, assertSameOrigin, withSsrStore } from ${JSON.stringify(resolve3(compilerRoot, "server-codegen.js"))};`,
|
|
48016
48152
|
`import { parseCookies } from ${JSON.stringify(resolve3(compilerRoot, "server-cookies.js"))};`,
|
|
48017
48153
|
`import * as __veskRuntime from ${JSON.stringify(resolve3(runtimeRoot, "index-server.js"))};`,
|
|
48154
|
+
`import * as __persistence from ${JSON.stringify(resolve3(runtimeRoot, "store-persistence.js"))};`,
|
|
48018
48155
|
"",
|
|
48019
48156
|
"// Inject runtime module so server-codegen can find components like NavLink, Link, etc.",
|
|
48020
48157
|
"setRuntimeModule(__veskRuntime);",
|
|
@@ -48080,6 +48217,40 @@ async function bundleRuntime(appDir, outDir) {
|
|
|
48080
48217
|
" return '/ssr-data.js?t=' + token;",
|
|
48081
48218
|
"}",
|
|
48082
48219
|
"",
|
|
48220
|
+
"// Persisted-store SSR continuity. `installPersistedStoreServerHooks` installs the",
|
|
48221
|
+
"// adapter-side read hook; `get/getReset` handle the per-request key registry",
|
|
48222
|
+
"// the server drains into the pre-paint payload. The init payload is delivered",
|
|
48223
|
+
"// as an origin-served script (/store-init.js?t=...) exactly like /ssr-data.js",
|
|
48224
|
+
"// so strict CSP (no unsafe-inline) cannot block it; it is never inlined.",
|
|
48225
|
+
"export const installPersistedStoreServerHooks = __persistence.installPersistedStoreServerHooks;",
|
|
48226
|
+
"export const persistedStoreCookieName = __persistence.persistedStoreCookieName;",
|
|
48227
|
+
"export const getPersistedStoreKeys = __persistence.getPersistedStoreKeys;",
|
|
48228
|
+
"export const resetPersistedStoreKeys = __persistence.resetPersistedStoreKeys;",
|
|
48229
|
+
"export const buildStorePrePaintPayload = __persistence.buildStorePrePaintPayload;",
|
|
48230
|
+
"export const storeInitScriptTag = __persistence.storeInitScriptTag;",
|
|
48231
|
+
"",
|
|
48232
|
+
"// Stash the pre-paint payload under a CSPRNG token and return the origin URL",
|
|
48233
|
+
"// the blocking <head> script points at. Own token store (NOT __vsk_ssr_payload_store)",
|
|
48234
|
+
"// so consuming the page hydration handoff never eats the store-init payload",
|
|
48235
|
+
"// and vice versa. Same 100-entry bound as /ssr-data.js.",
|
|
48236
|
+
"export function storeInitScriptGlobal(payload) {",
|
|
48237
|
+
" if (!payload) return null;",
|
|
48238
|
+
" const bytes = new Uint8Array(12);",
|
|
48239
|
+
" crypto.getRandomValues(bytes);",
|
|
48240
|
+
" let tk = '';",
|
|
48241
|
+
" for (const b of bytes) tk += b.toString(16).padStart(2, '0');",
|
|
48242
|
+
" const token = tk;",
|
|
48243
|
+
" const store = (globalThis.__vsk_store_init_payload_store ||= {});",
|
|
48244
|
+
" store[token] = payload;",
|
|
48245
|
+
" const keys = Object.keys(store);",
|
|
48246
|
+
" if (keys.length > 100) {",
|
|
48247
|
+
" for (let i = 0; i < keys.length - 100; i++) {",
|
|
48248
|
+
" delete store[keys[i]];",
|
|
48249
|
+
" }",
|
|
48250
|
+
" }",
|
|
48251
|
+
" return '/store-init.js?t=' + token;",
|
|
48252
|
+
"}",
|
|
48253
|
+
"",
|
|
48083
48254
|
"// Re-export runtime classes used by API routes",
|
|
48084
48255
|
"export const VeskRequest = __veskRuntime.VeskRequest;",
|
|
48085
48256
|
"export const PayloadTooLargeError = __veskRuntime.PayloadTooLargeError;",
|
|
@@ -48390,6 +48561,51 @@ function buildParamExtraction(node, urlParts) {
|
|
|
48390
48561
|
walk9(node);
|
|
48391
48562
|
return parts;
|
|
48392
48563
|
}
|
|
48564
|
+
function persistedStoreSsrCode() {
|
|
48565
|
+
return [
|
|
48566
|
+
"// \u2500\u2500 Persisted-store SSR continuity (createStore / createPathStore persist) \u2500\u2500",
|
|
48567
|
+
"// Reads a persisted store's cookie value through the adapter request context.",
|
|
48568
|
+
"// Client writes mirror URL-encoded; decode on the way back (best effort).",
|
|
48569
|
+
"function __persistRead(key) {",
|
|
48570
|
+
" const cookieName = persistedStoreCookieName(key);",
|
|
48571
|
+
" const req = globalThis.__vesk_request;",
|
|
48572
|
+
" if (!req) return null;",
|
|
48573
|
+
" const c = req.cookies || {};",
|
|
48574
|
+
" const v = typeof c.get === 'function' ? c.get(cookieName) : c[cookieName];",
|
|
48575
|
+
" if (v == null) return null;",
|
|
48576
|
+
" try { return decodeURIComponent(String(v)); } catch { return String(v); }",
|
|
48577
|
+
"}",
|
|
48578
|
+
"",
|
|
48579
|
+
"// Drain this request's registered persisted keys into a served pre-paint",
|
|
48580
|
+
"// script (/store-init.js?t=...) then forget them. `token` selects the",
|
|
48581
|
+
"// render's bucket for callers outside the ALS scope (the no-layout stream",
|
|
48582
|
+
"// path captures its token at the renderPageStream call site); the layout",
|
|
48583
|
+
"// path runs this inside the scope and relies on the ambient token.",
|
|
48584
|
+
"function __storeInitTag(token) {",
|
|
48585
|
+
" const keys = getPersistedStoreKeys(token);",
|
|
48586
|
+
" if (keys.length === 0) { resetPersistedStoreKeys(token); return ''; }",
|
|
48587
|
+
" const values = {};",
|
|
48588
|
+
" for (let __i = 0; __i < keys.length; __i++) values[keys[__i]] = __persistRead(keys[__i]);",
|
|
48589
|
+
" resetPersistedStoreKeys(token);",
|
|
48590
|
+
" const payload = buildStorePrePaintPayload(values);",
|
|
48591
|
+
" const url = storeInitScriptGlobal(payload);",
|
|
48592
|
+
" return url ? storeInitScriptTag(url) : '';",
|
|
48593
|
+
"}",
|
|
48594
|
+
"",
|
|
48595
|
+
"// Inject the blocking store-init <script src> into a full HTML string",
|
|
48596
|
+
"// (before </head>; append if the document has no head).",
|
|
48597
|
+
"function __injectStoreInit(html) {",
|
|
48598
|
+
" const tag = __storeInitTag();",
|
|
48599
|
+
" if (tag === '') return html;",
|
|
48600
|
+
" const idx = html.lastIndexOf('</head>');",
|
|
48601
|
+
" if (idx === -1) return html + tag;",
|
|
48602
|
+
" return html.slice(0, idx) + tag + html.slice(idx);",
|
|
48603
|
+
"}",
|
|
48604
|
+
"",
|
|
48605
|
+
"installPersistedStoreServerHooks({ read: __persistRead });",
|
|
48606
|
+
""
|
|
48607
|
+
].join("\n");
|
|
48608
|
+
}
|
|
48393
48609
|
function generateSsrFunction(routeNode, appDir, outDir, componentMap, options) {
|
|
48394
48610
|
const ancestorLayouts = options?.ancestorLayouts || [];
|
|
48395
48611
|
const middlewareCode = options?.middlewareCode || null;
|
|
@@ -48491,6 +48707,7 @@ ${layoutDecls.map((d) => " " + d.compiled + ",").join("\n")}
|
|
|
48491
48707
|
"",
|
|
48492
48708
|
"async function __renderHtml(params, requestUrl) {",
|
|
48493
48709
|
" return withSsrStore(async () => {",
|
|
48710
|
+
" resetPersistedStoreKeys();",
|
|
48494
48711
|
" let page;",
|
|
48495
48712
|
" let caughtError = null;",
|
|
48496
48713
|
" const __expose = process.env.NODE_ENV !== 'production';",
|
|
@@ -48511,7 +48728,7 @@ ${layoutDecls.map((d) => " " + d.compiled + ",").join("\n")}
|
|
|
48511
48728
|
" if (_inner.head) _head = _inner.head + _head;",
|
|
48512
48729
|
" }",
|
|
48513
48730
|
" const html = await renderFullPage('', _layoutCompList[0], { params, children: _body }, __componentRegistry, { hydrate: true, cached: _layoutCompiledList[0]" + bakedOptions + clientScriptOption + dataScriptOption + ", pageHead: _head });",
|
|
48514
|
-
" return new Response(html, { headers: { 'Content-Type': 'text/html' }, status: caughtError ? 500 : 200 });",
|
|
48731
|
+
" return new Response(__injectStoreInit(html), { headers: { 'Content-Type': 'text/html' }, status: caughtError ? 500 : 200 });",
|
|
48515
48732
|
" });",
|
|
48516
48733
|
"}",
|
|
48517
48734
|
""
|
|
@@ -48530,25 +48747,48 @@ ${layoutDecls.map((d) => " " + d.compiled + ",").join("\n")}
|
|
|
48530
48747
|
"async function __renderHtml(params, requestUrl) {",
|
|
48531
48748
|
" return withSsrStore(async () => {",
|
|
48532
48749
|
" let stream;",
|
|
48750
|
+
// The streamed no-layout page emits its <head> before the component body
|
|
48751
|
+
// renders, so its persisted stores don't exist yet when the head is
|
|
48752
|
+
// flushed — the pre-paint tag therefore goes into the final chunk, right
|
|
48753
|
+
// before </body> (still a blocking, pre-paint script). Capture the render
|
|
48754
|
+
// token now (renderPageStream adopts this exact ambient store) so the
|
|
48755
|
+
// registry drain in the consumer's start() can hit the right bucket even
|
|
48756
|
+
// though it runs outside the ALS scope.
|
|
48757
|
+
" const __streamToken = globalThis.__vsk_ssr_token || '';",
|
|
48533
48758
|
" try {",
|
|
48534
48759
|
" stream = renderPageStream('', _comp, { params }, __componentRegistry, { hydrate: true, cached: _compiled" + bakedOptions + clientScriptOption + dataScriptOption + " });",
|
|
48535
48760
|
" } catch (err) {",
|
|
48536
48761
|
" if (err && (err.name === 'NotFoundError' || err.name === 'Redirect')) throw err;",
|
|
48537
48762
|
" const html = await __renderErrorFullPage(params, requestUrl, err);",
|
|
48538
|
-
" return new Response(html, { headers: { 'Content-Type': 'text/html' }, status: 500 });",
|
|
48763
|
+
" return new Response(__injectStoreInit(html), { headers: { 'Content-Type': 'text/html' }, status: 500 });",
|
|
48539
48764
|
" }",
|
|
48540
48765
|
" return new Response(new ReadableStream({",
|
|
48541
48766
|
" async start(controller) {",
|
|
48542
48767
|
" const enc = new TextEncoder();",
|
|
48768
|
+
" let __tail = null;",
|
|
48769
|
+
" resetPersistedStoreKeys(__streamToken);",
|
|
48543
48770
|
" try {",
|
|
48544
48771
|
" for await (const chunk of stream) {",
|
|
48545
|
-
" controller.enqueue(enc.encode(
|
|
48772
|
+
" if (__tail !== null) controller.enqueue(enc.encode(__tail));",
|
|
48773
|
+
" __tail = chunk;",
|
|
48774
|
+
" }",
|
|
48775
|
+
" if (__tail !== null) {",
|
|
48776
|
+
" const __tag = __storeInitTag(__streamToken);",
|
|
48777
|
+
" if (__tag !== '') {",
|
|
48778
|
+
" const __bi = __tail.lastIndexOf('</body>');",
|
|
48779
|
+
" __tail = __bi === -1 ? __tail + __tag : __tail.slice(0, __bi) + __tag + __tail.slice(__bi);",
|
|
48780
|
+
" }",
|
|
48781
|
+
" controller.enqueue(enc.encode(__tail));",
|
|
48782
|
+
" } else {",
|
|
48783
|
+
" // Empty stream (no chunks) \u2014 nothing to attach the tag to; just",
|
|
48784
|
+
" // clear the registry so a later render can't inherit these keys.",
|
|
48785
|
+
" resetPersistedStoreKeys(__streamToken);",
|
|
48546
48786
|
" }",
|
|
48547
48787
|
" } catch (err) {",
|
|
48548
48788
|
" if (err && (err.name === 'NotFoundError' || err.name === 'Redirect')) throw err;",
|
|
48549
48789
|
" try {",
|
|
48550
48790
|
" const html = await __renderErrorFullPage(params, requestUrl, err);",
|
|
48551
|
-
" controller.enqueue(enc.encode(html));",
|
|
48791
|
+
" controller.enqueue(enc.encode(__injectStoreInit(html)));",
|
|
48552
48792
|
" } catch {}",
|
|
48553
48793
|
" }",
|
|
48554
48794
|
" controller.close();",
|
|
@@ -48559,6 +48799,7 @@ ${layoutDecls.map((d) => " " + d.compiled + ",").join("\n")}
|
|
|
48559
48799
|
""
|
|
48560
48800
|
].join("\n");
|
|
48561
48801
|
}
|
|
48802
|
+
const persistCode = persistedStoreSsrCode();
|
|
48562
48803
|
let dataCode;
|
|
48563
48804
|
const exposeErr = "process.env.NODE_ENV !== 'production'";
|
|
48564
48805
|
const dataNavCleanup = [
|
|
@@ -48572,6 +48813,9 @@ ${layoutDecls.map((d) => " " + d.compiled + ",").join("\n")}
|
|
|
48572
48813
|
// process-global token — the cross-request data-slot race, for good. The
|
|
48573
48814
|
// token dies with the withSsrStore scope wrapped around this block instead.
|
|
48574
48815
|
" delete globalThis.__vsk_ssr_data;",
|
|
48816
|
+
// SPA data-nav only runs renderPage, so the persisted-store registration
|
|
48817
|
+
// bucket would otherwise keep this request's keys forever.
|
|
48818
|
+
" resetPersistedStoreKeys();",
|
|
48575
48819
|
" }"
|
|
48576
48820
|
];
|
|
48577
48821
|
const dataNavWrap = (body) => [
|
|
@@ -48756,7 +49000,7 @@ ${layoutDecls.map((d) => " " + d.compiled + ",").join("\n")}
|
|
|
48756
49000
|
""
|
|
48757
49001
|
].join("\n");
|
|
48758
49002
|
const funcCode = [
|
|
48759
|
-
"import { renderFullPage, renderPageStream, renderPage, hydratePrecompile, parseCookies, getAction, validateActionInput, issuesToFieldMap, storeDataScriptGlobal, withSsrStore, assertSameOrigin, VeskRequest } from '../runtime.js';",
|
|
49003
|
+
"import { renderFullPage, renderPageStream, renderPage, hydratePrecompile, parseCookies, getAction, validateActionInput, issuesToFieldMap, storeDataScriptGlobal, withSsrStore, assertSameOrigin, VeskRequest, installPersistedStoreServerHooks, persistedStoreCookieName, getPersistedStoreKeys, resetPersistedStoreKeys, buildStorePrePaintPayload, storeInitScriptGlobal, storeInitScriptTag } from '../runtime.js';",
|
|
48760
49004
|
"",
|
|
48761
49005
|
middlewareCode || "",
|
|
48762
49006
|
registryCode,
|
|
@@ -48765,6 +49009,8 @@ ${layoutDecls.map((d) => " " + d.compiled + ",").join("\n")}
|
|
|
48765
49009
|
paramsCode,
|
|
48766
49010
|
htmlFnCode,
|
|
48767
49011
|
"",
|
|
49012
|
+
persistCode,
|
|
49013
|
+
"",
|
|
48768
49014
|
"export async function handle(request) {",
|
|
48769
49015
|
" const url = new URL(request.url);",
|
|
48770
49016
|
" const params = __paramsFor(url.pathname);",
|
|
@@ -49528,6 +49774,34 @@ function demoteExports(code) {
|
|
|
49528
49774
|
function chunkHasImports(headLen, mergeAborted) {
|
|
49529
49775
|
return headLen > 0 || mergeAborted;
|
|
49530
49776
|
}
|
|
49777
|
+
function runtimeImportsOf(filePath) {
|
|
49778
|
+
let text;
|
|
49779
|
+
try {
|
|
49780
|
+
text = readFileSync11(filePath, "utf8");
|
|
49781
|
+
} catch {
|
|
49782
|
+
return [];
|
|
49783
|
+
}
|
|
49784
|
+
const names = [];
|
|
49785
|
+
const pattern2 = /import\s+(type\s+)?\{([^}]*)\}\s*from\s*['"]@vesk\/runtime[^'"]*['"]/g;
|
|
49786
|
+
for (const match of text.matchAll(pattern2)) {
|
|
49787
|
+
if (match[1]) continue;
|
|
49788
|
+
for (const part of match[2].split(",")) {
|
|
49789
|
+
const cleaned = part.trim().replace(/^type\s+/, "");
|
|
49790
|
+
if (!cleaned) continue;
|
|
49791
|
+
const name = cleaned.split(/\s+as\s+/)[0].trim();
|
|
49792
|
+
if (name) names.push(name);
|
|
49793
|
+
}
|
|
49794
|
+
}
|
|
49795
|
+
return names;
|
|
49796
|
+
}
|
|
49797
|
+
function sharedRuntimeResolver(shimPath) {
|
|
49798
|
+
return {
|
|
49799
|
+
name: "vesk-shared-runtime",
|
|
49800
|
+
setup(build4) {
|
|
49801
|
+
build4.onResolve({ filter: /^@vesk\/runtime(\/.*)?$/ }, () => ({ path: shimPath }));
|
|
49802
|
+
}
|
|
49803
|
+
};
|
|
49804
|
+
}
|
|
49531
49805
|
var ChunkImports = class {
|
|
49532
49806
|
bySource = /* @__PURE__ */ new Map();
|
|
49533
49807
|
aborted = false;
|
|
@@ -49625,6 +49899,20 @@ var ChunkImports = class {
|
|
|
49625
49899
|
get reason() {
|
|
49626
49900
|
return this.abortReason;
|
|
49627
49901
|
}
|
|
49902
|
+
/** Every import source this chunk's merged block pulls in (absolute paths). */
|
|
49903
|
+
sources() {
|
|
49904
|
+
return this.aborted ? [] : [...this.bySource.keys()];
|
|
49905
|
+
}
|
|
49906
|
+
/**
|
|
49907
|
+
* The named bindings this chunk imports from `source`, so a shared-module
|
|
49908
|
+
* shim can re-export exactly what consumers use (re-exporting `*` from the
|
|
49909
|
+
* real module would drag it back into the chunk being built).
|
|
49910
|
+
*/
|
|
49911
|
+
bindingsFor(source) {
|
|
49912
|
+
const group = this.bySource.get(source);
|
|
49913
|
+
if (!group) return { named: [], hasDefault: false };
|
|
49914
|
+
return { named: [...group.named.keys()].sort(), hasDefault: !!group.default };
|
|
49915
|
+
}
|
|
49628
49916
|
/** Renders the deduped import block (empty string when there are no imports). */
|
|
49629
49917
|
render() {
|
|
49630
49918
|
if (this.aborted || this.bySource.size === 0) return "";
|
|
@@ -49760,6 +50048,7 @@ async function generateClientBundle(routeTree, appDir, componentMap, options) {
|
|
|
49760
50048
|
let cachedFileHits = 0;
|
|
49761
50049
|
let compiledFiles = 0;
|
|
49762
50050
|
let mainFromCache = false;
|
|
50051
|
+
let sharedModuleBundle = "";
|
|
49763
50052
|
function mustReuseWithoutStat(filePath) {
|
|
49764
50053
|
return !!only && !only.has(filePath);
|
|
49765
50054
|
}
|
|
@@ -49945,7 +50234,7 @@ async function generateClientBundle(routeTree, appDir, componentMap, options) {
|
|
|
49945
50234
|
if (!chunkImports.ok) console.error("[vesk] chunk import merge aborted for", chunkName + ":", chunkImports.reason);
|
|
49946
50235
|
const head = chunkImports.render();
|
|
49947
50236
|
const code = (head ? head + "\n\n" : "") + chunkCode.join("\n\n");
|
|
49948
|
-
chunkEntries.push({ name: chunkName, code, node, imports: chunkHasImports(head.length, !chunkImports.ok) });
|
|
50237
|
+
chunkEntries.push({ name: chunkName, code, node, importsTable: chunkImports, imports: chunkHasImports(head.length, !chunkImports.ok) });
|
|
49949
50238
|
}
|
|
49950
50239
|
walkSplit2(node.children || [], [..._chain, node]);
|
|
49951
50240
|
}
|
|
@@ -49974,7 +50263,7 @@ async function generateClientBundle(routeTree, appDir, componentMap, options) {
|
|
|
49974
50263
|
if (!sharedImports.ok) console.error("[vesk] chunk import merge aborted for shared.js:", sharedImports.reason);
|
|
49975
50264
|
const head = sharedImports.render();
|
|
49976
50265
|
const code = (head ? head + "\n\n" : "") + sharedCode.join("\n\n");
|
|
49977
|
-
chunkEntries.push({ name: "shared.js", code, node: null, imports: chunkHasImports(head.length, !sharedImports.ok) });
|
|
50266
|
+
chunkEntries.push({ name: "shared.js", code, node: null, importsTable: sharedImports, imports: chunkHasImports(head.length, !sharedImports.ok) });
|
|
49978
50267
|
}
|
|
49979
50268
|
const chunkIIFE = (body) => `(()=>{
|
|
49980
50269
|
const __components = globalThis.__components || (globalThis.__components = {});
|
|
@@ -49982,6 +50271,98 @@ const __hydrators = globalThis.__hydrators || (globalThis.__hydrators = {});
|
|
|
49982
50271
|
${body}
|
|
49983
50272
|
})();
|
|
49984
50273
|
`;
|
|
50274
|
+
const sharedUsage = /* @__PURE__ */ new Map();
|
|
50275
|
+
for (const entry of chunkEntries) {
|
|
50276
|
+
for (const source of new Set(entry.importsTable.sources())) {
|
|
50277
|
+
sharedUsage.set(source, (sharedUsage.get(source) ?? 0) + 1);
|
|
50278
|
+
}
|
|
50279
|
+
}
|
|
50280
|
+
const isAppLocal = (source) => !source.includes("node_modules") && source.startsWith(resolve10(appDir, ".."));
|
|
50281
|
+
const sharedSources = [...sharedUsage.entries()].filter(([source, uses]) => uses > 1 && isAppLocal(source)).map(([source]) => source);
|
|
50282
|
+
if (process.env.VESK_DEBUG_SHARED) {
|
|
50283
|
+
console.error("[shared] candidates:", [...sharedUsage.entries()].map(([s, n]) => `${n}x ${s}`).join("\n"));
|
|
50284
|
+
console.error("[shared] selected:", sharedSources.join(", "));
|
|
50285
|
+
}
|
|
50286
|
+
const chunkAlias = {};
|
|
50287
|
+
let sharedBundleCode = "";
|
|
50288
|
+
const sharedRuntimeNames = /* @__PURE__ */ new Set();
|
|
50289
|
+
if (sharedSources.length > 0) {
|
|
50290
|
+
const tmpBase = mkdtempSync(join7(resolve10(appDir, ".."), "tmp-vesk-shared-"));
|
|
50291
|
+
try {
|
|
50292
|
+
const sharedEntry = join7(tmpBase, "shared-entry.js");
|
|
50293
|
+
const lines = [];
|
|
50294
|
+
const members = [];
|
|
50295
|
+
sharedSources.forEach((source, i) => {
|
|
50296
|
+
lines.push(`import * as m${i} from ${JSON.stringify(source)};`);
|
|
50297
|
+
members.push(` ${JSON.stringify(source)}: m${i},`);
|
|
50298
|
+
});
|
|
50299
|
+
lines.push(`globalThis.__veskShared = { ${members.join("\n")} };`);
|
|
50300
|
+
writeFileSync4(sharedEntry, lines.join("\n"));
|
|
50301
|
+
const appTsconfig = findTsconfigPath(appDir);
|
|
50302
|
+
const runtimeShim = join7(tmpBase, "runtime-shim.js");
|
|
50303
|
+
const runtimeLines = [
|
|
50304
|
+
"// ONE runtime instance: the entry bundle publishes these on globalThis,",
|
|
50305
|
+
"// and route chunks import the same functions. A second bundled copy",
|
|
50306
|
+
"// would mean a second Cell class and a second currentEffect.",
|
|
50307
|
+
"const __r = (n) => (...args) => globalThis[n](...args);"
|
|
50308
|
+
];
|
|
50309
|
+
for (const source of sharedSources) {
|
|
50310
|
+
for (const name of runtimeImportsOf(source)) sharedRuntimeNames.add(name);
|
|
50311
|
+
}
|
|
50312
|
+
for (const name of [...sharedRuntimeNames].sort()) {
|
|
50313
|
+
runtimeLines.push(`export const ${name} = __r(${JSON.stringify(name)});`);
|
|
50314
|
+
}
|
|
50315
|
+
writeFileSync4(runtimeShim, runtimeLines.join("\n") + "\n");
|
|
50316
|
+
const result = await build({
|
|
50317
|
+
entryPoints: [sharedEntry],
|
|
50318
|
+
bundle: true,
|
|
50319
|
+
format: "iife",
|
|
50320
|
+
platform: "browser",
|
|
50321
|
+
write: false,
|
|
50322
|
+
logLevel: "silent",
|
|
50323
|
+
loader: { ".js": "tsx" },
|
|
50324
|
+
legalComments: "none",
|
|
50325
|
+
// `@vesk/runtime` MUST stay the entry bundle's instance. Bundling a
|
|
50326
|
+
// second copy in here gives the app a second `Cell` class and a
|
|
50327
|
+
// second `currentEffect` variable: a store cell written from a click
|
|
50328
|
+
// notifies subscribers registered against the OTHER copy, so nothing
|
|
50329
|
+
// the store drives ever updates — writes land, no error, no repaint.
|
|
50330
|
+
plugins: [sharedRuntimeResolver(runtimeShim)],
|
|
50331
|
+
...appTsconfig ? { tsconfig: appTsconfig } : {}
|
|
50332
|
+
});
|
|
50333
|
+
sharedBundleCode = result.outputFiles[0].text;
|
|
50334
|
+
sharedSources.forEach((source, i) => {
|
|
50335
|
+
const named = /* @__PURE__ */ new Set();
|
|
50336
|
+
let hasDefault = false;
|
|
50337
|
+
for (const entry of chunkEntries) {
|
|
50338
|
+
const bindings = entry.importsTable.bindingsFor(source);
|
|
50339
|
+
bindings.named.forEach((n) => named.add(n));
|
|
50340
|
+
hasDefault = hasDefault || bindings.hasDefault;
|
|
50341
|
+
}
|
|
50342
|
+
const shim = join7(tmpBase, `shim-${i}.js`);
|
|
50343
|
+
const shimLines = [`const m = globalThis.__veskShared[${JSON.stringify(source)}];`];
|
|
50344
|
+
if (hasDefault) shimLines.push(`export default m;`);
|
|
50345
|
+
for (const name of [...named].sort()) {
|
|
50346
|
+
shimLines.push(`export const ${name} = m[${JSON.stringify(name)}];`);
|
|
50347
|
+
}
|
|
50348
|
+
writeFileSync4(shim, shimLines.join("\n") + "\n");
|
|
50349
|
+
chunkAlias[source] = shim;
|
|
50350
|
+
});
|
|
50351
|
+
} catch (e) {
|
|
50352
|
+
console.error("[vesk] shared-module pass failed; falling back to per-chunk inlining:", e.message);
|
|
50353
|
+
sharedBundleCode = "";
|
|
50354
|
+
for (const key of Object.keys(chunkAlias)) delete chunkAlias[key];
|
|
50355
|
+
}
|
|
50356
|
+
}
|
|
50357
|
+
const sharedRedirectPlugin = Object.keys(chunkAlias).length > 0 ? {
|
|
50358
|
+
name: "vesk-shared-modules",
|
|
50359
|
+
setup(build4) {
|
|
50360
|
+
build4.onResolve({ filter: /.*/ }, (args2) => {
|
|
50361
|
+
const mapped = chunkAlias[args2.path];
|
|
50362
|
+
return mapped ? { path: mapped } : null;
|
|
50363
|
+
});
|
|
50364
|
+
}
|
|
50365
|
+
} : null;
|
|
49985
50366
|
for (const entry of chunkEntries) {
|
|
49986
50367
|
if (!entry.code.trim()) continue;
|
|
49987
50368
|
let finalCode;
|
|
@@ -50010,6 +50391,13 @@ ${entry.code}
|
|
|
50010
50391
|
// for a dependency stays in its own package; shipping every
|
|
50011
50392
|
// module's header inside our own chunk adds nothing.
|
|
50012
50393
|
legalComments: "none",
|
|
50394
|
+
// Shared app modules are NOT inlined here: the resolver below
|
|
50395
|
+
// redirects them to a generated shim reading
|
|
50396
|
+
// `globalThis.__veskShared`, so the single copy in
|
|
50397
|
+
// shared-modules.js serves every route chunk. (esbuild's `alias`
|
|
50398
|
+
// option only accepts bare package names, so this is a resolver
|
|
50399
|
+
// rather than a map.)
|
|
50400
|
+
...sharedRedirectPlugin ? { plugins: [sharedRedirectPlugin] } : {},
|
|
50013
50401
|
...appTsconfig ? { tsconfig: appTsconfig } : {}
|
|
50014
50402
|
});
|
|
50015
50403
|
finalCode = result.outputFiles[0].text;
|
|
@@ -50037,13 +50425,15 @@ ${entry.code}
|
|
|
50037
50425
|
chunks.push({ name: entry.name, code: finalCode });
|
|
50038
50426
|
}
|
|
50039
50427
|
annotate2(routeTree);
|
|
50040
|
-
|
|
50428
|
+
sharedModuleBundle = sharedBundleCode;
|
|
50429
|
+
for (const name of sharedRuntimeNames) runtimeImportNames.add(name);
|
|
50430
|
+
const mainKey = JSON.stringify(routeTree) + "|" + [...runtimeImportNames].sort().join(",") + `|${!!options?.hmr}|${!!options?.importRuntime}|${options?.routeDataCache ?? ""}|${sharedModuleBundle.length}`;
|
|
50041
50431
|
let main;
|
|
50042
50432
|
if (cache2?.mainBundle && cache2.mainBundle.key === mainKey) {
|
|
50043
50433
|
mainFromCache = true;
|
|
50044
50434
|
main = cache2.mainBundle.code;
|
|
50045
50435
|
} else {
|
|
50046
|
-
main = await buildMainBundle(routeTree, runtimeDir, true, {}, !!options?.hmr, !!options?.importRuntime, runtimeImportNames, options?.routeDataCache);
|
|
50436
|
+
main = await buildMainBundle(routeTree, runtimeDir, true, {}, !!options?.hmr, !!options?.importRuntime, runtimeImportNames, options?.routeDataCache, sharedModuleBundle);
|
|
50047
50437
|
if (cache2) cache2.mainBundle = { key: mainKey, code: main };
|
|
50048
50438
|
}
|
|
50049
50439
|
const transformedChunks = [];
|
|
@@ -50244,7 +50634,7 @@ export { ${unique.join(", ")} };
|
|
|
50244
50634
|
function appendHmrGlobals(code) {
|
|
50245
50635
|
return code + "globalThis.__vesk_hmr_eval = (code, n) => {\n if (!n || n !== globalThis.__vesk_hmr_nonce) throw new Error('vesk hmr: invalid nonce');\n return eval(code);\n};\n";
|
|
50246
50636
|
}
|
|
50247
|
-
async function buildMainBundle(routeTree, runtimeDir, codeSplit, mono, hmr, importRuntime, runtimeImportNames, routeDataCache) {
|
|
50637
|
+
async function buildMainBundle(routeTree, runtimeDir, codeSplit, mono, hmr, importRuntime, runtimeImportNames, routeDataCache, sharedModuleBundle = "") {
|
|
50248
50638
|
const baseRuntimeImports = ["createFileRouter", "get", "set", "effect", "track", "destroy_block", "getActiveComponent", "setActiveComponent", "NavLink", "Link", "reactiveProps", "matchRoute", "ensureChunk", "toDomNode", "rerenderNode"];
|
|
50249
50639
|
const allRuntimeImports = runtimeImportNames && runtimeImportNames.size > 0 ? [.../* @__PURE__ */ new Set([...baseRuntimeImports, ...runtimeImportNames])] : baseRuntimeImports;
|
|
50250
50640
|
const runtimeGlobals = [
|
|
@@ -50313,7 +50703,11 @@ if (__pendChunks.length > 0 && typeof ensureChunk === 'function') {
|
|
|
50313
50703
|
`).join("") + "globalThis.__runtime_comps = __runtime_comps;\nglobalThis.__cleanup = __cleanup;\nglobalThis.__place = __place;\n\n";
|
|
50314
50704
|
const extraGlobals = [...runtimeImportNames || []].filter((n) => n && n !== "default").map((n) => `globalThis.${n} = ${n};
|
|
50315
50705
|
`).join("");
|
|
50316
|
-
const code2 = preamble + "const __components = globalThis.__components || (globalThis.__components = {});\nconst __hydrators = globalThis.__hydrators || (globalThis.__hydrators = {});\nconst __runtime_comps = __components;\n\n" + runtimeGlobals2 + extraGlobals +
|
|
50706
|
+
const code2 = preamble + "const __components = globalThis.__components || (globalThis.__components = {});\nconst __hydrators = globalThis.__hydrators || (globalThis.__hydrators = {});\nconst __runtime_comps = __components;\n\n" + runtimeGlobals2 + extraGlobals + // Shared app modules run HERE: after the runtime bindings are published,
|
|
50707
|
+
// before anything can request a route chunk. Earlier (at the top of the
|
|
50708
|
+
// bundle) `globalThis.track` was still undefined, so every module-scope
|
|
50709
|
+
// cell in a store was created against a missing runtime.
|
|
50710
|
+
(sharedModuleBundle ? sharedModuleBundle + "\n" : "") + cleanupFn + placeFn + "globalThis.__components = __components;\n" + resolveNamesFn + updateComponentsFn + "const __routeTree = " + routeTreeJson + ";\n__resolveNames(__routeTree);\n" + pendCode + startRouterCode;
|
|
50317
50711
|
return hmr ? appendHmrGlobals(code2) : code2;
|
|
50318
50712
|
}
|
|
50319
50713
|
const componentLines = mono?.componentLines || [];
|
|
@@ -50751,6 +51145,15 @@ async function startProdServer(outDir, options) {
|
|
|
50751
51145
|
res.end(lines.join("\n") || "// no ssr data");
|
|
50752
51146
|
return;
|
|
50753
51147
|
}
|
|
51148
|
+
if (url.pathname === "/store-init.js") {
|
|
51149
|
+
const token = url.searchParams.get("t") || "";
|
|
51150
|
+
const store = globalThis.__vsk_store_init_payload_store;
|
|
51151
|
+
const payload = store?.[token];
|
|
51152
|
+
if (payload) delete store[token];
|
|
51153
|
+
res.writeHead(200, { "Content-Type": "application/javascript", "Cache-Control": "no-store" });
|
|
51154
|
+
res.end(payload ?? "// no store init");
|
|
51155
|
+
return;
|
|
51156
|
+
}
|
|
50754
51157
|
if (url.pathname === "/_vesk/runtime.js") {
|
|
50755
51158
|
const clientFile = buildConfig?.assets?.client?.file || "client.js";
|
|
50756
51159
|
const clientPath = resolve13(staticDir, clientFile);
|
|
@@ -51057,6 +51460,29 @@ async function resolveCompilerApi(name) {
|
|
|
51057
51460
|
}
|
|
51058
51461
|
return import(`@vesk/compiler/src/${name.replace(/\.js$/, "")}`);
|
|
51059
51462
|
}
|
|
51463
|
+
function findRouteConflicts(routeTree, appDir) {
|
|
51464
|
+
const projectRoot = resolve21(appDir, "..");
|
|
51465
|
+
const byPath = /* @__PURE__ */ new Map();
|
|
51466
|
+
const walk9 = (nodes) => {
|
|
51467
|
+
for (const node of nodes) {
|
|
51468
|
+
if (node.page) {
|
|
51469
|
+
const pageFile = join15(node.sourceDir, "page.vsk");
|
|
51470
|
+
const files = byPath.get(node.fullPath) ?? [];
|
|
51471
|
+
files.push(relative4(projectRoot, pageFile));
|
|
51472
|
+
byPath.set(node.fullPath, files);
|
|
51473
|
+
}
|
|
51474
|
+
if (node.children && node.children.length > 0)
|
|
51475
|
+
walk9(node.children);
|
|
51476
|
+
}
|
|
51477
|
+
};
|
|
51478
|
+
walk9(routeTree);
|
|
51479
|
+
const conflicts = [];
|
|
51480
|
+
for (const [fullPath, files] of byPath) {
|
|
51481
|
+
if (files.length > 1)
|
|
51482
|
+
conflicts.push({ fullPath, files });
|
|
51483
|
+
}
|
|
51484
|
+
return conflicts;
|
|
51485
|
+
}
|
|
51060
51486
|
function filterActivePlugins2(plugins, records) {
|
|
51061
51487
|
if (!records || records.length === 0)
|
|
51062
51488
|
return plugins;
|
|
@@ -51190,6 +51616,14 @@ async function build2(appDir, options) {
|
|
|
51190
51616
|
console.error("vesk build: no routes found in", appDir);
|
|
51191
51617
|
return;
|
|
51192
51618
|
}
|
|
51619
|
+
const routeConflicts = findRouteConflicts(routeTree, appDir);
|
|
51620
|
+
if (routeConflicts.length > 0) {
|
|
51621
|
+
for (const conflict of routeConflicts) {
|
|
51622
|
+
console.error(`vesk build: conflicting routes for ${conflict.fullPath}: ${conflict.files.join(", ")}`);
|
|
51623
|
+
}
|
|
51624
|
+
const first = routeConflicts[0];
|
|
51625
|
+
throw new Error(`conflicting routes: ${first.fullPath} is claimed by both ${first.files.join(" and ")}`);
|
|
51626
|
+
}
|
|
51193
51627
|
const projectRoot = resolve21(appDir, "..");
|
|
51194
51628
|
const componentsDir = resolve21(projectRoot, "components");
|
|
51195
51629
|
const componentMap = scanComponents2(componentsDir);
|
|
@@ -52200,8 +52634,14 @@ function emitNode2(ctx2, node, tracked2, effectsVar, parentVar, compPrefix = "__
|
|
|
52200
52634
|
if (node instanceof SlotNode) {
|
|
52201
52635
|
if (!parentVar) {
|
|
52202
52636
|
if (ctx2.hydrate) {
|
|
52637
|
+
const promptExpr = ctx2.markerless && (regionBudget || skipK > 0) ? markerlessSkipExpr2(regionBudget, skipK) : null;
|
|
52203
52638
|
ctx2.push(`if (props.children !== undefined && props.children !== null) {`);
|
|
52204
52639
|
ctx2.push(` if (typeof props.children === 'function') {`);
|
|
52640
|
+
if (promptExpr) {
|
|
52641
|
+
ctx2.push(` ${ctx2.walker}.injectSkipK(${promptExpr});`);
|
|
52642
|
+
if (regionBudget && ctx2.markerless)
|
|
52643
|
+
ctx2.push(` ${regionBudget} = 0;`);
|
|
52644
|
+
}
|
|
52205
52645
|
ctx2.push(` __pendingChild = props.children(__hydrate);`);
|
|
52206
52646
|
ctx2.push(` } else if (__hydrate && __hydrate.root) {`);
|
|
52207
52647
|
ctx2.push(` __hydrate.root.appendChild(toDomNode(props.children));`);
|
|
@@ -52568,6 +53008,9 @@ function isReactiveExpression2(node, tracked2) {
|
|
|
52568
53008
|
return false;
|
|
52569
53009
|
let reactive = false;
|
|
52570
53010
|
walk7(ast, tracked2, {
|
|
53011
|
+
CallExpression() {
|
|
53012
|
+
reactive = true;
|
|
53013
|
+
},
|
|
52571
53014
|
Identifier(n, context) {
|
|
52572
53015
|
if (reactive)
|
|
52573
53016
|
return;
|
|
@@ -52713,7 +53156,7 @@ function emitComponentCall2(ctx2, node, tracked2, effectsVar, parentVar, compPre
|
|
|
52713
53156
|
ctx2.push(`return $f; })();`);
|
|
52714
53157
|
propsEntries.push(`children: ${frag}`);
|
|
52715
53158
|
}
|
|
52716
|
-
if (ctx2.markerless && promptExpr
|
|
53159
|
+
if (ctx2.markerless && promptExpr) {
|
|
52717
53160
|
ctx2.push(`${walkerArg}.injectSkipK(${promptExpr});`);
|
|
52718
53161
|
}
|
|
52719
53162
|
ctx2.push(`let ${v} = undefined;`);
|
|
@@ -55489,6 +55932,37 @@ function demoteExports2(code) {
|
|
|
55489
55932
|
function chunkHasImports2(headLen, mergeAborted) {
|
|
55490
55933
|
return headLen > 0 || mergeAborted;
|
|
55491
55934
|
}
|
|
55935
|
+
function runtimeImportsOf2(filePath) {
|
|
55936
|
+
let text;
|
|
55937
|
+
try {
|
|
55938
|
+
text = readFileSync24(filePath, "utf8");
|
|
55939
|
+
} catch {
|
|
55940
|
+
return [];
|
|
55941
|
+
}
|
|
55942
|
+
const names = [];
|
|
55943
|
+
const pattern2 = /import\s+(type\s+)?\{([^}]*)\}\s*from\s*['"]@vesk\/runtime[^'"]*['"]/g;
|
|
55944
|
+
for (const match of text.matchAll(pattern2)) {
|
|
55945
|
+
if (match[1])
|
|
55946
|
+
continue;
|
|
55947
|
+
for (const part of match[2].split(",")) {
|
|
55948
|
+
const cleaned = part.trim().replace(/^type\s+/, "");
|
|
55949
|
+
if (!cleaned)
|
|
55950
|
+
continue;
|
|
55951
|
+
const name = cleaned.split(/\s+as\s+/)[0].trim();
|
|
55952
|
+
if (name)
|
|
55953
|
+
names.push(name);
|
|
55954
|
+
}
|
|
55955
|
+
}
|
|
55956
|
+
return names;
|
|
55957
|
+
}
|
|
55958
|
+
function sharedRuntimeResolver2(shimPath) {
|
|
55959
|
+
return {
|
|
55960
|
+
name: "vesk-shared-runtime",
|
|
55961
|
+
setup(build4) {
|
|
55962
|
+
build4.onResolve({ filter: /^@vesk\/runtime(\/.*)?$/ }, () => ({ path: shimPath }));
|
|
55963
|
+
}
|
|
55964
|
+
};
|
|
55965
|
+
}
|
|
55492
55966
|
var ChunkImports2 = class {
|
|
55493
55967
|
bySource = /* @__PURE__ */ new Map();
|
|
55494
55968
|
aborted = false;
|
|
@@ -55596,6 +56070,21 @@ var ChunkImports2 = class {
|
|
|
55596
56070
|
get reason() {
|
|
55597
56071
|
return this.abortReason;
|
|
55598
56072
|
}
|
|
56073
|
+
/** Every import source this chunk's merged block pulls in (absolute paths). */
|
|
56074
|
+
sources() {
|
|
56075
|
+
return this.aborted ? [] : [...this.bySource.keys()];
|
|
56076
|
+
}
|
|
56077
|
+
/**
|
|
56078
|
+
* The named bindings this chunk imports from `source`, so a shared-module
|
|
56079
|
+
* shim can re-export exactly what consumers use (re-exporting `*` from the
|
|
56080
|
+
* real module would drag it back into the chunk being built).
|
|
56081
|
+
*/
|
|
56082
|
+
bindingsFor(source) {
|
|
56083
|
+
const group = this.bySource.get(source);
|
|
56084
|
+
if (!group)
|
|
56085
|
+
return { named: [], hasDefault: false };
|
|
56086
|
+
return { named: [...group.named.keys()].sort(), hasDefault: !!group.default };
|
|
56087
|
+
}
|
|
55599
56088
|
/** Renders the deduped import block (empty string when there are no imports). */
|
|
55600
56089
|
render() {
|
|
55601
56090
|
if (this.aborted || this.bySource.size === 0)
|
|
@@ -55750,6 +56239,7 @@ async function generateClientBundle2(routeTree, appDir, componentMap, options) {
|
|
|
55750
56239
|
let cachedFileHits = 0;
|
|
55751
56240
|
let compiledFiles = 0;
|
|
55752
56241
|
let mainFromCache = false;
|
|
56242
|
+
let sharedModuleBundle = "";
|
|
55753
56243
|
function mustReuseWithoutStat(filePath) {
|
|
55754
56244
|
return !!only && !only.has(filePath);
|
|
55755
56245
|
}
|
|
@@ -55948,7 +56438,7 @@ async function generateClientBundle2(routeTree, appDir, componentMap, options) {
|
|
|
55948
56438
|
console.error("[vesk] chunk import merge aborted for", chunkName + ":", chunkImports.reason);
|
|
55949
56439
|
const head = chunkImports.render();
|
|
55950
56440
|
const code = (head ? head + "\n\n" : "") + chunkCode.join("\n\n");
|
|
55951
|
-
chunkEntries.push({ name: chunkName, code, node, imports: chunkHasImports2(head.length, !chunkImports.ok) });
|
|
56441
|
+
chunkEntries.push({ name: chunkName, code, node, importsTable: chunkImports, imports: chunkHasImports2(head.length, !chunkImports.ok) });
|
|
55952
56442
|
}
|
|
55953
56443
|
walkSplit2(node.children || [], [..._chain, node]);
|
|
55954
56444
|
}
|
|
@@ -55978,7 +56468,7 @@ async function generateClientBundle2(routeTree, appDir, componentMap, options) {
|
|
|
55978
56468
|
console.error("[vesk] chunk import merge aborted for shared.js:", sharedImports.reason);
|
|
55979
56469
|
const head = sharedImports.render();
|
|
55980
56470
|
const code = (head ? head + "\n\n" : "") + sharedCode.join("\n\n");
|
|
55981
|
-
chunkEntries.push({ name: "shared.js", code, node: null, imports: chunkHasImports2(head.length, !sharedImports.ok) });
|
|
56471
|
+
chunkEntries.push({ name: "shared.js", code, node: null, importsTable: sharedImports, imports: chunkHasImports2(head.length, !sharedImports.ok) });
|
|
55982
56472
|
}
|
|
55983
56473
|
const chunkIIFE = (body) => `(()=>{
|
|
55984
56474
|
const __components = globalThis.__components || (globalThis.__components = {});
|
|
@@ -55986,6 +56476,101 @@ const __hydrators = globalThis.__hydrators || (globalThis.__hydrators = {});
|
|
|
55986
56476
|
${body}
|
|
55987
56477
|
})();
|
|
55988
56478
|
`;
|
|
56479
|
+
const sharedUsage = /* @__PURE__ */ new Map();
|
|
56480
|
+
for (const entry of chunkEntries) {
|
|
56481
|
+
for (const source of new Set(entry.importsTable.sources())) {
|
|
56482
|
+
sharedUsage.set(source, (sharedUsage.get(source) ?? 0) + 1);
|
|
56483
|
+
}
|
|
56484
|
+
}
|
|
56485
|
+
const isAppLocal = (source) => !source.includes("node_modules") && source.startsWith(resolve24(appDir, ".."));
|
|
56486
|
+
const sharedSources = [...sharedUsage.entries()].filter(([source, uses]) => uses > 1 && isAppLocal(source)).map(([source]) => source);
|
|
56487
|
+
if (process.env.VESK_DEBUG_SHARED) {
|
|
56488
|
+
console.error("[shared] candidates:", [...sharedUsage.entries()].map(([s, n]) => `${n}x ${s}`).join("\n"));
|
|
56489
|
+
console.error("[shared] selected:", sharedSources.join(", "));
|
|
56490
|
+
}
|
|
56491
|
+
const chunkAlias = {};
|
|
56492
|
+
let sharedBundleCode = "";
|
|
56493
|
+
const sharedRuntimeNames = /* @__PURE__ */ new Set();
|
|
56494
|
+
if (sharedSources.length > 0) {
|
|
56495
|
+
const tmpBase = mkdtempSync2(join20(resolve24(appDir, ".."), "tmp-vesk-shared-"));
|
|
56496
|
+
try {
|
|
56497
|
+
const sharedEntry = join20(tmpBase, "shared-entry.js");
|
|
56498
|
+
const lines = [];
|
|
56499
|
+
const members = [];
|
|
56500
|
+
sharedSources.forEach((source, i) => {
|
|
56501
|
+
lines.push(`import * as m${i} from ${JSON.stringify(source)};`);
|
|
56502
|
+
members.push(` ${JSON.stringify(source)}: m${i},`);
|
|
56503
|
+
});
|
|
56504
|
+
lines.push(`globalThis.__veskShared = { ${members.join("\n")} };`);
|
|
56505
|
+
writeFileSync13(sharedEntry, lines.join("\n"));
|
|
56506
|
+
const appTsconfig = findTsconfigPath(appDir);
|
|
56507
|
+
const runtimeShim = join20(tmpBase, "runtime-shim.js");
|
|
56508
|
+
const runtimeLines = [
|
|
56509
|
+
"// ONE runtime instance: the entry bundle publishes these on globalThis,",
|
|
56510
|
+
"// and route chunks import the same functions. A second bundled copy",
|
|
56511
|
+
"// would mean a second Cell class and a second currentEffect.",
|
|
56512
|
+
"const __r = (n) => (...args) => globalThis[n](...args);"
|
|
56513
|
+
];
|
|
56514
|
+
for (const source of sharedSources) {
|
|
56515
|
+
for (const name of runtimeImportsOf2(source))
|
|
56516
|
+
sharedRuntimeNames.add(name);
|
|
56517
|
+
}
|
|
56518
|
+
for (const name of [...sharedRuntimeNames].sort()) {
|
|
56519
|
+
runtimeLines.push(`export const ${name} = __r(${JSON.stringify(name)});`);
|
|
56520
|
+
}
|
|
56521
|
+
writeFileSync13(runtimeShim, runtimeLines.join("\n") + "\n");
|
|
56522
|
+
const result = await build3({
|
|
56523
|
+
entryPoints: [sharedEntry],
|
|
56524
|
+
bundle: true,
|
|
56525
|
+
format: "iife",
|
|
56526
|
+
platform: "browser",
|
|
56527
|
+
write: false,
|
|
56528
|
+
logLevel: "silent",
|
|
56529
|
+
loader: { ".js": "tsx" },
|
|
56530
|
+
legalComments: "none",
|
|
56531
|
+
// `@vesk/runtime` MUST stay the entry bundle's instance. Bundling a
|
|
56532
|
+
// second copy in here gives the app a second `Cell` class and a
|
|
56533
|
+
// second `currentEffect` variable: a store cell written from a click
|
|
56534
|
+
// notifies subscribers registered against the OTHER copy, so nothing
|
|
56535
|
+
// the store drives ever updates — writes land, no error, no repaint.
|
|
56536
|
+
plugins: [sharedRuntimeResolver2(runtimeShim)],
|
|
56537
|
+
...appTsconfig ? { tsconfig: appTsconfig } : {}
|
|
56538
|
+
});
|
|
56539
|
+
sharedBundleCode = result.outputFiles[0].text;
|
|
56540
|
+
sharedSources.forEach((source, i) => {
|
|
56541
|
+
const named = /* @__PURE__ */ new Set();
|
|
56542
|
+
let hasDefault = false;
|
|
56543
|
+
for (const entry of chunkEntries) {
|
|
56544
|
+
const bindings = entry.importsTable.bindingsFor(source);
|
|
56545
|
+
bindings.named.forEach((n) => named.add(n));
|
|
56546
|
+
hasDefault = hasDefault || bindings.hasDefault;
|
|
56547
|
+
}
|
|
56548
|
+
const shim = join20(tmpBase, `shim-${i}.js`);
|
|
56549
|
+
const shimLines = [`const m = globalThis.__veskShared[${JSON.stringify(source)}];`];
|
|
56550
|
+
if (hasDefault)
|
|
56551
|
+
shimLines.push(`export default m;`);
|
|
56552
|
+
for (const name of [...named].sort()) {
|
|
56553
|
+
shimLines.push(`export const ${name} = m[${JSON.stringify(name)}];`);
|
|
56554
|
+
}
|
|
56555
|
+
writeFileSync13(shim, shimLines.join("\n") + "\n");
|
|
56556
|
+
chunkAlias[source] = shim;
|
|
56557
|
+
});
|
|
56558
|
+
} catch (e) {
|
|
56559
|
+
console.error("[vesk] shared-module pass failed; falling back to per-chunk inlining:", e.message);
|
|
56560
|
+
sharedBundleCode = "";
|
|
56561
|
+
for (const key of Object.keys(chunkAlias))
|
|
56562
|
+
delete chunkAlias[key];
|
|
56563
|
+
}
|
|
56564
|
+
}
|
|
56565
|
+
const sharedRedirectPlugin = Object.keys(chunkAlias).length > 0 ? {
|
|
56566
|
+
name: "vesk-shared-modules",
|
|
56567
|
+
setup(build4) {
|
|
56568
|
+
build4.onResolve({ filter: /.*/ }, (args2) => {
|
|
56569
|
+
const mapped = chunkAlias[args2.path];
|
|
56570
|
+
return mapped ? { path: mapped } : null;
|
|
56571
|
+
});
|
|
56572
|
+
}
|
|
56573
|
+
} : null;
|
|
55989
56574
|
for (const entry of chunkEntries) {
|
|
55990
56575
|
if (!entry.code.trim())
|
|
55991
56576
|
continue;
|
|
@@ -56015,6 +56600,13 @@ ${entry.code}
|
|
|
56015
56600
|
// for a dependency stays in its own package; shipping every
|
|
56016
56601
|
// module's header inside our own chunk adds nothing.
|
|
56017
56602
|
legalComments: "none",
|
|
56603
|
+
// Shared app modules are NOT inlined here: the resolver below
|
|
56604
|
+
// redirects them to a generated shim reading
|
|
56605
|
+
// `globalThis.__veskShared`, so the single copy in
|
|
56606
|
+
// shared-modules.js serves every route chunk. (esbuild's `alias`
|
|
56607
|
+
// option only accepts bare package names, so this is a resolver
|
|
56608
|
+
// rather than a map.)
|
|
56609
|
+
...sharedRedirectPlugin ? { plugins: [sharedRedirectPlugin] } : {},
|
|
56018
56610
|
...appTsconfig ? { tsconfig: appTsconfig } : {}
|
|
56019
56611
|
});
|
|
56020
56612
|
finalCode = result.outputFiles[0].text;
|
|
@@ -56042,13 +56634,16 @@ ${entry.code}
|
|
|
56042
56634
|
chunks.push({ name: entry.name, code: finalCode });
|
|
56043
56635
|
}
|
|
56044
56636
|
annotate2(routeTree);
|
|
56045
|
-
|
|
56637
|
+
sharedModuleBundle = sharedBundleCode;
|
|
56638
|
+
for (const name of sharedRuntimeNames)
|
|
56639
|
+
runtimeImportNames.add(name);
|
|
56640
|
+
const mainKey = JSON.stringify(routeTree) + "|" + [...runtimeImportNames].sort().join(",") + `|${!!options?.hmr}|${!!options?.importRuntime}|${options?.routeDataCache ?? ""}|${sharedModuleBundle.length}`;
|
|
56046
56641
|
let main;
|
|
56047
56642
|
if (cache2?.mainBundle && cache2.mainBundle.key === mainKey) {
|
|
56048
56643
|
mainFromCache = true;
|
|
56049
56644
|
main = cache2.mainBundle.code;
|
|
56050
56645
|
} else {
|
|
56051
|
-
main = await buildMainBundle2(routeTree, runtimeDir, true, {}, !!options?.hmr, !!options?.importRuntime, runtimeImportNames, options?.routeDataCache);
|
|
56646
|
+
main = await buildMainBundle2(routeTree, runtimeDir, true, {}, !!options?.hmr, !!options?.importRuntime, runtimeImportNames, options?.routeDataCache, sharedModuleBundle);
|
|
56052
56647
|
if (cache2)
|
|
56053
56648
|
cache2.mainBundle = { key: mainKey, code: main };
|
|
56054
56649
|
}
|
|
@@ -56265,7 +56860,7 @@ export { ${unique.join(", ")} };
|
|
|
56265
56860
|
function appendHmrGlobals2(code) {
|
|
56266
56861
|
return code + "globalThis.__vesk_hmr_eval = (code, n) => {\n if (!n || n !== globalThis.__vesk_hmr_nonce) throw new Error('vesk hmr: invalid nonce');\n return eval(code);\n};\n";
|
|
56267
56862
|
}
|
|
56268
|
-
async function buildMainBundle2(routeTree, runtimeDir, codeSplit, mono, hmr, importRuntime, runtimeImportNames, routeDataCache) {
|
|
56863
|
+
async function buildMainBundle2(routeTree, runtimeDir, codeSplit, mono, hmr, importRuntime, runtimeImportNames, routeDataCache, sharedModuleBundle = "") {
|
|
56269
56864
|
const baseRuntimeImports = ["createFileRouter", "get", "set", "effect", "track", "destroy_block", "getActiveComponent", "setActiveComponent", "NavLink", "Link", "reactiveProps", "matchRoute", "ensureChunk", "toDomNode", "rerenderNode"];
|
|
56270
56865
|
const allRuntimeImports = runtimeImportNames && runtimeImportNames.size > 0 ? [.../* @__PURE__ */ new Set([...baseRuntimeImports, ...runtimeImportNames])] : baseRuntimeImports;
|
|
56271
56866
|
const runtimeGlobals = [
|
|
@@ -56334,7 +56929,11 @@ if (__pendChunks.length > 0 && typeof ensureChunk === 'function') {
|
|
|
56334
56929
|
`).join("") + "globalThis.__runtime_comps = __runtime_comps;\nglobalThis.__cleanup = __cleanup;\nglobalThis.__place = __place;\n\n";
|
|
56335
56930
|
const extraGlobals = [...runtimeImportNames || []].filter((n) => n && n !== "default").map((n) => `globalThis.${n} = ${n};
|
|
56336
56931
|
`).join("");
|
|
56337
|
-
const code2 = preamble + "const __components = globalThis.__components || (globalThis.__components = {});\nconst __hydrators = globalThis.__hydrators || (globalThis.__hydrators = {});\nconst __runtime_comps = __components;\n\n" + runtimeGlobals2 + extraGlobals +
|
|
56932
|
+
const code2 = preamble + "const __components = globalThis.__components || (globalThis.__components = {});\nconst __hydrators = globalThis.__hydrators || (globalThis.__hydrators = {});\nconst __runtime_comps = __components;\n\n" + runtimeGlobals2 + extraGlobals + // Shared app modules run HERE: after the runtime bindings are published,
|
|
56933
|
+
// before anything can request a route chunk. Earlier (at the top of the
|
|
56934
|
+
// bundle) `globalThis.track` was still undefined, so every module-scope
|
|
56935
|
+
// cell in a store was created against a missing runtime.
|
|
56936
|
+
(sharedModuleBundle ? sharedModuleBundle + "\n" : "") + cleanupFn + placeFn + "globalThis.__components = __components;\n" + resolveNamesFn + updateComponentsFn + "const __routeTree = " + routeTreeJson + ";\n__resolveNames(__routeTree);\n" + pendCode + startRouterCode;
|
|
56338
56937
|
return hmr ? appendHmrGlobals2(code2) : code2;
|
|
56339
56938
|
}
|
|
56340
56939
|
const componentLines = mono?.componentLines || [];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vesk/vesk-cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.60",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Vesk — compiler-first framework for the post-VDOM web. vesk dev, vesk build.",
|
|
6
6
|
"bin": {
|
|
@@ -8,10 +8,10 @@
|
|
|
8
8
|
},
|
|
9
9
|
"main": "./dist/cli.js",
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@vesk/adapter": "^0.2.
|
|
12
|
-
"@vesk/compiler": "^0.2.
|
|
13
|
-
"@vesk/plugin-tailwind": "^0.2.
|
|
14
|
-
"@vesk/runtime": "^0.2.
|
|
11
|
+
"@vesk/adapter": "^0.2.60",
|
|
12
|
+
"@vesk/compiler": "^0.2.60",
|
|
13
|
+
"@vesk/plugin-tailwind": "^0.2.60",
|
|
14
|
+
"@vesk/runtime": "^0.2.60",
|
|
15
15
|
"esrap": "^2.3.0",
|
|
16
16
|
"typescript": "^5.8.0",
|
|
17
17
|
"ws": "^8.18.0",
|