@vesk/vesk-cli 0.2.63 → 0.2.65

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.
Files changed (2) hide show
  1. package/dist/cli.js +1232 -39
  2. package/package.json +5 -5
package/dist/cli.js CHANGED
@@ -22494,6 +22494,7 @@ __export(server_utils_exports, {
22494
22494
  escapeHtml: () => escapeHtml,
22495
22495
  evalTopLevelCode: () => evalTopLevelCode,
22496
22496
  exprJS: () => exprJS,
22497
+ extractRuntimeBindingPairs: () => extractRuntimeBindingPairs,
22497
22498
  extractRuntimeNames: () => extractRuntimeNames,
22498
22499
  extractTopLevelNames: () => extractTopLevelNames,
22499
22500
  getClientIp: () => getClientIp,
@@ -23281,33 +23282,39 @@ function tryParseTopLevel(code) {
23281
23282
  return null;
23282
23283
  }
23283
23284
  }
23284
- function extractRuntimeNames(importStrs) {
23285
- const names = [];
23285
+ function extractRuntimeBindingPairs(importStrs) {
23286
+ const pairs = [];
23287
+ const isRuntimeTarget = (src2) => src2 === "@vesk/runtime" || src2 === "@vesk/reactivity" || src2.startsWith("@vesk/runtime/");
23286
23288
  for (const imp of importStrs) {
23287
23289
  const ast = tryParseImport(imp);
23288
23290
  if (ast) {
23289
23291
  for (const stmt of ast.body) {
23290
23292
  if (stmt.type !== "ImportDeclaration") continue;
23293
+ if (stmt.importKind === "type") continue;
23291
23294
  const src2 = stmt.source?.value;
23292
- if (typeof src2 !== "string" || src2 !== "@vesk/runtime" && src2 !== "@vesk/reactivity") continue;
23295
+ if (typeof src2 !== "string" || !isRuntimeTarget(src2)) continue;
23293
23296
  for (const spec of stmt.specifiers || []) {
23294
23297
  if (spec.importKind === "type") continue;
23295
23298
  if (spec.type === "ImportSpecifier") {
23296
- const name = spec.local?.name || spec.imported?.name;
23297
- if (name) names.push(name);
23299
+ const local = spec.local?.name;
23300
+ const imported = spec.imported?.name;
23301
+ if (local) pairs.push({ imported: imported || local, local });
23298
23302
  } else if (spec.type === "ImportDefaultSpecifier" || spec.type === "ImportNamespaceSpecifier") {
23299
- if (spec.local?.name) names.push(spec.local.name);
23303
+ if (spec.local?.name) pairs.push({ imported: "*", local: spec.local.name });
23300
23304
  }
23301
23305
  }
23302
23306
  }
23303
23307
  continue;
23304
23308
  }
23305
23309
  const target = importModuleTarget(imp);
23306
- if (target === "@vesk/runtime" || target === "@vesk/reactivity") {
23307
- for (const name of extractImportNames(imp)) names.push(name);
23310
+ if (target && isRuntimeTarget(target)) {
23311
+ for (const name of extractImportNames(imp)) pairs.push({ imported: name, local: name });
23308
23312
  }
23309
23313
  }
23310
- return names;
23314
+ return pairs;
23315
+ }
23316
+ function extractRuntimeNames(importStrs) {
23317
+ return extractRuntimeBindingPairs(importStrs).map((p) => p.local);
23311
23318
  }
23312
23319
  function tryParseImport(code) {
23313
23320
  try {
@@ -23348,7 +23355,7 @@ function setRuntimeModule(mod) {
23348
23355
  __cachedRuntimeModule = mod;
23349
23356
  }
23350
23357
  function loadRuntimeImports(importStrs) {
23351
- const names = extractRuntimeNames(importStrs);
23358
+ const pairs = extractRuntimeBindingPairs(importStrs);
23352
23359
  const mod = __cachedRuntimeModule || index_server_exports;
23353
23360
  if (mod) {
23354
23361
  const result = {};
@@ -23357,8 +23364,12 @@ function loadRuntimeImports(importStrs) {
23357
23364
  for (const name of ["get", "set", "track"]) {
23358
23365
  if (name in mod) result[name] = mod[name];
23359
23366
  }
23360
- for (const name of names) {
23361
- if (name in mod) result[name] = mod[name];
23367
+ for (const { imported, local } of pairs) {
23368
+ if (imported === "*") {
23369
+ result[local] = mod;
23370
+ } else if (imported in mod) {
23371
+ result[local] = mod[imported];
23372
+ }
23362
23373
  }
23363
23374
  return result;
23364
23375
  }
@@ -27755,6 +27766,1019 @@ var init_nested_update = __esm({
27755
27766
  }
27756
27767
  });
27757
27768
 
27769
+ // ../runtime/src/store-persistence.ts
27770
+ function currentSsrToken() {
27771
+ const g4 = globalThis;
27772
+ return typeof g4.__vsk_ssr_token === "string" ? g4.__vsk_ssr_token : "";
27773
+ }
27774
+ function persistedStoreCookieName(storageKey) {
27775
+ return "vsk_store_" + encodeURIComponent(storageKey);
27776
+ }
27777
+ function bucketFor(token) {
27778
+ const set2 = pendingKeys.get(token);
27779
+ if (set2) return set2;
27780
+ const fresh = /* @__PURE__ */ new Set();
27781
+ pendingKeys.set(token, fresh);
27782
+ return fresh;
27783
+ }
27784
+ function readPersistedStorage(storageKey) {
27785
+ if (!storageKey) return null;
27786
+ if (typeof window === "undefined") {
27787
+ bucketFor(currentSsrToken()).add(storageKey);
27788
+ return serverReadHook ? serverReadHook(storageKey) ?? null : null;
27789
+ }
27790
+ const init = globalThis.__VESK_STORE_INIT__;
27791
+ if (init && init[storageKey] !== void 0) {
27792
+ const raw2 = init[storageKey];
27793
+ delete init[storageKey];
27794
+ try {
27795
+ localStorage.setItem(storageKey, raw2);
27796
+ } catch {
27797
+ }
27798
+ return raw2;
27799
+ }
27800
+ try {
27801
+ return localStorage.getItem(storageKey);
27802
+ } catch {
27803
+ return null;
27804
+ }
27805
+ }
27806
+ function writePersistedStorage(storageKey, raw2) {
27807
+ if (!storageKey) return;
27808
+ if (typeof window !== "undefined") {
27809
+ try {
27810
+ localStorage.setItem(storageKey, raw2);
27811
+ } catch {
27812
+ }
27813
+ }
27814
+ if (typeof document !== "undefined") {
27815
+ try {
27816
+ document.cookie = persistedStoreCookieName(storageKey) + "=" + encodeURIComponent(raw2) + "; path=/; max-age=31536000; SameSite=Lax";
27817
+ } catch {
27818
+ }
27819
+ }
27820
+ }
27821
+ function clearPersistedStorage(storageKey) {
27822
+ if (!storageKey) return;
27823
+ if (typeof window !== "undefined") {
27824
+ try {
27825
+ localStorage.removeItem(storageKey);
27826
+ } catch {
27827
+ }
27828
+ }
27829
+ if (typeof document !== "undefined") {
27830
+ try {
27831
+ document.cookie = persistedStoreCookieName(storageKey) + "=; path=/; max-age=0";
27832
+ } catch {
27833
+ }
27834
+ }
27835
+ }
27836
+ var serverReadHook, pendingKeys;
27837
+ var init_store_persistence = __esm({
27838
+ "../runtime/src/store-persistence.ts"() {
27839
+ "use strict";
27840
+ serverReadHook = null;
27841
+ pendingKeys = /* @__PURE__ */ new Map();
27842
+ }
27843
+ });
27844
+
27845
+ // ../runtime/src/store.ts
27846
+ function cloneState(value) {
27847
+ return Array.isArray(value) ? value.slice() : { ...value };
27848
+ }
27849
+ function createStore(initial, options = {}) {
27850
+ const { persist = false, storageKey, devtools = false } = options;
27851
+ let value = cloneState(initial);
27852
+ if (persist && storageKey) {
27853
+ const stored = readPersistedStorage(storageKey);
27854
+ if (stored) {
27855
+ try {
27856
+ value = JSON.parse(stored);
27857
+ } catch {
27858
+ }
27859
+ }
27860
+ }
27861
+ const stateCell = track(value);
27862
+ const subs = /* @__PURE__ */ new Set();
27863
+ const watchers = [];
27864
+ const middlewares = [];
27865
+ let prevValue = cloneState(value);
27866
+ let batchDepth = 0;
27867
+ let dirty = false;
27868
+ function notifyNow(action, payload) {
27869
+ const current2 = stateCell.get();
27870
+ if (current2 === prevValue) return;
27871
+ subs.forEach((fn) => fn(current2));
27872
+ watchers.forEach(({ selector, cb, equals }) => {
27873
+ const eq = equals ?? Object.is;
27874
+ const newVal = selector(current2);
27875
+ const oldVal = selector(prevValue);
27876
+ if (!eq(newVal, oldVal)) cb(newVal, oldVal);
27877
+ });
27878
+ middlewares.forEach((fn) => fn(current2, action, payload));
27879
+ if (devtools && typeof window !== "undefined") {
27880
+ const dt = window.__VESK_STORE_DEVTOOLS__;
27881
+ if (dt && typeof dt.send === "function") {
27882
+ dt.send({ type: action, payload, state: structuredClone(current2) });
27883
+ }
27884
+ }
27885
+ prevValue = cloneState(current2);
27886
+ }
27887
+ function notifyDirty(action, payload) {
27888
+ if (batchDepth > 0) {
27889
+ dirty = true;
27890
+ } else {
27891
+ notifyNow(action, payload);
27892
+ }
27893
+ }
27894
+ function persistToStorage() {
27895
+ if (persist && storageKey) {
27896
+ try {
27897
+ writePersistedStorage(storageKey, JSON.stringify(stateCell.get()));
27898
+ } catch (err) {
27899
+ console.log("error saving to localStorage: ", err);
27900
+ }
27901
+ }
27902
+ }
27903
+ function get2() {
27904
+ return stateCell.get();
27905
+ }
27906
+ function set2(next, action = "set") {
27907
+ stateCell.set(next);
27908
+ persistToStorage();
27909
+ notifyDirty(action, next);
27910
+ }
27911
+ function update(partialOrFn, action = "update") {
27912
+ const current2 = stateCell.get();
27913
+ const patch = typeof partialOrFn === "function" ? partialOrFn(current2) : partialOrFn;
27914
+ const next = Object.assign(cloneState(current2), patch);
27915
+ stateCell.set(next);
27916
+ persistToStorage();
27917
+ notifyDirty(action, patch);
27918
+ }
27919
+ function deleteKeys(keys, action = "delete") {
27920
+ const current2 = stateCell.get();
27921
+ const kArray = Array.isArray(keys) ? keys : [keys];
27922
+ const next = cloneState(current2);
27923
+ kArray.forEach((k) => {
27924
+ delete next[k];
27925
+ });
27926
+ stateCell.set(next);
27927
+ persistToStorage();
27928
+ notifyDirty(action, keys);
27929
+ }
27930
+ function reset2() {
27931
+ stateCell.set(cloneState(initial));
27932
+ notifyDirty("reset");
27933
+ }
27934
+ function rehydrate(newInitial) {
27935
+ Object.assign(initial, newInitial);
27936
+ stateCell.set(cloneState(initial));
27937
+ notifyDirty("rehydrate");
27938
+ }
27939
+ function clear() {
27940
+ stateCell.set(cloneState(initial));
27941
+ if (persist && storageKey) {
27942
+ clearPersistedStorage(storageKey);
27943
+ }
27944
+ notifyDirty("clear");
27945
+ }
27946
+ function batch(fn) {
27947
+ batchDepth++;
27948
+ try {
27949
+ return flush_sync(fn);
27950
+ } finally {
27951
+ batchDepth--;
27952
+ if (batchDepth === 0 && dirty) {
27953
+ notifyDirty("batch");
27954
+ dirty = false;
27955
+ }
27956
+ }
27957
+ }
27958
+ function subscribe(fn, selector, equals) {
27959
+ const eq = equals ?? Object.is;
27960
+ let hasPrev = false;
27961
+ let prev;
27962
+ const wrapper = selector ? (state) => {
27963
+ const selected = selector(state);
27964
+ if (!hasPrev || !eq(selected, prev)) {
27965
+ hasPrev = true;
27966
+ prev = selected;
27967
+ fn(selected);
27968
+ }
27969
+ } : fn;
27970
+ subs.add(wrapper);
27971
+ wrapper(stateCell.get());
27972
+ return () => subs.delete(wrapper);
27973
+ }
27974
+ function watch2(selector, callback, equals) {
27975
+ watchers.push({ selector, cb: callback, equals });
27976
+ return () => {
27977
+ const i = watchers.findIndex((w) => w.cb === callback);
27978
+ if (i >= 0) watchers.splice(i, 1);
27979
+ };
27980
+ }
27981
+ function use(middleware) {
27982
+ middlewares.push(middleware);
27983
+ return () => {
27984
+ const i = middlewares.indexOf(middleware);
27985
+ if (i >= 0) middlewares.splice(i, 1);
27986
+ };
27987
+ }
27988
+ function derive(selector, equals) {
27989
+ return {
27990
+ subscribe(cb) {
27991
+ return subscribe(
27992
+ (v) => cb(v),
27993
+ selector,
27994
+ equals
27995
+ );
27996
+ }
27997
+ };
27998
+ }
27999
+ function toJSON() {
28000
+ return structuredClone(stateCell.get());
28001
+ }
28002
+ return {
28003
+ get: get2,
28004
+ set: set2,
28005
+ update,
28006
+ delete: deleteKeys,
28007
+ clear,
28008
+ subscribe,
28009
+ watch: watch2,
28010
+ use,
28011
+ derive,
28012
+ batch,
28013
+ reset: reset2,
28014
+ rehydrate,
28015
+ toJSON
28016
+ };
28017
+ }
28018
+ var init_store = __esm({
28019
+ "../runtime/src/store.ts"() {
28020
+ "use strict";
28021
+ init_ripple_runtime();
28022
+ init_store_persistence();
28023
+ }
28024
+ });
28025
+
28026
+ // ../runtime/src/path-store.ts
28027
+ function isObject2(value) {
28028
+ return value !== null && typeof value === "object";
28029
+ }
28030
+ function isDigits(s) {
28031
+ if (s.length === 0) return false;
28032
+ for (let i = 0; i < s.length; i++) {
28033
+ const c = s.charCodeAt(i);
28034
+ if (c < 48 || c > 57) return false;
28035
+ }
28036
+ return true;
28037
+ }
28038
+ function parseStorePath(input) {
28039
+ const tokens = [];
28040
+ let i = 0;
28041
+ const n = input.length;
28042
+ const readBracketed = () => {
28043
+ i++;
28044
+ let start = i;
28045
+ while (i < n && input[i] >= "0" && input[i] <= "9") i++;
28046
+ if (start === i || input[i] !== "]") {
28047
+ throw new Error(`Path store: bad index in path "${input}"`);
28048
+ }
28049
+ tokens.push(Number(input.slice(start, i)));
28050
+ i++;
28051
+ };
28052
+ while (i < n) {
28053
+ const c = input[i];
28054
+ if (c === ".") {
28055
+ i++;
28056
+ continue;
28057
+ }
28058
+ if (c === "[") {
28059
+ readBracketed();
28060
+ continue;
28061
+ }
28062
+ let start = i;
28063
+ while (i < n && input[i] !== "." && input[i] !== "[") i++;
28064
+ tokens.push(input.slice(start, i));
28065
+ }
28066
+ return tokens;
28067
+ }
28068
+ function pathKey(tokens) {
28069
+ return tokens.join("\0");
28070
+ }
28071
+ function tokensOfKey(key) {
28072
+ if (key === "") return [];
28073
+ return key.split("\0").map((t) => isDigits(t) ? Number(t) : t);
28074
+ }
28075
+ function isPrefix(prefix, full) {
28076
+ if (prefix.length > full.length) return false;
28077
+ for (let i = 0; i < prefix.length; i++) {
28078
+ if (String(prefix[i]) !== String(full[i])) return false;
28079
+ }
28080
+ return true;
28081
+ }
28082
+ function isStrictPrefix(prefix, full) {
28083
+ return prefix.length > 0 && prefix.length < full.length && isPrefix(prefix, full);
28084
+ }
28085
+ function cloneValue(value, seen) {
28086
+ if (value === null || typeof value !== "object") return value;
28087
+ seen = seen ?? /* @__PURE__ */ new Map();
28088
+ const existing = seen.get(value);
28089
+ if (existing !== void 0) return existing;
28090
+ if (value instanceof Date) {
28091
+ const d = new Date(value.getTime());
28092
+ seen.set(value, d);
28093
+ return d;
28094
+ }
28095
+ if (value instanceof RegExp) {
28096
+ const r = new RegExp(value.source, value.flags);
28097
+ seen.set(value, r);
28098
+ return r;
28099
+ }
28100
+ if (value instanceof Map) {
28101
+ const out = /* @__PURE__ */ new Map();
28102
+ seen.set(value, out);
28103
+ for (const [k, v] of value) out.set(cloneValue(k, seen), cloneValue(v, seen));
28104
+ return out;
28105
+ }
28106
+ if (value instanceof Set) {
28107
+ const out = /* @__PURE__ */ new Set();
28108
+ seen.set(value, out);
28109
+ for (const v of value) out.add(cloneValue(v, seen));
28110
+ return out;
28111
+ }
28112
+ if (Array.isArray(value)) {
28113
+ const out = [];
28114
+ seen.set(value, out);
28115
+ for (const item of value) out.push(cloneValue(item, seen));
28116
+ return out;
28117
+ }
28118
+ if (ArrayBuffer.isView(value)) {
28119
+ const out = value.slice();
28120
+ seen.set(value, out);
28121
+ return out;
28122
+ }
28123
+ const proto = Object.getPrototypeOf(value);
28124
+ if (proto === Object.prototype || proto === null) {
28125
+ const out = {};
28126
+ seen.set(value, out);
28127
+ for (const key of Object.keys(value)) {
28128
+ out[key] = cloneValue(value[key], seen);
28129
+ }
28130
+ return out;
28131
+ }
28132
+ seen.set(value, value);
28133
+ try {
28134
+ return structuredClone(value);
28135
+ } catch {
28136
+ return value;
28137
+ }
28138
+ }
28139
+ function plainClone(value, seen) {
28140
+ if (value === null || typeof value !== "object") return value;
28141
+ seen = seen ?? /* @__PURE__ */ new Set();
28142
+ if (seen.has(value)) throw new Error("Path store: toJSON() cannot serialize cyclic state");
28143
+ seen.add(value);
28144
+ if (value instanceof Date) return value.toISOString();
28145
+ if (value instanceof RegExp) return String(value);
28146
+ if (value instanceof Map) {
28147
+ const out2 = [];
28148
+ for (const [k, v] of value) out2.push([plainClone(k, seen), plainClone(v, seen)]);
28149
+ return out2;
28150
+ }
28151
+ if (value instanceof Set) {
28152
+ const out2 = [];
28153
+ for (const v of value) out2.push(plainClone(v, seen));
28154
+ return out2;
28155
+ }
28156
+ if (Array.isArray(value)) {
28157
+ const out2 = [];
28158
+ for (const item of value) out2.push(plainClone(item, seen));
28159
+ return out2;
28160
+ }
28161
+ const out = {};
28162
+ for (const key of Object.keys(value)) {
28163
+ out[key] = plainClone(value[key], seen);
28164
+ }
28165
+ return out;
28166
+ }
28167
+ function shallowDiff(before, after, base, out) {
28168
+ if (Object.is(before, after)) return;
28169
+ const beforeObj = isObject2(before);
28170
+ const afterObj = isObject2(after);
28171
+ if (!beforeObj || !afterObj || Array.isArray(before) !== Array.isArray(after)) {
28172
+ out.push({ path: pathKey(base), before, after });
28173
+ return;
28174
+ }
28175
+ const array = Array.isArray(before);
28176
+ const keys = /* @__PURE__ */ new Set([
28177
+ ...Object.keys(before),
28178
+ ...Object.keys(after)
28179
+ ]);
28180
+ for (const key of keys) {
28181
+ const segment = array && isDigits(key) ? Number(key) : key;
28182
+ shallowDiff(
28183
+ before[key],
28184
+ after[key],
28185
+ [...base, segment],
28186
+ out
28187
+ );
28188
+ }
28189
+ }
28190
+ function createPathStore(initial, options = {}) {
28191
+ const { persist = false, storageKey, historyLimit = 500 } = options;
28192
+ let state = cloneValue(initial);
28193
+ if (persist && storageKey) {
28194
+ const raw2 = readPersistedStorage(storageKey);
28195
+ if (raw2) {
28196
+ try {
28197
+ const parsed = JSON.parse(raw2);
28198
+ if (parsed !== null && typeof parsed === "object") {
28199
+ state = { ...state, ...cloneValue(parsed) };
28200
+ }
28201
+ } catch {
28202
+ }
28203
+ }
28204
+ }
28205
+ const rootCell = track(state);
28206
+ const cellRoot = {};
28207
+ function nodeFor(path, create) {
28208
+ let node = cellRoot;
28209
+ for (const seg of path) {
28210
+ const key = String(seg);
28211
+ let child = node.children?.get(key);
28212
+ if (!child) {
28213
+ if (!create) return null;
28214
+ child = {};
28215
+ if (!node.children) node.children = /* @__PURE__ */ new Map();
28216
+ node.children.set(key, child);
28217
+ }
28218
+ node = child;
28219
+ }
28220
+ return node;
28221
+ }
28222
+ function cellFor(path) {
28223
+ const node = nodeFor(path, true);
28224
+ if (!node.cell) {
28225
+ node.cell = track(getIn(state, path));
28226
+ setImprint(node, path);
28227
+ }
28228
+ return node.cell;
28229
+ }
28230
+ function collectCellNodes(node) {
28231
+ const out = [];
28232
+ if (!node) return out;
28233
+ const stack = [node];
28234
+ while (stack.length > 0) {
28235
+ const n = stack.pop();
28236
+ if (n.cell) out.push(n);
28237
+ if (n.children) for (const child of n.children.values()) stack.push(child);
28238
+ }
28239
+ return out;
28240
+ }
28241
+ function cellsRelatedTo(path) {
28242
+ const out = [];
28243
+ const tNode = nodeFor(path, false);
28244
+ out.push(...collectCellNodes(tNode));
28245
+ for (let i = path.length - 1; i > 0; i--) {
28246
+ const ancestor = nodeFor(path.slice(0, i), false);
28247
+ if (ancestor?.cell) out.push(ancestor);
28248
+ }
28249
+ return out;
28250
+ }
28251
+ function syncCell(node, path) {
28252
+ const cell = node.cell;
28253
+ const next = getIn(state, path);
28254
+ if (!Object.is(cell.get(), next)) cell.set(next);
28255
+ }
28256
+ function syncPathCells(touched) {
28257
+ if (touched === null) {
28258
+ for (const node of collectCellNodes(cellRoot)) {
28259
+ if (node.cell) syncCell(node, nodePathOf(node));
28260
+ }
28261
+ return;
28262
+ }
28263
+ for (const node of cellsRelatedTo(touched)) {
28264
+ if (!node.cell) continue;
28265
+ syncCell(node, nodePathOf(node));
28266
+ }
28267
+ }
28268
+ function nodePathOf(node) {
28269
+ return nodePathCache.get(node) ?? [];
28270
+ }
28271
+ const nodePathCache = /* @__PURE__ */ new Map();
28272
+ function setImprint(node, path) {
28273
+ nodePathCache.set(node, path.slice());
28274
+ }
28275
+ const derivedDefs = /* @__PURE__ */ new Map();
28276
+ const depRoot = { defs: null };
28277
+ function depNodeFor(tokens, create) {
28278
+ let node = depRoot;
28279
+ for (const seg of tokens) {
28280
+ const key = String(seg);
28281
+ let child = node.children?.get(key);
28282
+ if (!child) {
28283
+ if (!create) return null;
28284
+ child = { defs: null };
28285
+ if (!node.children) node.children = /* @__PURE__ */ new Map();
28286
+ node.children.set(key, child);
28287
+ }
28288
+ node = child;
28289
+ }
28290
+ return node;
28291
+ }
28292
+ function registerDep(def, tokens) {
28293
+ const node = depNodeFor(tokens, true);
28294
+ if (!node.defs) node.defs = /* @__PURE__ */ new Set();
28295
+ node.defs.add(def);
28296
+ }
28297
+ function unregisterDep(def, tokens) {
28298
+ const node = depNodeFor(tokens, false);
28299
+ if (node?.defs) {
28300
+ node.defs.delete(def);
28301
+ if (node.defs.size === 0) node.defs = null;
28302
+ }
28303
+ }
28304
+ function registerDef(def) {
28305
+ for (const dep of def.deps) registerDep(def, dep);
28306
+ }
28307
+ function unregisterDef(def) {
28308
+ for (const dep of def.deps) unregisterDep(def, dep);
28309
+ }
28310
+ function derivedsRelatedTo(path, out) {
28311
+ const n = depNodeFor(path, false);
28312
+ if (n) {
28313
+ const stack = [n];
28314
+ while (stack.length > 0) {
28315
+ const node = stack.pop();
28316
+ if (node.defs) for (const def of node.defs) out.add(def);
28317
+ if (node.children) for (const child of node.children.values()) stack.push(child);
28318
+ }
28319
+ }
28320
+ for (let i = path.length - 1; i > 0; i--) {
28321
+ const ancestor = depNodeFor(path.slice(0, i), false);
28322
+ if (ancestor?.defs) for (const def of ancestor.defs) out.add(def);
28323
+ }
28324
+ return Array.from(out);
28325
+ }
28326
+ const COLLAPSE_THRESHOLD = 8;
28327
+ const proxyTargets = /* @__PURE__ */ new WeakMap();
28328
+ function evaluate(selector) {
28329
+ return untrack2(() => {
28330
+ const deps = [];
28331
+ const seen = /* @__PURE__ */ new Set();
28332
+ const envelopeLeaves = /* @__PURE__ */ new Map();
28333
+ const collapsed = /* @__PURE__ */ new Set();
28334
+ const recordLeaf = (path) => {
28335
+ const k = pathKey(path);
28336
+ if (!seen.has(k)) {
28337
+ seen.add(k);
28338
+ deps.push(path);
28339
+ }
28340
+ };
28341
+ const recordEnvelope = (env) => {
28342
+ if (env.length === 0) return;
28343
+ const k = pathKey(env);
28344
+ const count = (envelopeLeaves.get(k) ?? 0) + 1;
28345
+ envelopeLeaves.set(k, count);
28346
+ if (count >= COLLAPSE_THRESHOLD) collapsed.add(k);
28347
+ recordLeaf(env);
28348
+ };
28349
+ const isPlain = (value) => value !== null && typeof value === "object" && (Array.isArray(value) || Object.prototype.toString.call(value) === "[object Object]");
28350
+ const wrap = (value, base) => {
28351
+ if (!isPlain(value)) return value;
28352
+ const proxy = new Proxy(value, {
28353
+ get(target, prop, receiver) {
28354
+ if (typeof prop === "symbol") return Reflect.get(target, prop, receiver);
28355
+ const array = Array.isArray(target);
28356
+ const segment = array && isDigits(String(prop)) ? Number(prop) : String(prop);
28357
+ const child = base.concat(segment);
28358
+ const v = Reflect.get(target, prop, receiver);
28359
+ if (isPlain(v)) return wrap(v, child);
28360
+ if (typeof v === "function") return v;
28361
+ recordLeaf(child);
28362
+ if (array) recordEnvelope(base);
28363
+ return v;
28364
+ },
28365
+ set() {
28366
+ throw new Error("Path store: derived selectors must be pure \u2014 no writes.");
28367
+ }
28368
+ });
28369
+ proxyTargets.set(proxy, value);
28370
+ return proxy;
28371
+ };
28372
+ const unwrap = (value) => {
28373
+ if (value === null || typeof value !== "object") return value;
28374
+ const target = proxyTargets.get(value);
28375
+ if (target !== void 0) return unwrap(target);
28376
+ if (Array.isArray(value)) {
28377
+ let changed2 = false;
28378
+ const out2 = [];
28379
+ for (const item of value) {
28380
+ const next = unwrap(item);
28381
+ if (next !== item) changed2 = true;
28382
+ out2.push(next);
28383
+ }
28384
+ return changed2 ? out2 : value;
28385
+ }
28386
+ let changed = false;
28387
+ const out = {};
28388
+ for (const key of Object.keys(value)) {
28389
+ const next = unwrap(value[key]);
28390
+ if (next !== value[key]) changed = true;
28391
+ out[key] = next;
28392
+ }
28393
+ return changed ? out : value;
28394
+ };
28395
+ const result = selector(wrap(state, []));
28396
+ const finalDeps = collapsed.size === 0 ? deps : deps.filter((d) => {
28397
+ for (const envKey of collapsed) {
28398
+ if (isStrictPrefix(tokensOfKey(envKey), d)) return false;
28399
+ }
28400
+ return true;
28401
+ });
28402
+ return { value: unwrap(result), deps: finalDeps };
28403
+ });
28404
+ }
28405
+ function recomputeDerived(changes, version3) {
28406
+ const queue = [];
28407
+ const queued = /* @__PURE__ */ new Set();
28408
+ const collect = (tokens) => {
28409
+ for (const def of derivedsRelatedTo(tokens, /* @__PURE__ */ new Set())) {
28410
+ if (!queued.has(def)) {
28411
+ queued.add(def);
28412
+ queue.push(def);
28413
+ }
28414
+ }
28415
+ };
28416
+ for (const change of changes) collect(tokensOfKey(change.path));
28417
+ while (queue.length > 0) {
28418
+ const def = queue.pop();
28419
+ unregisterDef(def);
28420
+ const { value, deps } = evaluate(def.selector);
28421
+ def.deps = deps;
28422
+ registerDef(def);
28423
+ const before = def.cell.get();
28424
+ if (!def.equals(before, value)) {
28425
+ def.cell.set(value);
28426
+ def.lastTrigger = changes.map((c) => tokensOfKey(c.path));
28427
+ def.lastTriggerVersion = version3;
28428
+ mergedDirty = true;
28429
+ const change = { path: def.path, before, after: value };
28430
+ changes.push(change);
28431
+ collect(def.tokens);
28432
+ }
28433
+ }
28434
+ }
28435
+ let mergedCache = null;
28436
+ let mergedDirty = true;
28437
+ function invalidateMerged() {
28438
+ mergedCache = null;
28439
+ mergedDirty = true;
28440
+ }
28441
+ function buildMerged() {
28442
+ if (!mergedDirty && mergedCache !== null) return mergedCache;
28443
+ const base = rootCell.get();
28444
+ if (derivedDefs.size === 0) {
28445
+ mergedCache = base;
28446
+ mergedDirty = false;
28447
+ return base;
28448
+ }
28449
+ let acc = base;
28450
+ for (const def of derivedDefs.values()) {
28451
+ acc = setIn(acc, def.tokens, def.cell.get());
28452
+ }
28453
+ mergedCache = acc;
28454
+ mergedDirty = false;
28455
+ return acc;
28456
+ }
28457
+ const events = [];
28458
+ let version2 = 0;
28459
+ let undoStack = [];
28460
+ let redoStack = [];
28461
+ const lastCause = /* @__PURE__ */ new Map();
28462
+ function recordCause(changes, action, atVersion) {
28463
+ for (const change of changes) {
28464
+ lastCause.set(change.path, { action, version: atVersion });
28465
+ }
28466
+ }
28467
+ function commit(next, action, touched) {
28468
+ untrack2(() => {
28469
+ if (Object.is(next, state)) return;
28470
+ const changes = [];
28471
+ if (touched !== null) {
28472
+ shallowDiff(getIn(state, touched), getIn(next, touched), touched, changes);
28473
+ } else {
28474
+ shallowDiff(state, next, [], changes);
28475
+ }
28476
+ if (changes.length === 0) return;
28477
+ undoStack.push(state);
28478
+ if (undoStack.length > historyLimit) undoStack.shift();
28479
+ redoStack = [];
28480
+ state = next;
28481
+ rootCell.set(state);
28482
+ invalidateMerged();
28483
+ const nextVersion = version2 + 1;
28484
+ recordCause(changes, action, nextVersion);
28485
+ recomputeDerived(changes, nextVersion);
28486
+ syncPathCells(touched);
28487
+ dispatchAll();
28488
+ persistToStorage();
28489
+ version2 = nextVersion;
28490
+ events.push({ version: version2, action, at: Date.now(), changes });
28491
+ if (events.length > historyLimit) events.shift();
28492
+ });
28493
+ }
28494
+ function restore(snapshot, action) {
28495
+ const changes = [];
28496
+ untrack2(() => {
28497
+ shallowDiff(state, snapshot, [], changes);
28498
+ state = snapshot;
28499
+ rootCell.set(state);
28500
+ invalidateMerged();
28501
+ const nextVersion = version2 + 1;
28502
+ recordCause(changes, action, nextVersion);
28503
+ recomputeDerived(changes, nextVersion);
28504
+ syncPathCells(null);
28505
+ if (changes.length > 0) dispatchAll();
28506
+ persistToStorage();
28507
+ version2 = nextVersion;
28508
+ events.push({ version: version2, action, at: Date.now(), changes });
28509
+ if (events.length > historyLimit) events.shift();
28510
+ });
28511
+ return changes;
28512
+ }
28513
+ function persistToStorage() {
28514
+ if (!persist || !storageKey) return;
28515
+ try {
28516
+ writePersistedStorage(storageKey, JSON.stringify(state));
28517
+ } catch {
28518
+ }
28519
+ }
28520
+ const subscribers = /* @__PURE__ */ new Set();
28521
+ const watchers = /* @__PURE__ */ new Set();
28522
+ function dispatchAll() {
28523
+ const current2 = buildMerged();
28524
+ for (const wrapper of subscribers) wrapper(current2);
28525
+ for (const wrapper of watchers) wrapper();
28526
+ }
28527
+ function whyAt(tokens, depth = 0, versionNow = version2) {
28528
+ const path = pathKey(tokens);
28529
+ const value = getIn(state, tokens);
28530
+ if (depth > 64) return { path, value, cause: "initial" };
28531
+ const def = derivedDefs.get(path);
28532
+ if (def) {
28533
+ const node = {
28534
+ path,
28535
+ value: def.cell.get(),
28536
+ cause: "derived",
28537
+ from: def.deps.map((dep) => whyAt(dep, depth + 1))
28538
+ };
28539
+ if (def.lastTrigger) {
28540
+ node.changedBy = def.lastTrigger.map((trigger, i) => ({
28541
+ path: pathKey(trigger),
28542
+ value: getIn(state, trigger),
28543
+ cause: "action",
28544
+ action: i === 0 ? void 0 : void 0,
28545
+ // filled below from events
28546
+ version: def.lastTriggerVersion
28547
+ }));
28548
+ const first = def.lastTrigger[0];
28549
+ const ev = events.slice().reverse().find((e) => e.changes.some((c) => c.path === pathKey(first)));
28550
+ if (ev) {
28551
+ node.changedBy[0].action = ev.action;
28552
+ node.changedBy[0].version = ev.version;
28553
+ node.version = ev.version;
28554
+ }
28555
+ }
28556
+ void versionNow;
28557
+ return node;
28558
+ }
28559
+ const cause = lastCause.get(path);
28560
+ if (cause) {
28561
+ if (cause.action === "undo" || cause.action === "redo") {
28562
+ return { path, value, cause: "time-travel", action: cause.action, version: cause.version };
28563
+ }
28564
+ return { path, value, cause: "action", action: cause.action, version: cause.version };
28565
+ }
28566
+ return { path, value, cause: "initial" };
28567
+ }
28568
+ function renderExplanation(node, indent4 = 0) {
28569
+ const pad = " ".repeat(indent4);
28570
+ const lines = [];
28571
+ const tag = node.cause === "derived" ? "derived" : node.cause === "action" ? `${node.action ?? "action"} \xB7 v${node.version ?? "?"}` : node.cause === "time-travel" ? `time-travel \xB7 v${node.version ?? "?"}` : "initial";
28572
+ lines.push(`${pad}${node.path} = ${JSON.stringify(node.value)} (${tag})`);
28573
+ if (node.changedBy && node.changedBy.length > 0) {
28574
+ lines.push(`${pad} recomputed after:`);
28575
+ for (const change of node.changedBy) {
28576
+ lines.push(renderExplanation({ ...change, from: void 0 }, indent4 + 2));
28577
+ }
28578
+ } else if (node.from && node.from.length > 0) {
28579
+ for (const child of node.from) lines.push(renderExplanation(child, indent4 + 1));
28580
+ }
28581
+ return lines.join("\n");
28582
+ }
28583
+ function derivedHandle(def, displayPath2) {
28584
+ return {
28585
+ path: def.path,
28586
+ get deps() {
28587
+ return def.deps.map((dep) => dep.join("."));
28588
+ },
28589
+ get() {
28590
+ return def.cell.get();
28591
+ },
28592
+ subscribe(cb) {
28593
+ let prev = def.cell.get();
28594
+ return store.subscribe(() => {
28595
+ const next = def.cell.get();
28596
+ if (!Object.is(prev, next)) {
28597
+ prev = next;
28598
+ cb(next);
28599
+ }
28600
+ });
28601
+ }
28602
+ };
28603
+ void displayPath2;
28604
+ }
28605
+ const store = {
28606
+ /** Reactive whole-state read — re-runs on any commit. Includes derived
28607
+ * values at their registered paths (derived wins over a raw key). */
28608
+ get() {
28609
+ rootCell.get();
28610
+ return buildMerged();
28611
+ },
28612
+ /** A fine-grained, causally-aware handle for one nested path. When a
28613
+ * derived is registered at this path, the handle reads/writes the
28614
+ * derived (set/update then throw read-only). */
28615
+ at(path) {
28616
+ const tokens = parseStorePath(path);
28617
+ const key = pathKey(tokens);
28618
+ const def = derivedDefs.get(key);
28619
+ if (def) {
28620
+ const handle2 = derivedHandle(def, path);
28621
+ return {
28622
+ path: key,
28623
+ get: handle2.get,
28624
+ set() {
28625
+ throw new Error(`Path store: derived path "${path}" is read-only.`);
28626
+ },
28627
+ update() {
28628
+ throw new Error(`Path store: derived path "${path}" is read-only.`);
28629
+ },
28630
+ subscribe: handle2.subscribe
28631
+ };
28632
+ }
28633
+ return {
28634
+ path: key,
28635
+ get() {
28636
+ return cellFor(tokens).get();
28637
+ },
28638
+ set(value, action = "set") {
28639
+ commit(setIn(state, tokens, cloneValue(value)), action, tokens);
28640
+ },
28641
+ update(fn, action = "update") {
28642
+ commit(updateIn(state, tokens, fn), action, tokens);
28643
+ },
28644
+ subscribe(cb) {
28645
+ let prev = cellFor(tokens).get();
28646
+ return store.subscribe(() => {
28647
+ const next = cellFor(tokens).get();
28648
+ if (!Object.is(prev, next)) {
28649
+ prev = next;
28650
+ cb(next);
28651
+ }
28652
+ });
28653
+ }
28654
+ };
28655
+ },
28656
+ /** Replace the whole state (attributed to `action`). */
28657
+ set(next, action = "set") {
28658
+ commit(cloneValue(next), action, null);
28659
+ },
28660
+ /** Shallow merge a partial (or `(prev) => partial`) into the root. */
28661
+ update(patch, action = "update") {
28662
+ const partial = typeof patch === "function" ? patch(state) : patch;
28663
+ commit({ ...state, ...cloneValue(partial) }, action, null);
28664
+ },
28665
+ setIn(path, value, action = "setIn") {
28666
+ const tokens = typeof path === "string" ? parseStorePath(path) : path;
28667
+ commit(setIn(state, tokens, cloneValue(value)), action, tokens);
28668
+ },
28669
+ updateIn(path, fn, action = "updateIn") {
28670
+ const tokens = typeof path === "string" ? parseStorePath(path) : path;
28671
+ commit(updateIn(state, tokens, fn), action, tokens);
28672
+ },
28673
+ /**
28674
+ * Register a derived node at `path`. The selector is evaluated inside
28675
+ * `untrack` against a read-recording proxy, so its source paths are
28676
+ * captured automatically — including array envelopes, which make
28677
+ * aggregate deriveds re-run when the array's membership changes.
28678
+ */
28679
+ derived(path, selector, equals = Object.is) {
28680
+ const tokens = parseStorePath(path);
28681
+ const key = pathKey(tokens);
28682
+ const first = evaluate(selector);
28683
+ const def = {
28684
+ path: key,
28685
+ tokens,
28686
+ selector,
28687
+ equals,
28688
+ cell: track(first.value),
28689
+ deps: first.deps,
28690
+ lastTrigger: null,
28691
+ lastTriggerVersion: 0
28692
+ };
28693
+ derivedDefs.set(key, def);
28694
+ registerDef(def);
28695
+ mergedDirty = true;
28696
+ return derivedHandle(def, path);
28697
+ },
28698
+ subscribe(fn, selector, equals) {
28699
+ const eq = equals ?? Object.is;
28700
+ let hasPrev = false;
28701
+ let prev;
28702
+ const wrapper = selector ? () => {
28703
+ const selected = selector(buildMerged());
28704
+ if (!hasPrev || !eq(selected, prev)) {
28705
+ hasPrev = true;
28706
+ prev = selected;
28707
+ fn(selected);
28708
+ }
28709
+ } : (current2) => fn(current2);
28710
+ subscribers.add(wrapper);
28711
+ wrapper(buildMerged());
28712
+ return () => {
28713
+ subscribers.delete(wrapper);
28714
+ };
28715
+ },
28716
+ watch(selector, callback) {
28717
+ let prev = selector(buildMerged());
28718
+ const wrapper = () => {
28719
+ const next = selector(buildMerged());
28720
+ if (!Object.is(prev, next)) {
28721
+ const old = prev;
28722
+ prev = next;
28723
+ callback(next, old);
28724
+ }
28725
+ };
28726
+ watchers.add(wrapper);
28727
+ return () => {
28728
+ watchers.delete(wrapper);
28729
+ };
28730
+ },
28731
+ /** Causal explanation for the current value at `path`. */
28732
+ why(path) {
28733
+ return whyAt(parseStorePath(path));
28734
+ },
28735
+ /** A printable causal chain for devtools / tests. */
28736
+ explain(path) {
28737
+ return renderExplanation(whyAt(parseStorePath(path)));
28738
+ },
28739
+ /** The recorded events, oldest first. */
28740
+ get events() {
28741
+ return events;
28742
+ },
28743
+ get version() {
28744
+ return version2;
28745
+ },
28746
+ canUndo() {
28747
+ return undoStack.length > 0;
28748
+ },
28749
+ canRedo() {
28750
+ return redoStack.length > 0;
28751
+ },
28752
+ undo() {
28753
+ const prev = undoStack.pop();
28754
+ if (prev === void 0) return false;
28755
+ redoStack.push(state);
28756
+ restore(prev, "undo");
28757
+ return true;
28758
+ },
28759
+ redo() {
28760
+ const next = redoStack.pop();
28761
+ if (next === void 0) return false;
28762
+ undoStack.push(state);
28763
+ restore(next, "redo");
28764
+ return true;
28765
+ },
28766
+ /** A JSON-safe snapshot of the current merged state. */
28767
+ toJSON() {
28768
+ return plainClone(buildMerged());
28769
+ }
28770
+ };
28771
+ return store;
28772
+ }
28773
+ var init_path_store = __esm({
28774
+ "../runtime/src/path-store.ts"() {
28775
+ "use strict";
28776
+ init_ripple_runtime();
28777
+ init_nested_update();
28778
+ init_store_persistence();
28779
+ }
28780
+ });
28781
+
27758
28782
  // ../runtime/src/index-server.ts
27759
28783
  var index_server_exports = {};
27760
28784
  __export(index_server_exports, {
@@ -27809,8 +28833,10 @@ __export(index_server_exports, {
27809
28833
  createContext: () => createContext,
27810
28834
  createFileRouter: () => createFileRouter,
27811
28835
  createLocals: () => createLocals,
28836
+ createPathStore: () => createPathStore,
27812
28837
  createResource: () => createResource,
27813
28838
  createRouter: () => createRouter,
28839
+ createStore: () => createStore,
27814
28840
  create_component_ctx: () => create_component_ctx,
27815
28841
  create_try_block: () => create_try_block,
27816
28842
  custom: () => custom,
@@ -27936,6 +28962,8 @@ var init_index_server = __esm({
27936
28962
  init_action();
27937
28963
  init_metadata();
27938
28964
  init_nested_update();
28965
+ init_store();
28966
+ init_path_store();
27939
28967
  }
27940
28968
  });
27941
28969
 
@@ -36153,16 +37181,21 @@ function __matchPath(pattern, pathname) {
36153
37181
  let pi = 0, pp = 0;
36154
37182
  const params = {};
36155
37183
  while (pi < pathParts.length && pp < patternParts.length) {
36156
- if (patternParts[pp].startsWith(':')) {
36157
- const name = patternParts[pp].slice(1);
36158
- params[name] = pathParts[pi];
37184
+ const seg = patternParts[pp];
37185
+ // A "*name" segment is a catch-all and absorbs the rest of the path.
37186
+ if (seg.startsWith('*')) { params[seg.slice(1)] = pathParts.slice(pi).join('/'); pi = pathParts.length; pp++; }
37187
+ else if (seg.startsWith(':')) {
37188
+ params[seg.slice(1)] = pathParts[pi];
36159
37189
  pi++; pp++;
36160
- } else if (patternParts[pp] === pathParts[pi]) {
37190
+ } else if (seg === pathParts[pi]) {
36161
37191
  pi++; pp++;
36162
37192
  } else {
36163
37193
  return null;
36164
37194
  }
36165
37195
  }
37196
+ // A trailing catch-all still matches an empty tail; the loop above exits as
37197
+ // soon as the URL is exhausted, so without this it was never reached.
37198
+ if (pp === patternParts.length - 1 && patternParts[pp].startsWith('*')) { params[patternParts[pp].slice(1)] = pathParts.slice(pi).join('/'); pp++; }
36166
37199
  if (pp === patternParts.length && pi === pathParts.length) return params;
36167
37200
  return null;
36168
37201
  }
@@ -47726,7 +48759,7 @@ __export(migrate_exports, {
47726
48759
  detectInstalledVersion: () => detectInstalledVersion,
47727
48760
  runMigrate: () => runMigrate
47728
48761
  });
47729
- import { readFileSync as readFileSync41, writeFileSync as writeFileSync21, existsSync as existsSync44, statSync as statSync23, readdirSync as readdirSync15 } from "node:fs";
48762
+ import { readFileSync as readFileSync41, writeFileSync as writeFileSync22, existsSync as existsSync44, statSync as statSync23, readdirSync as readdirSync15 } from "node:fs";
47730
48763
  import { join as join29, relative as relative9, extname as extname9 } from "node:path";
47731
48764
  function detectInstalledVersion(projectDir, cliVersion) {
47732
48765
  for (const pkg of ["@vesk/vesk-cli", "@vesk/adapter", "@vesk/compiler"]) {
@@ -47815,7 +48848,7 @@ function runMigrate(options) {
47815
48848
  }
47816
48849
  if (!changed) continue;
47817
48850
  report.filesChanged.push(relPath);
47818
- if (!options.dryRun) writeFileSync21(abs, current2, "utf-8");
48851
+ if (!options.dryRun) writeFileSync22(abs, current2, "utf-8");
47819
48852
  }
47820
48853
  return report;
47821
48854
  }
@@ -47830,7 +48863,7 @@ var init_migrate = __esm({
47830
48863
  });
47831
48864
 
47832
48865
  // src/index.ts
47833
- import { readFileSync as readFileSync42, writeFileSync as writeFileSync22, mkdirSync as mkdirSync20, existsSync as existsSync45 } from "fs";
48866
+ import { readFileSync as readFileSync42, writeFileSync as writeFileSync23, mkdirSync as mkdirSync20, existsSync as existsSync45 } from "fs";
47834
48867
  import { resolve as resolve40, join as join30 } from "path";
47835
48868
  import { fileURLToPath as fileURLToPath9 } from "url";
47836
48869
 
@@ -50924,10 +51957,17 @@ async function buildTreeShakenRuntimeNow(runtimeDir, usedNames) {
50924
51957
  const missing = unique.filter((n) => !available.has(n));
50925
51958
  if (missing.length > 0) {
50926
51959
  console.error(`vesk: runtime names not exported \u2014 ${missing.join(", ")}; falling back to full runtime`);
51960
+ const full = await bundleRuntimeNames(runtimeDir, [...available]);
51961
+ if (full) return full;
50927
51962
  return buildRuntimeCode(runtimeDir);
50928
51963
  }
51964
+ return await bundleRuntimeNames(runtimeDir, unique, true) ?? buildRuntimeCode(runtimeDir);
51965
+ }
51966
+ async function bundleRuntimeNames(runtimeDir, names, strict = false) {
51967
+ if (names.length === 0) return null;
50929
51968
  const entry = runtimeTreeShakeEntry();
50930
51969
  const indexClient = esbuildPath(join7(runtimeDir, "index-client.js"));
51970
+ const unique = [...new Set(names)];
50931
51971
  try {
50932
51972
  try {
50933
51973
  mkdirSync3(dirname8(entry), { recursive: true });
@@ -50964,8 +52004,8 @@ const { ${unique.join(", ")} } = __veskRuntime;
50964
52004
  export { ${unique.join(", ")} };
50965
52005
  `;
50966
52006
  } catch (e) {
50967
- console.error("vesk: runtime tree-shake failed, falling back to full runtime:", e.message);
50968
- return buildRuntimeCode(runtimeDir);
52007
+ if (strict) console.error("vesk: runtime tree-shake failed, falling back to full runtime:", e.message);
52008
+ return null;
50969
52009
  } finally {
50970
52010
  try {
50971
52011
  unlinkSync3(entry);
@@ -51072,6 +52112,18 @@ if (typeof document !== 'undefined') __router.start();
51072
52112
  }
51073
52113
 
51074
52114
  // ../adapter/src/manifest.ts
52115
+ function specificityKey(path) {
52116
+ return path.split("/").filter(Boolean).map((seg) => seg.startsWith("*") ? "2" + seg : seg.startsWith(":") ? "1" + seg : "0" + seg);
52117
+ }
52118
+ function compareSpecificity(a, b) {
52119
+ const ka = specificityKey(a);
52120
+ const kb = specificityKey(b);
52121
+ const len = Math.min(ka.length, kb.length);
52122
+ for (let i = 0; i < len; i++) {
52123
+ if (ka[i] !== kb[i]) return ka[i] < kb[i] ? -1 : 1;
52124
+ }
52125
+ return kb.length - ka.length;
52126
+ }
51075
52127
  function generateManifest(routes, ssrRoutes, apiRoutes, staticRoutes, middlewareEnabled, actionMap, headExtra, eventsEnabled = false) {
51076
52128
  const routeEntries = [];
51077
52129
  for (const r of ssrRoutes) {
@@ -51086,15 +52138,23 @@ function generateManifest(routes, ssrRoutes, apiRoutes, staticRoutes, middleware
51086
52138
  if (r._isrTags) entry.tags = r._isrTags;
51087
52139
  routeEntries.push(entry);
51088
52140
  }
52141
+ const apiEntries = [];
51089
52142
  for (const r of apiRoutes) {
51090
52143
  const urlParts = r.fullPath.split("/").filter(Boolean);
51091
- const name = urlParts.map((s) => s.startsWith(":") ? s.slice(1) || "param" : s).join("_") || "index";
51092
- routeEntries.push({
51093
- path: `/api${r.fullPath}`,
52144
+ const parts = urlParts.map((s, i) => {
52145
+ const last = i === urlParts.length - 1;
52146
+ if (last && r.isCatchAll && s.startsWith(":")) return "*" + s.slice(1);
52147
+ return s;
52148
+ });
52149
+ const name = parts.map((s) => s.startsWith(":") || s.startsWith("*") ? s.slice(1) || "param" : s).join("_") || "index";
52150
+ apiEntries.push({
52151
+ path: parts.length ? `/api/${parts.join("/")}` : "/api",
51094
52152
  type: "api",
51095
52153
  function: `server/api/${name}.js`
51096
52154
  });
51097
52155
  }
52156
+ apiEntries.sort((a, b) => compareSpecificity(a.path, b.path));
52157
+ routeEntries.push(...apiEntries);
51098
52158
  const ssgEntries = [];
51099
52159
  for (const r of staticRoutes) {
51100
52160
  ssgEntries.push({
@@ -51423,18 +52483,27 @@ async function startProdServer(outDir, options) {
51423
52483
  let pi = 0, pp2 = 0;
51424
52484
  const params = {};
51425
52485
  while (pi < pathParts.length && pp2 < patternParts.length) {
51426
- if (patternParts[pp2].startsWith(":")) {
51427
- const name = patternParts[pp2].slice(1);
52486
+ const seg = patternParts[pp2];
52487
+ if (seg.startsWith("*")) {
52488
+ params[seg.slice(1)] = pathParts.slice(pi).join("/");
52489
+ pi = pathParts.length;
52490
+ pp2++;
52491
+ } else if (seg.startsWith(":")) {
52492
+ const name = seg.slice(1);
51428
52493
  params[name] = pathParts[pi];
51429
52494
  pi++;
51430
52495
  pp2++;
51431
- } else if (patternParts[pp2] === pathParts[pi]) {
52496
+ } else if (seg === pathParts[pi]) {
51432
52497
  pi++;
51433
52498
  pp2++;
51434
52499
  } else {
51435
52500
  return null;
51436
52501
  }
51437
52502
  }
52503
+ if (pp2 === patternParts.length - 1 && patternParts[pp2].startsWith("*")) {
52504
+ params[patternParts[pp2].slice(1)] = pathParts.slice(pi).join("/");
52505
+ pp2++;
52506
+ }
51438
52507
  if (pp2 === patternParts.length && pi === pathParts.length) return params;
51439
52508
  return null;
51440
52509
  }
@@ -52184,7 +53253,8 @@ vesk build: done (${outDir})`);
52184
53253
  init_seo_audit();
52185
53254
 
52186
53255
  // src/dev-server.ts
52187
- import { readFileSync as readFileSync38, watch, statSync as statSync21, existsSync as existsSync42, readdirSync as readdirSync13 } from "node:fs";
53256
+ import { readFileSync as readFileSync38, watch, statSync as statSync21, existsSync as existsSync42, mkdirSync as mkdirSync19, readdirSync as readdirSync13, writeFileSync as writeFileSync21, renameSync as renameSync2 } from "node:fs";
53257
+ import { createHash as createHash2 } from "node:crypto";
52188
53258
  import { resolve as resolve38, extname as extname8, join as join26, dirname as dirname26 } from "node:path";
52189
53259
  import { createServer as createServer2 } from "node:http";
52190
53260
  import { WebSocketServer as WebSocketServer2 } from "ws";
@@ -55371,6 +56441,20 @@ function collectSources(tree) {
55371
56441
  walk9(tree);
55372
56442
  return map;
55373
56443
  }
56444
+ function segmentRank(node) {
56445
+ if (node.isGroup || node.fullPath === "/")
56446
+ return 0;
56447
+ if (node.isCatchAll)
56448
+ return 3;
56449
+ if (node.isDynamic)
56450
+ return 2;
56451
+ return 1;
56452
+ }
56453
+ function bySegmentPrecedence(nodes) {
56454
+ if (nodes.length < 2)
56455
+ return nodes;
56456
+ return nodes.map((node, index) => ({ node, index, rank: segmentRank(node) })).sort((a, b) => a.rank - b.rank || a.index - b.index).map((entry) => entry.node);
56457
+ }
55374
56458
  function matchUrl(tree, pathname) {
55375
56459
  const parts = pathname.split("/").filter(Boolean);
55376
56460
  const chain = [];
@@ -55386,7 +56470,7 @@ function matchUrl(tree, pathname) {
55386
56470
  chain.push(node);
55387
56471
  }
55388
56472
  function matchNodes(nodes, partIndex) {
55389
- for (const node of nodes) {
56473
+ for (const node of bySegmentPrecedence(nodes)) {
55390
56474
  if (node.isGroup) {
55391
56475
  const marker = chain.length;
55392
56476
  if (node.layout || node.page)
@@ -55559,6 +56643,20 @@ function scanApiDir(rootDir, dir, parentPath) {
55559
56643
  }
55560
56644
  return nodes;
55561
56645
  }
56646
+ function specificityRank(node) {
56647
+ if (node.fullPath === "/")
56648
+ return 0;
56649
+ if (node.isCatchAll)
56650
+ return 3;
56651
+ if (node.isDynamic)
56652
+ return 2;
56653
+ return 1;
56654
+ }
56655
+ function bySpecificity(nodes) {
56656
+ if (nodes.length < 2)
56657
+ return nodes;
56658
+ return nodes.map((node, index) => ({ node, index, rank: specificityRank(node) })).sort((a, b) => a.rank - b.rank || a.index - b.index).map((entry) => entry.node);
56659
+ }
55562
56660
  function matchApiUrl(tree, pathname) {
55563
56661
  let normalized = pathname.split("?")[0].split("#")[0];
55564
56662
  if (normalized === "/api") {
@@ -55568,31 +56666,40 @@ function matchApiUrl(tree, pathname) {
55568
56666
  }
55569
56667
  const parts = normalized.split("/").filter(Boolean);
55570
56668
  const params = {};
56669
+ function restoreParams(snapshot) {
56670
+ for (const key of Object.keys(params)) {
56671
+ if (!(key in snapshot))
56672
+ delete params[key];
56673
+ }
56674
+ for (const key of Object.keys(snapshot))
56675
+ params[key] = snapshot[key];
56676
+ }
55571
56677
  function matchNodes(nodes, partIndex) {
55572
- for (const node of nodes) {
56678
+ for (const node of bySpecificity(nodes)) {
55573
56679
  if (node.fullPath === "/") {
55574
56680
  if (partIndex >= parts.length && node.filePath)
55575
56681
  return node;
55576
56682
  return matchNodes(node.children, partIndex);
55577
56683
  }
55578
- if (partIndex >= parts.length) {
55579
- if (node.filePath)
55580
- return node;
55581
- continue;
55582
- }
55583
- const part = parts[partIndex];
56684
+ const part = partIndex < parts.length ? parts[partIndex] : void 0;
55584
56685
  if (node.isCatchAll) {
56686
+ if (!node.filePath)
56687
+ continue;
55585
56688
  const paramName = node.path.startsWith(":") ? node.path.slice(1) : node.path;
55586
56689
  params[paramName] = parts.slice(partIndex).map(decodeURIComponent).join("/");
55587
56690
  return node;
55588
56691
  }
56692
+ if (part === void 0)
56693
+ continue;
55589
56694
  if (node.isDynamic) {
55590
56695
  const paramName = node.path.startsWith(":") ? node.path.slice(1) : node.path;
55591
56696
  params[paramName] = decodeURIComponent(part);
55592
56697
  if (node.children.length > 0) {
56698
+ const snapshot = { ...params };
55593
56699
  const result = matchNodes(node.children, partIndex + 1);
55594
56700
  if (result)
55595
56701
  return result;
56702
+ restoreParams(snapshot);
55596
56703
  }
55597
56704
  if (node.filePath)
55598
56705
  return node;
@@ -55600,10 +56707,14 @@ function matchApiUrl(tree, pathname) {
55600
56707
  continue;
55601
56708
  }
55602
56709
  if (node.path === part) {
56710
+ if (partIndex + 1 >= parts.length && node.filePath)
56711
+ return node;
55603
56712
  if (node.children.length > 0) {
56713
+ const snapshot = { ...params };
55604
56714
  const result = matchNodes(node.children, partIndex + 1);
55605
56715
  if (result)
55606
56716
  return result;
56717
+ restoreParams(snapshot);
55607
56718
  }
55608
56719
  if (node.filePath)
55609
56720
  return node;
@@ -57366,10 +58477,19 @@ async function buildTreeShakenRuntimeNow2(runtimeDir, usedNames) {
57366
58477
  const missing = unique.filter((n) => !available.has(n));
57367
58478
  if (missing.length > 0) {
57368
58479
  console.error(`vesk: runtime names not exported \u2014 ${missing.join(", ")}; falling back to full runtime`);
58480
+ const full = await bundleRuntimeNames2(runtimeDir, [...available]);
58481
+ if (full)
58482
+ return full;
57369
58483
  return buildRuntimeCode2(runtimeDir);
57370
58484
  }
58485
+ return await bundleRuntimeNames2(runtimeDir, unique, true) ?? buildRuntimeCode2(runtimeDir);
58486
+ }
58487
+ async function bundleRuntimeNames2(runtimeDir, names, strict = false) {
58488
+ if (names.length === 0)
58489
+ return null;
57371
58490
  const entry = runtimeTreeShakeEntry2();
57372
58491
  const indexClient = esbuildPath2(join20(runtimeDir, "index-client.js"));
58492
+ const unique = [...new Set(names)];
57373
58493
  try {
57374
58494
  try {
57375
58495
  mkdirSync12(dirname18(entry), { recursive: true });
@@ -57406,8 +58526,9 @@ const { ${unique.join(", ")} } = __veskRuntime;
57406
58526
  export { ${unique.join(", ")} };
57407
58527
  `;
57408
58528
  } catch (e) {
57409
- console.error("vesk: runtime tree-shake failed, falling back to full runtime:", e.message);
57410
- return buildRuntimeCode2(runtimeDir);
58529
+ if (strict)
58530
+ console.error("vesk: runtime tree-shake failed, falling back to full runtime:", e.message);
58531
+ return null;
57411
58532
  } finally {
57412
58533
  try {
57413
58534
  unlinkSync4(entry);
@@ -64196,6 +65317,61 @@ async function startDevServer(port, projectDir, config, host) {
64196
65317
  }
64197
65318
  const routeChunksBuilt = /* @__PURE__ */ new Set();
64198
65319
  let clientGeneration = 0;
65320
+ const devCacheDir = () => join26(projectDir, "node_modules", ".vesk", "dev-cache");
65321
+ function devCacheKey() {
65322
+ const parts = [`flags:${!!config.routeDataCache}`];
65323
+ const walk9 = (dir) => {
65324
+ let entries = [];
65325
+ try {
65326
+ entries = readdirSync13(dir);
65327
+ } catch {
65328
+ return;
65329
+ }
65330
+ for (const name of entries.sort()) {
65331
+ if (name === "node_modules" || name.startsWith(".")) continue;
65332
+ const p = join26(dir, name);
65333
+ let st;
65334
+ try {
65335
+ st = statSync21(p);
65336
+ } catch {
65337
+ continue;
65338
+ }
65339
+ if (st.isDirectory()) {
65340
+ walk9(p);
65341
+ continue;
65342
+ }
65343
+ if (!/\.(vsk|ts|tsx|js|jsx|vue|svelte)$/.test(name)) continue;
65344
+ parts.push(`${p}:${st.mtimeMs}:${st.size}`);
65345
+ }
65346
+ };
65347
+ walk9(appDirPath);
65348
+ try {
65349
+ parts.push(`compiler:${readFileSync38(join26(process.cwd(), "node_modules", "@vesk", "compiler", "package.json"), "utf8")}`);
65350
+ } catch {
65351
+ }
65352
+ return createHash2("sha256").update(parts.join("\n")).digest("hex").slice(0, 32);
65353
+ }
65354
+ function readDevBundleCache() {
65355
+ try {
65356
+ const file = join26(devCacheDir(), "client-bundle.json");
65357
+ const parsed = JSON.parse(readFileSync38(file, "utf8"));
65358
+ if (parsed.key !== devCacheKey() || typeof parsed.main !== "string" || !Array.isArray(parsed.chunks)) return null;
65359
+ return { main: parsed.main, chunks: parsed.chunks };
65360
+ } catch {
65361
+ return null;
65362
+ }
65363
+ }
65364
+ function writeDevBundleCache(main, chunks) {
65365
+ try {
65366
+ const dir = devCacheDir();
65367
+ mkdirSync19(dir, { recursive: true });
65368
+ const file = join26(dir, "client-bundle.json");
65369
+ const tmp = join26(dir, `client-bundle.${process.pid}.tmp`);
65370
+ writeFileSync21(tmp, JSON.stringify({ key: devCacheKey(), main, chunks }), "utf8");
65371
+ renameSync2(tmp, file);
65372
+ } catch {
65373
+ }
65374
+ }
64199
65375
  async function ensureRouteChunk(fullPath) {
64200
65376
  if (routeChunksBuilt.has(fullPath)) return;
64201
65377
  routeChunksBuilt.add(fullPath);
@@ -64233,6 +65409,18 @@ async function startDevServer(port, projectDir, config, host) {
64233
65409
  }
64234
65410
  async function buildClientBundle() {
64235
65411
  try {
65412
+ const cached = readDevBundleCache();
65413
+ if (cached) {
65414
+ clientBundle = cached.main;
65415
+ devBundleBytes = Buffer.byteLength(cached.main, "utf8");
65416
+ storeChunks(cached.chunks);
65417
+ for (const c of cached.chunks) {
65418
+ const fullPath = c.name === SHARED_CHUNK_NAME2 ? null : routeFullPathForChunk(c.name);
65419
+ if (fullPath) routeChunksBuilt.add(fullPath);
65420
+ }
65421
+ LOG.info?.(`client bundle restored from cache (${cached.chunks.length} chunks)`);
65422
+ return;
65423
+ }
64236
65424
  const { main, chunks } = await generateClientBundle2(routeTree, appDirPath, /* @__PURE__ */ new Map(), {
64237
65425
  importRuntime: true,
64238
65426
  hmr: true,
@@ -64248,6 +65436,7 @@ async function startDevServer(port, projectDir, config, host) {
64248
65436
  clientBundle = main;
64249
65437
  devBundleBytes = Buffer.byteLength(main, "utf8");
64250
65438
  storeChunks(chunks);
65439
+ writeDevBundleCache(main, chunks);
64251
65440
  } catch (e) {
64252
65441
  LOG.err(`client build error:`, e.message);
64253
65442
  throw e;
@@ -65523,8 +66712,10 @@ __export(index_server_exports2, {
65523
66712
  createContext: () => createContext,
65524
66713
  createFileRouter: () => createFileRouter,
65525
66714
  createLocals: () => createLocals,
66715
+ createPathStore: () => createPathStore,
65526
66716
  createResource: () => createResource,
65527
66717
  createRouter: () => createRouter,
66718
+ createStore: () => createStore,
65528
66719
  create_component_ctx: () => create_component_ctx,
65529
66720
  create_try_block: () => create_try_block,
65530
66721
  custom: () => custom,
@@ -65647,6 +66838,8 @@ init_loading_indicator();
65647
66838
  init_action();
65648
66839
  init_metadata();
65649
66840
  init_nested_update();
66841
+ init_store();
66842
+ init_path_store();
65650
66843
 
65651
66844
  // src/index.ts
65652
66845
  var __filename2 = fileURLToPath9(import.meta.url);
@@ -65875,7 +67068,7 @@ if (cmd === "init") {
65875
67068
  process.exit(0);
65876
67069
  }
65877
67070
  mkdirSync20(appDirPath, { recursive: true });
65878
- writeFileSync22(target, [
67071
+ writeFileSync23(target, [
65879
67072
  `@import 'tailwindcss';`,
65880
67073
  ``,
65881
67074
  `@layer base {`,