@vesk/vesk-cli 0.2.13 → 0.2.15

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 +1286 -829
  2. package/package.json +5 -5
package/dist/cli.js CHANGED
@@ -1708,7 +1708,7 @@ async function runFetcher(handle2, timeout) {
1708
1708
  }
1709
1709
  }
1710
1710
  function sleep(ms) {
1711
- return new Promise((resolve35) => setTimeout(resolve35, ms));
1711
+ return new Promise((resolve38) => setTimeout(resolve38, ms));
1712
1712
  }
1713
1713
  function streamText(res, into, onChunk) {
1714
1714
  const decoder = new TextDecoder();
@@ -2117,10 +2117,10 @@ function createHydrateWalker(container, markerList) {
2117
2117
  }
2118
2118
  function hydrateViewport(container, componentFn, props, rootMargin = 500) {
2119
2119
  if (document.readyState !== "complete") {
2120
- return new Promise((resolve35) => {
2120
+ return new Promise((resolve38) => {
2121
2121
  const onLoad = () => {
2122
2122
  window.removeEventListener("load", onLoad);
2123
- resolve35(hydrateViewport(container, componentFn, props, rootMargin));
2123
+ resolve38(hydrateViewport(container, componentFn, props, rootMargin));
2124
2124
  };
2125
2125
  window.addEventListener("load", onLoad);
2126
2126
  });
@@ -2147,7 +2147,7 @@ function hydrateViewport(container, componentFn, props, rootMargin = 500) {
2147
2147
  const viewportWalker = createHydrateWalker(container, viewportMarkers);
2148
2148
  componentFn(props || {}, /* @__PURE__ */ new Map(), viewportWalker);
2149
2149
  if (deferredMarkers.length > 0) {
2150
- return new Promise((resolve35) => {
2150
+ return new Promise((resolve38) => {
2151
2151
  const observer = new IntersectionObserver((entries) => {
2152
2152
  const toHydrate = [];
2153
2153
  for (const entry of entries) {
@@ -2170,7 +2170,7 @@ function hydrateViewport(container, componentFn, props, rootMargin = 500) {
2170
2170
  }
2171
2171
  if (observer._observed === 0) {
2172
2172
  observer.disconnect();
2173
- resolve35();
2173
+ resolve38();
2174
2174
  }
2175
2175
  }, { rootMargin: `${rootMargin}px` });
2176
2176
  observer._observed = deferredMarkers.length;
@@ -3033,12 +3033,12 @@ function ensureChunk(chunkUrl) {
3033
3033
  if (typeof document === "undefined" || typeof document.createElement !== "function") {
3034
3034
  return Promise.resolve();
3035
3035
  }
3036
- return new Promise((resolve35, reject) => {
3036
+ return new Promise((resolve38, reject) => {
3037
3037
  const s = document.createElement("script");
3038
3038
  s.src = chunkUrl;
3039
3039
  s.onload = () => {
3040
3040
  failedChunks.delete(chunkUrl);
3041
- resolve35();
3041
+ resolve38();
3042
3042
  };
3043
3043
  s.onerror = () => {
3044
3044
  loadedChunks.delete(chunkUrl);
@@ -16728,8 +16728,7 @@ function parse4(source, options2 = {}) {
16728
16728
  "Check the line indicated by the ^ marker for missing brackets, quotes, or JSX syntax.",
16729
16729
  "If you wrote literal { or } inside JSX text, escape them as {'{'} and {'}'} or use { }.",
16730
16730
  "Ensure all JSX tags are properly closed and component names start with an uppercase letter."
16731
- ],
16732
- tip: "Vesk parses with Acorn + TypeScript + JSX \u2014 use the code frame above to locate the error."
16731
+ ]
16733
16732
  });
16734
16733
  }
16735
16734
  }
@@ -21173,7 +21172,7 @@ function custom(fn, msg) {
21173
21172
  return { validate: fn, message: msg || "Invalid value" };
21174
21173
  }
21175
21174
  function Field(props, registry, hydrate) {
21176
- const { name, label, rules = [], children, errorClass, class: className, style, ...rest } = props;
21175
+ const { name, label, rules: rules2 = [], children, errorClass, class: className, style, ...rest } = props;
21177
21176
  if (formIsSSR()) {
21178
21177
  const labelHtml = label ? `<label>${escapeHtml2(String(label))}</label>` : "";
21179
21178
  const serverErrors = readServerFieldErrors();
@@ -21195,7 +21194,7 @@ function Field(props, registry, hydrate) {
21195
21194
  }
21196
21195
  const inner = wrapper2 ? wrapper2.querySelector(`[data-vsk-field="${name}"]`) : null;
21197
21196
  const fieldEl = inner || wrapper2;
21198
- if (fieldEl) fieldEl.__vsk_rules = rules;
21197
+ if (fieldEl) fieldEl.__vsk_rules = rules2;
21199
21198
  return document.createDocumentFragment();
21200
21199
  }
21201
21200
  const wrapper = document.createElement("div");
@@ -21205,7 +21204,7 @@ function Field(props, registry, hydrate) {
21205
21204
  for (const [k, v] of Object.entries(rest)) {
21206
21205
  if (v != null && v !== false) wrapper.setAttribute(k, v === true ? "" : String(v));
21207
21206
  }
21208
- wrapper.__vsk_rules = rules;
21207
+ wrapper.__vsk_rules = rules2;
21209
21208
  if (label) {
21210
21209
  const lbl = document.createElement("label");
21211
21210
  lbl.textContent = label;
@@ -21240,10 +21239,10 @@ function bindFormSubmit(form, { action, method, onSubmit, onError, onSuccess })
21240
21239
  const fieldName = el.getAttribute("data-vsk-field");
21241
21240
  const propRules = el.__vsk_rules || [];
21242
21241
  const schemaRules = fieldName && actionSchema && actionSchema[fieldName] ? Array.isArray(actionSchema[fieldName]) ? actionSchema[fieldName] : [actionSchema[fieldName]] : [];
21243
- const rules = [...propRules, ...schemaRules];
21242
+ const rules2 = [...propRules, ...schemaRules];
21244
21243
  const errEl = el.querySelector("[data-vsk-error]");
21245
21244
  let errMsg = "";
21246
- for (const rule of rules) {
21245
+ for (const rule of rules2) {
21247
21246
  if (!rule.validate(obj[fieldName || ""])) {
21248
21247
  errMsg = rule.message;
21249
21248
  break;
@@ -23764,8 +23763,8 @@ function isFormAction(action) {
23764
23763
  function validateActionInput(def, input) {
23765
23764
  const issues = [];
23766
23765
  for (const [field, ruleOrRules] of Object.entries(def.input || {})) {
23767
- const rules = Array.isArray(ruleOrRules) ? ruleOrRules : [ruleOrRules];
23768
- for (const rule of rules) {
23766
+ const rules2 = Array.isArray(ruleOrRules) ? ruleOrRules : [ruleOrRules];
23767
+ for (const rule of rules2) {
23769
23768
  if (rule && !rule.validate(input[field])) {
23770
23769
  issues.push({ field, message: rule.message });
23771
23770
  break;
@@ -24862,7 +24861,7 @@ is not a problem with esbuild. You need to fix your environment instead.
24862
24861
  let latestResultPromise;
24863
24862
  let provideLatestResult;
24864
24863
  if (isContext)
24865
- requestCallbacks["on-end"] = (id, request2) => new Promise((resolve35) => {
24864
+ requestCallbacks["on-end"] = (id, request2) => new Promise((resolve38) => {
24866
24865
  buildResponseToResult(request2, (err, result2, onEndErrors, onEndWarnings) => {
24867
24866
  const response = {
24868
24867
  errors: onEndErrors,
@@ -24872,7 +24871,7 @@ is not a problem with esbuild. You need to fix your environment instead.
24872
24871
  latestResultPromise = void 0;
24873
24872
  provideLatestResult = void 0;
24874
24873
  sendResponse(id, response);
24875
- resolve35();
24874
+ resolve38();
24876
24875
  });
24877
24876
  });
24878
24877
  sendRequest(refs, request, (error, response) => {
@@ -24889,10 +24888,10 @@ is not a problem with esbuild. You need to fix your environment instead.
24889
24888
  let didDispose = false;
24890
24889
  const result2 = {
24891
24890
  rebuild: () => {
24892
- if (!latestResultPromise) latestResultPromise = new Promise((resolve35, reject) => {
24891
+ if (!latestResultPromise) latestResultPromise = new Promise((resolve38, reject) => {
24893
24892
  let settlePromise;
24894
24893
  provideLatestResult = (err, result22) => {
24895
- if (!settlePromise) settlePromise = () => err ? reject(err) : resolve35(result22);
24894
+ if (!settlePromise) settlePromise = () => err ? reject(err) : resolve38(result22);
24896
24895
  };
24897
24896
  const triggerAnotherBuild = () => {
24898
24897
  const request2 = {
@@ -24913,7 +24912,7 @@ is not a problem with esbuild. You need to fix your environment instead.
24913
24912
  });
24914
24913
  return latestResultPromise;
24915
24914
  },
24916
- watch: (options22 = {}) => new Promise((resolve35, reject) => {
24915
+ watch: (options22 = {}) => new Promise((resolve38, reject) => {
24917
24916
  if (!streamIn.hasFS) throw new Error(`Cannot use the "watch" API in this environment`);
24918
24917
  const keys = {};
24919
24918
  const delay = getFlag(options22, keys, "delay", mustBeInteger);
@@ -24925,10 +24924,10 @@ is not a problem with esbuild. You need to fix your environment instead.
24925
24924
  if (delay) request2.delay = delay;
24926
24925
  sendRequest(refs, request2, (error2) => {
24927
24926
  if (error2) reject(new Error(error2));
24928
- else resolve35(void 0);
24927
+ else resolve38(void 0);
24929
24928
  });
24930
24929
  }),
24931
- serve: (options22 = {}) => new Promise((resolve35, reject) => {
24930
+ serve: (options22 = {}) => new Promise((resolve38, reject) => {
24932
24931
  if (!streamIn.hasFS) throw new Error(`Cannot use the "serve" API in this environment`);
24933
24932
  const keys = {};
24934
24933
  const port2 = getFlag(options22, keys, "port", mustBeValidPortNumber);
@@ -24966,28 +24965,28 @@ is not a problem with esbuild. You need to fix your environment instead.
24966
24965
  sendResponse(id, {});
24967
24966
  };
24968
24967
  }
24969
- resolve35(response2);
24968
+ resolve38(response2);
24970
24969
  });
24971
24970
  }),
24972
- cancel: () => new Promise((resolve35) => {
24973
- if (didDispose) return resolve35();
24971
+ cancel: () => new Promise((resolve38) => {
24972
+ if (didDispose) return resolve38();
24974
24973
  const request2 = {
24975
24974
  command: "cancel",
24976
24975
  key: buildKey
24977
24976
  };
24978
24977
  sendRequest(refs, request2, () => {
24979
- resolve35();
24978
+ resolve38();
24980
24979
  });
24981
24980
  }),
24982
- dispose: () => new Promise((resolve35) => {
24983
- if (didDispose) return resolve35();
24981
+ dispose: () => new Promise((resolve38) => {
24982
+ if (didDispose) return resolve38();
24984
24983
  didDispose = true;
24985
24984
  const request2 = {
24986
24985
  command: "dispose",
24987
24986
  key: buildKey
24988
24987
  };
24989
24988
  sendRequest(refs, request2, () => {
24990
- resolve35();
24989
+ resolve38();
24991
24990
  scheduleOnDisposeCallbacks();
24992
24991
  refs.unref();
24993
24992
  });
@@ -25026,7 +25025,7 @@ is not a problem with esbuild. You need to fix your environment instead.
25026
25025
  onLoad: []
25027
25026
  };
25028
25027
  i++;
25029
- let resolve35 = (path3, options2 = {}) => {
25028
+ let resolve38 = (path3, options2 = {}) => {
25030
25029
  if (!isSetupDone) throw new Error('Cannot call "resolve" before plugin setup has completed');
25031
25030
  if (typeof path3 !== "string") throw new Error(`The path to resolve must be a string`);
25032
25031
  let keys2 = /* @__PURE__ */ Object.create(null);
@@ -25070,7 +25069,7 @@ is not a problem with esbuild. You need to fix your environment instead.
25070
25069
  };
25071
25070
  let promise = setup({
25072
25071
  initialOptions,
25073
- resolve: resolve35,
25072
+ resolve: resolve38,
25074
25073
  onStart(callback) {
25075
25074
  let registeredText = `This error came from the "onStart" callback registered here:`;
25076
25075
  let registeredNote = extractCallerV8(new Error(registeredText), streamIn, "onStart");
@@ -25763,46 +25762,46 @@ More information: The file containing the code for esbuild's JavaScript API (${_
25763
25762
  }
25764
25763
  };
25765
25764
  longLivedService = {
25766
- build: (options2) => new Promise((resolve35, reject) => {
25765
+ build: (options2) => new Promise((resolve38, reject) => {
25767
25766
  service.buildOrContext({
25768
25767
  callName: "build",
25769
25768
  refs,
25770
25769
  options: options2,
25771
25770
  isTTY: isTTY(),
25772
25771
  defaultWD,
25773
- callback: (err, res) => err ? reject(err) : resolve35(res)
25772
+ callback: (err, res) => err ? reject(err) : resolve38(res)
25774
25773
  });
25775
25774
  }),
25776
- context: (options2) => new Promise((resolve35, reject) => service.buildOrContext({
25775
+ context: (options2) => new Promise((resolve38, reject) => service.buildOrContext({
25777
25776
  callName: "context",
25778
25777
  refs,
25779
25778
  options: options2,
25780
25779
  isTTY: isTTY(),
25781
25780
  defaultWD,
25782
- callback: (err, res) => err ? reject(err) : resolve35(res)
25781
+ callback: (err, res) => err ? reject(err) : resolve38(res)
25783
25782
  })),
25784
- transform: (input, options2) => new Promise((resolve35, reject) => service.transform({
25783
+ transform: (input, options2) => new Promise((resolve38, reject) => service.transform({
25785
25784
  callName: "transform",
25786
25785
  refs,
25787
25786
  input,
25788
25787
  options: options2 || {},
25789
25788
  isTTY: isTTY(),
25790
25789
  fs: fsAsync,
25791
- callback: (err, res) => err ? reject(err) : resolve35(res)
25790
+ callback: (err, res) => err ? reject(err) : resolve38(res)
25792
25791
  })),
25793
- formatMessages: (messages, options2) => new Promise((resolve35, reject) => service.formatMessages({
25792
+ formatMessages: (messages, options2) => new Promise((resolve38, reject) => service.formatMessages({
25794
25793
  callName: "formatMessages",
25795
25794
  refs,
25796
25795
  messages,
25797
25796
  options: options2,
25798
- callback: (err, res) => err ? reject(err) : resolve35(res)
25797
+ callback: (err, res) => err ? reject(err) : resolve38(res)
25799
25798
  })),
25800
- analyzeMetafile: (metafile, options2) => new Promise((resolve35, reject) => service.analyzeMetafile({
25799
+ analyzeMetafile: (metafile, options2) => new Promise((resolve38, reject) => service.analyzeMetafile({
25801
25800
  callName: "analyzeMetafile",
25802
25801
  refs,
25803
25802
  metafile: typeof metafile === "string" ? metafile : JSON.stringify(metafile),
25804
25803
  options: options2,
25805
- callback: (err, res) => err ? reject(err) : resolve35(res)
25804
+ callback: (err, res) => err ? reject(err) : resolve38(res)
25806
25805
  }))
25807
25806
  };
25808
25807
  return longLivedService;
@@ -25880,13 +25879,13 @@ error: ${text}`);
25880
25879
  worker.postMessage(msg);
25881
25880
  let status = Atomics.wait(sharedBufferView, 0, 0);
25882
25881
  if (status !== "ok" && status !== "not-equal") throw new Error("Internal error: Atomics.wait() failed: " + status);
25883
- let { message: { id: id2, resolve: resolve35, reject, properties } } = worker_threads2.receiveMessageOnPort(mainPort);
25882
+ let { message: { id: id2, resolve: resolve38, reject, properties } } = worker_threads2.receiveMessageOnPort(mainPort);
25884
25883
  if (id !== id2) throw new Error(`Internal error: Expected id ${id} but got id ${id2}`);
25885
25884
  if (reject) {
25886
25885
  applyProperties(reject, properties);
25887
25886
  throw reject;
25888
25887
  }
25889
- return resolve35;
25888
+ return resolve38;
25890
25889
  };
25891
25890
  worker.unref();
25892
25891
  return {
@@ -26178,8 +26177,9 @@ function scanHeadTag(html, lt) {
26178
26177
  if (aName) attrs.set(aName, value);
26179
26178
  }
26180
26179
  let raw2 = html.slice(lt, i);
26181
- if (!selfClosing && tag === "title") {
26182
- const closeTag = html.indexOf("</title", i);
26180
+ const nonVoidTags = /* @__PURE__ */ new Set(["title", "script", "style", "noscript"]);
26181
+ if (!selfClosing && nonVoidTags.has(tag)) {
26182
+ const closeTag = html.indexOf("</" + tag, i);
26183
26183
  if (closeTag !== -1) {
26184
26184
  const end = html.indexOf(">", closeTag);
26185
26185
  if (end !== -1) {
@@ -26262,8 +26262,12 @@ function mergeHeadHtml(pageHead, layoutHead) {
26262
26262
  const bi = order.findIndex((o) => bk.startsWith(o));
26263
26263
  return (ai === -1 ? 999 : ai) - (bi === -1 ? 999 : bi);
26264
26264
  });
26265
+ const unkeyed = [];
26266
+ for (const e of [...layoutEntries, ...pageEntries]) {
26267
+ if (extractKey(e) === null && !unkeyed.includes(e.raw)) unkeyed.push(e.raw);
26268
+ }
26265
26269
  return {
26266
- html: sorted.map((e) => e.html).join("\n"),
26270
+ html: [...sorted.map((e) => e.html), ...unkeyed].join("\n"),
26267
26271
  conflicts
26268
26272
  };
26269
26273
  }
@@ -28349,6 +28353,9 @@ var init_ssr_store = __esm({
28349
28353
  // ../compiler/src/server-render.ts
28350
28354
  var server_render_exports = {};
28351
28355
  __export(server_render_exports, {
28356
+ applyHeadInjects: () => applyHeadInjects,
28357
+ applyHeadPlugins: () => applyHeadPlugins,
28358
+ applyHtmlPlugins: () => applyHtmlPlugins,
28352
28359
  buildDataScripts: () => buildDataScripts,
28353
28360
  compileFile: () => compileFile,
28354
28361
  render: () => render2,
@@ -28509,6 +28516,37 @@ function clearSsrCells(token) {
28509
28516
  if (typeof k === "string" && k.startsWith(token)) cells.delete(k);
28510
28517
  }
28511
28518
  }
28519
+ async function applyHeadPlugins(headHtml, plugins, ctx2) {
28520
+ if (!plugins || plugins.length === 0) return headHtml;
28521
+ let out = headHtml;
28522
+ for (const plugin of plugins) {
28523
+ if (typeof plugin.onHead === "function") {
28524
+ const result2 = await plugin.onHead(out, ctx2);
28525
+ if (typeof result2 === "string") out = result2;
28526
+ }
28527
+ }
28528
+ return out;
28529
+ }
28530
+ async function applyHtmlPlugins(html, plugins, ctx2) {
28531
+ if (!plugins || plugins.length === 0) return html;
28532
+ let out = html;
28533
+ for (const plugin of plugins) {
28534
+ if (typeof plugin.onHtml === "function") {
28535
+ const result2 = await plugin.onHtml(out, ctx2);
28536
+ if (typeof result2 === "string") out = result2;
28537
+ }
28538
+ }
28539
+ return out;
28540
+ }
28541
+ async function applyHeadInjects(headHtml, options2, ctx2) {
28542
+ if (options2.plugins && options2.plugins.length > 0) {
28543
+ return applyHeadPlugins(headHtml, options2.plugins, ctx2);
28544
+ }
28545
+ if (options2.headExtra) {
28546
+ return mergeHeadHtml(headHtml, options2.headExtra).html;
28547
+ }
28548
+ return headHtml;
28549
+ }
28512
28550
  async function ssg(source, componentName, customProps, options2 = {}) {
28513
28551
  const ast = parse4(source, options2.sourcePath ? { filename: options2.sourcePath } : {});
28514
28552
  const ir = generateIR(ast, source, options2.sourcePath);
@@ -28548,23 +28586,32 @@ async function ssg(source, componentName, customProps, options2 = {}) {
28548
28586
  const cssUrls = options2.cssUrls || (options2.cssUrl ? [options2.cssUrl] : []);
28549
28587
  const cssLink = cssUrls.map((u) => ` <link rel="stylesheet" href="${u}" />
28550
28588
  `).join("");
28589
+ const renderCtx = { sourcePath: options2.sourcePath };
28590
+ let finalHead = [' <meta charset="utf-8" />', ' <meta name="viewport" content="width=device-width, initial-scale=1" />'].join("\n");
28591
+ if (cssLink) finalHead += "\n" + cssLink.trimEnd();
28592
+ if (headHtml) finalHead += "\n" + headHtml.split("\n").map((l) => " " + l).join("\n");
28593
+ finalHead = await applyHeadInjects(
28594
+ finalHead,
28595
+ { plugins: options2.plugins, headExtra: options2.headExtra },
28596
+ renderCtx
28597
+ );
28551
28598
  const html = `<!DOCTYPE html>
28552
28599
  <html>
28553
28600
  <head>
28554
- <meta charset="utf-8" />
28555
- <meta name="viewport" content="width=device-width, initial-scale=1" />
28556
- ${cssLink}${headHtml ? " " + headHtml.split("\n").join("\n ") + "\n" : ""}</head>
28601
+ ${finalHead}
28602
+ </head>
28557
28603
  <body>
28558
28604
  ${bodyHtml}${scriptBlock}</body>
28559
28605
  </html>
28560
28606
  `;
28607
+ const finalHtml = await applyHtmlPlugins(html, options2.plugins, renderCtx);
28561
28608
  const staticLists = ir.components.some((c) => {
28562
28609
  return c.body.some((node) => {
28563
28610
  if (node instanceof MapRegion) return isStaticIR(node.bodyTemplate) && isStaticIR(node.alternateNodes);
28564
28611
  return false;
28565
28612
  });
28566
28613
  });
28567
- return { html, body: bodyHtml, head: headHtml, props: serializedProps, clientCode, static: !hasClient, staticLists };
28614
+ return { html: finalHtml, body: bodyHtml, head: headHtml, props: serializedProps, clientCode, static: !hasClient, staticLists };
28568
28615
  }
28569
28616
  function buildDataScripts(ssrProps, ssrData, external) {
28570
28617
  const meaningfulKeys = ssrProps !== void 0 && ssrProps !== null ? Object.keys(ssrProps).filter((k) => k !== "children" && k !== "params") : [];
@@ -28634,16 +28681,22 @@ async function renderFullPage(source, componentName, props = {}, registry = /* @
28634
28681
  if (sec.contentSecurityPolicy !== false) headLines.push(` <meta http-equiv="Content-Security-Policy" content="${quoteAttr(sec.contentSecurityPolicy || "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; frame-src 'self'; connect-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'")}" />`);
28635
28682
  if (sec.autoEscape !== false) headLines.push(` <!-- vesk: auto-escape enabled -->`);
28636
28683
  }
28637
- return `<!DOCTYPE html>
28684
+ const finalHead = await applyHeadInjects(
28685
+ headLines.join("\n"),
28686
+ { plugins: options2.plugins, headExtra: options2.headExtra },
28687
+ { sourcePath: options2.sourcePath, url: options2.__vesk?.url || void 0 }
28688
+ );
28689
+ const docHtml = `<!DOCTYPE html>
28638
28690
  <html>
28639
28691
  <head>
28640
- ${headLines.join("\n")}</head>
28692
+ ${finalHead}</head>
28641
28693
  <body>
28642
28694
  <div id="root">
28643
28695
  ${bodyHtml}
28644
28696
  </div>
28645
28697
  ${dataScriptBlock}${clientScript}</body>
28646
28698
  </html>`;
28699
+ return applyHtmlPlugins(docHtml, options2.plugins, { sourcePath: options2.sourcePath, url: options2.__vesk?.url || void 0 });
28647
28700
  } finally {
28648
28701
  delete globalThis.__vsk_ssr;
28649
28702
  }
@@ -28678,16 +28731,13 @@ function renderPageStream(source, componentName, props = {}, registry = /* @__PU
28678
28731
  const cssUrls = options2.cssUrls || (options2.cssUrl ? [options2.cssUrl] : []);
28679
28732
  const cssLink = cssUrls.map((u) => ` <link rel="stylesheet" href="${u}" />
28680
28733
  `).join("");
28681
- yield '<!DOCTYPE html>\n<html>\n<head>\n <meta charset="utf-8" />\n <meta name="viewport" content="width=device-width, initial-scale=1" />\n';
28682
- if (cssLink) yield cssLink;
28734
+ const headParts = [' <meta charset="utf-8" />', ' <meta name="viewport" content="width=device-width, initial-scale=1" />'];
28735
+ if (cssLink) headParts.push(cssLink.trimEnd());
28683
28736
  if (options2.security) {
28684
28737
  const sec = options2.security;
28685
- if (sec.referrerPolicy !== false) yield ` <meta name="referrer" content="${quoteAttr(sec.referrerPolicy || "strict-origin-when-cross-origin")}" />
28686
- `;
28687
- if (sec.contentSecurityPolicy !== false) yield ` <meta http-equiv="Content-Security-Policy" content="${quoteAttr(sec.contentSecurityPolicy || "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; frame-src 'self'; connect-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'")}" />
28688
- `;
28689
- if (sec.autoEscape !== false) yield ` <!-- vesk: auto-escape enabled -->
28690
- `;
28738
+ if (sec.referrerPolicy !== false) headParts.push(` <meta name="referrer" content="${quoteAttr(sec.referrerPolicy || "strict-origin-when-cross-origin")}" />`);
28739
+ if (sec.contentSecurityPolicy !== false) headParts.push(` <meta http-equiv="Content-Security-Policy" content="${quoteAttr(sec.contentSecurityPolicy || "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; frame-src 'self'; connect-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'")}" />`);
28740
+ if (sec.autoEscape !== false) headParts.push(" <!-- vesk: auto-escape enabled -->");
28691
28741
  }
28692
28742
  if (targetComp) {
28693
28743
  let headHtml = renderHeadHtml(targetComp, ssrProps);
@@ -28700,8 +28750,15 @@ function renderPageStream(source, componentName, props = {}, registry = /* @__PU
28700
28750
  }
28701
28751
  }
28702
28752
  }
28703
- if (headHtml) yield " " + headHtml.split("\n").join("\n ") + "\n";
28753
+ if (headHtml) headParts.push(" " + headHtml.split("\n").join("\n "));
28704
28754
  }
28755
+ yield "<!DOCTYPE html>\n<html>\n<head>\n";
28756
+ const finalHead = await applyHeadInjects(
28757
+ headParts.join("\n"),
28758
+ { plugins: options2.plugins, headExtra: options2.headExtra },
28759
+ { sourcePath: options2.sourcePath, url: options2.__vesk?.url || void 0 }
28760
+ );
28761
+ yield finalHead + "\n";
28705
28762
  yield '</head>\n<body>\n<div id="root">\n';
28706
28763
  globalThis.__vsk_ssr = true;
28707
28764
  globalThis.__vsk_ssr_token = Math.random().toString(36).slice(2);
@@ -28753,17 +28810,17 @@ var init_server_render = __esm({
28753
28810
  });
28754
28811
 
28755
28812
  // ../adapter/src/paths.ts
28756
- import { resolve as resolve9, sep as sep2 } from "node:path";
28757
- import { existsSync as existsSync8, statSync as statSync4, readFileSync as readFileSync9 } from "node:fs";
28813
+ import { resolve as resolve10, sep as sep2 } from "node:path";
28814
+ import { existsSync as existsSync9, statSync as statSync4, readFileSync as readFileSync10 } from "node:fs";
28758
28815
  function resolveWithin(baseDir, relPath) {
28759
- const base = resolve9(baseDir);
28760
- const target = resolve9(baseDir, relPath);
28816
+ const base = resolve10(baseDir);
28817
+ const target = resolve10(baseDir, relPath);
28761
28818
  const prefix = base + sep2;
28762
28819
  if (!target.startsWith(prefix)) return null;
28763
28820
  return target;
28764
28821
  }
28765
28822
  function installMdReadHook(publicDirs) {
28766
- const dirs = publicDirs.map((d) => resolve9(d));
28823
+ const dirs = publicDirs.map((d) => resolve10(d));
28767
28824
  globalThis.__vsk_md_read_file = (p) => {
28768
28825
  for (const dir of dirs) {
28769
28826
  try {
@@ -28773,7 +28830,7 @@ function installMdReadHook(publicDirs) {
28773
28830
  if (!abs) continue;
28774
28831
  const lower = abs.toLowerCase();
28775
28832
  if (!lower.endsWith(".md") && !lower.endsWith(".markdown")) continue;
28776
- if (existsSync8(abs) && statSync4(abs).isFile()) return readFileSync9(abs, "utf8");
28833
+ if (existsSync9(abs) && statSync4(abs).isFile()) return readFileSync10(abs, "utf8");
28777
28834
  } catch {
28778
28835
  }
28779
28836
  }
@@ -28806,13 +28863,13 @@ __export(plugins_exports, {
28806
28863
  writePluginState: () => writePluginState
28807
28864
  });
28808
28865
  import {
28809
- readFileSync as readFileSync12,
28866
+ readFileSync as readFileSync13,
28810
28867
  writeFileSync as writeFileSync4,
28811
- existsSync as existsSync11,
28868
+ existsSync as existsSync12,
28812
28869
  mkdirSync as mkdirSync2,
28813
28870
  statSync as statSync7
28814
28871
  } from "node:fs";
28815
- import { resolve as resolve12, dirname as dirname8, join as join7, extname as extname4, basename } from "node:path";
28872
+ import { resolve as resolve13, dirname as dirname8, join as join7, extname as extname4, basename } from "node:path";
28816
28873
  import { createRequire as createRequire3 } from "node:module";
28817
28874
  import { spawn } from "node:child_process";
28818
28875
  function defaultState() {
@@ -28822,14 +28879,14 @@ function eqIgnoreCase(a, b) {
28822
28879
  return String(a || "").toLowerCase() === String(b || "").toLowerCase();
28823
28880
  }
28824
28881
  function stateFilePath(veskDir) {
28825
- return resolve12(veskDir, PLUGIN_STATE_FILENAME);
28882
+ return resolve13(veskDir, PLUGIN_STATE_FILENAME);
28826
28883
  }
28827
28884
  function readPluginState(veskDir) {
28828
28885
  const file = stateFilePath(veskDir);
28829
- if (!existsSync11(file)) return defaultState();
28886
+ if (!existsSync12(file)) return defaultState();
28830
28887
  let raw2;
28831
28888
  try {
28832
- raw2 = JSON.parse(readFileSync12(file, "utf-8"));
28889
+ raw2 = JSON.parse(readFileSync13(file, "utf-8"));
28833
28890
  } catch {
28834
28891
  return defaultState();
28835
28892
  }
@@ -28847,11 +28904,11 @@ function readPluginState(veskDir) {
28847
28904
  function writePluginState(veskDir, state) {
28848
28905
  const file = stateFilePath(veskDir);
28849
28906
  const dir = dirname8(file);
28850
- if (!existsSync11(dir)) mkdirSync2(dir, { recursive: true });
28907
+ if (!existsSync12(dir)) mkdirSync2(dir, { recursive: true });
28851
28908
  writeFileSync4(file, JSON.stringify(state, null, 2) + "\n", "utf-8");
28852
28909
  }
28853
28910
  function resolvePackage(appDir, pkg) {
28854
- const require3 = createRequire3(resolve12(appDir, "package.json"));
28911
+ const require3 = createRequire3(resolve13(appDir, "package.json"));
28855
28912
  let entryPath = null;
28856
28913
  let pkgJsonPath = null;
28857
28914
  let pkgJson = null;
@@ -28865,7 +28922,7 @@ function resolvePackage(appDir, pkg) {
28865
28922
  while (cur && cur !== dirname8(cur) && !seen.has(cur)) {
28866
28923
  seen.add(cur);
28867
28924
  const candidate = join7(cur, "package.json");
28868
- if (existsSync11(candidate)) {
28925
+ if (existsSync12(candidate)) {
28869
28926
  pkgJsonPath = candidate;
28870
28927
  break;
28871
28928
  }
@@ -28876,15 +28933,15 @@ function resolvePackage(appDir, pkg) {
28876
28933
  } catch {
28877
28934
  }
28878
28935
  }
28879
- if (pkgJsonPath && existsSync11(pkgJsonPath)) {
28936
+ if (pkgJsonPath && existsSync12(pkgJsonPath)) {
28880
28937
  pkgJson = readJsonFile(pkgJsonPath);
28881
28938
  const main = pkgJson?.main || pkgJson?.module || "index.js";
28882
- entryPath = resolve12(dirname8(pkgJsonPath), main);
28939
+ entryPath = resolve13(dirname8(pkgJsonPath), main);
28883
28940
  }
28884
28941
  let localPath = localDir(appDir, pkg);
28885
28942
  if (!localPath) {
28886
28943
  for (const sub of ["src/plugins", "plugins", "lib/plugins"]) {
28887
- const candidate = localDir(resolve12(appDir, sub), pkg);
28944
+ const candidate = localDir(resolve13(appDir, sub), pkg);
28888
28945
  if (candidate) {
28889
28946
  localPath = candidate;
28890
28947
  break;
@@ -28894,28 +28951,28 @@ function resolvePackage(appDir, pkg) {
28894
28951
  if (localPath) {
28895
28952
  const localJson = join7(localPath, "package.json");
28896
28953
  let json = null;
28897
- if (existsSync11(localJson)) {
28954
+ if (existsSync12(localJson)) {
28898
28955
  json = readJsonFile(localJson);
28899
28956
  }
28900
28957
  return { installed: true, path: localPath, dir: localPath, packageJson: json ?? pkgJson };
28901
28958
  }
28902
- const installed2 = !!pkgJsonPath && existsSync11(pkgJsonPath);
28959
+ const installed2 = !!pkgJsonPath && existsSync12(pkgJsonPath);
28903
28960
  return { installed: installed2, path: entryPath, dir: installed2 ? dirname8(pkgJsonPath) : null, packageJson: pkgJson };
28904
28961
  }
28905
28962
  function localDir(base, pkg) {
28906
28963
  if (pkg.startsWith("@")) {
28907
28964
  const parts = pkg.split("/");
28908
- const p2 = resolve12(base, parts[0], parts[1] ?? "");
28909
- if (existsSync11(p2)) return p2;
28965
+ const p2 = resolve13(base, parts[0], parts[1] ?? "");
28966
+ if (existsSync12(p2)) return p2;
28910
28967
  return null;
28911
28968
  }
28912
- const p = resolve12(base, pkg);
28913
- if (existsSync11(p)) return p;
28969
+ const p = resolve13(base, pkg);
28970
+ if (existsSync12(p)) return p;
28914
28971
  return null;
28915
28972
  }
28916
28973
  function readJsonFile(file) {
28917
28974
  try {
28918
- if (existsSync11(file)) return JSON.parse(readFileSync12(file, "utf-8"));
28975
+ if (existsSync12(file)) return JSON.parse(readFileSync13(file, "utf-8"));
28919
28976
  } catch {
28920
28977
  }
28921
28978
  return null;
@@ -28955,7 +29012,7 @@ function repositoryToString(r) {
28955
29012
  function assemblePluginMeta(probe) {
28956
29013
  const pkgJson = probe.packageJson || {};
28957
29014
  const dir = probe.dir;
28958
- const meta = dir ? readJsonFile(resolve12(dir, "vesk.meta.json")) : null;
29015
+ const meta = dir ? readJsonFile(resolve13(dir, "vesk.meta.json")) : null;
28959
29016
  const hasMeta = !!meta && Object.keys(meta).length > 0;
28960
29017
  const m = meta || {};
28961
29018
  const metaSource = hasMeta ? "vesk.meta.json" : probe.packageJson ? "package.json" : "none";
@@ -29194,11 +29251,11 @@ function findIconFile(dir, meta) {
29194
29251
  const explicit = str(meta?.icon);
29195
29252
  if (explicit) {
29196
29253
  const p = resolveWithin(dir, explicit);
29197
- if (p && existsSync11(p) && statSync7(p).isFile()) return p;
29254
+ if (p && existsSync12(p) && statSync7(p).isFile()) return p;
29198
29255
  }
29199
29256
  for (const name of ["icon.png", "icon.ico"]) {
29200
- const p = resolve12(dir, name);
29201
- if (existsSync11(p) && statSync7(p).isFile()) return p;
29257
+ const p = resolve13(dir, name);
29258
+ if (existsSync12(p) && statSync7(p).isFile()) return p;
29202
29259
  }
29203
29260
  return null;
29204
29261
  }
@@ -29206,7 +29263,7 @@ function findPluginIcon(appDir, name) {
29206
29263
  const probe = resolvePackage(appDir, name);
29207
29264
  const dir = probe.dir;
29208
29265
  if (!dir) return null;
29209
- const meta = readJsonFile(resolve12(dir, "vesk.meta.json"));
29266
+ const meta = readJsonFile(resolve13(dir, "vesk.meta.json"));
29210
29267
  const iconPath = findIconFile(dir, meta);
29211
29268
  if (!iconPath) return null;
29212
29269
  const ext = extname4(iconPath).toLowerCase();
@@ -29269,7 +29326,7 @@ function resolveDtsPath(probe, pkgJson) {
29269
29326
  for (const rel of candidates) {
29270
29327
  if (!rel) continue;
29271
29328
  const abs = resolveWithin(dir, rel);
29272
- if (abs && existsSync11(abs) && statSync7(abs).isFile()) return abs;
29329
+ if (abs && existsSync12(abs) && statSync7(abs).isFile()) return abs;
29273
29330
  }
29274
29331
  return null;
29275
29332
  }
@@ -29585,7 +29642,7 @@ function introspectPlugin(appDir, name) {
29585
29642
  const pkgName = str(pkgJson.name) ?? name;
29586
29643
  const exportsMap = flattenPackageExports(pkgJson.exports);
29587
29644
  const dtsPath = resolveDtsPath(probe, pkgJson);
29588
- const dtsExports = dtsPath ? parseDtsExports(readFileSync12(dtsPath, "utf-8")) : [];
29645
+ const dtsExports = dtsPath ? parseDtsExports(readFileSync13(dtsPath, "utf-8")) : [];
29589
29646
  return {
29590
29647
  ok: true,
29591
29648
  name: pkgName,
@@ -29726,12 +29783,12 @@ __export(static_exports, {
29726
29783
  generateSitemap: () => generateSitemap,
29727
29784
  generateSsgRoutes: () => generateSsgRoutes
29728
29785
  });
29729
- import { mkdirSync as mkdirSync3, copyFileSync as copyFileSync2, readdirSync as readdirSync3, statSync as statSync8, existsSync as existsSync12, writeFileSync as writeFileSync5, readFileSync as readFileSync13 } from "node:fs";
29730
- import { resolve as resolve13, join as join8 } from "node:path";
29786
+ import { mkdirSync as mkdirSync3, copyFileSync as copyFileSync2, readdirSync as readdirSync3, statSync as statSync8, existsSync as existsSync13, writeFileSync as writeFileSync5, readFileSync as readFileSync14 } from "node:fs";
29787
+ import { resolve as resolve14, join as join8 } from "node:path";
29731
29788
  function copyStaticAssets2(publicDir, outDir2) {
29732
- const targetDir = resolve13(outDir2, "static", "public");
29789
+ const targetDir = resolve14(outDir2, "static", "public");
29733
29790
  mkdirSync3(targetDir, { recursive: true });
29734
- if (!existsSync12(publicDir))
29791
+ if (!existsSync13(publicDir))
29735
29792
  return;
29736
29793
  function copyDir(src2, dest) {
29737
29794
  mkdirSync3(dest, { recursive: true });
@@ -29749,10 +29806,11 @@ function copyStaticAssets2(publicDir, outDir2) {
29749
29806
  }
29750
29807
  copyDir(publicDir, targetDir);
29751
29808
  }
29752
- async function generateSsgRoutes(routeTree, appDir, outDir2) {
29809
+ async function generateSsgRoutes(routeTree, appDir, outDir2, plugins, headExtra, cssUrls) {
29753
29810
  const { ssg: ssg2 } = await Promise.resolve().then(() => (init_server_render(), server_render_exports));
29754
- const prerenderDir = resolve13(outDir2, "prerendered");
29811
+ const prerenderDir = resolve14(outDir2, "prerendered");
29755
29812
  mkdirSync3(prerenderDir, { recursive: true });
29813
+ const ssgOptions = { plugins, headExtra, cssUrls };
29756
29814
  const results = [];
29757
29815
  async function evaluateExport(src2, exportName) {
29758
29816
  try {
@@ -29770,8 +29828,8 @@ async function generateSsgRoutes(routeTree, appDir, outDir2) {
29770
29828
  async function walk6(nodes) {
29771
29829
  for (const node of nodes) {
29772
29830
  if (node.page) {
29773
- const pagePath = resolve13(appDir, node.sourceDir, "page.vsk");
29774
- const src2 = readFileSync13(pagePath, "utf-8");
29831
+ const pagePath = resolve14(appDir, node.sourceDir, "page.vsk");
29832
+ const src2 = readFileSync14(pagePath, "utf-8");
29775
29833
  const hasStaticProps = src2.includes("getStaticProps");
29776
29834
  const hasStaticPaths = src2.includes("getStaticPaths");
29777
29835
  if (hasStaticPaths) {
@@ -29780,7 +29838,7 @@ async function generateSsgRoutes(routeTree, appDir, outDir2) {
29780
29838
  for (const entry of paths) {
29781
29839
  try {
29782
29840
  const params = entry.params || {};
29783
- const result2 = await ssg2(src2, null, params, {});
29841
+ const result2 = await ssg2(src2, null, params, ssgOptions);
29784
29842
  const urlPath = entry.path || node.fullPath;
29785
29843
  const relName = urlPath === "/" ? "index.html" : `${urlPath.replace(/^\//, "")}.html`;
29786
29844
  const htmlPath = resolveWithin(prerenderDir, relName);
@@ -29788,7 +29846,7 @@ async function generateSsgRoutes(routeTree, appDir, outDir2) {
29788
29846
  console.error(`vesk: SSG path escaped output dir \u2014 skipping ${pagePath} (path: ${urlPath})`);
29789
29847
  continue;
29790
29848
  }
29791
- mkdirSync3(resolve13(htmlPath, ".."), { recursive: true });
29849
+ mkdirSync3(resolve14(htmlPath, ".."), { recursive: true });
29792
29850
  writeFileSync5(htmlPath, result2.html);
29793
29851
  results.push({ path: urlPath, html: htmlPath, static: result2.static, params });
29794
29852
  } catch (e) {
@@ -29799,9 +29857,9 @@ async function generateSsgRoutes(routeTree, appDir, outDir2) {
29799
29857
  }
29800
29858
  } else if (hasStaticProps) {
29801
29859
  try {
29802
- const result2 = await ssg2(src2, null, void 0, {});
29803
- const htmlPath = resolve13(prerenderDir, node.fullPath === "/" ? "index.html" : `${node.fullPath.slice(1)}.html`);
29804
- mkdirSync3(resolve13(htmlPath, ".."), { recursive: true });
29860
+ const result2 = await ssg2(src2, null, void 0, ssgOptions);
29861
+ const htmlPath = resolve14(prerenderDir, node.fullPath === "/" ? "index.html" : `${node.fullPath.slice(1)}.html`);
29862
+ mkdirSync3(resolve14(htmlPath, ".."), { recursive: true });
29805
29863
  writeFileSync5(htmlPath, result2.html);
29806
29864
  results.push({ path: node.fullPath, html: htmlPath, static: result2.static });
29807
29865
  } catch (e) {
@@ -29871,14 +29929,14 @@ var image_pipeline_exports = {};
29871
29929
  __export(image_pipeline_exports, {
29872
29930
  optimizeImages: () => optimizeImages
29873
29931
  });
29874
- import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync6, readFileSync as readFileSync14, existsSync as existsSync13, readdirSync as readdirSync4, statSync as statSync9 } from "node:fs";
29875
- import { resolve as resolve14, extname as extname5, dirname as dirname9 } from "node:path";
29932
+ import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync6, readFileSync as readFileSync15, existsSync as existsSync14, readdirSync as readdirSync4, statSync as statSync9 } from "node:fs";
29933
+ import { resolve as resolve15, extname as extname5, dirname as dirname9 } from "node:path";
29876
29934
  async function processImage(srcPath, outDir2, baseName) {
29877
29935
  const image = sharpFn ? sharpFn(srcPath) : null;
29878
29936
  if (!image) {
29879
- const original = readFileSync14(srcPath);
29937
+ const original = readFileSync15(srcPath);
29880
29938
  for (const w of OUTPUT_WIDTHS) {
29881
- const outputPath = resolve14(outDir2, `${baseName}-${w}w`);
29939
+ const outputPath = resolve15(outDir2, `${baseName}-${w}w`);
29882
29940
  mkdirSync4(dirname9(outputPath), { recursive: true });
29883
29941
  writeFileSync6(outputPath, original);
29884
29942
  }
@@ -29892,12 +29950,12 @@ async function processImage(srcPath, outDir2, baseName) {
29892
29950
  continue;
29893
29951
  const resized = image.clone().resize({ width: w, withoutEnlargement: true });
29894
29952
  const base = `${baseName}-${w}w`;
29895
- const jpgPath = resolve14(outDir2, `${base}${extname5(srcPath)}`);
29953
+ const jpgPath = resolve15(outDir2, `${base}${extname5(srcPath)}`);
29896
29954
  mkdirSync4(dirname9(jpgPath), { recursive: true });
29897
29955
  await resized.toFile(jpgPath);
29898
29956
  generated.push(jpgPath);
29899
29957
  for (const fmt of FORMATS) {
29900
- const fmtPath = resolve14(outDir2, `${base}.${fmt}`);
29958
+ const fmtPath = resolve15(outDir2, `${base}.${fmt}`);
29901
29959
  await resized.toFormat(fmt, { quality: 80 }).toFile(fmtPath);
29902
29960
  generated.push(fmtPath);
29903
29961
  }
@@ -29914,14 +29972,14 @@ function collectImageRefs(appDir) {
29914
29972
  return;
29915
29973
  }
29916
29974
  for (const entry of entries) {
29917
- const full = resolve14(dir, entry);
29975
+ const full = resolve15(dir, entry);
29918
29976
  const st = statSync9(full);
29919
29977
  if (st.isDirectory()) {
29920
29978
  if (entry.startsWith("."))
29921
29979
  continue;
29922
29980
  walk6(full);
29923
29981
  } else if (entry === "page.vsk") {
29924
- const src2 = readFileSync14(full, "utf-8");
29982
+ const src2 = readFileSync15(full, "utf-8");
29925
29983
  const imgRegex = /<Image\s+src=["']([^"']+)["']/g;
29926
29984
  let m;
29927
29985
  while ((m = imgRegex.exec(src2)) !== null) {
@@ -29934,7 +29992,7 @@ function collectImageRefs(appDir) {
29934
29992
  return refs;
29935
29993
  }
29936
29994
  async function optimizeImages(appDir, outDir2) {
29937
- const imageOutDir = resolve14(outDir2, "static", "images");
29995
+ const imageOutDir = resolve15(outDir2, "static", "images");
29938
29996
  mkdirSync4(imageOutDir, { recursive: true });
29939
29997
  const refs = collectImageRefs(appDir);
29940
29998
  if (refs.length === 0) {
@@ -29944,14 +30002,14 @@ async function optimizeImages(appDir, outDir2) {
29944
30002
  const results = [];
29945
30003
  for (const ref2 of refs) {
29946
30004
  const possiblePaths = [
29947
- resolve14(appDir, ref2.src),
29948
- resolve14(appDir, "..", "public", ref2.src.replace(/^\//, "")),
29949
- resolve14(appDir, "..", "src", ref2.src.replace(/^\//, "")),
29950
- resolve14(outDir2, "static", "public", ref2.src.replace(/^\//, ""))
30005
+ resolve15(appDir, ref2.src),
30006
+ resolve15(appDir, "..", "public", ref2.src.replace(/^\//, "")),
30007
+ resolve15(appDir, "..", "src", ref2.src.replace(/^\//, "")),
30008
+ resolve15(outDir2, "static", "public", ref2.src.replace(/^\//, ""))
29951
30009
  ];
29952
30010
  let srcPath = null;
29953
30011
  for (const p of possiblePaths) {
29954
- if (existsSync13(p)) {
30012
+ if (existsSync14(p)) {
29955
30013
  srcPath = p;
29956
30014
  break;
29957
30015
  }
@@ -29998,8 +30056,8 @@ var seo_audit_exports = {};
29998
30056
  __export(seo_audit_exports, {
29999
30057
  runSeoAudit: () => runSeoAudit
30000
30058
  });
30001
- import { readFileSync as readFileSync15, existsSync as existsSync14, readdirSync as readdirSync5, statSync as statSync10 } from "node:fs";
30002
- import { resolve as resolve15 } from "node:path";
30059
+ import { readFileSync as readFileSync16, existsSync as existsSync15, readdirSync as readdirSync5, statSync as statSync10 } from "node:fs";
30060
+ import { resolve as resolve16 } from "node:path";
30003
30061
  function walkFiles(dir) {
30004
30062
  const results = [];
30005
30063
  let entries;
@@ -30009,7 +30067,7 @@ function walkFiles(dir) {
30009
30067
  return results;
30010
30068
  }
30011
30069
  for (const entry of entries) {
30012
- const full = resolve15(dir, entry);
30070
+ const full = resolve16(dir, entry);
30013
30071
  const st = statSync10(full);
30014
30072
  if (st.isDirectory()) {
30015
30073
  if (!entry.startsWith("."))
@@ -30024,10 +30082,10 @@ function collectCombinedSource(appDir) {
30024
30082
  const pages = files.filter((f) => f.endsWith("/page.vsk") || f.endsWith("\\page.vsk"));
30025
30083
  const combined = [];
30026
30084
  for (const pagePath of pages) {
30027
- const dir = resolve15(pagePath, "..");
30028
- const layoutPath = resolve15(dir, "layout.vsk");
30029
- const pageSrc = readFileSync15(pagePath, "utf-8");
30030
- const layoutSrc = existsSync14(layoutPath) ? readFileSync15(layoutPath, "utf-8") : "";
30085
+ const dir = resolve16(pagePath, "..");
30086
+ const layoutPath = resolve16(dir, "layout.vsk");
30087
+ const pageSrc = readFileSync16(pagePath, "utf-8");
30088
+ const layoutSrc = existsSync15(layoutPath) ? readFileSync16(layoutPath, "utf-8") : "";
30031
30089
  const combinedSrc = layoutSrc ? layoutSrc + "\n" + pageSrc : pageSrc;
30032
30090
  combined.push({
30033
30091
  path: pagePath,
@@ -30202,8 +30260,8 @@ var init_platform = __esm({
30202
30260
  });
30203
30261
 
30204
30262
  // ../adapter/src/platform-handler.ts
30205
- import { existsSync as existsSync15 } from "node:fs";
30206
- import { resolve as resolve16, dirname as dirname10 } from "node:path";
30263
+ import { existsSync as existsSync16 } from "node:fs";
30264
+ import { resolve as resolve17, dirname as dirname10 } from "node:path";
30207
30265
  import { fileURLToPath as fileURLToPath4 } from "node:url";
30208
30266
  function routeName2(segments) {
30209
30267
  const parts = segments.filter(Boolean).map((s) => {
@@ -30220,8 +30278,8 @@ function toId(s) {
30220
30278
  return s.replace(/[^a-zA-Z0-9_]/g, "_").replace(/^_/, "");
30221
30279
  }
30222
30280
  function findCompilerSrc2() {
30223
- const monorepo = resolve16(__dirname5, "..", "..", "..", "packages", "compiler", "dist");
30224
- if (existsSync15(monorepo)) return monorepo;
30281
+ const monorepo = resolve17(__dirname5, "..", "..", "..", "packages", "compiler", "dist");
30282
+ if (existsSync16(monorepo)) return monorepo;
30225
30283
  throw new Error('@vesk/compiler/dist not found \u2014 run "npm run build" first');
30226
30284
  }
30227
30285
  function generatePlatformHandlerSource(input) {
@@ -30252,7 +30310,7 @@ function generatePlatformHandlerSource(input) {
30252
30310
  ` : "const __prerendered = new Set();\n";
30253
30311
  const isrCache = "const __isrCache = new Map();";
30254
30312
  const compilerSrc = findCompilerSrc2();
30255
- const parseCookiesImport = hasMiddleware ? `import { parseCookies } from ${JSON.stringify(resolve16(compilerSrc, "server-cookies.js"))};` : "";
30313
+ const parseCookiesImport = hasMiddleware ? `import { parseCookies } from ${JSON.stringify(resolve17(compilerSrc, "server-cookies.js"))};` : "";
30256
30314
  return `
30257
30315
  ${imports}
30258
30316
  ${parseCookiesImport}
@@ -30443,18 +30501,18 @@ import {
30443
30501
  copyFileSync as copyFileSync3,
30444
30502
  readdirSync as readdirSync6,
30445
30503
  statSync as statSync11,
30446
- existsSync as existsSync16,
30504
+ existsSync as existsSync17,
30447
30505
  writeFileSync as writeFileSync7,
30448
30506
  rmSync as rmSync2,
30449
- readFileSync as readFileSync16
30507
+ readFileSync as readFileSync17
30450
30508
  } from "node:fs";
30451
- import { resolve as resolve17, join as join9, extname as extname6, dirname as dirname11 } from "node:path";
30509
+ import { resolve as resolve18, join as join9, extname as extname6, dirname as dirname11 } from "node:path";
30452
30510
  function ensureCleanDir(dir) {
30453
30511
  rmSync2(dir, { recursive: true, force: true });
30454
30512
  mkdirSync5(dir, { recursive: true });
30455
30513
  }
30456
30514
  function copyDirContents(srcDir, destDir) {
30457
- if (!existsSync16(srcDir)) return;
30515
+ if (!existsSync17(srcDir)) return;
30458
30516
  mkdirSync5(destDir, { recursive: true });
30459
30517
  for (const entry of readdirSync6(srcDir)) {
30460
30518
  const srcPath = join9(srcDir, entry);
@@ -30473,35 +30531,35 @@ function writeFile(path, content) {
30473
30531
  }
30474
30532
  function writePlatformStatic(buildStaticDir, platformStaticDir) {
30475
30533
  mkdirSync5(platformStaticDir, { recursive: true });
30476
- const publicDir = resolve17(buildStaticDir, "public");
30477
- if (existsSync16(publicDir)) {
30534
+ const publicDir = resolve18(buildStaticDir, "public");
30535
+ if (existsSync17(publicDir)) {
30478
30536
  copyDirContents(publicDir, platformStaticDir);
30479
30537
  }
30480
- const assetsDir = resolve17(platformStaticDir, "_vesk", "static");
30538
+ const assetsDir = resolve18(platformStaticDir, "_vesk", "static");
30481
30539
  copyDirContents(buildStaticDir, assetsDir);
30482
- const runtimeAlias = resolve17(platformStaticDir, "_vesk", "runtime.js");
30483
- const clientPath = resolve17(buildStaticDir, "client.js");
30484
- if (existsSync16(clientPath)) {
30540
+ const runtimeAlias = resolve18(platformStaticDir, "_vesk", "runtime.js");
30541
+ const clientPath = resolve18(buildStaticDir, "client.js");
30542
+ if (existsSync17(clientPath)) {
30485
30543
  mkdirSync5(dirname11(runtimeAlias), { recursive: true });
30486
30544
  copyFileSync3(clientPath, runtimeAlias);
30487
30545
  }
30488
30546
  }
30489
30547
  function writePrerenderedStatic(prerenderedRoutes, platformStaticDir) {
30490
30548
  for (const route of prerenderedRoutes) {
30491
- if (!existsSync16(route.html)) continue;
30492
- const content = readFileSync16(route.html);
30549
+ if (!existsSync17(route.html)) continue;
30550
+ const content = readFileSync17(route.html);
30493
30551
  const htmlRel = route.path === "/" ? "index.html" : `${route.path.replace(/^\//, "")}.html`;
30494
- const target = resolve17(platformStaticDir, "_vesk", "static", "public", htmlRel);
30552
+ const target = resolve18(platformStaticDir, "_vesk", "static", "public", htmlRel);
30495
30553
  writeFile(target, content);
30496
30554
  if (route.path !== "/" && route.path.endsWith("/")) {
30497
- const dirIndex = resolve17(platformStaticDir, "_vesk", "static", "public", `${route.path.replace(/^\//, "")}index.html`);
30555
+ const dirIndex = resolve18(platformStaticDir, "_vesk", "static", "public", `${route.path.replace(/^\//, "")}index.html`);
30498
30556
  writeFile(dirIndex, content);
30499
30557
  }
30500
30558
  }
30501
30559
  }
30502
30560
  function listStaticDir(dir) {
30503
30561
  const out = [];
30504
- if (!existsSync16(dir)) return out;
30562
+ if (!existsSync17(dir)) return out;
30505
30563
  function walk6(d, prefix) {
30506
30564
  for (const entry of readdirSync6(d)) {
30507
30565
  const full = join9(d, entry);
@@ -30509,7 +30567,7 @@ function listStaticDir(dir) {
30509
30567
  if (statSync11(full).isDirectory()) {
30510
30568
  walk6(full, rel);
30511
30569
  } else {
30512
- out.push({ rel, buffer: readFileSync16(full) });
30570
+ out.push({ rel, buffer: readFileSync17(full) });
30513
30571
  }
30514
30572
  }
30515
30573
  }
@@ -30557,7 +30615,7 @@ __export(platform_deploy_exports, {
30557
30615
  emitPlatformOutput: () => emitPlatformOutput
30558
30616
  });
30559
30617
  import { writeFileSync as writeFileSync8, mkdirSync as mkdirSync6, rmSync as rmSync3, symlinkSync } from "node:fs";
30560
- import { resolve as resolve18, dirname as dirname12, relative as relative3 } from "node:path";
30618
+ import { resolve as resolve19, dirname as dirname12, relative as relative3 } from "node:path";
30561
30619
  async function emitPlatformOutput(platform, ctx2) {
30562
30620
  if (platform === "node") return null;
30563
30621
  const prerenderedPaths = ctx2.prerenderedRoutes.map((r) => r.path);
@@ -30568,13 +30626,13 @@ async function emitPlatformOutput(platform, ctx2) {
30568
30626
  hasMiddleware: ctx2.hasMiddleware
30569
30627
  });
30570
30628
  const shell = shellFor(platform);
30571
- const projectRoot = resolve18(ctx2.outDir, "..");
30572
- const outRoot = resolve18(projectRoot, shell.root);
30629
+ const projectRoot = resolve19(ctx2.outDir, "..");
30630
+ const outRoot = resolve19(projectRoot, shell.root);
30573
30631
  ensureCleanDir(outRoot);
30574
- const staticDir2 = shell.staticSubdir === "" ? outRoot : resolve18(outRoot, shell.staticSubdir || "static");
30575
- writePlatformStatic(resolve18(ctx2.outDir, "static"), staticDir2);
30632
+ const staticDir2 = shell.staticSubdir === "" ? outRoot : resolve19(outRoot, shell.staticSubdir || "static");
30633
+ writePlatformStatic(resolve19(ctx2.outDir, "static"), staticDir2);
30576
30634
  writePrerenderedStatic(ctx2.prerenderedRoutes, staticDir2);
30577
- const entry = resolve18(ctx2.outDir, ".platform-entry.mjs");
30635
+ const entry = resolve19(ctx2.outDir, ".platform-entry.mjs");
30578
30636
  let source = handler;
30579
30637
  if (shell.imports) source = `${shell.imports}
30580
30638
  ${source}`;
@@ -30592,24 +30650,24 @@ ${shell.bootstrap}
30592
30650
  writeFileSync8(entry, source, "utf-8");
30593
30651
  let handlerRel;
30594
30652
  if (shell.functionFile) {
30595
- const funcDir = resolve18(outRoot, shell.functionFile.dir);
30653
+ const funcDir = resolve19(outRoot, shell.functionFile.dir);
30596
30654
  mkdirSync6(funcDir, { recursive: true });
30597
30655
  if (shell.functionConfig) {
30598
- writeFileSync8(resolve18(funcDir, ".vc-config.json"), JSON.stringify(shell.functionConfig, null, 2), "utf-8");
30656
+ writeFileSync8(resolve19(funcDir, ".vc-config.json"), JSON.stringify(shell.functionConfig, null, 2), "utf-8");
30599
30657
  }
30600
30658
  handlerRel = `${shell.functionFile.dir}/${shell.functionFile.file}`;
30601
- await bundlePlatformHandler({ entry, outfile: resolve18(funcDir, shell.functionFile.file), nodeBuiltins: shell.nodeBuiltins });
30659
+ await bundlePlatformHandler({ entry, outfile: resolve19(funcDir, shell.functionFile.file), nodeBuiltins: shell.nodeBuiltins });
30602
30660
  } else {
30603
30661
  handlerRel = shell.outfile || "index.js";
30604
- await bundlePlatformHandler({ entry, outfile: resolve18(outRoot, handlerRel), nodeBuiltins: shell.nodeBuiltins });
30662
+ await bundlePlatformHandler({ entry, outfile: resolve19(outRoot, handlerRel), nodeBuiltins: shell.nodeBuiltins });
30605
30663
  }
30606
30664
  for (const file of shell.extraFiles || []) {
30607
- writeFileSync8(resolve18(outRoot, file.path), file.content, "utf-8");
30665
+ writeFileSync8(resolve19(outRoot, file.path), file.content, "utf-8");
30608
30666
  }
30609
30667
  if (platform === "vercel") {
30610
- writeFileSync8(resolve18(outRoot, "config.json"), vercelConfigJson(prerenderedPaths), "utf-8");
30668
+ writeFileSync8(resolve19(outRoot, "config.json"), vercelConfigJson(prerenderedPaths), "utf-8");
30611
30669
  }
30612
- writeFileSync8(resolve18(outRoot, "manifest.json"), JSON.stringify({
30670
+ writeFileSync8(resolve19(outRoot, "manifest.json"), JSON.stringify({
30613
30671
  platform,
30614
30672
  runtime: shell.nodeBuiltins ? "node" : "edge",
30615
30673
  static: shell.staticMode,
@@ -30619,9 +30677,9 @@ ${shell.bootstrap}
30619
30677
  prerendered: prerenderedPaths
30620
30678
  }, null, 2), "utf-8");
30621
30679
  if (platform === "vercel") {
30622
- const vercelDir = resolve18(projectRoot, ".vercel");
30680
+ const vercelDir = resolve19(projectRoot, ".vercel");
30623
30681
  mkdirSync6(vercelDir, { recursive: true });
30624
- const linkPath = resolve18(vercelDir, "output");
30682
+ const linkPath = resolve19(vercelDir, "output");
30625
30683
  rmSync3(linkPath, { recursive: true, force: true });
30626
30684
  symlinkSync(relative3(dirname12(linkPath), outRoot), linkPath, "dir");
30627
30685
  }
@@ -34935,8 +34993,8 @@ __export(typecheck_exports, {
34935
34993
  formatTypecheckWarnings: () => formatTypecheckWarnings,
34936
34994
  typecheckProject: () => typecheckProject
34937
34995
  });
34938
- import { readFileSync as readFileSync31, readdirSync as readdirSync14, statSync as statSync22 } from "node:fs";
34939
- import { join as join20, dirname as dirname21, normalize, relative as relative7, resolve as resolve33, sep as sep7 } from "node:path";
34996
+ import { readFileSync as readFileSync34, readdirSync as readdirSync14, statSync as statSync22 } from "node:fs";
34997
+ import { join as join20, dirname as dirname22, normalize, relative as relative7, resolve as resolve36, sep as sep7 } from "node:path";
34940
34998
  import * as ts8 from "typescript";
34941
34999
  function walkProjectFiles(projectRoot) {
34942
35000
  const code = [];
@@ -34977,8 +35035,8 @@ function walkProjectFiles(projectRoot) {
34977
35035
  return { code, js };
34978
35036
  }
34979
35037
  function isUnder(dir, file) {
34980
- const base = resolve33(dir);
34981
- const abs = resolve33(file);
35038
+ const base = resolve36(dir);
35039
+ const abs = resolve36(file);
34982
35040
  return abs === base || abs.startsWith(base + sep7);
34983
35041
  }
34984
35042
  function structureWarning(rel, message) {
@@ -35086,7 +35144,7 @@ function createTypecheckHost(projectRoot, appDir, vskFiles) {
35086
35144
  resolveModuleNameLiterals(moduleLiterals, containingFile, redirectedReference, options2) {
35087
35145
  return moduleLiterals.map(({ text }) => {
35088
35146
  if (text.endsWith(".vsk")) {
35089
- const abs = normalize(join20(dirname21(containingFile), text));
35147
+ const abs = normalize(join20(dirname22(containingFile), text));
35090
35148
  return {
35091
35149
  resolvedModule: {
35092
35150
  resolvedFileName: abs + ".d.ts",
@@ -35097,7 +35155,7 @@ function createTypecheckHost(projectRoot, appDir, vskFiles) {
35097
35155
  };
35098
35156
  }
35099
35157
  if (text.endsWith(".css")) {
35100
- const abs = normalize(join20(dirname21(containingFile), text));
35158
+ const abs = normalize(join20(dirname22(containingFile), text));
35101
35159
  return {
35102
35160
  resolvedModule: {
35103
35161
  resolvedFileName: abs + ".d.ts",
@@ -35137,7 +35195,7 @@ function typecheckProject(projectRoot, opts = {}) {
35137
35195
  }
35138
35196
  }
35139
35197
  if (f.endsWith(".vsk")) {
35140
- const src2 = readFileSync31(f, "utf-8");
35198
+ const src2 = readFileSync34(f, "utf-8");
35141
35199
  try {
35142
35200
  parse4(src2);
35143
35201
  } catch (e) {
@@ -35719,9 +35777,9 @@ declare module '@vesk/runtime' {
35719
35777
  });
35720
35778
 
35721
35779
  // src/index.ts
35722
- import { readFileSync as readFileSync32, writeFileSync as writeFileSync17, mkdirSync as mkdirSync15, existsSync as existsSync33 } from "fs";
35723
- import { resolve as resolve34, join as join21, dirname as dirname22 } from "path";
35724
- import { fileURLToPath as fileURLToPath8 } from "url";
35780
+ import { readFileSync as readFileSync35, writeFileSync as writeFileSync18, mkdirSync as mkdirSync15, existsSync as existsSync36 } from "fs";
35781
+ import { resolve as resolve37, join as join21, dirname as dirname23 } from "path";
35782
+ import { fileURLToPath as fileURLToPath9 } from "url";
35725
35783
 
35726
35784
  // ../compiler/dist/config.js
35727
35785
  init_errors();
@@ -35828,9 +35886,9 @@ function validateConfig(config) {
35828
35886
  if (typeof plugin.name !== "string" || !plugin.name) {
35829
35887
  throw new Error("[vesk] A plugin is missing a `name` property. Use a Vesk-native plugin factory (e.g. tailwindcss({...}) from @vesk/plugin-tailwind) that returns a plugin object with the correct shape.");
35830
35888
  }
35831
- const hasKnownHook = typeof plugin.onCSS === "function" || typeof plugin.onFileWatch === "function" || typeof plugin.onTransformJS === "function" || typeof plugin.onBuildStart === "function" || typeof plugin.onBuildEnd === "function" || typeof plugin.onRequest === "function" || plugin.provides && typeof plugin.provides === "object" && Object.keys(plugin.provides).length > 0;
35889
+ const hasKnownHook = typeof plugin.onCSS === "function" || typeof plugin.onFileWatch === "function" || typeof plugin.onTransformJS === "function" || typeof plugin.onBuildStart === "function" || typeof plugin.onBuildEnd === "function" || typeof plugin.onRequest === "function" || typeof plugin.onHead === "function" || typeof plugin.onHtml === "function" || plugin.provides && typeof plugin.provides === "object" && Object.keys(plugin.provides).length > 0;
35832
35890
  if (!hasKnownHook) {
35833
- throw new Error(`[vesk] Plugin "${plugin.name}" implements none of the recognized hooks (onCSS, onFileWatch, onTransformJS, onBuildStart, onBuildEnd, onRequest) or provides \u2014 it will never be called. Check the plugin package version, or see /docu/cli/plugin-api.md for the current hook contract.`);
35891
+ throw new Error(`[vesk] Plugin "${plugin.name}" implements none of the recognized hooks (onCSS, onFileWatch, onTransformJS, onBuildStart, onBuildEnd, onRequest, onHead, onHtml) or provides \u2014 it will never be called. Check the plugin package version, or see /docu/cli/plugin-api.md for the current hook contract.`);
35834
35892
  }
35835
35893
  }
35836
35894
  return config;
@@ -36218,9 +36276,8 @@ function setRuntimeModule2(mod) {
36218
36276
  }
36219
36277
 
36220
36278
  // ../adapter/dist/index.js
36221
- init_scan();
36222
- import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync9, existsSync as existsSync17, readFileSync as readFileSync17 } from "node:fs";
36223
- import { resolve as resolve19, dirname as dirname13, relative as relative4, basename as basename2 } from "node:path";
36279
+ import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync9, existsSync as existsSync18, readFileSync as readFileSync18 } from "node:fs";
36280
+ import { resolve as resolve20, dirname as dirname13, relative as relative4, basename as basename2 } from "node:path";
36224
36281
  import { fileURLToPath as fileURLToPath5 } from "node:url";
36225
36282
 
36226
36283
  // ../adapter/src/runtime-bundle.ts
@@ -36367,8 +36424,8 @@ async function bundleRuntime(appDir, outDir2) {
36367
36424
  }
36368
36425
 
36369
36426
  // ../adapter/src/ssr-function.ts
36370
- import { readFileSync as readFileSync4, existsSync as existsSync5 } from "node:fs";
36371
- import { resolve as resolve6, relative, join as join4 } from "node:path";
36427
+ import { readFileSync as readFileSync5, existsSync as existsSync6 } from "node:fs";
36428
+ import { resolve as resolve7, relative, join as join4 } from "node:path";
36372
36429
 
36373
36430
  // ../compiler/src/server-codegen.ts
36374
36431
  init_server_utils();
@@ -36376,6 +36433,55 @@ init_server_head();
36376
36433
  init_server_jsgen();
36377
36434
  init_server_render();
36378
36435
 
36436
+ // ../adapter/src/css.ts
36437
+ init_scan();
36438
+ import { readFileSync as readFileSync4, existsSync as existsSync5 } from "node:fs";
36439
+ import { resolve as resolve6 } from "node:path";
36440
+ var TAILWIND_CSS_URL = "/_vesk/static/_tailwind.css";
36441
+ var GLOBAL_CSS_URL = "/_vesk/static/global.css";
36442
+ function resolveUserCssPath(appDir) {
36443
+ const cssSrc = resolve6(appDir, "..", "src", "global.css");
36444
+ if (existsSync5(cssSrc)) return cssSrc;
36445
+ const altCssSrc = resolve6(appDir, "..", "src", "app.css");
36446
+ if (existsSync5(altCssSrc)) return altCssSrc;
36447
+ return null;
36448
+ }
36449
+ function hasUserCss(appDir) {
36450
+ return resolveUserCssPath(appDir) !== null;
36451
+ }
36452
+ function hasBuiltTailwindCss(outDir2) {
36453
+ const p = resolve6(outDir2, "static", "_tailwind.css");
36454
+ return existsSync5(p) && readFileSync4(p, "utf-8").trim().length > 0;
36455
+ }
36456
+ function isTailwindPlugin(plugins) {
36457
+ return (plugins || []).some((p) => String(p && p.name).toLowerCase().includes("tailwind"));
36458
+ }
36459
+ function resolveCssUrls(opts) {
36460
+ const urls = [];
36461
+ if (opts.tailwind) urls.push(TAILWIND_CSS_URL);
36462
+ if (opts.userCss) urls.push(GLOBAL_CSS_URL);
36463
+ return urls;
36464
+ }
36465
+ function stripTailwindDirectives(css) {
36466
+ const blockStart = /^\s*@(theme\s*\{|layer\s+(components|utilities)\s*\{|utility\s+[\w-]+\s*\{)/;
36467
+ let result2 = css.replace(/^\s*@import\s+['"]tailwindcss['"]\s*;?\s*$/gm, "");
36468
+ result2 = result2.replace(/^\s*@source\s+['"][^'"]+['"]\s*;?\s*$/gm, "");
36469
+ const output = [];
36470
+ let pos = 0;
36471
+ while (pos < result2.length) {
36472
+ const lineEnd = result2.indexOf("\n", pos) === -1 ? result2.length : result2.indexOf("\n", pos) + 1;
36473
+ const line = result2.slice(pos, lineEnd);
36474
+ if (blockStart.test(line.trim())) {
36475
+ const end = cssBlockEnd(result2, pos);
36476
+ pos = end;
36477
+ continue;
36478
+ }
36479
+ output.push(line);
36480
+ pos = lineEnd;
36481
+ }
36482
+ return output.join("").trim();
36483
+ }
36484
+
36379
36485
  // ../adapter/src/ssr-function.ts
36380
36486
  function escapeSource(src2) {
36381
36487
  return src2.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$/g, "\\$");
@@ -36385,7 +36491,7 @@ function resolveErrorFile(sourceDir, appDir) {
36385
36491
  for (let depth = rel.length; depth >= 0; depth--) {
36386
36492
  const dir = depth === 0 ? appDir : join4(appDir, ...rel.slice(0, depth));
36387
36493
  const p = join4(dir, "error.vsk");
36388
- if (existsSync5(p)) return p;
36494
+ if (existsSync6(p)) return p;
36389
36495
  }
36390
36496
  return null;
36391
36497
  }
@@ -36436,27 +36542,26 @@ function buildParamExtraction(node, urlParts) {
36436
36542
  function generateSsrFunction(routeNode, appDir, outDir2, componentMap, options2) {
36437
36543
  const ancestorLayouts = options2?.ancestorLayouts || [];
36438
36544
  const middlewareCode = options2?.middlewareCode || null;
36439
- const pagePath = resolve6(appDir, routeNode.sourceDir, "page.vsk");
36440
- const layoutPath = resolve6(appDir, routeNode.sourceDir, "layout.vsk");
36545
+ const headExtra = options2?.headExtra || null;
36546
+ const pagePath = resolve7(appDir, routeNode.sourceDir, "page.vsk");
36547
+ const layoutPath = resolve7(appDir, routeNode.sourceDir, "layout.vsk");
36441
36548
  const parts = routeNode.fullPath.split("/").filter(Boolean);
36442
36549
  const name = routeName(parts);
36443
- const funcDir = resolve6(outDir2, "server", "functions");
36444
- const funcPath = resolve6(funcDir, `${name}.js`);
36445
- const tailwindPath = resolve6(outDir2, "static", "_tailwind.css");
36446
- const globalCssPath = resolve6(appDir, "..", "src", "global.css");
36447
- const altCssPath = resolve6(appDir, "..", "src", "app.css");
36448
- const hasGlobalCss = existsSync5(globalCssPath) || existsSync5(altCssPath);
36449
- const hasTailwind = existsSync5(tailwindPath) && readFileSync4(tailwindPath, "utf-8").trim().length > 0;
36450
- const cssUrls = [];
36451
- if (hasTailwind) cssUrls.push("/_vesk/static/_tailwind.css");
36452
- if (hasGlobalCss) cssUrls.push("/_vesk/static/global.css");
36550
+ const funcDir = resolve7(outDir2, "server", "functions");
36551
+ const funcPath = resolve7(funcDir, `${name}.js`);
36552
+ const cssUrls = resolveCssUrls({
36553
+ tailwind: hasBuiltTailwindCss(outDir2),
36554
+ userCss: hasUserCss(appDir)
36555
+ });
36453
36556
  const cssOption = cssUrls.length > 0 ? `, cssUrls: ${JSON.stringify(cssUrls)}` : "";
36557
+ const headExtraOption = headExtra ? `, headExtra: ${JSON.stringify(headExtra)}` : "";
36558
+ const bakedOptions = cssOption + headExtraOption;
36454
36559
  const hasLayout = !!routeNode.layout;
36455
36560
  const hasAncestorLayout = ancestorLayouts.length > 0;
36456
- const pageSrc = readFileSync4(pagePath, "utf-8");
36561
+ const pageSrc = readFileSync5(pagePath, "utf-8");
36457
36562
  const pageComp = extractCompName(pageSrc) || "Page";
36458
36563
  const errorPath = resolveErrorFile(routeNode.sourceDir, appDir);
36459
- const errorSrc = errorPath ? readFileSync4(errorPath, "utf-8") : null;
36564
+ const errorSrc = errorPath ? readFileSync5(errorPath, "utf-8") : null;
36460
36565
  const errorComp = errorPath ? extractCompName(errorSrc) || "Error" : null;
36461
36566
  const errorVars = errorPath ? `const _errorSrc = \`${escapeSource(errorSrc)}\`;
36462
36567
  const _errorComp = ${JSON.stringify(errorComp)};
@@ -36465,7 +36570,7 @@ const _errorCompiled = (() => { try { setVskHydrate(true); return compileFile(_e
36465
36570
  ` : "const _errorSrc = null;\nconst _errorComp = null;\nconst _errorPath = null;\nconst _errorCompiled = null;\n";
36466
36571
  let src2 = "";
36467
36572
  if (hasLayout) {
36468
- const layoutSrc = readFileSync4(layoutPath, "utf-8");
36573
+ const layoutSrc = readFileSync5(layoutPath, "utf-8");
36469
36574
  const layoutComp = extractCompName(layoutSrc) || "Layout";
36470
36575
  src2 = `const _layoutSrc = \`${escapeSource(layoutSrc)}\`;
36471
36576
  const _pageSrc = \`${escapeSource(pageSrc)}\`;
@@ -36483,8 +36588,8 @@ const _pagePath = ${JSON.stringify(pagePath)};
36483
36588
  src2 += errorVars;
36484
36589
  } else if (hasAncestorLayout) {
36485
36590
  const outerLayout = ancestorLayouts[0];
36486
- const outerLayoutPath = resolve6(appDir, outerLayout.sourceDir, "layout.vsk");
36487
- const outerLayoutSrc = readFileSync4(outerLayoutPath, "utf-8");
36591
+ const outerLayoutPath = resolve7(appDir, outerLayout.sourceDir, "layout.vsk");
36592
+ const outerLayoutSrc = readFileSync5(outerLayoutPath, "utf-8");
36488
36593
  const outerLayoutComp = extractCompName(outerLayoutSrc) || "Layout";
36489
36594
  src2 = `const _pageSrc = \`${escapeSource(pageSrc)}\`;
36490
36595
  `;
@@ -36525,7 +36630,7 @@ const _comp = ${JSON.stringify(pageComp)};
36525
36630
  const compRegEntries = [];
36526
36631
  const compMap = componentMap || /* @__PURE__ */ new Map();
36527
36632
  for (const [compName, compPath] of compMap) {
36528
- const compSrc = readFileSync4(compPath, "utf-8");
36633
+ const compSrc = readFileSync5(compPath, "utf-8");
36529
36634
  const escapedSrc = escapeSource(compSrc);
36530
36635
  compRegEntries.push(` registry.set(${JSON.stringify(compName)}, async (props, __registry, __vesk) => {
36531
36636
  const _src = \`${escapedSrc}\`;
@@ -36571,7 +36676,7 @@ ${compRegEntries.join("\n")}
36571
36676
  " const stack = err && typeof err === 'object' && 'stack' in err ? String(err.stack) : '';",
36572
36677
  " page = { body: await __renderErrorBody({ params, statusCode: 500, error: __expose ? message : 'Internal Server Error', stack: __expose ? stack : '', url: requestUrl || '' }), head: '' };",
36573
36678
  " }",
36574
- " const html = await renderFullPage(_layoutSrc, _layoutComp, { params, children: (caughtError ? '<!--vesk-ssr-error:' + (caughtError && typeof caughtError === 'object' && 'message' in caughtError ? encodeURIComponent(__expose ? String(caughtError.message) : 'Internal Server Error') : '') + '-->' : '') + page.body }, __componentRegistry, { hydrate: true, cached: _layoutCompiled" + cssOption + clientScriptOption + dataScriptOption + ", pageHead: page.head, sourcePath: _layoutPath });",
36679
+ " const html = await renderFullPage(_layoutSrc, _layoutComp, { params, children: (caughtError ? '<!--vesk-ssr-error:' + (caughtError && typeof caughtError === 'object' && 'message' in caughtError ? encodeURIComponent(__expose ? String(caughtError.message) : 'Internal Server Error') : '') + '-->' : '') + page.body }, __componentRegistry, { hydrate: true, cached: _layoutCompiled" + bakedOptions + clientScriptOption + dataScriptOption + ", pageHead: page.head, sourcePath: _layoutPath });",
36575
36680
  " return new Response(html, { headers: { 'Content-Type': 'text/html' }, status: caughtError ? 500 : 200 });",
36576
36681
  " });",
36577
36682
  "}",
@@ -36585,14 +36690,14 @@ ${compRegEntries.join("\n")}
36585
36690
  " const message = err && typeof err === 'object' && 'message' in err ? String(err.message) : String(err);",
36586
36691
  " const stack = err && typeof err === 'object' && 'stack' in err ? String(err.stack) : '';",
36587
36692
  " const props = { params, statusCode: 500, error: __expose ? message : 'Internal Server Error', stack: __expose ? stack : '', url: requestUrl || '' };",
36588
- " return renderFullPage(_errorSrc, _errorComp, props, __componentRegistry, { hydrate: true, cached: _errorCompiled" + cssOption + clientScriptOption + dataScriptOption + ", sourcePath: _errorPath });",
36693
+ " return renderFullPage(_errorSrc, _errorComp, props, __componentRegistry, { hydrate: true, cached: _errorCompiled" + bakedOptions + clientScriptOption + dataScriptOption + ", sourcePath: _errorPath });",
36589
36694
  "}",
36590
36695
  "",
36591
36696
  "async function __renderHtml(params, requestUrl) {",
36592
36697
  " return withSsrStore(async () => {",
36593
36698
  " let stream;",
36594
36699
  " try {",
36595
- " stream = renderPageStream(_src, _comp, { params }, __componentRegistry, { hydrate: true, cached: _srcCompiled" + cssOption + clientScriptOption + dataScriptOption + ", sourcePath: _srcPath });",
36700
+ " stream = renderPageStream(_src, _comp, { params }, __componentRegistry, { hydrate: true, cached: _srcCompiled" + bakedOptions + clientScriptOption + dataScriptOption + ", sourcePath: _srcPath });",
36596
36701
  " } catch (err) {",
36597
36702
  " if (err && (err.name === 'NotFoundError' || err.name === 'Redirect')) throw err;",
36598
36703
  " const html = await __renderErrorFullPage(params, requestUrl, err);",
@@ -36833,8 +36938,8 @@ init_actions();
36833
36938
 
36834
36939
  // ../adapter/src/api-function.ts
36835
36940
  init_strip_ts();
36836
- import { readFileSync as readFileSync5 } from "node:fs";
36837
- import { resolve as resolve7 } from "node:path";
36941
+ import { readFileSync as readFileSync6 } from "node:fs";
36942
+ import { resolve as resolve8 } from "node:path";
36838
36943
  function apiRouteName(fullPath) {
36839
36944
  const parts = fullPath.split("/").filter(Boolean);
36840
36945
  return parts.map((s) => s.startsWith(":") ? s.slice(1) || "param" : s).join("_") || "index";
@@ -36842,10 +36947,10 @@ function apiRouteName(fullPath) {
36842
36947
  function generateApiFunction(apiNode, _apiDir, outDir2, options2) {
36843
36948
  const middlewareCode = options2?.middlewareCode || null;
36844
36949
  const name = apiRouteName(apiNode.fullPath);
36845
- const funcPath = resolve7(outDir2, "server", "api", `${name}.js`);
36950
+ const funcPath = resolve8(outDir2, "server", "api", `${name}.js`);
36846
36951
  const routeFilePath = apiNode.filePath;
36847
36952
  if (!routeFilePath) throw new Error(`api route ${apiNode.fullPath} has no filePath`);
36848
- let routeSrc = readFileSync5(routeFilePath, "utf-8");
36953
+ let routeSrc = readFileSync6(routeFilePath, "utf-8");
36849
36954
  routeSrc = routeSrc.replace(/from\s+['"]@vesk\/runtime['"]\s*;?/g, "from '../runtime.js';").replace(/from\s+['"]@vesk\/runtime\/(\w+)['"]\s*;?/g, () => {
36850
36955
  return "from '../runtime.js';";
36851
36956
  });
@@ -37013,10 +37118,10 @@ function generateApiFunction(apiNode, _apiDir, outDir2, options2) {
37013
37118
  }
37014
37119
 
37015
37120
  // ../adapter/src/middleware.ts
37016
- import { readFileSync as readFileSync7 } from "node:fs";
37121
+ import { readFileSync as readFileSync8 } from "node:fs";
37017
37122
 
37018
37123
  // ../compiler/src/router.ts
37019
- import { readdirSync, statSync as statSync2, existsSync as existsSync6, readFileSync as readFileSync6 } from "fs";
37124
+ import { readdirSync, statSync as statSync2, existsSync as existsSync7, readFileSync as readFileSync7 } from "fs";
37020
37125
  init_parser();
37021
37126
  init_tokens();
37022
37127
  init_scan();
@@ -37098,8 +37203,8 @@ function fallbackExtractMiddleware(src2) {
37098
37203
  }
37099
37204
  function extractMiddleware(sourcePath2) {
37100
37205
  try {
37101
- if (!existsSync6(sourcePath2)) return null;
37102
- const src2 = readFileSync6(sourcePath2, "utf-8");
37206
+ if (!existsSync7(sourcePath2)) return null;
37207
+ const src2 = readFileSync7(sourcePath2, "utf-8");
37103
37208
  const parts = extractMiddlewareParts(src2);
37104
37209
  if (!parts) return null;
37105
37210
  return `async function middleware(${parts.params}) {
@@ -37121,7 +37226,7 @@ function compileMiddleware(mwChain, _appDir) {
37121
37226
  const parts = [];
37122
37227
  for (let i = 0; i < mwChain.length; i++) {
37123
37228
  const { sourcePath: sourcePath2 } = mwChain[i];
37124
- const src2 = readFileSync7(sourcePath2, "utf-8");
37229
+ const src2 = readFileSync8(sourcePath2, "utf-8");
37125
37230
  const extracted = extractMiddlewareBody(src2);
37126
37231
  if (!extracted) continue;
37127
37232
  parts.push(`async function mw_${i}(${extracted.params}) {
@@ -37214,8 +37319,8 @@ init_esbuild_fallback();
37214
37319
  init_strip_ts();
37215
37320
  init_parser();
37216
37321
  init_client_codegen();
37217
- import { readFileSync as readFileSync8, existsSync as existsSync7, writeFileSync as writeFileSync2, unlinkSync as unlinkSync2, statSync as statSync3, rmSync } from "node:fs";
37218
- import { resolve as resolve8, join as join5, dirname as dirname6, relative as relative2, sep } from "node:path";
37322
+ import { readFileSync as readFileSync9, existsSync as existsSync8, writeFileSync as writeFileSync2, unlinkSync as unlinkSync2, statSync as statSync3, rmSync } from "node:fs";
37323
+ import { resolve as resolve9, join as join5, dirname as dirname6, relative as relative2, sep } from "node:path";
37219
37324
  import { fileURLToPath as fileURLToPath2 } from "node:url";
37220
37325
  init_vsk_imports();
37221
37326
  init_md_inline();
@@ -37236,15 +37341,15 @@ function buildRouterOpts(options2) {
37236
37341
  return "";
37237
37342
  }
37238
37343
  function findRuntimeSrc2(appDir) {
37239
- const monorepoRoot = resolve8(__dirname3, "..", "..", "..");
37344
+ const monorepoRoot = resolve9(__dirname3, "..", "..", "..");
37240
37345
  const candidates = [
37241
- resolve8(monorepoRoot, "packages", "runtime", "dist"),
37242
- resolve8(appDir, "..", "node_modules", "@vesk/runtime"),
37243
- resolve8(appDir, "node_modules", "@vesk/runtime")
37346
+ resolve9(monorepoRoot, "packages", "runtime", "dist"),
37347
+ resolve9(appDir, "..", "node_modules", "@vesk/runtime"),
37348
+ resolve9(appDir, "node_modules", "@vesk/runtime")
37244
37349
  ];
37245
37350
  for (const base of candidates) {
37246
37351
  for (const dir of [base, join5(base, "dist")]) {
37247
- if (existsSync7(join5(dir, "index-client.js"))) return dir;
37352
+ if (existsSync8(join5(dir, "index-client.js"))) return dir;
37248
37353
  }
37249
37354
  }
37250
37355
  throw new Error('@vesk/runtime/dist not found \u2014 run "npm run build" first');
@@ -37432,11 +37537,11 @@ async function generateClientBundle(routeTree, appDir, componentMap, options2) {
37432
37537
  return removeCompiledNodes(code, isVskImport);
37433
37538
  }
37434
37539
  function resolveVskImports(filePath, compile) {
37435
- const src2 = readFileSync8(filePath, "utf-8");
37540
+ const src2 = readFileSync9(filePath, "utf-8");
37436
37541
  const resolved = [];
37437
37542
  for (const importPath of collectVskImportPaths(vskImportLines(src2), filePath)) {
37438
37543
  try {
37439
- readFileSync8(importPath);
37544
+ readFileSync9(importPath);
37440
37545
  } catch {
37441
37546
  continue;
37442
37547
  }
@@ -37476,7 +37581,7 @@ async function generateClientBundle(routeTree, appDir, componentMap, options2) {
37476
37581
  return;
37477
37582
  }
37478
37583
  compiledFiles++;
37479
- let src2 = readFileSync8(filePath, "utf-8");
37584
+ let src2 = readFileSync9(filePath, "utf-8");
37480
37585
  if (/content=["'][^"']*\.md["']/i.test(src2)) {
37481
37586
  src2 = inlineMdContentAttrs(src2, dirname6(filePath), guessProjectRoots(appDir));
37482
37587
  }
@@ -37517,36 +37622,48 @@ async function generateClientBundle(routeTree, appDir, componentMap, options2) {
37517
37622
  return slug.replace(/[\[\]]/g, "_");
37518
37623
  }
37519
37624
  const codeSplit = !!options2?.codeSplit;
37625
+ const transformPlugins = options2?.plugins || [];
37626
+ async function applyTransformPlugins(code, filePath) {
37627
+ if (transformPlugins.length === 0) return code;
37628
+ let out = code;
37629
+ for (const plugin of transformPlugins) {
37630
+ if (typeof plugin.onTransformJS === "function") {
37631
+ const result2 = await plugin.onTransformJS(out, filePath);
37632
+ if (typeof result2 === "string") out = result2;
37633
+ }
37634
+ }
37635
+ return out;
37636
+ }
37520
37637
  if (codeSplit) {
37521
37638
  let walkSplit2 = function(nodes, _chain) {
37522
37639
  for (const node of nodes) {
37523
37640
  const chunkCode = [];
37524
- const pagePath = resolve8(appDir, node.sourceDir, "page.vsk");
37525
- if (node.page && existsSync7(pagePath)) {
37641
+ const pagePath = resolve9(appDir, node.sourceDir, "page.vsk");
37642
+ if (node.page && existsSync8(pagePath)) {
37526
37643
  compileFile2(pagePath, node.page, chunkCode);
37527
37644
  }
37528
- const layoutPath = resolve8(appDir, node.sourceDir, "layout.vsk");
37529
- if (node.layout && existsSync7(layoutPath)) {
37645
+ const layoutPath = resolve9(appDir, node.sourceDir, "layout.vsk");
37646
+ if (node.layout && existsSync8(layoutPath)) {
37530
37647
  compileFile2(layoutPath, node.layout, chunkCode);
37531
37648
  }
37532
- const errorPath = resolve8(appDir, node.sourceDir, "error.vsk");
37533
- if (node.error && existsSync7(errorPath)) {
37649
+ const errorPath = resolve9(appDir, node.sourceDir, "error.vsk");
37650
+ if (node.error && existsSync8(errorPath)) {
37534
37651
  compileFile2(errorPath, node.error, chunkCode);
37535
37652
  }
37536
- const notFoundPath = resolve8(appDir, node.sourceDir, "not-found.vsk");
37537
- if (node.notFound && existsSync7(notFoundPath)) {
37653
+ const notFoundPath = resolve9(appDir, node.sourceDir, "not-found.vsk");
37654
+ if (node.notFound && existsSync8(notFoundPath)) {
37538
37655
  compileFile2(notFoundPath, node.notFound, chunkCode);
37539
37656
  }
37540
- const offlinePath = resolve8(appDir, node.sourceDir, "offline.vsk");
37541
- if (node.offline && existsSync7(offlinePath)) {
37657
+ const offlinePath = resolve9(appDir, node.sourceDir, "offline.vsk");
37658
+ if (node.offline && existsSync8(offlinePath)) {
37542
37659
  compileFile2(offlinePath, node.offline, chunkCode);
37543
37660
  }
37544
- const networkPath = resolve8(appDir, node.sourceDir, "network.vsk");
37545
- if (node.network && existsSync7(networkPath)) {
37661
+ const networkPath = resolve9(appDir, node.sourceDir, "network.vsk");
37662
+ if (node.network && existsSync8(networkPath)) {
37546
37663
  compileFile2(networkPath, node.network, chunkCode);
37547
37664
  }
37548
- const loadingPath = resolve8(appDir, node.sourceDir, "loading.vsk");
37549
- if (node.loading && existsSync7(loadingPath)) {
37665
+ const loadingPath = resolve9(appDir, node.sourceDir, "loading.vsk");
37666
+ if (node.loading && existsSync8(loadingPath)) {
37550
37667
  compileFile2(loadingPath, node.loading, chunkCode);
37551
37668
  }
37552
37669
  if (chunkCode.length > 0) {
@@ -37597,12 +37714,16 @@ ${entry.code}
37597
37714
  main = await buildMainBundle(routeTree, runtimeDir, true, {}, !!options2?.hmr, !!options2?.importRuntime, runtimeImportNames, options2?.routeDataCache);
37598
37715
  if (cache2) cache2.mainBundle = { key: mainKey, code: main };
37599
37716
  }
37600
- return { main, chunks, cachedFileHits, compiledFiles, mainFromCache, editedSources, editedNames };
37717
+ const transformedChunks = [];
37718
+ for (const chunk of chunks) {
37719
+ transformedChunks.push({ ...chunk, code: await applyTransformPlugins(chunk.code, chunk.name) });
37720
+ }
37721
+ return { main: await applyTransformPlugins(main, "client.js"), chunks: transformedChunks, cachedFileHits, compiledFiles, mainFromCache, editedSources, editedNames };
37601
37722
  } else {
37602
37723
  let compileFileMono2 = function(filePath, resolvedName) {
37603
37724
  if (seen.has(filePath)) return;
37604
37725
  seen.add(filePath);
37605
- const src2 = readFileSync8(filePath, "utf-8");
37726
+ const src2 = readFileSync9(filePath, "utf-8");
37606
37727
  resolveVskImports(filePath, (p, n) => compileFileMono2(p, n || ""));
37607
37728
  const compCode = compileClient(src2, null, { forceClient: true, sourcePath: filePath });
37608
37729
  const hydCode = compileClient(src2, null, { hydrate: true, forceClient: true, includeTopLevel: false, sourcePath: filePath });
@@ -37619,20 +37740,20 @@ ${entry.code}
37619
37740
  }
37620
37741
  }, walkMono2 = function(nodes) {
37621
37742
  for (const node of nodes) {
37622
- const pagePath = resolve8(appDir, node.sourceDir, "page.vsk");
37623
- if (node.page && existsSync7(pagePath)) compileFileMono2(pagePath, node.page);
37624
- const layoutPath = resolve8(appDir, node.sourceDir, "layout.vsk");
37625
- if (node.layout && existsSync7(layoutPath)) compileFileMono2(layoutPath, node.layout);
37626
- const errorPath = resolve8(appDir, node.sourceDir, "error.vsk");
37627
- if (node.error && existsSync7(errorPath)) compileFileMono2(errorPath, node.error);
37628
- const notFoundPath = resolve8(appDir, node.sourceDir, "not-found.vsk");
37629
- if (node.notFound && existsSync7(notFoundPath)) compileFileMono2(notFoundPath, node.notFound);
37630
- const offlinePath = resolve8(appDir, node.sourceDir, "offline.vsk");
37631
- if (node.offline && existsSync7(offlinePath)) compileFileMono2(offlinePath, node.offline);
37632
- const networkPath = resolve8(appDir, node.sourceDir, "network.vsk");
37633
- if (node.network && existsSync7(networkPath)) compileFileMono2(networkPath, node.network);
37634
- const loadingPath = resolve8(appDir, node.sourceDir, "loading.vsk");
37635
- if (node.loading && existsSync7(loadingPath)) compileFileMono2(loadingPath, node.loading);
37743
+ const pagePath = resolve9(appDir, node.sourceDir, "page.vsk");
37744
+ if (node.page && existsSync8(pagePath)) compileFileMono2(pagePath, node.page);
37745
+ const layoutPath = resolve9(appDir, node.sourceDir, "layout.vsk");
37746
+ if (node.layout && existsSync8(layoutPath)) compileFileMono2(layoutPath, node.layout);
37747
+ const errorPath = resolve9(appDir, node.sourceDir, "error.vsk");
37748
+ if (node.error && existsSync8(errorPath)) compileFileMono2(errorPath, node.error);
37749
+ const notFoundPath = resolve9(appDir, node.sourceDir, "not-found.vsk");
37750
+ if (node.notFound && existsSync8(notFoundPath)) compileFileMono2(notFoundPath, node.notFound);
37751
+ const offlinePath = resolve9(appDir, node.sourceDir, "offline.vsk");
37752
+ if (node.offline && existsSync8(offlinePath)) compileFileMono2(offlinePath, node.offline);
37753
+ const networkPath = resolve9(appDir, node.sourceDir, "network.vsk");
37754
+ if (node.network && existsSync8(networkPath)) compileFileMono2(networkPath, node.network);
37755
+ const loadingPath = resolve9(appDir, node.sourceDir, "loading.vsk");
37756
+ if (node.loading && existsSync8(loadingPath)) compileFileMono2(loadingPath, node.loading);
37636
37757
  walkMono2(node.children || []);
37637
37758
  }
37638
37759
  };
@@ -37652,7 +37773,7 @@ ${entry.code}
37652
37773
  aliasLines,
37653
37774
  hydratorAliasLines
37654
37775
  }, !!options2?.hmr, !!options2?.importRuntime, runtimeImportNames, options2?.routeDataCache);
37655
- return { main, chunks: [] };
37776
+ return { main: await applyTransformPlugins(main, "client.js"), chunks: [] };
37656
37777
  }
37657
37778
  }
37658
37779
  function stripTypes(code) {
@@ -37682,8 +37803,8 @@ function buildRuntimeCode(runtimeDir) {
37682
37803
  let code = "";
37683
37804
  for (const f of runtimeFiles) {
37684
37805
  const p = join5(runtimeDir, f);
37685
- if (existsSync7(p)) {
37686
- let src2 = readFileSync8(p, "utf-8");
37806
+ if (existsSync8(p)) {
37807
+ let src2 = readFileSync9(p, "utf-8");
37687
37808
  src2 = stripTypes(src2);
37688
37809
  src2 = src2.replace(/^import\s+[\s\S]*?from\s+['"](?:\.\/.*?|@vesk\/runtime\/src\/.*?)['"];?\n?/gm, "");
37689
37810
  src2 = src2.replace(/^import\s+['"](?:\.\/.*?|@vesk\/runtime\/src\/.*?)['"];?\n?/gm, "");
@@ -37695,7 +37816,7 @@ ${src2}
37695
37816
  `;
37696
37817
  }
37697
37818
  }
37698
- const indexSrc = readFileSync8(join5(runtimeDir, "index-client.js"), "utf-8");
37819
+ const indexSrc = readFileSync9(join5(runtimeDir, "index-client.js"), "utf-8");
37699
37820
  const exportNames = stripTypes(indexSrc).match(/export\s*\{\s*([^}]+)\s*\}\s*from/g)?.flatMap((m) => m.replace(/export\s*\{\s*|\s*\}\s*from/g, "").split(",").map((s) => s.trim())) || [];
37700
37821
  code += "// --- exports ---\n";
37701
37822
  for (const name of [...new Set(exportNames)]) {
@@ -37705,7 +37826,7 @@ ${src2}
37705
37826
  return code;
37706
37827
  }
37707
37828
  function runtimeExportNames(runtimeDir) {
37708
- const indexSrc = readFileSync8(join5(runtimeDir, "index-client.js"), "utf-8");
37829
+ const indexSrc = readFileSync9(join5(runtimeDir, "index-client.js"), "utf-8");
37709
37830
  const names = /* @__PURE__ */ new Set();
37710
37831
  for (const m of indexSrc.matchAll(/export\s*\{([^}]+)\}\s*from/g)) {
37711
37832
  for (const raw2 of m[1].split(",")) {
@@ -37861,7 +37982,7 @@ if (typeof document !== 'undefined') __router.start();
37861
37982
  }
37862
37983
 
37863
37984
  // ../adapter/src/manifest.ts
37864
- function generateManifest(routes, ssrRoutes, apiRoutes, staticRoutes, middlewareEnabled, actionMap) {
37985
+ function generateManifest(routes, ssrRoutes, apiRoutes, staticRoutes, middlewareEnabled, actionMap, headExtra) {
37865
37986
  const routeEntries = [];
37866
37987
  for (const r of ssrRoutes) {
37867
37988
  const urlParts = r.fullPath.split("/").filter(Boolean);
@@ -37901,18 +38022,19 @@ function generateManifest(routes, ssrRoutes, apiRoutes, staticRoutes, middleware
37901
38022
  prefix: "/_vesk/static",
37902
38023
  dir: "static"
37903
38024
  },
37904
- ...actionEntries.length > 0 ? { actions: actionEntries } : {}
38025
+ ...actionEntries.length > 0 ? { actions: actionEntries } : {},
38026
+ ...headExtra ? { headExtra } : {}
37905
38027
  };
37906
38028
  }
37907
38029
 
37908
38030
  // ../adapter/src/static.ts
37909
38031
  init_paths();
37910
- import { mkdirSync, copyFileSync, readdirSync as readdirSync2, statSync as statSync5, existsSync as existsSync9, writeFileSync as writeFileSync3, readFileSync as readFileSync10 } from "node:fs";
37911
- import { resolve as resolve10, join as join6 } from "node:path";
38032
+ import { mkdirSync, copyFileSync, readdirSync as readdirSync2, statSync as statSync5, existsSync as existsSync10, writeFileSync as writeFileSync3, readFileSync as readFileSync11 } from "node:fs";
38033
+ import { resolve as resolve11, join as join6 } from "node:path";
37912
38034
  function copyStaticAssets(publicDir, outDir2) {
37913
- const targetDir = resolve10(outDir2, "static", "public");
38035
+ const targetDir = resolve11(outDir2, "static", "public");
37914
38036
  mkdirSync(targetDir, { recursive: true });
37915
- if (!existsSync9(publicDir)) return;
38037
+ if (!existsSync10(publicDir)) return;
37916
38038
  function copyDir(src2, dest) {
37917
38039
  mkdirSync(dest, { recursive: true });
37918
38040
  const entries = readdirSync2(src2);
@@ -37931,8 +38053,8 @@ function copyStaticAssets(publicDir, outDir2) {
37931
38053
  }
37932
38054
 
37933
38055
  // ../adapter/src/prod-server.ts
37934
- import { readFileSync as readFileSync11, existsSync as existsSync10, statSync as statSync6 } from "node:fs";
37935
- import { resolve as resolve11, extname as extname3, dirname as dirname7 } from "node:path";
38056
+ import { readFileSync as readFileSync12, existsSync as existsSync11, statSync as statSync6 } from "node:fs";
38057
+ import { resolve as resolve12, extname as extname3, dirname as dirname7 } from "node:path";
37936
38058
  import { createServer } from "node:http";
37937
38059
  import { createRequire as createRequire2 } from "node:module";
37938
38060
  import { fileURLToPath as fileURLToPath3 } from "node:url";
@@ -38037,6 +38159,7 @@ var MIME = {
38037
38159
  ".ico": "image/x-icon",
38038
38160
  ".html": "text/html",
38039
38161
  ".json": "application/json",
38162
+ ".webmanifest": "application/manifest+json",
38040
38163
  ".woff": "font/woff",
38041
38164
  ".woff2": "font/woff2",
38042
38165
  ".wasm": "application/wasm"
@@ -38046,28 +38169,29 @@ async function startProdServer(outDir, options) {
38046
38169
  const host = options?.host || "127.0.0.1";
38047
38170
  const maxBodyBytes = options?.maxBodyBytes || DEFAULT_MAX_BODY_BYTES;
38048
38171
  if (!process.env.NODE_ENV) process.env.NODE_ENV = "production";
38049
- const staticDir = resolve11(outDir, "static");
38050
- const configPath = resolve11(outDir, "config.json");
38051
- installMdReadHook([resolve11(staticDir, "public")]);
38052
- if (!existsSync10(configPath)) {
38172
+ const staticDir = resolve12(outDir, "static");
38173
+ const configPath = resolve12(outDir, "config.json");
38174
+ installMdReadHook([resolve12(staticDir, "public")]);
38175
+ if (!existsSync11(configPath)) {
38053
38176
  console.error(`vesk start: no build found at ${outDir}`);
38054
38177
  console.error('Run "vesk build" first');
38055
38178
  process.exit(1);
38056
38179
  }
38057
- const buildConfig = JSON.parse(readFileSync11(configPath, "utf-8"));
38180
+ const buildConfig = JSON.parse(readFileSync12(configPath, "utf-8"));
38181
+ const bakedHeadExtra = buildConfig.headExtra || "";
38058
38182
  console.error(`vesk start: serving from ${outDir}`);
38059
- const projectDir = resolve11(outDir, "..");
38183
+ const projectDir = resolve12(outDir, "..");
38060
38184
  let securityConfig = {};
38061
38185
  let mdConfig;
38062
38186
  try {
38063
- const veskConfigPath = resolve11(projectDir, "vesk.config.js");
38064
- const veskConfigTsPath = resolve11(projectDir, "vesk.config.ts");
38187
+ const veskConfigPath = resolve12(projectDir, "vesk.config.js");
38188
+ const veskConfigTsPath = resolve12(projectDir, "vesk.config.ts");
38065
38189
  let rawConfig = {};
38066
- if (existsSync10(veskConfigPath)) {
38190
+ if (existsSync11(veskConfigPath)) {
38067
38191
  rawConfig = _require(veskConfigPath);
38068
- } else if (existsSync10(veskConfigTsPath)) {
38192
+ } else if (existsSync11(veskConfigTsPath)) {
38069
38193
  const { transpile } = _require("typescript");
38070
- const src = readFileSync11(veskConfigTsPath, "utf-8");
38194
+ const src = readFileSync12(veskConfigTsPath, "utf-8");
38071
38195
  const result = transpile(src, { module: 99, target: 99 });
38072
38196
  rawConfig = eval(`(${result})`);
38073
38197
  }
@@ -38096,8 +38220,8 @@ async function startProdServer(outDir, options) {
38096
38220
  } catch {
38097
38221
  }
38098
38222
  let middlewareMod = null;
38099
- const mwPath = resolve11(outDir, "server", "middleware.js");
38100
- if (existsSync10(mwPath)) {
38223
+ const mwPath = resolve12(outDir, "server", "middleware.js");
38224
+ if (existsSync11(mwPath)) {
38101
38225
  try {
38102
38226
  middlewareMod = await import(`${mwPath}?t=${Date.now()}`);
38103
38227
  } catch {
@@ -38106,8 +38230,8 @@ async function startProdServer(outDir, options) {
38106
38230
  const functionCache = /* @__PURE__ */ new Map();
38107
38231
  async function loadFunction(funcPath) {
38108
38232
  if (functionCache.has(funcPath)) return functionCache.get(funcPath);
38109
- const fullPath = resolve11(outDir, funcPath);
38110
- if (!existsSync10(fullPath)) return null;
38233
+ const fullPath = resolve12(outDir, funcPath);
38234
+ if (!existsSync11(fullPath)) return null;
38111
38235
  try {
38112
38236
  const mod = await import(`${fullPath}?t=${Date.now()}`);
38113
38237
  functionCache.set(funcPath, mod);
@@ -38167,12 +38291,12 @@ async function startProdServer(outDir, options) {
38167
38291
  }
38168
38292
  return origWriteHead(statusCode, headers2);
38169
38293
  });
38170
- const publicDir = resolve11(staticDir, "public");
38294
+ const publicDir = resolve12(staticDir, "public");
38171
38295
  const rootFile = url.pathname.length > 1 ? resolveWithin(publicDir, url.pathname.slice(1)) : null;
38172
- if (rootFile && existsSync10(rootFile) && statSync6(rootFile).isFile()) {
38296
+ if (rootFile && existsSync11(rootFile) && statSync6(rootFile).isFile()) {
38173
38297
  const ext = extname3(rootFile);
38174
38298
  res.writeHead(200, { "Content-Type": MIME[ext] || "application/octet-stream" });
38175
- res.end(readFileSync11(rootFile));
38299
+ res.end(readFileSync12(rootFile));
38176
38300
  return;
38177
38301
  }
38178
38302
  if (url.pathname === "/ssr-data.js") {
@@ -38188,10 +38312,10 @@ async function startProdServer(outDir, options) {
38188
38312
  return;
38189
38313
  }
38190
38314
  if (url.pathname === "/_vesk/runtime.js") {
38191
- const clientPath = resolve11(staticDir, "client.js");
38192
- if (existsSync10(clientPath)) {
38315
+ const clientPath = resolve12(staticDir, "client.js");
38316
+ if (existsSync11(clientPath)) {
38193
38317
  res.writeHead(200, { "Content-Type": "application/javascript" });
38194
- res.end(readFileSync11(clientPath));
38318
+ res.end(readFileSync12(clientPath));
38195
38319
  return;
38196
38320
  }
38197
38321
  }
@@ -38203,20 +38327,20 @@ async function startProdServer(outDir, options) {
38203
38327
  res.end("Forbidden");
38204
38328
  return;
38205
38329
  }
38206
- if (existsSync10(staticPath) && statSync6(staticPath).isFile()) {
38330
+ if (existsSync11(staticPath) && statSync6(staticPath).isFile()) {
38207
38331
  const ext = extname3(staticPath);
38208
38332
  res.writeHead(200, { "Content-Type": MIME[ext] || "application/octet-stream" });
38209
- res.end(readFileSync11(staticPath));
38333
+ res.end(readFileSync12(staticPath));
38210
38334
  return;
38211
38335
  }
38212
38336
  }
38213
38337
  if (buildConfig.prerendered) {
38214
38338
  const prerendered = buildConfig.prerendered.find((r) => r.path === url.pathname);
38215
38339
  if (prerendered) {
38216
- const htmlPath = resolve11(outDir, prerendered.file);
38217
- if (existsSync10(htmlPath)) {
38340
+ const htmlPath = resolve12(outDir, prerendered.file);
38341
+ if (existsSync11(htmlPath)) {
38218
38342
  res.writeHead(200, { "Content-Type": "text/html" });
38219
- res.end(readFileSync11(htmlPath));
38343
+ res.end(readFileSync12(htmlPath));
38220
38344
  return;
38221
38345
  }
38222
38346
  }
@@ -38310,21 +38434,20 @@ async function startProdServer(outDir, options) {
38310
38434
  }
38311
38435
  }
38312
38436
  }
38313
- const appDir = resolve11(projectDir, "app");
38314
- const nfPath = resolve11(appDir, "not-found.vsk");
38437
+ const appDir = resolve12(projectDir, "app");
38438
+ const pageCssUrls = resolveCssUrls({
38439
+ tailwind: hasBuiltTailwindCss(outDir),
38440
+ userCss: hasUserCss(appDir)
38441
+ });
38442
+ const nfPath = resolve12(appDir, "not-found.vsk");
38315
38443
  let notFoundHtml = null;
38316
- if (existsSync10(nfPath)) {
38444
+ if (existsSync11(nfPath)) {
38317
38445
  try {
38318
- const runtimePath = resolve11(outDir, "server", "runtime.js");
38446
+ const runtimePath = resolve12(outDir, "server", "runtime.js");
38319
38447
  const { renderFullPage: renderFullPage2, storeDataScriptGlobal } = await import(runtimePath);
38320
- const src2 = readFileSync11(nfPath, "utf-8");
38448
+ const src2 = readFileSync12(nfPath, "utf-8");
38321
38449
  const compName = resolveComponentName(src2) || "NotFound";
38322
- const tailwindPathNF = resolve11(outDir, "static", "_tailwind.css");
38323
- const hasTailwindNF = existsSync10(tailwindPathNF) && readFileSync11(tailwindPathNF, "utf-8").trim().length > 0;
38324
- const cssUrlsNF = [];
38325
- if (hasTailwindNF) cssUrlsNF.push("/_vesk/static/_tailwind.css");
38326
- cssUrlsNF.push("/_vesk/static/global.css");
38327
- notFoundHtml = await renderFullPage2(src2, compName, { params: {}, url: url.pathname }, /* @__PURE__ */ new Map(), { hydrate: true, cssUrls: cssUrlsNF, security: securityConfig?.security || {}, externalDataScript: storeDataScriptGlobal, sourcePath: nfPath });
38450
+ notFoundHtml = await renderFullPage2(src2, compName, { params: {}, url: url.pathname }, /* @__PURE__ */ new Map(), { hydrate: true, cssUrls: pageCssUrls, security: securityConfig?.security || {}, externalDataScript: storeDataScriptGlobal, sourcePath: nfPath, headExtra: bakedHeadExtra });
38328
38451
  } catch {
38329
38452
  }
38330
38453
  }
@@ -38380,21 +38503,16 @@ async function startProdServer(outDir, options) {
38380
38503
  return;
38381
38504
  }
38382
38505
  console.error("vesk ssr error:", err.message);
38383
- const errPath = resolve11(appDir, "error.vsk");
38506
+ const errPath = resolve12(appDir, "error.vsk");
38384
38507
  let errorHtml = null;
38385
- if (existsSync10(errPath)) {
38508
+ if (existsSync11(errPath)) {
38386
38509
  try {
38387
- const runtimePath = resolve11(outDir, "server", "runtime.js");
38510
+ const runtimePath = resolve12(outDir, "server", "runtime.js");
38388
38511
  const { renderFullPage: renderFullPage2, storeDataScriptGlobal } = await import(runtimePath);
38389
- const src2 = readFileSync11(errPath, "utf-8");
38512
+ const src2 = readFileSync12(errPath, "utf-8");
38390
38513
  const compName = resolveComponentName(src2) || "Error";
38391
38514
  const expose = process.env.NODE_ENV !== "production";
38392
- const tailwindPathErr = resolve11(outDir, "static", "_tailwind.css");
38393
- const hasTailwindErr = existsSync10(tailwindPathErr) && readFileSync11(tailwindPathErr, "utf-8").trim().length > 0;
38394
- const cssUrlsErr = [];
38395
- if (hasTailwindErr) cssUrlsErr.push("/_vesk/static/_tailwind.css");
38396
- cssUrlsErr.push("/_vesk/static/global.css");
38397
- errorHtml = await renderFullPage2(src2, compName, { error: expose ? err.message : "Internal Server Error", stack: expose ? err.stack : "", statusCode: 500, url: url.pathname }, /* @__PURE__ */ new Map(), { hydrate: true, cssUrls: cssUrlsErr, clientScriptUrl: "/_vesk/static/client.js", security: securityConfig?.security || {}, externalDataScript: storeDataScriptGlobal, sourcePath: errPath });
38515
+ errorHtml = await renderFullPage2(src2, compName, { error: expose ? err.message : "Internal Server Error", stack: expose ? err.stack : "", statusCode: 500, url: url.pathname }, /* @__PURE__ */ new Map(), { hydrate: true, cssUrls: pageCssUrls, clientScriptUrl: "/_vesk/static/client.js", security: securityConfig?.security || {}, externalDataScript: storeDataScriptGlobal, sourcePath: errPath, headExtra: bakedHeadExtra });
38398
38516
  } catch {
38399
38517
  }
38400
38518
  }
@@ -38508,10 +38626,10 @@ function validateConfig2(config) {
38508
38626
  "[vesk] A plugin is missing a `name` property. Use a Vesk-native plugin factory (e.g. tailwindcss({...}) from @vesk/plugin-tailwind) that returns a plugin object with the correct shape."
38509
38627
  );
38510
38628
  }
38511
- const hasKnownHook = typeof plugin.onCSS === "function" || typeof plugin.onFileWatch === "function" || typeof plugin.onTransformJS === "function" || typeof plugin.onBuildStart === "function" || typeof plugin.onBuildEnd === "function" || typeof plugin.onRequest === "function" || plugin.provides && typeof plugin.provides === "object" && Object.keys(plugin.provides).length > 0;
38629
+ const hasKnownHook = typeof plugin.onCSS === "function" || typeof plugin.onFileWatch === "function" || typeof plugin.onTransformJS === "function" || typeof plugin.onBuildStart === "function" || typeof plugin.onBuildEnd === "function" || typeof plugin.onRequest === "function" || typeof plugin.onHead === "function" || typeof plugin.onHtml === "function" || plugin.provides && typeof plugin.provides === "object" && Object.keys(plugin.provides).length > 0;
38512
38630
  if (!hasKnownHook) {
38513
38631
  throw new Error(
38514
- `[vesk] Plugin "${plugin.name}" implements none of the recognized hooks (onCSS, onFileWatch, onTransformJS, onBuildStart, onBuildEnd, onRequest) or provides \u2014 it will never be called. Check the plugin package version, or see /docu/cli/plugin-api.md for the current hook contract.`
38632
+ `[vesk] Plugin "${plugin.name}" implements none of the recognized hooks (onCSS, onFileWatch, onTransformJS, onBuildStart, onBuildEnd, onRequest, onHead, onHtml) or provides \u2014 it will never be called. Check the plugin package version, or see /docu/cli/plugin-api.md for the current hook contract.`
38515
38633
  );
38516
38634
  }
38517
38635
  }
@@ -38527,13 +38645,13 @@ init_paths();
38527
38645
  // ../adapter/dist/index.js
38528
38646
  var __dirname6 = dirname13(fileURLToPath5(import.meta.url));
38529
38647
  async function resolveCompilerApi(name) {
38530
- const monorepoSrc = resolve19(__dirname6, "..", "..", "compiler", "src");
38531
- if (existsSync17(monorepoSrc)) {
38532
- const tsFile = resolve19(monorepoSrc, name.replace(/\.js$/, ".ts"));
38533
- if (existsSync17(tsFile)) {
38648
+ const monorepoSrc = resolve20(__dirname6, "..", "..", "compiler", "src");
38649
+ if (existsSync18(monorepoSrc)) {
38650
+ const tsFile = resolve20(monorepoSrc, name.replace(/\.js$/, ".ts"));
38651
+ if (existsSync18(tsFile)) {
38534
38652
  return import(tsFile);
38535
38653
  }
38536
- return import(resolve19(monorepoSrc, name));
38654
+ return import(resolve20(monorepoSrc, name));
38537
38655
  }
38538
38656
  return import(`@vesk/compiler/src/${name.replace(/\.js$/, "")}`);
38539
38657
  }
@@ -38556,10 +38674,24 @@ function veskDirFromOutDir(outDir2) {
38556
38674
  return dirname13(outDir2);
38557
38675
  return outDir2;
38558
38676
  }
38677
+ async function collectPluginHeadExtra(pluginsPipelines) {
38678
+ const parts = [];
38679
+ for (const plugin of pluginsPipelines) {
38680
+ if (typeof plugin.onHead !== "function")
38681
+ continue;
38682
+ try {
38683
+ const result2 = await plugin.onHead("", { sourcePath: "build" });
38684
+ if (typeof result2 === "string" && result2.trim())
38685
+ parts.push(result2);
38686
+ } catch {
38687
+ }
38688
+ }
38689
+ return parts.join("\n");
38690
+ }
38559
38691
  async function build2(appDir, options2) {
38560
- appDir = resolve19(appDir);
38561
- const outDir2 = resolve19(options2?.outDir || resolve19(appDir, "..", ".vesk"));
38562
- const publicDir = options2?.publicDir || resolve19(appDir, "..", "public");
38692
+ appDir = resolve20(appDir);
38693
+ const outDir2 = resolve20(options2?.outDir || resolve20(appDir, "..", ".vesk"));
38694
+ const publicDir = options2?.publicDir || resolve20(appDir, "..", "public");
38563
38695
  const plugins = options2?.plugins || [];
38564
38696
  if (options2?.md) {
38565
38697
  const { configureMd: configureMd3 } = await Promise.resolve().then(() => (init_md(), md_exports));
@@ -38594,15 +38726,57 @@ async function build2(appDir, options2) {
38594
38726
  await plugin.onBuildStart();
38595
38727
  }
38596
38728
  }
38729
+ const pluginHeadExtra = await collectPluginHeadExtra(pluginsPipelines);
38730
+ if (pluginHeadExtra)
38731
+ console.error("vesk build: baked plugin head \u2192 config.json + SSR functions");
38597
38732
  console.error(`vesk build: output \u2192 ${outDir2}`);
38598
38733
  const dirs = [
38599
- resolve19(outDir2, "server", "functions"),
38600
- resolve19(outDir2, "server", "api"),
38601
- resolve19(outDir2, "static", "public"),
38602
- resolve19(outDir2, "prerendered")
38734
+ resolve20(outDir2, "server", "functions"),
38735
+ resolve20(outDir2, "server", "api"),
38736
+ resolve20(outDir2, "static", "public"),
38737
+ resolve20(outDir2, "prerendered")
38603
38738
  ];
38604
38739
  for (const d of dirs)
38605
38740
  mkdirSync7(d, { recursive: true });
38741
+ const cssSourcePath = resolveUserCssPath(appDir);
38742
+ if (cssSourcePath !== null) {
38743
+ const cssContent = readFileSync18(cssSourcePath, "utf-8");
38744
+ const userCss = stripTailwindDirectives(cssContent);
38745
+ const userCssTarget = resolve20(outDir2, "static", "global.css");
38746
+ writeFileSync9(userCssTarget, userCss, "utf-8");
38747
+ console.error(`vesk build: css \u2192 static/global.css (${userCss.length} bytes)`);
38748
+ const twCssTarget = resolve20(outDir2, "static", "_tailwind.css");
38749
+ const tailwindActive = isTailwindPlugin(pluginsPipelines);
38750
+ if (!tailwindActive) {
38751
+ writeFileSync9(twCssTarget, "", "utf-8");
38752
+ console.error("vesk build: css \u2192 static/_tailwind.css (empty, tailwind plugin inactive)");
38753
+ } else {
38754
+ let twCss = cssContent;
38755
+ for (const plugin of pluginsPipelines) {
38756
+ if (typeof plugin.onCSS === "function") {
38757
+ const result2 = await plugin.onCSS(twCss, cssSourcePath);
38758
+ if (result2 !== null && typeof result2 === "string") {
38759
+ twCss = result2;
38760
+ }
38761
+ }
38762
+ }
38763
+ const hasUnresolvedTailwindImport = /@import\s+['"]tailwindcss['"]/.test(twCss);
38764
+ if (hasUnresolvedTailwindImport) {
38765
+ const lines = twCss.split("\n").filter((l) => !/^\s*@import\s+['"]tailwindcss['"]/.test(l));
38766
+ twCss = lines.join("\n").trim();
38767
+ if (twCss.length === 0) {
38768
+ writeFileSync9(twCssTarget, "", "utf-8");
38769
+ console.error("vesk build: css \u2192 static/_tailwind.css (empty, tailwind unresolved)");
38770
+ } else {
38771
+ writeFileSync9(twCssTarget, twCss, "utf-8");
38772
+ console.error(`vesk build: css \u2192 static/_tailwind.css (${twCss.length} bytes, tailwind partially unresolved)`);
38773
+ }
38774
+ } else {
38775
+ writeFileSync9(twCssTarget, twCss, "utf-8");
38776
+ console.error(`vesk build: css \u2192 static/_tailwind.css (${twCss.length} bytes)`);
38777
+ }
38778
+ }
38779
+ }
38606
38780
  const { scanRoutes: scanRoutes2, scanComponents } = await resolveCompilerApi("router.js");
38607
38781
  const { scanApiRoutes: scanApiRoutes2 } = await resolveCompilerApi("api-routes.js");
38608
38782
  const { collectMiddlewareChain: collectMiddlewareChain2 } = await resolveCompilerApi("middleware.js");
@@ -38611,14 +38785,14 @@ async function build2(appDir, options2) {
38611
38785
  console.error("vesk build: no routes found in", appDir);
38612
38786
  return;
38613
38787
  }
38614
- const projectRoot = resolve19(appDir, "..");
38615
- const componentsDir = resolve19(projectRoot, "components");
38788
+ const projectRoot = resolve20(appDir, "..");
38789
+ const componentsDir = resolve20(projectRoot, "components");
38616
38790
  const componentMap = scanComponents(componentsDir);
38617
38791
  if (componentMap.size > 0) {
38618
38792
  console.error(`vesk build: ${componentMap.size} external components found in ${componentsDir}`);
38619
38793
  }
38620
- const apiDir = resolve19(appDir, "api");
38621
- const apiTree = existsSync17(apiDir) ? scanApiRoutes2(apiDir) : [];
38794
+ const apiDir = resolve20(appDir, "api");
38795
+ const apiTree = existsSync18(apiDir) ? scanApiRoutes2(apiDir) : [];
38622
38796
  console.error(`vesk build: ${routeTree.length} root routes, ${apiTree.length} API routes`);
38623
38797
  console.error("vesk build: bundling server runtime...");
38624
38798
  await bundleRuntime(appDir, outDir2);
@@ -38631,21 +38805,21 @@ async function build2(appDir, options2) {
38631
38805
  const mwChain2 = collectMiddlewareChain2(routeTree, node.fullPath, appDir);
38632
38806
  let mwCode = null;
38633
38807
  if (mwChain2.length > 0) {
38634
- const mwSources = mwChain2.map((m) => readFileSync17(m.sourcePath, "utf-8"));
38808
+ const mwSources = mwChain2.map((m) => readFileSync18(m.sourcePath, "utf-8"));
38635
38809
  mwCode = compileMiddlewareCode(mwSources);
38636
38810
  }
38637
- const { funcPath, funcCode, name } = generateSsrFunction(node, appDir, outDir2, componentMap, { ancestorLayouts, middlewareCode: mwCode });
38811
+ const { funcPath, funcCode, name } = generateSsrFunction(node, appDir, outDir2, componentMap, { ancestorLayouts, middlewareCode: mwCode, headExtra: pluginHeadExtra });
38638
38812
  writeFileSync9(funcPath, funcCode, "utf-8");
38639
- const pagePath = resolve19(appDir, node.sourceDir, "page.vsk");
38640
- if (existsSync17(pagePath)) {
38641
- const src2 = readFileSync17(pagePath, "utf-8");
38813
+ const pagePath = resolve20(appDir, node.sourceDir, "page.vsk");
38814
+ if (existsSync18(pagePath)) {
38815
+ const src2 = readFileSync18(pagePath, "utf-8");
38642
38816
  const actionIds = collectActionIds(src2);
38643
38817
  if (node.layout) {
38644
- const layoutSrc = readFileSync17(resolve19(appDir, node.sourceDir, "layout.vsk"), "utf-8");
38818
+ const layoutSrc = readFileSync18(resolve20(appDir, node.sourceDir, "layout.vsk"), "utf-8");
38645
38819
  actionIds.push(...collectActionIds(layoutSrc));
38646
38820
  }
38647
38821
  for (const a of ancestorLayouts) {
38648
- const ancestorSrc = readFileSync17(resolve19(appDir, a.sourceDir, "layout.vsk"), "utf-8");
38822
+ const ancestorSrc = readFileSync18(resolve20(appDir, a.sourceDir, "layout.vsk"), "utf-8");
38649
38823
  actionIds.push(...collectActionIds(ancestorSrc));
38650
38824
  }
38651
38825
  for (const id of actionIds) {
@@ -38685,7 +38859,7 @@ async function build2(appDir, options2) {
38685
38859
  if (mwChain.length > 0) {
38686
38860
  const mwCode = compileMiddleware(mwChain, appDir);
38687
38861
  if (mwCode) {
38688
- writeFileSync9(resolve19(outDir2, "server", "middleware.js"), mwCode, "utf-8");
38862
+ writeFileSync9(resolve20(outDir2, "server", "middleware.js"), mwCode, "utf-8");
38689
38863
  middlewareEnabled = true;
38690
38864
  console.error(`vesk build: mw \u2192 server/middleware.js (${mwChain.length} middlewares)`);
38691
38865
  }
@@ -38698,91 +38872,29 @@ async function build2(appDir, options2) {
38698
38872
  bundleOpts.hmr = true;
38699
38873
  if (options2?.routeDataCache !== void 0)
38700
38874
  bundleOpts.routeDataCache = options2.routeDataCache;
38875
+ if (pluginsPipelines.length > 0)
38876
+ bundleOpts.plugins = pluginsPipelines;
38701
38877
  const { main, chunks } = await generateClientBundle(routeTree, appDir, componentMap, bundleOpts);
38702
- writeFileSync9(resolve19(outDir2, "static", "client.js"), main, "utf-8");
38878
+ writeFileSync9(resolve20(outDir2, "static", "client.js"), main, "utf-8");
38703
38879
  const mode = chunks.length > 0 ? "code-split" : "monolithic";
38704
38880
  console.error(`vesk build: client \u2192 static/client.js (${main.length} bytes, ${mode})`);
38705
38881
  if (chunks.length > 0) {
38706
- const staticDir2 = resolve19(outDir2, "static");
38882
+ const staticDir2 = resolve20(outDir2, "static");
38707
38883
  for (const chunk of chunks) {
38708
- writeFileSync9(resolve19(staticDir2, chunk.name), chunk.code, "utf-8");
38884
+ writeFileSync9(resolve20(staticDir2, chunk.name), chunk.code, "utf-8");
38709
38885
  console.error(`vesk build: chunk \u2192 static/${chunk.name} (${chunk.code.length} bytes)`);
38710
38886
  }
38711
38887
  }
38712
38888
  copyStaticAssets(publicDir, outDir2);
38713
38889
  console.error("vesk build: static \u2192 static/public/");
38714
- const srcDir = resolve19(appDir, "..", "src");
38715
- const cssSrc = resolve19(srcDir, "global.css");
38716
- const altCssSrc = resolve19(srcDir, "app.css");
38717
- let cssContent = null;
38718
- let cssSourcePath = null;
38719
- if (existsSync17(cssSrc)) {
38720
- cssContent = readFileSync17(cssSrc, "utf-8");
38721
- cssSourcePath = cssSrc;
38722
- } else if (existsSync17(altCssSrc)) {
38723
- cssContent = readFileSync17(altCssSrc, "utf-8");
38724
- cssSourcePath = altCssSrc;
38725
- }
38726
- function stripTailwindDirectives2(css) {
38727
- const blockStart = /^\s*@(theme\s*\{|layer\s+(components|utilities)\s*\{|utility\s+\w+\s*\{)/;
38728
- let result2 = css.replace(/^\s*@import\s+['"]tailwindcss['"]\s*;?\s*$/gm, "");
38729
- result2 = result2.replace(/^\s*@source\s+['"][^'"]+['"]\s*;?\s*$/gm, "");
38730
- const output = [];
38731
- let pos = 0;
38732
- while (pos < result2.length) {
38733
- const lineEnd = result2.indexOf("\n", pos) === -1 ? result2.length : result2.indexOf("\n", pos) + 1;
38734
- const line = result2.slice(pos, lineEnd);
38735
- if (blockStart.test(line.trim())) {
38736
- const end = cssBlockEnd(result2, pos);
38737
- pos = end;
38738
- continue;
38739
- }
38740
- output.push(line);
38741
- pos = lineEnd;
38742
- }
38743
- return output.join("").trim();
38744
- }
38745
- if (cssContent !== null) {
38746
- const userCss = stripTailwindDirectives2(cssContent);
38747
- const userCssTarget = resolve19(outDir2, "static", "global.css");
38748
- writeFileSync9(userCssTarget, userCss, "utf-8");
38749
- console.error(`vesk build: css \u2192 static/global.css (${userCss.length} bytes)`);
38750
- const twCssTarget = resolve19(outDir2, "static", "_tailwind.css");
38751
- const isTailwindActive = pluginsPipelines.some((p) => String(p.name).toLowerCase().includes("tailwind"));
38752
- if (!isTailwindActive) {
38753
- writeFileSync9(twCssTarget, "", "utf-8");
38754
- console.error("vesk build: css \u2192 static/_tailwind.css (empty, tailwind plugin inactive)");
38755
- } else {
38756
- let twCss = cssContent;
38757
- for (const plugin of pluginsPipelines) {
38758
- if (typeof plugin.onCSS === "function") {
38759
- const result2 = await plugin.onCSS(twCss, cssSourcePath);
38760
- if (result2 !== null && typeof result2 === "string") {
38761
- twCss = result2;
38762
- }
38763
- }
38764
- }
38765
- const hasUnresolvedTailwindImport = /@import\s+['"]tailwindcss['"]/.test(twCss);
38766
- if (hasUnresolvedTailwindImport) {
38767
- const lines = twCss.split("\n").filter((l) => !/^\s*@import\s+['"]tailwindcss['"]/.test(l));
38768
- twCss = lines.join("\n").trim();
38769
- if (twCss.length === 0) {
38770
- writeFileSync9(twCssTarget, "", "utf-8");
38771
- console.error("vesk build: css \u2192 static/_tailwind.css (empty, tailwind unresolved)");
38772
- } else {
38773
- writeFileSync9(twCssTarget, twCss, "utf-8");
38774
- console.error(`vesk build: css \u2192 static/_tailwind.css (${twCss.length} bytes, tailwind partially unresolved)`);
38775
- }
38776
- } else {
38777
- writeFileSync9(twCssTarget, twCss, "utf-8");
38778
- console.error(`vesk build: css \u2192 static/_tailwind.css (${twCss.length} bytes)`);
38779
- }
38780
- }
38781
- }
38782
38890
  let prerenderedRoutes = [];
38783
38891
  if (options2?.ssg) {
38784
38892
  const { generateSsgRoutes: generateSsgRoutes2 } = await Promise.resolve().then(() => (init_static(), static_exports));
38785
- prerenderedRoutes = await generateSsgRoutes2(routeTree, appDir, outDir2);
38893
+ const cssUrls = resolveCssUrls({
38894
+ tailwind: hasBuiltTailwindCss(outDir2),
38895
+ userCss: hasUserCss(appDir)
38896
+ });
38897
+ prerenderedRoutes = await generateSsgRoutes2(routeTree, appDir, outDir2, pluginsPipelines, pluginHeadExtra, cssUrls);
38786
38898
  console.error(`vesk build: ssg \u2192 prerendered/ (${prerenderedRoutes.length} pages)`);
38787
38899
  }
38788
38900
  {
@@ -38802,23 +38914,23 @@ async function build2(appDir, options2) {
38802
38914
  }
38803
38915
  {
38804
38916
  const { generateSitemap: generateSitemap2, generateRobotsTxt: generateRobotsTxt2 } = await Promise.resolve().then(() => (init_static(), static_exports));
38805
- const publicDirResolved = resolve19(outDir2, "static", "public");
38917
+ const publicDirResolved = resolve20(outDir2, "static", "public");
38806
38918
  const siteUrl = options2?.siteUrl || "http://localhost:3000";
38807
- const sitemapOverride = resolve19(publicDirResolved, "sitemap.xml");
38808
- if (!existsSync17(sitemapOverride)) {
38919
+ const sitemapOverride = resolve20(publicDirResolved, "sitemap.xml");
38920
+ if (!existsSync18(sitemapOverride)) {
38809
38921
  const sitemap = generateSitemap2(routeTree, ssrRoutes, prerenderedRoutes, { siteUrl });
38810
38922
  writeFileSync9(sitemapOverride, sitemap, "utf-8");
38811
38923
  console.error(`vesk build: seo \u2192 static/public/sitemap.xml (${sitemap.length} bytes)`);
38812
38924
  }
38813
- const robotsOverride = resolve19(publicDirResolved, "robots.txt");
38814
- if (!existsSync17(robotsOverride)) {
38925
+ const robotsOverride = resolve20(publicDirResolved, "robots.txt");
38926
+ if (!existsSync18(robotsOverride)) {
38815
38927
  const robots = generateRobotsTxt2(siteUrl);
38816
38928
  writeFileSync9(robotsOverride, robots, "utf-8");
38817
38929
  console.error(`vesk build: seo \u2192 static/public/robots.txt (${robots.length} bytes)`);
38818
38930
  }
38819
38931
  }
38820
- const manifest = generateManifest(routeTree, ssrRoutes, apiRoutes, prerenderedRoutes, middlewareEnabled, actionMap);
38821
- writeFileSync9(resolve19(outDir2, "config.json"), JSON.stringify(manifest, null, 2) + "\n", "utf-8");
38932
+ const manifest = generateManifest(routeTree, ssrRoutes, apiRoutes, prerenderedRoutes, middlewareEnabled, actionMap, pluginHeadExtra);
38933
+ writeFileSync9(resolve20(outDir2, "config.json"), JSON.stringify(manifest, null, 2) + "\n", "utf-8");
38822
38934
  console.error("vesk build: config \u2192 config.json");
38823
38935
  {
38824
38936
  const { detectPlatform: detectPlatform2 } = await Promise.resolve().then(() => (init_platform(), platform_exports));
@@ -38857,10 +38969,10 @@ vesk build: done (${outDir2})`);
38857
38969
  init_seo_audit();
38858
38970
 
38859
38971
  // src/dev-server.ts
38860
- import { readFileSync as readFileSync30, watch, statSync as statSync21, existsSync as existsSync32, readdirSync as readdirSync13 } from "node:fs";
38861
- import { resolve as resolve32, extname as extname8, join as join19 } from "node:path";
38972
+ import { readFileSync as readFileSync33, watch, statSync as statSync21, existsSync as existsSync35, readdirSync as readdirSync13 } from "node:fs";
38973
+ import { resolve as resolve35, extname as extname8, join as join19 } from "node:path";
38862
38974
  import { createServer as createServer2 } from "node:http";
38863
- import { WebSocketServer } from "ws";
38975
+ import { WebSocketServer as WebSocketServer2 } from "ws";
38864
38976
 
38865
38977
  // ../compiler/dist/strip-ts.js
38866
38978
  init_parser();
@@ -40578,7 +40690,7 @@ init_parser();
40578
40690
  init_tokens();
40579
40691
  init_scan();
40580
40692
  init_strip_ts();
40581
- import { readdirSync as readdirSync7, statSync as statSync12, existsSync as existsSync18, readFileSync as readFileSync18 } from "fs";
40693
+ import { readdirSync as readdirSync7, statSync as statSync12, existsSync as existsSync19, readFileSync as readFileSync19 } from "fs";
40582
40694
  import { join as join10, relative as relative5, basename as basename3 } from "path";
40583
40695
  function collapseSlashes2(p) {
40584
40696
  let out = "";
@@ -40596,7 +40708,7 @@ function collapseSlashes2(p) {
40596
40708
  return out;
40597
40709
  }
40598
40710
  function scanRoutes(appDir, options2 = {}) {
40599
- if (!existsSync18(appDir)) {
40711
+ if (!existsSync19(appDir)) {
40600
40712
  return [];
40601
40713
  }
40602
40714
  return scanDirectory(appDir, appDir, "/", options2);
@@ -40849,7 +40961,7 @@ function matchUrl(tree, pathname) {
40849
40961
  }
40850
40962
 
40851
40963
  // ../compiler/dist/api-routes.js
40852
- import { readdirSync as readdirSync8, statSync as statSync13, existsSync as existsSync19 } from "fs";
40964
+ import { readdirSync as readdirSync8, statSync as statSync13, existsSync as existsSync20 } from "fs";
40853
40965
  import { join as join11 } from "path";
40854
40966
  init_server_utils();
40855
40967
  function basename4(p) {
@@ -40857,7 +40969,7 @@ function basename4(p) {
40857
40969
  return idx === -1 ? p : p.slice(idx + 1);
40858
40970
  }
40859
40971
  function scanApiRoutes(apiDir) {
40860
- if (!existsSync19(apiDir))
40972
+ if (!existsSync20(apiDir))
40861
40973
  return [];
40862
40974
  return scanApiDir(apiDir, apiDir, "/");
40863
40975
  }
@@ -41222,8 +41334,8 @@ async function executeRewrite(url, originalRequest) {
41222
41334
  }
41223
41335
 
41224
41336
  // ../compiler/dist/middleware.js
41225
- import { existsSync as existsSync20 } from "fs";
41226
- import { resolve as resolve20 } from "path";
41337
+ import { existsSync as existsSync21 } from "fs";
41338
+ import { resolve as resolve21 } from "path";
41227
41339
 
41228
41340
  // ../compiler/src/api-routes.ts
41229
41341
  init_server_utils();
@@ -41282,8 +41394,8 @@ function collectMiddlewareChain(routeTree, url, appDir) {
41282
41394
  }
41283
41395
  function collectForNode(node) {
41284
41396
  if (node.hasMiddleware) {
41285
- const mwPath2 = resolve20(appDir, node.sourceDir, "middleware.ts");
41286
- if (existsSync20(mwPath2)) {
41397
+ const mwPath2 = resolve21(appDir, node.sourceDir, "middleware.ts");
41398
+ if (existsSync21(mwPath2)) {
41287
41399
  chain.push({ sourcePath: mwPath2, node });
41288
41400
  }
41289
41401
  }
@@ -41446,8 +41558,8 @@ async function executeMiddlewareChain(chain, request, params, options2 = {}) {
41446
41558
  }
41447
41559
 
41448
41560
  // ../adapter/dist/client-bundle.js
41449
- import { readFileSync as readFileSync19, existsSync as existsSync21, writeFileSync as writeFileSync10, unlinkSync as unlinkSync3, statSync as statSync14, rmSync as rmSync4 } from "node:fs";
41450
- import { resolve as resolve21, join as join12, dirname as dirname14, relative as relative6, sep as sep3 } from "node:path";
41561
+ import { readFileSync as readFileSync20, existsSync as existsSync22, writeFileSync as writeFileSync10, unlinkSync as unlinkSync3, statSync as statSync14, rmSync as rmSync4 } from "node:fs";
41562
+ import { resolve as resolve22, join as join12, dirname as dirname14, relative as relative6, sep as sep3 } from "node:path";
41451
41563
  import { fileURLToPath as fileURLToPath6 } from "node:url";
41452
41564
 
41453
41565
  // ../adapter/dist/esbuild-fallback.js
@@ -41520,15 +41632,15 @@ function buildRouterOpts2(options2) {
41520
41632
  return "";
41521
41633
  }
41522
41634
  function findRuntimeSrc3(appDir) {
41523
- const monorepoRoot = resolve21(__dirname7, "..", "..", "..");
41635
+ const monorepoRoot = resolve22(__dirname7, "..", "..", "..");
41524
41636
  const candidates = [
41525
- resolve21(monorepoRoot, "packages", "runtime", "dist"),
41526
- resolve21(appDir, "..", "node_modules", "@vesk/runtime"),
41527
- resolve21(appDir, "node_modules", "@vesk/runtime")
41637
+ resolve22(monorepoRoot, "packages", "runtime", "dist"),
41638
+ resolve22(appDir, "..", "node_modules", "@vesk/runtime"),
41639
+ resolve22(appDir, "node_modules", "@vesk/runtime")
41528
41640
  ];
41529
41641
  for (const base of candidates) {
41530
41642
  for (const dir of [base, join12(base, "dist")]) {
41531
- if (existsSync21(join12(dir, "index-client.js")))
41643
+ if (existsSync22(join12(dir, "index-client.js")))
41532
41644
  return dir;
41533
41645
  }
41534
41646
  }
@@ -41735,11 +41847,11 @@ async function generateClientBundle2(routeTree, appDir, componentMap, options2)
41735
41847
  return removeCompiledNodes2(code, isVskImport2);
41736
41848
  }
41737
41849
  function resolveVskImports(filePath, compile) {
41738
- const src2 = readFileSync19(filePath, "utf-8");
41850
+ const src2 = readFileSync20(filePath, "utf-8");
41739
41851
  const resolved = [];
41740
41852
  for (const importPath of collectVskImportPaths(vskImportLines(src2), filePath)) {
41741
41853
  try {
41742
- readFileSync19(importPath);
41854
+ readFileSync20(importPath);
41743
41855
  } catch {
41744
41856
  continue;
41745
41857
  }
@@ -41783,7 +41895,7 @@ async function generateClientBundle2(routeTree, appDir, componentMap, options2)
41783
41895
  return;
41784
41896
  }
41785
41897
  compiledFiles++;
41786
- let src2 = readFileSync19(filePath, "utf-8");
41898
+ let src2 = readFileSync20(filePath, "utf-8");
41787
41899
  if (/content=["'][^"']*\.md["']/i.test(src2)) {
41788
41900
  src2 = inlineMdContentAttrs(src2, dirname14(filePath), guessProjectRoots(appDir));
41789
41901
  }
@@ -41827,36 +41939,50 @@ async function generateClientBundle2(routeTree, appDir, componentMap, options2)
41827
41939
  return slug.replace(/[\[\]]/g, "_");
41828
41940
  }
41829
41941
  const codeSplit = !!options2?.codeSplit;
41942
+ const transformPlugins = options2?.plugins || [];
41943
+ async function applyTransformPlugins(code, filePath) {
41944
+ if (transformPlugins.length === 0)
41945
+ return code;
41946
+ let out = code;
41947
+ for (const plugin of transformPlugins) {
41948
+ if (typeof plugin.onTransformJS === "function") {
41949
+ const result2 = await plugin.onTransformJS(out, filePath);
41950
+ if (typeof result2 === "string")
41951
+ out = result2;
41952
+ }
41953
+ }
41954
+ return out;
41955
+ }
41830
41956
  if (codeSplit) {
41831
41957
  let walkSplit2 = function(nodes, _chain) {
41832
41958
  for (const node of nodes) {
41833
41959
  const chunkCode = [];
41834
- const pagePath = resolve21(appDir, node.sourceDir, "page.vsk");
41835
- if (node.page && existsSync21(pagePath)) {
41960
+ const pagePath = resolve22(appDir, node.sourceDir, "page.vsk");
41961
+ if (node.page && existsSync22(pagePath)) {
41836
41962
  compileFile2(pagePath, node.page, chunkCode);
41837
41963
  }
41838
- const layoutPath = resolve21(appDir, node.sourceDir, "layout.vsk");
41839
- if (node.layout && existsSync21(layoutPath)) {
41964
+ const layoutPath = resolve22(appDir, node.sourceDir, "layout.vsk");
41965
+ if (node.layout && existsSync22(layoutPath)) {
41840
41966
  compileFile2(layoutPath, node.layout, chunkCode);
41841
41967
  }
41842
- const errorPath = resolve21(appDir, node.sourceDir, "error.vsk");
41843
- if (node.error && existsSync21(errorPath)) {
41968
+ const errorPath = resolve22(appDir, node.sourceDir, "error.vsk");
41969
+ if (node.error && existsSync22(errorPath)) {
41844
41970
  compileFile2(errorPath, node.error, chunkCode);
41845
41971
  }
41846
- const notFoundPath = resolve21(appDir, node.sourceDir, "not-found.vsk");
41847
- if (node.notFound && existsSync21(notFoundPath)) {
41972
+ const notFoundPath = resolve22(appDir, node.sourceDir, "not-found.vsk");
41973
+ if (node.notFound && existsSync22(notFoundPath)) {
41848
41974
  compileFile2(notFoundPath, node.notFound, chunkCode);
41849
41975
  }
41850
- const offlinePath = resolve21(appDir, node.sourceDir, "offline.vsk");
41851
- if (node.offline && existsSync21(offlinePath)) {
41976
+ const offlinePath = resolve22(appDir, node.sourceDir, "offline.vsk");
41977
+ if (node.offline && existsSync22(offlinePath)) {
41852
41978
  compileFile2(offlinePath, node.offline, chunkCode);
41853
41979
  }
41854
- const networkPath = resolve21(appDir, node.sourceDir, "network.vsk");
41855
- if (node.network && existsSync21(networkPath)) {
41980
+ const networkPath = resolve22(appDir, node.sourceDir, "network.vsk");
41981
+ if (node.network && existsSync22(networkPath)) {
41856
41982
  compileFile2(networkPath, node.network, chunkCode);
41857
41983
  }
41858
- const loadingPath = resolve21(appDir, node.sourceDir, "loading.vsk");
41859
- if (node.loading && existsSync21(loadingPath)) {
41984
+ const loadingPath = resolve22(appDir, node.sourceDir, "loading.vsk");
41985
+ if (node.loading && existsSync22(loadingPath)) {
41860
41986
  compileFile2(loadingPath, node.loading, chunkCode);
41861
41987
  }
41862
41988
  if (chunkCode.length > 0) {
@@ -41909,13 +42035,17 @@ ${entry.code}
41909
42035
  if (cache2)
41910
42036
  cache2.mainBundle = { key: mainKey, code: main };
41911
42037
  }
41912
- return { main, chunks, cachedFileHits, compiledFiles, mainFromCache, editedSources, editedNames };
42038
+ const transformedChunks = [];
42039
+ for (const chunk of chunks) {
42040
+ transformedChunks.push({ ...chunk, code: await applyTransformPlugins(chunk.code, chunk.name) });
42041
+ }
42042
+ return { main: await applyTransformPlugins(main, "client.js"), chunks: transformedChunks, cachedFileHits, compiledFiles, mainFromCache, editedSources, editedNames };
41913
42043
  } else {
41914
42044
  let compileFileMono2 = function(filePath, resolvedName) {
41915
42045
  if (seen.has(filePath))
41916
42046
  return;
41917
42047
  seen.add(filePath);
41918
- const src2 = readFileSync19(filePath, "utf-8");
42048
+ const src2 = readFileSync20(filePath, "utf-8");
41919
42049
  resolveVskImports(filePath, (p, n) => compileFileMono2(p, n || ""));
41920
42050
  const compCode = compileClient(src2, null, { forceClient: true, sourcePath: filePath });
41921
42051
  const hydCode = compileClient(src2, null, { hydrate: true, forceClient: true, includeTopLevel: false, sourcePath: filePath });
@@ -41935,26 +42065,26 @@ ${entry.code}
41935
42065
  }
41936
42066
  }, walkMono2 = function(nodes) {
41937
42067
  for (const node of nodes) {
41938
- const pagePath = resolve21(appDir, node.sourceDir, "page.vsk");
41939
- if (node.page && existsSync21(pagePath))
42068
+ const pagePath = resolve22(appDir, node.sourceDir, "page.vsk");
42069
+ if (node.page && existsSync22(pagePath))
41940
42070
  compileFileMono2(pagePath, node.page);
41941
- const layoutPath = resolve21(appDir, node.sourceDir, "layout.vsk");
41942
- if (node.layout && existsSync21(layoutPath))
42071
+ const layoutPath = resolve22(appDir, node.sourceDir, "layout.vsk");
42072
+ if (node.layout && existsSync22(layoutPath))
41943
42073
  compileFileMono2(layoutPath, node.layout);
41944
- const errorPath = resolve21(appDir, node.sourceDir, "error.vsk");
41945
- if (node.error && existsSync21(errorPath))
42074
+ const errorPath = resolve22(appDir, node.sourceDir, "error.vsk");
42075
+ if (node.error && existsSync22(errorPath))
41946
42076
  compileFileMono2(errorPath, node.error);
41947
- const notFoundPath = resolve21(appDir, node.sourceDir, "not-found.vsk");
41948
- if (node.notFound && existsSync21(notFoundPath))
42077
+ const notFoundPath = resolve22(appDir, node.sourceDir, "not-found.vsk");
42078
+ if (node.notFound && existsSync22(notFoundPath))
41949
42079
  compileFileMono2(notFoundPath, node.notFound);
41950
- const offlinePath = resolve21(appDir, node.sourceDir, "offline.vsk");
41951
- if (node.offline && existsSync21(offlinePath))
42080
+ const offlinePath = resolve22(appDir, node.sourceDir, "offline.vsk");
42081
+ if (node.offline && existsSync22(offlinePath))
41952
42082
  compileFileMono2(offlinePath, node.offline);
41953
- const networkPath = resolve21(appDir, node.sourceDir, "network.vsk");
41954
- if (node.network && existsSync21(networkPath))
42083
+ const networkPath = resolve22(appDir, node.sourceDir, "network.vsk");
42084
+ if (node.network && existsSync22(networkPath))
41955
42085
  compileFileMono2(networkPath, node.network);
41956
- const loadingPath = resolve21(appDir, node.sourceDir, "loading.vsk");
41957
- if (node.loading && existsSync21(loadingPath))
42086
+ const loadingPath = resolve22(appDir, node.sourceDir, "loading.vsk");
42087
+ if (node.loading && existsSync22(loadingPath))
41958
42088
  compileFileMono2(loadingPath, node.loading);
41959
42089
  walkMono2(node.children || []);
41960
42090
  }
@@ -41975,7 +42105,7 @@ ${entry.code}
41975
42105
  aliasLines,
41976
42106
  hydratorAliasLines
41977
42107
  }, !!options2?.hmr, !!options2?.importRuntime, runtimeImportNames, options2?.routeDataCache);
41978
- return { main, chunks: [] };
42108
+ return { main: await applyTransformPlugins(main, "client.js"), chunks: [] };
41979
42109
  }
41980
42110
  }
41981
42111
  function stripTypes2(code) {
@@ -42005,8 +42135,8 @@ function buildRuntimeCode2(runtimeDir) {
42005
42135
  let code = "";
42006
42136
  for (const f of runtimeFiles) {
42007
42137
  const p = join12(runtimeDir, f);
42008
- if (existsSync21(p)) {
42009
- let src2 = readFileSync19(p, "utf-8");
42138
+ if (existsSync22(p)) {
42139
+ let src2 = readFileSync20(p, "utf-8");
42010
42140
  src2 = stripTypes2(src2);
42011
42141
  src2 = src2.replace(/^import\s+[\s\S]*?from\s+['"](?:\.\/.*?|@vesk\/runtime\/src\/.*?)['"];?\n?/gm, "");
42012
42142
  src2 = src2.replace(/^import\s+['"](?:\.\/.*?|@vesk\/runtime\/src\/.*?)['"];?\n?/gm, "");
@@ -42018,7 +42148,7 @@ ${src2}
42018
42148
  `;
42019
42149
  }
42020
42150
  }
42021
- const indexSrc = readFileSync19(join12(runtimeDir, "index-client.js"), "utf-8");
42151
+ const indexSrc = readFileSync20(join12(runtimeDir, "index-client.js"), "utf-8");
42022
42152
  const exportNames = stripTypes2(indexSrc).match(/export\s*\{\s*([^}]+)\s*\}\s*from/g)?.flatMap((m) => m.replace(/export\s*\{\s*|\s*\}\s*from/g, "").split(",").map((s) => s.trim())) || [];
42023
42153
  code += "// --- exports ---\n";
42024
42154
  for (const name of [...new Set(exportNames)]) {
@@ -42029,7 +42159,7 @@ ${src2}
42029
42159
  return code;
42030
42160
  }
42031
42161
  function runtimeExportNames2(runtimeDir) {
42032
- const indexSrc = readFileSync19(join12(runtimeDir, "index-client.js"), "utf-8");
42162
+ const indexSrc = readFileSync20(join12(runtimeDir, "index-client.js"), "utf-8");
42033
42163
  const names = /* @__PURE__ */ new Set();
42034
42164
  for (const m of indexSrc.matchAll(/export\s*\{([^}]+)\}\s*from/g)) {
42035
42165
  for (const raw2 of m[1].split(",")) {
@@ -42186,18 +42316,18 @@ if (typeof document !== 'undefined') __router.start();
42186
42316
  }
42187
42317
 
42188
42318
  // ../adapter/dist/paths.js
42189
- import { resolve as resolve22, sep as sep4 } from "node:path";
42190
- import { existsSync as existsSync22, statSync as statSync15, readFileSync as readFileSync20 } from "node:fs";
42319
+ import { resolve as resolve23, sep as sep4 } from "node:path";
42320
+ import { existsSync as existsSync23, statSync as statSync15, readFileSync as readFileSync21 } from "node:fs";
42191
42321
  function resolveWithin2(baseDir, relPath) {
42192
- const base = resolve22(baseDir);
42193
- const target = resolve22(baseDir, relPath);
42322
+ const base = resolve23(baseDir);
42323
+ const target = resolve23(baseDir, relPath);
42194
42324
  const prefix = base + sep4;
42195
42325
  if (!target.startsWith(prefix))
42196
42326
  return null;
42197
42327
  return target;
42198
42328
  }
42199
42329
  function installMdReadHook2(publicDirs) {
42200
- const dirs = publicDirs.map((d) => resolve22(d));
42330
+ const dirs = publicDirs.map((d) => resolve23(d));
42201
42331
  globalThis.__vsk_md_read_file = (p) => {
42202
42332
  for (const dir of dirs) {
42203
42333
  try {
@@ -42210,8 +42340,8 @@ function installMdReadHook2(publicDirs) {
42210
42340
  const lower = abs.toLowerCase();
42211
42341
  if (!lower.endsWith(".md") && !lower.endsWith(".markdown"))
42212
42342
  continue;
42213
- if (existsSync22(abs) && statSync15(abs).isFile())
42214
- return readFileSync20(abs, "utf8");
42343
+ if (existsSync23(abs) && statSync15(abs).isFile())
42344
+ return readFileSync21(abs, "utf8");
42215
42345
  } catch {
42216
42346
  }
42217
42347
  }
@@ -42278,13 +42408,13 @@ function urlAuthority3(url) {
42278
42408
  }
42279
42409
 
42280
42410
  // ../adapter/dist/dev-api.js
42281
- import { readFileSync as readFileSync23, statSync as statSync17, existsSync as existsSync25, readdirSync as readdirSync9 } from "node:fs";
42282
- import { resolve as resolve25 } from "node:path";
42411
+ import { readFileSync as readFileSync24, statSync as statSync17, existsSync as existsSync26, readdirSync as readdirSync9 } from "node:fs";
42412
+ import { resolve as resolve26 } from "node:path";
42283
42413
 
42284
42414
  // ../adapter/dist/plugins.js
42285
42415
  init_paths();
42286
- import { readFileSync as readFileSync21, writeFileSync as writeFileSync11, existsSync as existsSync23, mkdirSync as mkdirSync8, statSync as statSync16 } from "node:fs";
42287
- import { resolve as resolve23, dirname as dirname15, join as join13, extname as extname7, basename as basename5 } from "node:path";
42416
+ import { readFileSync as readFileSync22, writeFileSync as writeFileSync11, existsSync as existsSync24, mkdirSync as mkdirSync8, statSync as statSync16 } from "node:fs";
42417
+ import { resolve as resolve24, dirname as dirname15, join as join13, extname as extname7, basename as basename5 } from "node:path";
42288
42418
  import { createRequire as createRequire4 } from "node:module";
42289
42419
  import { spawn as spawn2 } from "node:child_process";
42290
42420
  var PLUGIN_STATE_FILENAME2 = "plugins.json";
@@ -42299,15 +42429,15 @@ function eqIgnoreCase2(a, b) {
42299
42429
  return String(a || "").toLowerCase() === String(b || "").toLowerCase();
42300
42430
  }
42301
42431
  function stateFilePath2(veskDir) {
42302
- return resolve23(veskDir, PLUGIN_STATE_FILENAME2);
42432
+ return resolve24(veskDir, PLUGIN_STATE_FILENAME2);
42303
42433
  }
42304
42434
  function readPluginState2(veskDir) {
42305
42435
  const file = stateFilePath2(veskDir);
42306
- if (!existsSync23(file))
42436
+ if (!existsSync24(file))
42307
42437
  return defaultState2();
42308
42438
  let raw2;
42309
42439
  try {
42310
- raw2 = JSON.parse(readFileSync21(file, "utf-8"));
42440
+ raw2 = JSON.parse(readFileSync22(file, "utf-8"));
42311
42441
  } catch {
42312
42442
  return defaultState2();
42313
42443
  }
@@ -42326,12 +42456,12 @@ function readPluginState2(veskDir) {
42326
42456
  function writePluginState2(veskDir, state) {
42327
42457
  const file = stateFilePath2(veskDir);
42328
42458
  const dir = dirname15(file);
42329
- if (!existsSync23(dir))
42459
+ if (!existsSync24(dir))
42330
42460
  mkdirSync8(dir, { recursive: true });
42331
42461
  writeFileSync11(file, JSON.stringify(state, null, 2) + "\n", "utf-8");
42332
42462
  }
42333
42463
  function resolvePackage2(appDir, pkg) {
42334
- const require3 = createRequire4(resolve23(appDir, "package.json"));
42464
+ const require3 = createRequire4(resolve24(appDir, "package.json"));
42335
42465
  let entryPath = null;
42336
42466
  let pkgJsonPath = null;
42337
42467
  let pkgJson = null;
@@ -42345,7 +42475,7 @@ function resolvePackage2(appDir, pkg) {
42345
42475
  while (cur && cur !== dirname15(cur) && !seen.has(cur)) {
42346
42476
  seen.add(cur);
42347
42477
  const candidate = join13(cur, "package.json");
42348
- if (existsSync23(candidate)) {
42478
+ if (existsSync24(candidate)) {
42349
42479
  pkgJsonPath = candidate;
42350
42480
  break;
42351
42481
  }
@@ -42357,15 +42487,15 @@ function resolvePackage2(appDir, pkg) {
42357
42487
  } catch {
42358
42488
  }
42359
42489
  }
42360
- if (pkgJsonPath && existsSync23(pkgJsonPath)) {
42490
+ if (pkgJsonPath && existsSync24(pkgJsonPath)) {
42361
42491
  pkgJson = readJsonFile2(pkgJsonPath);
42362
42492
  const main = pkgJson?.main || pkgJson?.module || "index.js";
42363
- entryPath = resolve23(dirname15(pkgJsonPath), main);
42493
+ entryPath = resolve24(dirname15(pkgJsonPath), main);
42364
42494
  }
42365
42495
  let localPath = localDir2(appDir, pkg);
42366
42496
  if (!localPath) {
42367
42497
  for (const sub of ["src/plugins", "plugins", "lib/plugins"]) {
42368
- const candidate = localDir2(resolve23(appDir, sub), pkg);
42498
+ const candidate = localDir2(resolve24(appDir, sub), pkg);
42369
42499
  if (candidate) {
42370
42500
  localPath = candidate;
42371
42501
  break;
@@ -42375,31 +42505,31 @@ function resolvePackage2(appDir, pkg) {
42375
42505
  if (localPath) {
42376
42506
  const localJson = join13(localPath, "package.json");
42377
42507
  let json = null;
42378
- if (existsSync23(localJson)) {
42508
+ if (existsSync24(localJson)) {
42379
42509
  json = readJsonFile2(localJson);
42380
42510
  }
42381
42511
  return { installed: true, path: localPath, dir: localPath, packageJson: json ?? pkgJson };
42382
42512
  }
42383
- const installed2 = !!pkgJsonPath && existsSync23(pkgJsonPath);
42513
+ const installed2 = !!pkgJsonPath && existsSync24(pkgJsonPath);
42384
42514
  return { installed: installed2, path: entryPath, dir: installed2 ? dirname15(pkgJsonPath) : null, packageJson: pkgJson };
42385
42515
  }
42386
42516
  function localDir2(base, pkg) {
42387
42517
  if (pkg.startsWith("@")) {
42388
42518
  const parts = pkg.split("/");
42389
- const p2 = resolve23(base, parts[0], parts[1] ?? "");
42390
- if (existsSync23(p2))
42519
+ const p2 = resolve24(base, parts[0], parts[1] ?? "");
42520
+ if (existsSync24(p2))
42391
42521
  return p2;
42392
42522
  return null;
42393
42523
  }
42394
- const p = resolve23(base, pkg);
42395
- if (existsSync23(p))
42524
+ const p = resolve24(base, pkg);
42525
+ if (existsSync24(p))
42396
42526
  return p;
42397
42527
  return null;
42398
42528
  }
42399
42529
  function readJsonFile2(file) {
42400
42530
  try {
42401
- if (existsSync23(file))
42402
- return JSON.parse(readFileSync21(file, "utf-8"));
42531
+ if (existsSync24(file))
42532
+ return JSON.parse(readFileSync22(file, "utf-8"));
42403
42533
  } catch {
42404
42534
  }
42405
42535
  return null;
@@ -42445,7 +42575,7 @@ function repositoryToString2(r) {
42445
42575
  function assemblePluginMeta2(probe) {
42446
42576
  const pkgJson = probe.packageJson || {};
42447
42577
  const dir = probe.dir;
42448
- const meta = dir ? readJsonFile2(resolve23(dir, "vesk.meta.json")) : null;
42578
+ const meta = dir ? readJsonFile2(resolve24(dir, "vesk.meta.json")) : null;
42449
42579
  const hasMeta = !!meta && Object.keys(meta).length > 0;
42450
42580
  const m = meta || {};
42451
42581
  const metaSource = hasMeta ? "vesk.meta.json" : probe.packageJson ? "package.json" : "none";
@@ -42682,12 +42812,12 @@ function findIconFile2(dir, meta) {
42682
42812
  const explicit = str2(meta?.icon);
42683
42813
  if (explicit) {
42684
42814
  const p = resolveWithin(dir, explicit);
42685
- if (p && existsSync23(p) && statSync16(p).isFile())
42815
+ if (p && existsSync24(p) && statSync16(p).isFile())
42686
42816
  return p;
42687
42817
  }
42688
42818
  for (const name of ["icon.png", "icon.ico"]) {
42689
- const p = resolve23(dir, name);
42690
- if (existsSync23(p) && statSync16(p).isFile())
42819
+ const p = resolve24(dir, name);
42820
+ if (existsSync24(p) && statSync16(p).isFile())
42691
42821
  return p;
42692
42822
  }
42693
42823
  return null;
@@ -42697,7 +42827,7 @@ function findPluginIcon2(appDir, name) {
42697
42827
  const dir = probe.dir;
42698
42828
  if (!dir)
42699
42829
  return null;
42700
- const meta = readJsonFile2(resolve23(dir, "vesk.meta.json"));
42830
+ const meta = readJsonFile2(resolve24(dir, "vesk.meta.json"));
42701
42831
  const iconPath = findIconFile2(dir, meta);
42702
42832
  if (!iconPath)
42703
42833
  return null;
@@ -42772,7 +42902,7 @@ function resolveDtsPath2(probe, pkgJson) {
42772
42902
  if (!rel)
42773
42903
  continue;
42774
42904
  const abs = resolveWithin(dir, rel);
42775
- if (abs && existsSync23(abs) && statSync16(abs).isFile())
42905
+ if (abs && existsSync24(abs) && statSync16(abs).isFile())
42776
42906
  return abs;
42777
42907
  }
42778
42908
  return null;
@@ -43121,7 +43251,7 @@ function introspectPlugin2(appDir, name) {
43121
43251
  const pkgName = str2(pkgJson.name) ?? name;
43122
43252
  const exportsMap = flattenPackageExports2(pkgJson.exports);
43123
43253
  const dtsPath = resolveDtsPath2(probe, pkgJson);
43124
- const dtsExports = dtsPath ? parseDtsExports2(readFileSync21(dtsPath, "utf-8")) : [];
43254
+ const dtsExports = dtsPath ? parseDtsExports2(readFileSync22(dtsPath, "utf-8")) : [];
43125
43255
  return {
43126
43256
  ok: true,
43127
43257
  name: pkgName,
@@ -43259,16 +43389,16 @@ var __internals2 = {
43259
43389
  };
43260
43390
 
43261
43391
  // ../adapter/dist/dev-config.js
43262
- import { existsSync as existsSync24, readFileSync as readFileSync22, writeFileSync as writeFileSync12, mkdirSync as mkdirSync9, mkdtempSync, rmSync as rmSync5 } from "node:fs";
43392
+ import { existsSync as existsSync25, readFileSync as readFileSync23, writeFileSync as writeFileSync12, mkdirSync as mkdirSync9, mkdtempSync, rmSync as rmSync5 } from "node:fs";
43263
43393
  import { tmpdir } from "node:os";
43264
- import { resolve as resolve24, dirname as dirname16, join as join14 } from "node:path";
43394
+ import { resolve as resolve25, dirname as dirname16, join as join14 } from "node:path";
43265
43395
  init_parser();
43266
43396
  function findConfigFile2(projectDir2) {
43267
- const ts9 = resolve24(projectDir2, "vesk.config.ts");
43268
- if (existsSync24(ts9))
43397
+ const ts9 = resolve25(projectDir2, "vesk.config.ts");
43398
+ if (existsSync25(ts9))
43269
43399
  return { path: ts9, isTs: true };
43270
- const js = resolve24(projectDir2, "vesk.config.js");
43271
- if (existsSync24(js))
43400
+ const js = resolve25(projectDir2, "vesk.config.js");
43401
+ if (existsSync25(js))
43272
43402
  return { path: js, isTs: false };
43273
43403
  return { path: null, isTs: false };
43274
43404
  }
@@ -43318,13 +43448,13 @@ async function readConfig2(projectDir2) {
43318
43448
  const { path, isTs } = findConfigFile2(projectDir2);
43319
43449
  if (!path)
43320
43450
  return { path: null, exists: false, source: "", config: {} };
43321
- const source = readFileSync22(path, "utf-8");
43451
+ const source = readFileSync23(path, "utf-8");
43322
43452
  const config = await parseConfigSource(source, isTs, projectDir2);
43323
43453
  return { path, exists: true, source, config };
43324
43454
  }
43325
43455
  async function writeConfigSource2(projectDir2, source) {
43326
43456
  const { path, isTs } = findConfigFile2(projectDir2);
43327
- const target = path || resolve24(projectDir2, "vesk.config.ts");
43457
+ const target = path || resolve25(projectDir2, "vesk.config.ts");
43328
43458
  await parseConfigSource(source, isTs, projectDir2);
43329
43459
  mkdirSync9(dirname16(target), { recursive: true });
43330
43460
  writeFileSync12(target, source, "utf-8");
@@ -44034,11 +44164,11 @@ export default defineConfig({
44034
44164
  ]
44035
44165
  })
44036
44166
  `;
44037
- target = resolve24(projectDir2, "vesk.config.ts");
44167
+ target = resolve25(projectDir2, "vesk.config.ts");
44038
44168
  await writeConfigSource2(projectDir2, source);
44039
44169
  return;
44040
44170
  }
44041
- source = readFileSync22(path, "utf-8");
44171
+ source = readFileSync23(path, "utf-8");
44042
44172
  const existingImport = findPluginImportAst(source, pkg);
44043
44173
  let importName;
44044
44174
  if (existingImport) {
@@ -44118,7 +44248,7 @@ async function removePluginFromConfig2(projectDir2, pkg) {
44118
44248
  const { path } = findConfigFile2(projectDir2);
44119
44249
  if (!path)
44120
44250
  return false;
44121
- let source = readFileSync22(path, "utf-8");
44251
+ let source = readFileSync23(path, "utf-8");
44122
44252
  const original = source;
44123
44253
  const existingImport = findPluginImportAst(source, pkg);
44124
44254
  let importName = existingImport ? existingImport.name : null;
@@ -44196,7 +44326,7 @@ function jsonStatus(status, data2) {
44196
44326
  function createDevApiRouter2(opts) {
44197
44327
  const veskDir = opts.veskDir;
44198
44328
  const caps = new CapabilityTable2(opts.caps, opts.commandAllowlist);
44199
- const projectDir2 = opts.projectDir || resolve25(opts.appDir, "..");
44329
+ const projectDir2 = opts.projectDir || resolve26(opts.appDir, "..");
44200
44330
  const getState = opts.getHmrState || (() => ({ status: "up", lastCompileMs: null, error: null, hasError: false, componentCount: 0 }));
44201
44331
  function denied2(cap) {
44202
44332
  return jsonStatus(403, { error: `capability denied: ${cap}` });
@@ -44239,7 +44369,7 @@ function createDevApiRouter2(opts) {
44239
44369
  return badRequest2("no vesk.config file to edit");
44240
44370
  if (!isTs)
44241
44371
  return badRequest2("single-key toggle edits only apply to vesk.config.ts (use the source editor for .js)");
44242
- const patched = applyConfigToggle2(readFileSync23(path, "utf-8"), b.key, b.value);
44372
+ const patched = applyConfigToggle2(readFileSync24(path, "utf-8"), b.key, b.value);
44243
44373
  if (patched === null)
44244
44374
  return badRequest2("could not safely edit the config object; use the source editor");
44245
44375
  const cfg = await writeConfigSource2(projectDir2, patched);
@@ -44278,14 +44408,14 @@ function createDevApiRouter2(opts) {
44278
44408
  const resolved = resolveWithin2(projectDir2, target);
44279
44409
  if (!resolved)
44280
44410
  return jsonStatus(403, { error: "path escapes project root" });
44281
- if (!existsSync25(resolved))
44411
+ if (!existsSync26(resolved))
44282
44412
  return jsonStatus(404, { error: "not found" });
44283
44413
  if (statSync17(resolved).isDirectory()) {
44284
44414
  const entries = readdirSync9(resolved, { withFileTypes: true }).map((e) => e.name);
44285
44415
  return jsonStatus(200, { ok: true, path: target, directory: true, entries });
44286
44416
  }
44287
44417
  if (statSync17(resolved).isFile()) {
44288
- return jsonStatus(200, { ok: true, path: target, directory: false, content: readFileSync23(resolved, "utf-8") });
44418
+ return jsonStatus(200, { ok: true, path: target, directory: false, content: readFileSync24(resolved, "utf-8") });
44289
44419
  }
44290
44420
  return badRequest2("unsupported file type");
44291
44421
  } catch (e) {
@@ -44421,7 +44551,7 @@ function createDevApiRouter2(opts) {
44421
44551
  return {
44422
44552
  status: 200,
44423
44553
  headers: { "Content-Type": icon.mime, "Cache-Control": "private, max-age=60" },
44424
- body: readFileSync23(icon.file).toString("base64"),
44554
+ body: readFileSync24(icon.file).toString("base64"),
44425
44555
  encoding: "base64"
44426
44556
  };
44427
44557
  }
@@ -44478,8 +44608,8 @@ function produceDiagnostics(input) {
44478
44608
  }
44479
44609
 
44480
44610
  // ../agentic/dist/checkpoints.js
44481
- import { existsSync as existsSync26, mkdirSync as mkdirSync10, readFileSync as readFileSync24, writeFileSync as writeFileSync13, statSync as statSync18, unlinkSync as unlinkSync4, rmSync as rmSync6, renameSync } from "node:fs";
44482
- import { join as join15, resolve as resolve26, dirname as dirname17, sep as sep5 } from "node:path";
44611
+ import { existsSync as existsSync27, mkdirSync as mkdirSync10, readFileSync as readFileSync25, writeFileSync as writeFileSync13, statSync as statSync18, unlinkSync as unlinkSync4, rmSync as rmSync6, renameSync } from "node:fs";
44612
+ import { join as join15, resolve as resolve27, dirname as dirname17, sep as sep5 } from "node:path";
44483
44613
  import { randomUUID as nodeRandomUUID } from "node:crypto";
44484
44614
  function generateId() {
44485
44615
  try {
@@ -44612,7 +44742,7 @@ var CheckpointManager = class {
44612
44742
  }
44613
44743
  };
44614
44744
  function getAgenticDir(projectDir2) {
44615
- return join15(resolve26(projectDir2), ".vesk", "agentic");
44745
+ return join15(resolve27(projectDir2), ".vesk", "agentic");
44616
44746
  }
44617
44747
  function getHistoryPath(projectDir2) {
44618
44748
  return join15(getAgenticDir(projectDir2), "history.json");
@@ -44628,9 +44758,9 @@ function ensureDir(dir) {
44628
44758
  }
44629
44759
  function readJson(filePath, fallback) {
44630
44760
  try {
44631
- if (!existsSync26(filePath))
44761
+ if (!existsSync27(filePath))
44632
44762
  return fallback;
44633
- const raw2 = readFileSync24(filePath, "utf-8");
44763
+ const raw2 = readFileSync25(filePath, "utf-8");
44634
44764
  if (raw2.trim() === "")
44635
44765
  return fallback;
44636
44766
  return JSON.parse(raw2);
@@ -44722,14 +44852,14 @@ function rollback(projectDir2, id) {
44722
44852
  const cp = getCheckpoint(projectDir2, id);
44723
44853
  if (!cp)
44724
44854
  return null;
44725
- const projectRoot = resolve26(projectDir2);
44855
+ const projectRoot = resolve27(projectDir2);
44726
44856
  for (const f of cp.files) {
44727
44857
  if (!f.path || !f.path.trim())
44728
44858
  continue;
44729
- const abs = resolve26(projectRoot, f.path);
44859
+ const abs = resolve27(projectRoot, f.path);
44730
44860
  if (f.before === null) {
44731
44861
  try {
44732
- if (existsSync26(abs)) {
44862
+ if (existsSync27(abs)) {
44733
44863
  const s = statSync18(abs);
44734
44864
  if (s.isDirectory())
44735
44865
  rmSync6(abs, { recursive: true, force: true });
@@ -44750,8 +44880,8 @@ function rollback(projectDir2, id) {
44750
44880
  }
44751
44881
 
44752
44882
  // ../agentic/dist/config.js
44753
- import { readFileSync as readFileSync25, writeFileSync as writeFileSync14, existsSync as existsSync27, mkdirSync as mkdirSync11, chmodSync } from "node:fs";
44754
- import { resolve as resolve27, dirname as dirname18 } from "node:path";
44883
+ import { readFileSync as readFileSync26, writeFileSync as writeFileSync14, existsSync as existsSync28, mkdirSync as mkdirSync11, chmodSync } from "node:fs";
44884
+ import { resolve as resolve28, dirname as dirname18 } from "node:path";
44755
44885
  var DEFAULT_CONFIG = {
44756
44886
  provider: "openai",
44757
44887
  model: "gpt-4o-mini",
@@ -44770,10 +44900,10 @@ var SUPPORTED_PROVIDERS = [
44770
44900
  "custom"
44771
44901
  ];
44772
44902
  function configPath2(projectDir2) {
44773
- return resolve27(projectDir2, ".vesk", "agentic", "config.json");
44903
+ return resolve28(projectDir2, ".vesk", "agentic", "config.json");
44774
44904
  }
44775
44905
  function keysDir(projectDir2) {
44776
- return resolve27(projectDir2, ".vesk", "agentic", "keys");
44906
+ return resolve28(projectDir2, ".vesk", "agentic", "keys");
44777
44907
  }
44778
44908
  function sanitizeProvider(provider) {
44779
44909
  const p = provider.trim().toLowerCase();
@@ -44785,21 +44915,21 @@ function normalizeProvider(provider) {
44785
44915
  return provider.trim().toLowerCase();
44786
44916
  }
44787
44917
  function providerKeyPath(projectDir2, provider) {
44788
- return resolve27(keysDir(projectDir2), `${sanitizeProvider(provider)}.key`);
44918
+ return resolve28(keysDir(projectDir2), `${sanitizeProvider(provider)}.key`);
44789
44919
  }
44790
44920
  function providerDotenvVar(provider) {
44791
44921
  const prov = sanitizeProvider(provider);
44792
44922
  return `VK_${prov.toUpperCase().replace(/[^A-Z0-9]/g, "_")}_KEY`;
44793
44923
  }
44794
44924
  function dotenvPath(projectDir2) {
44795
- return resolve27(projectDir2, ".env.local");
44925
+ return resolve28(projectDir2, ".env.local");
44796
44926
  }
44797
44927
  function readDotenvValue(projectDir2, key, def = null) {
44798
44928
  try {
44799
44929
  const p = dotenvPath(projectDir2);
44800
- if (!existsSync27(p))
44930
+ if (!existsSync28(p))
44801
44931
  return def;
44802
- const content = readFileSync25(p, "utf-8");
44932
+ const content = readFileSync26(p, "utf-8");
44803
44933
  for (const rawLine of content.split("\n")) {
44804
44934
  const line = rawLine.trim();
44805
44935
  if (!line || line.startsWith("#"))
@@ -44826,8 +44956,8 @@ function writeDotenvValue(projectDir2, key, value) {
44826
44956
  try {
44827
44957
  let out = "";
44828
44958
  let replaced = false;
44829
- if (existsSync27(p)) {
44830
- const lines = readFileSync25(p, "utf-8").split("\n");
44959
+ if (existsSync28(p)) {
44960
+ const lines = readFileSync26(p, "utf-8").split("\n");
44831
44961
  for (const rawLine of lines) {
44832
44962
  const trimmed = rawLine.trim();
44833
44963
  const eq = trimmed.indexOf("=");
@@ -44856,8 +44986,8 @@ function loadAgenticConfig(projectDir2) {
44856
44986
  const p = configPath2(projectDir2);
44857
44987
  let cfg = { ...DEFAULT_CONFIG };
44858
44988
  try {
44859
- if (existsSync27(p))
44860
- cfg = { ...cfg, ...JSON.parse(readFileSync25(p, "utf-8")) };
44989
+ if (existsSync28(p))
44990
+ cfg = { ...cfg, ...JSON.parse(readFileSync26(p, "utf-8")) };
44861
44991
  } catch {
44862
44992
  }
44863
44993
  let hasKey = false;
@@ -44899,8 +45029,8 @@ function getProviderSpecificKey(projectDir2, provider) {
44899
45029
  return dotenvFile.trim();
44900
45030
  try {
44901
45031
  const pp2 = providerKeyPath(projectDir2, prov);
44902
- if (existsSync27(pp2)) {
44903
- const v = readFileSync25(pp2, "utf-8").trim();
45032
+ if (existsSync28(pp2)) {
45033
+ const v = readFileSync26(pp2, "utf-8").trim();
44904
45034
  if (v)
44905
45035
  return v;
44906
45036
  }
@@ -44947,8 +45077,8 @@ function getApiKey(projectDir2, provider) {
44947
45077
  }
44948
45078
  try {
44949
45079
  const pp2 = providerKeyPath(projectDir2, prov);
44950
- if (existsSync27(pp2)) {
44951
- const v = readFileSync25(pp2, "utf-8").trim();
45080
+ if (existsSync28(pp2)) {
45081
+ const v = readFileSync26(pp2, "utf-8").trim();
44952
45082
  if (v)
44953
45083
  return v;
44954
45084
  }
@@ -44971,8 +45101,8 @@ function getApiKey(projectDir2, provider) {
44971
45101
  }
44972
45102
 
44973
45103
  // ../agentic/dist/dev-api.js
44974
- import { existsSync as existsSync28, readFileSync as readFileSync26 } from "node:fs";
44975
- import { resolve as resolve28 } from "node:path";
45104
+ import { existsSync as existsSync29, readFileSync as readFileSync27 } from "node:fs";
45105
+ import { resolve as resolve29 } from "node:path";
44976
45106
 
44977
45107
  // ../agentic/dist/providers/openai.js
44978
45108
  var OPENAI_FALLBACK_MODELS = ["gpt-4o-mini", "gpt-4o", "gpt-3.5-turbo"];
@@ -45342,9 +45472,9 @@ function getPerProviderKeyRaw(projectDir2, provider) {
45342
45472
  } catch {
45343
45473
  }
45344
45474
  try {
45345
- const p = resolve28(projectDir2, ".vesk", "agentic", "keys", `${sanitizeProviderName(prov)}.key`);
45346
- if (existsSync28(p)) {
45347
- const v = readFileSync26(p, "utf-8").trim();
45475
+ const p = resolve29(projectDir2, ".vesk", "agentic", "keys", `${sanitizeProviderName(prov)}.key`);
45476
+ if (existsSync29(p)) {
45477
+ const v = readFileSync27(p, "utf-8").trim();
45348
45478
  if (v)
45349
45479
  return v;
45350
45480
  }
@@ -46205,11 +46335,11 @@ var Agent = class {
46205
46335
  };
46206
46336
 
46207
46337
  // ../agentic/dist/tools/vesk.js
46208
- import { existsSync as existsSync29, readFileSync as readFileSync27, writeFileSync as writeFileSync15, mkdirSync as mkdirSync12, readdirSync as readdirSync10, statSync as statSync19 } from "node:fs";
46209
- import { resolve as resolve29, join as join16, dirname as dirname19, sep as sep6 } from "node:path";
46338
+ import { existsSync as existsSync30, readFileSync as readFileSync28, writeFileSync as writeFileSync15, mkdirSync as mkdirSync12, readdirSync as readdirSync10, statSync as statSync19 } from "node:fs";
46339
+ import { resolve as resolve30, join as join16, dirname as dirname19, sep as sep6 } from "node:path";
46210
46340
  function resolveWithin3(baseDir, relPath) {
46211
- const base = resolve29(baseDir);
46212
- const target = resolve29(baseDir, relPath);
46341
+ const base = resolve30(baseDir);
46342
+ const target = resolve30(baseDir, relPath);
46213
46343
  const prefix = base + sep6;
46214
46344
  if (target === base || !target.startsWith(prefix))
46215
46345
  return null;
@@ -46217,14 +46347,14 @@ function resolveWithin3(baseDir, relPath) {
46217
46347
  }
46218
46348
  var PLUGIN_STATE_FILENAME3 = "plugins.json";
46219
46349
  function stateFilePath3(veskDir) {
46220
- return resolve29(veskDir, PLUGIN_STATE_FILENAME3);
46350
+ return resolve30(veskDir, PLUGIN_STATE_FILENAME3);
46221
46351
  }
46222
46352
  function readPluginState3(veskDir) {
46223
46353
  const file = stateFilePath3(veskDir);
46224
- if (!existsSync29(file))
46354
+ if (!existsSync30(file))
46225
46355
  return { version: 1, plugins: [] };
46226
46356
  try {
46227
- const raw2 = JSON.parse(readFileSync27(file, "utf-8"));
46357
+ const raw2 = JSON.parse(readFileSync28(file, "utf-8"));
46228
46358
  if (!raw2 || typeof raw2 !== "object")
46229
46359
  return { version: 1, plugins: [] };
46230
46360
  if (raw2.version !== 1)
@@ -46259,16 +46389,16 @@ function validatePackageSpec3(pkg) {
46259
46389
  return null;
46260
46390
  }
46261
46391
  function findConfigFile3(projectDir2) {
46262
- const ts9 = resolve29(projectDir2, "vesk.config.ts");
46263
- if (existsSync29(ts9))
46392
+ const ts9 = resolve30(projectDir2, "vesk.config.ts");
46393
+ if (existsSync30(ts9))
46264
46394
  return { path: ts9, isTs: true };
46265
- const js = resolve29(projectDir2, "vesk.config.js");
46266
- if (existsSync29(js))
46395
+ const js = resolve30(projectDir2, "vesk.config.js");
46396
+ if (existsSync30(js))
46267
46397
  return { path: js, isTs: false };
46268
46398
  return { path: null, isTs: false };
46269
46399
  }
46270
46400
  function checkpointDir(veskDir) {
46271
- return join16(resolve29(veskDir), "checkpoints");
46401
+ return join16(resolve30(veskDir), "checkpoints");
46272
46402
  }
46273
46403
  function findMatchingBrace2(src2, openIdx) {
46274
46404
  let inStr = null;
@@ -46397,9 +46527,9 @@ function jsonError(message, extra) {
46397
46527
  return JSON.stringify({ ok: false, error: message, ...extra || {} });
46398
46528
  }
46399
46529
  function createVeskTools(deps) {
46400
- const projectDir2 = resolve29(deps.projectDir);
46401
- const appDir = resolve29(deps.appDir);
46402
- const veskDir = resolve29(deps.veskDir);
46530
+ const projectDir2 = resolve30(deps.projectDir);
46531
+ const appDir = resolve30(deps.appDir);
46532
+ const veskDir = resolve30(deps.veskDir);
46403
46533
  const tools = [
46404
46534
  // 1. vesk.inspectProject
46405
46535
  {
@@ -46412,28 +46542,28 @@ function createVeskTools(deps) {
46412
46542
  },
46413
46543
  async execute(_args) {
46414
46544
  try {
46415
- const projExists = existsSync29(projectDir2);
46545
+ const projExists = existsSync30(projectDir2);
46416
46546
  const projEntries = projExists ? readdirSync10(projectDir2, { withFileTypes: true }).map((e) => e.isDirectory() ? e.name + "/" : e.name) : [];
46417
- const appExists = existsSync29(appDir);
46547
+ const appExists = existsSync30(appDir);
46418
46548
  const appEntries = appExists ? readdirSync10(appDir, { withFileTypes: true }).map((e) => e.isDirectory() ? e.name + "/" : e.name) : [];
46419
- const veskExists = existsSync29(veskDir);
46549
+ const veskExists = existsSync30(veskDir);
46420
46550
  const veskEntries = veskExists ? readdirSync10(veskDir, { withFileTypes: true }).map((e) => e.isDirectory() ? e.name + "/" : e.name) : [];
46421
46551
  const cfgInfo = findConfigFile3(projectDir2);
46422
46552
  let configSource = null;
46423
46553
  let configExists = false;
46424
- if (cfgInfo.path && existsSync29(cfgInfo.path)) {
46554
+ if (cfgInfo.path && existsSync30(cfgInfo.path)) {
46425
46555
  configExists = true;
46426
46556
  try {
46427
- configSource = readFileSync27(cfgInfo.path, "utf-8").slice(0, 8e3);
46557
+ configSource = readFileSync28(cfgInfo.path, "utf-8").slice(0, 8e3);
46428
46558
  } catch {
46429
46559
  configSource = null;
46430
46560
  }
46431
46561
  }
46432
46562
  let packageJson = null;
46433
- const pkgPath = resolve29(projectDir2, "package.json");
46434
- if (existsSync29(pkgPath)) {
46563
+ const pkgPath = resolve30(projectDir2, "package.json");
46564
+ if (existsSync30(pkgPath)) {
46435
46565
  try {
46436
- packageJson = JSON.parse(readFileSync27(pkgPath, "utf-8"));
46566
+ packageJson = JSON.parse(readFileSync28(pkgPath, "utf-8"));
46437
46567
  } catch {
46438
46568
  packageJson = null;
46439
46569
  }
@@ -46513,7 +46643,7 @@ function createVeskTools(deps) {
46513
46643
  resolved = resolveWithin3(appDir, rel);
46514
46644
  if (!resolved)
46515
46645
  return jsonError("path escapes project root", { path: rel });
46516
- if (!existsSync29(resolved))
46646
+ if (!existsSync30(resolved))
46517
46647
  return jsonError("not found", { path: rel });
46518
46648
  const st = statSync19(resolved);
46519
46649
  if (st.isDirectory()) {
@@ -46521,7 +46651,7 @@ function createVeskTools(deps) {
46521
46651
  return jsonOk({ ok: true, path: rel, directory: true, entries: entries.slice(0, 200) });
46522
46652
  }
46523
46653
  if (st.isFile()) {
46524
- const content = readFileSync27(resolved, "utf-8");
46654
+ const content = readFileSync28(resolved, "utf-8");
46525
46655
  const capped = content.length > 2e4 ? content.slice(0, 2e4) + "\n/* truncated */" : content;
46526
46656
  return jsonOk({ ok: true, path: rel, directory: false, content: capped, size: content.length });
46527
46657
  }
@@ -46554,10 +46684,10 @@ function createVeskTools(deps) {
46554
46684
  }
46555
46685
  }
46556
46686
  const info = findConfigFile3(projectDir2);
46557
- if (!info.path || !existsSync29(info.path)) {
46687
+ if (!info.path || !existsSync30(info.path)) {
46558
46688
  return jsonOk({ ok: true, path: null, exists: false, source: "", config: {} });
46559
46689
  }
46560
- const source = readFileSync27(info.path, "utf-8");
46690
+ const source = readFileSync28(info.path, "utf-8");
46561
46691
  return jsonOk({ ok: true, path: info.path, exists: true, source, config: null });
46562
46692
  } catch (e) {
46563
46693
  return jsonError(e instanceof Error ? e.message : String(e));
@@ -46590,11 +46720,11 @@ function createVeskTools(deps) {
46590
46720
  target = info.path;
46591
46721
  const rel = target.startsWith(projectDir2 + sep6) ? target.slice(projectDir2.length + 1) : "vesk.config.ts";
46592
46722
  const contained = resolveWithin3(projectDir2, rel);
46593
- if (!contained && target !== resolve29(projectDir2, "vesk.config.ts") && target !== resolve29(projectDir2, "vesk.config.js")) {
46723
+ if (!contained && target !== resolve30(projectDir2, "vesk.config.ts") && target !== resolve30(projectDir2, "vesk.config.js")) {
46594
46724
  return jsonError("path escapes project root");
46595
46725
  }
46596
46726
  } else {
46597
- target = resolve29(projectDir2, "vesk.config.ts");
46727
+ target = resolve30(projectDir2, "vesk.config.ts");
46598
46728
  const contained = resolveWithin3(projectDir2, "vesk.config.ts");
46599
46729
  if (!contained)
46600
46730
  return jsonError("path escapes project root");
@@ -46615,7 +46745,7 @@ function createVeskTools(deps) {
46615
46745
  const contained = resolveWithin3(projectDir2, info.path.slice(projectDir2.length + 1));
46616
46746
  if (!contained)
46617
46747
  return jsonError("path escapes project root");
46618
- const current2 = readFileSync27(info.path, "utf-8");
46748
+ const current2 = readFileSync28(info.path, "utf-8");
46619
46749
  const patched = applySimpleConfigToggle(current2, key, a.value);
46620
46750
  if (patched === null)
46621
46751
  return jsonError("could not safely edit the config object; use the source editor");
@@ -46936,9 +47066,9 @@ function createVeskTools(deps) {
46936
47066
  const contained = resolveWithin3(dir, `${checkpointId}.json`);
46937
47067
  if (!contained)
46938
47068
  return jsonError("path escapes project root");
46939
- if (!existsSync29(file))
47069
+ if (!existsSync30(file))
46940
47070
  return jsonError(`checkpoint not found: ${checkpointId}`, { checkpointId });
46941
- const raw2 = readFileSync27(file, "utf-8");
47071
+ const raw2 = readFileSync28(file, "utf-8");
46942
47072
  let data2;
46943
47073
  try {
46944
47074
  data2 = JSON.parse(raw2);
@@ -46955,15 +47085,354 @@ function createVeskTools(deps) {
46955
47085
  return tools;
46956
47086
  }
46957
47087
 
47088
+ // ../adapter/dist/css.js
47089
+ init_scan();
47090
+ import { readFileSync as readFileSync29, existsSync as existsSync31 } from "node:fs";
47091
+ import { resolve as resolve31 } from "node:path";
47092
+ var TAILWIND_CSS_URL2 = "/_vesk/static/_tailwind.css";
47093
+ var GLOBAL_CSS_URL2 = "/_vesk/static/global.css";
47094
+ function resolveUserCssPath2(appDir) {
47095
+ const cssSrc = resolve31(appDir, "..", "src", "global.css");
47096
+ if (existsSync31(cssSrc))
47097
+ return cssSrc;
47098
+ const altCssSrc = resolve31(appDir, "..", "src", "app.css");
47099
+ if (existsSync31(altCssSrc))
47100
+ return altCssSrc;
47101
+ return null;
47102
+ }
47103
+ function hasUserCss2(appDir) {
47104
+ return resolveUserCssPath2(appDir) !== null;
47105
+ }
47106
+ function isTailwindPlugin2(plugins) {
47107
+ return (plugins || []).some((p) => String(p && p.name).toLowerCase().includes("tailwind"));
47108
+ }
47109
+ function resolveCssUrls2(opts) {
47110
+ const urls = [];
47111
+ if (opts.tailwind)
47112
+ urls.push(TAILWIND_CSS_URL2);
47113
+ if (opts.userCss)
47114
+ urls.push(GLOBAL_CSS_URL2);
47115
+ return urls;
47116
+ }
47117
+ function stripTailwindDirectives2(css) {
47118
+ const blockStart = /^\s*@(theme\s*\{|layer\s+(components|utilities)\s*\{|utility\s+[\w-]+\s*\{)/;
47119
+ let result2 = css.replace(/^\s*@import\s+['"]tailwindcss['"]\s*;?\s*$/gm, "");
47120
+ result2 = result2.replace(/^\s*@source\s+['"][^'"]+['"]\s*;?\s*$/gm, "");
47121
+ const output = [];
47122
+ let pos = 0;
47123
+ while (pos < result2.length) {
47124
+ const lineEnd = result2.indexOf("\n", pos) === -1 ? result2.length : result2.indexOf("\n", pos) + 1;
47125
+ const line = result2.slice(pos, lineEnd);
47126
+ if (blockStart.test(line.trim())) {
47127
+ const end = cssBlockEnd(result2, pos);
47128
+ pos = end;
47129
+ continue;
47130
+ }
47131
+ output.push(line);
47132
+ pos = lineEnd;
47133
+ }
47134
+ return output.join("").trim();
47135
+ }
47136
+
47137
+ // ../adapter/dist/hmr.js
47138
+ init_client_codegen();
47139
+ import { WebSocketServer } from "ws";
47140
+ import { readFileSync as readFileSync30, existsSync as existsSync32, writeFileSync as writeFileSync16 } from "node:fs";
47141
+ import { resolve as resolve32, dirname as dirname20 } from "node:path";
47142
+ import { fileURLToPath as fileURLToPath7 } from "node:url";
47143
+ init_paths();
47144
+
47145
+ // ../adapter/src/error-codeframe.ts
47146
+ function buildCodeframe(src2, line, column, context = 5) {
47147
+ if (typeof src2 !== "string" || src2.length === 0) return null;
47148
+ if (typeof line !== "number" || !Number.isInteger(line)) return null;
47149
+ const lines = src2.split("\n");
47150
+ if (line < 1 || line > lines.length) return null;
47151
+ const col = typeof column === "number" && Number.isInteger(column) && column >= 1 ? column : 1;
47152
+ const window2 = typeof context === "number" && Number.isFinite(context) && context >= 0 ? context : 5;
47153
+ const start = Math.max(1, line - window2);
47154
+ const end = Math.min(lines.length, line + window2);
47155
+ const code = [];
47156
+ for (let i = start; i <= end; i++) {
47157
+ code.push({ no: i, text: lines[i - 1] ?? "", isError: i === line });
47158
+ }
47159
+ return { file: "", line, column: col, context: window2, code };
47160
+ }
47161
+ var LOCATION_RE = /\((\d+):(\d+)\)/;
47162
+ function asRecord(v) {
47163
+ if (typeof v === "object" && v !== null) return v;
47164
+ return null;
47165
+ }
47166
+ function asNumber(v) {
47167
+ if (typeof v === "number" && Number.isFinite(v)) return Math.trunc(v);
47168
+ return null;
47169
+ }
47170
+ function parseEmbeddedLocation(message) {
47171
+ const m = message.match(LOCATION_RE);
47172
+ if (!m) return null;
47173
+ const line = parseInt(m[1], 10);
47174
+ const column = parseInt(m[2], 10);
47175
+ if (!Number.isFinite(line) || !Number.isFinite(column)) return null;
47176
+ return { line, column: column + 1 };
47177
+ }
47178
+ function parseCompilerError(err, file, src2) {
47179
+ if (err === void 0 || err === null) return null;
47180
+ const record = asRecord(err);
47181
+ let message;
47182
+ let stack = null;
47183
+ if (record && typeof record.message === "string") {
47184
+ message = record.message;
47185
+ if (typeof record.stack === "string") stack = record.stack;
47186
+ } else if (typeof err === "string") {
47187
+ message = err;
47188
+ } else {
47189
+ try {
47190
+ message = String(err);
47191
+ } catch {
47192
+ message = "Unknown compiler error";
47193
+ }
47194
+ const asAny = err;
47195
+ if (asAny && typeof asAny.stack === "string") stack = asAny.stack;
47196
+ }
47197
+ let line = null;
47198
+ let column = null;
47199
+ let fileResolved = typeof file === "string" ? file : "";
47200
+ if (record) {
47201
+ const loc = asRecord(record.loc);
47202
+ if (loc) {
47203
+ const ln = asNumber(loc.line);
47204
+ if (ln !== null) {
47205
+ line = ln;
47206
+ const rawCol = asNumber(loc.column);
47207
+ column = rawCol !== null ? rawCol + 1 : 1;
47208
+ }
47209
+ }
47210
+ if (line === null) {
47211
+ const pos = asRecord(record.position);
47212
+ if (pos) {
47213
+ const ln = asNumber(pos.line);
47214
+ if (ln !== null) {
47215
+ line = ln;
47216
+ const rawCol = asNumber(pos.column);
47217
+ column = rawCol !== null ? rawCol + 1 : 1;
47218
+ }
47219
+ }
47220
+ }
47221
+ if (line === null) {
47222
+ const ln = asNumber(record.line);
47223
+ if (ln !== null && ln > 0) {
47224
+ line = ln;
47225
+ const rawCol = asNumber(record.column);
47226
+ if (rawCol !== null) column = rawCol;
47227
+ }
47228
+ }
47229
+ if (typeof record.file === "string" && record.file) fileResolved = record.file;
47230
+ }
47231
+ if (line === null) {
47232
+ const embedded = parseEmbeddedLocation(message);
47233
+ if (embedded) {
47234
+ line = embedded.line;
47235
+ column = embedded.column;
47236
+ }
47237
+ }
47238
+ let codeframe = null;
47239
+ if (src2 !== void 0 && typeof src2 === "string" && src2.length > 0 && line !== null) {
47240
+ codeframe = buildCodeframe(src2, line, column ?? 1);
47241
+ if (codeframe) codeframe.file = fileResolved;
47242
+ }
47243
+ return {
47244
+ file: fileResolved,
47245
+ line,
47246
+ column,
47247
+ message,
47248
+ stack,
47249
+ codeframe
47250
+ };
47251
+ }
47252
+
47253
+ // ../adapter/src/error-tips.ts
47254
+ var RUNTIME_AUTOIMPORTS = "effect, derived, untrack, peek, tick, flushSync, on_destroy, createContext";
47255
+ var SYNTAX_KINDS = ["Unexpected token", "Parse error", "SyntaxError"];
47256
+ var MODULE_KINDS = ["Cannot find module", "Cannot load module", "Module not found"];
47257
+ var NULL_DEREF_KINDS = ["Cannot read properties of", "Cannot read property"];
47258
+ var rules = [
47259
+ {
47260
+ match: (m) => m.includes("is not defined"),
47261
+ build: () => ({
47262
+ tips: [
47263
+ "The name was referenced before it was imported or declared in this file, so the compiler treated it as undeclared."
47264
+ ],
47265
+ suggestions: [
47266
+ `Vesk auto-imports the reactive helpers from @vesk/runtime (${RUNTIME_AUTOIMPORTS}); note that \`batch\` does NOT exist \u2014 never import it.`
47267
+ ],
47268
+ nextSteps: [
47269
+ "Check the spelling, add an explicit import for the name, or declare it as a binding before use."
47270
+ ]
47271
+ })
47272
+ },
47273
+ {
47274
+ match: (m) => SYNTAX_KINDS.some((k) => m.includes(k)),
47275
+ build: () => ({
47276
+ tips: ["The parser hit a token it could not place in the current context."],
47277
+ suggestions: [
47278
+ "Statement mode accepts bare JSX plus if/for/while/switch/try \u2014 no return statement needed; expression mode requires `return <jsx>;`."
47279
+ ],
47280
+ nextSteps: [
47281
+ "Check the line under the ^ marker for missing brackets, quotes, or unclosed JSX tags, then fix and re-save."
47282
+ ]
47283
+ })
47284
+ },
47285
+ {
47286
+ match: (m) => MODULE_KINDS.some((k) => m.includes(k)),
47287
+ build: () => ({
47288
+ tips: ["An import path could not be resolved from this file."],
47289
+ suggestions: ["Check the specifier spelling and the relative path (./ vs ../) in the import statement."],
47290
+ nextSteps: [
47291
+ "Install the missing dependency or create the file at the expected path, then restart the dev server."
47292
+ ]
47293
+ })
47294
+ },
47295
+ {
47296
+ match: (m) => m.toLowerCase().includes("unterminated"),
47297
+ build: () => ({
47298
+ tips: ["A string or template literal was opened earlier in the file and never closed."],
47299
+ suggestions: ["Look for a missing closing quote or backtick on the line just above the marker."],
47300
+ nextSteps: [
47301
+ "Close the literal; to span lines, open it with a backtick and use ${expr} for interpolation."
47302
+ ]
47303
+ })
47304
+ },
47305
+ {
47306
+ match: (m) => m.includes("is not a function") || m.includes("undefined is not"),
47307
+ build: () => ({
47308
+ tips: ["The value being called is not callable \u2014 often undefined, null, or the wrong import."],
47309
+ suggestions: ["Check that you imported the function itself and used the correct export name."],
47310
+ nextSteps: [
47311
+ "Guard the call (typeof x === 'function' && x()) or trace where the value is assigned before invoking it."
47312
+ ]
47313
+ })
47314
+ },
47315
+ {
47316
+ match: (m) => NULL_DEREF_KINDS.some((k) => m.includes(k)) || m.includes(" of null") || m.includes(" of undefined"),
47317
+ build: () => ({
47318
+ tips: ["A property was read on null or undefined at the marked line."],
47319
+ suggestions: ["Guard the access with optional chaining (obj?.prop) or a default value (const x = data ?? {})."],
47320
+ nextSteps: [
47321
+ "Trace where the value is set \u2014 async data may not have arrived when the component first renders."
47322
+ ]
47323
+ })
47324
+ }
47325
+ ];
47326
+ var FALLBACK = {
47327
+ tips: ["The compiler reported an error in this file but no rule matched its message text."],
47328
+ suggestions: [
47329
+ "Verify imports and that every referenced name is declared \u2014 and check the body in both statement mode (bare JSX, if/for/while/switch/try) and expression mode (return <jsx>)."
47330
+ ],
47331
+ nextSteps: [
47332
+ "Look for a fuller error message printed above this one.",
47333
+ "Restart the dev server if the error persists after the fix."
47334
+ ]
47335
+ };
47336
+ function suggestFor(message) {
47337
+ if (typeof message !== "string") return FALLBACK;
47338
+ for (const rule of rules) {
47339
+ if (rule.match(message)) return rule.build(message);
47340
+ }
47341
+ return FALLBACK;
47342
+ }
47343
+
47344
+ // ../adapter/dist/hmr.js
47345
+ var __dirname8 = dirname20(fileURLToPath7(import.meta.url));
47346
+ function buildErrorPayload(error, filename, opts = {}) {
47347
+ const file = typeof filename === "string" && filename ? filename : "unknown";
47348
+ const parsed = parseCompilerError(error, file);
47349
+ const fallbackMessage = error instanceof Error ? error.message : typeof error === "string" ? error : (() => {
47350
+ try {
47351
+ return String(error);
47352
+ } catch {
47353
+ return "Unknown error";
47354
+ }
47355
+ })();
47356
+ const message = parsed && parsed.message ? parsed.message : fallbackMessage;
47357
+ const line = parsed ? parsed.line : null;
47358
+ const column = parsed ? parsed.column : null;
47359
+ const stack = parsed && typeof parsed.stack === "string" && parsed.stack ? parsed.stack : error instanceof Error && error.stack ? error.stack : void 0;
47360
+ let codeframe;
47361
+ if (line !== null && line >= 1 && typeof opts.appDir === "string") {
47362
+ let src2;
47363
+ try {
47364
+ const absPath = resolve32(opts.appDir, file);
47365
+ if (existsSync32(absPath))
47366
+ src2 = readFileSync30(absPath, "utf-8");
47367
+ } catch {
47368
+ src2 = void 0;
47369
+ }
47370
+ if (typeof src2 === "string" && src2.length > 0) {
47371
+ const cf = buildCodeframe(src2, line, column ?? 1);
47372
+ if (cf) {
47373
+ cf.file = file;
47374
+ codeframe = cf;
47375
+ }
47376
+ }
47377
+ }
47378
+ const tipsData = suggestFor(message);
47379
+ const filePath = typeof opts.appDir === "string" ? resolve32(opts.appDir, file) : void 0;
47380
+ const cleanMessage = filePath && message.endsWith(` in ${filePath}`) ? message.slice(0, -` in ${filePath}`.length).trim() : message.endsWith(` in ${file}`) ? message.slice(0, -` in ${file}`.length).trim() : message;
47381
+ const payload = {
47382
+ file,
47383
+ line,
47384
+ column,
47385
+ message: cleanMessage
47386
+ };
47387
+ if (filePath)
47388
+ payload.filePath = filePath;
47389
+ if (codeframe)
47390
+ payload.codeframe = codeframe;
47391
+ if (tipsData.tips && tipsData.tips.length)
47392
+ payload.tips = tipsData.tips;
47393
+ if (tipsData.suggestions && tipsData.suggestions.length)
47394
+ payload.suggestions = tipsData.suggestions;
47395
+ if (tipsData.nextSteps && tipsData.nextSteps.length)
47396
+ payload.nextSteps = tipsData.nextSteps;
47397
+ if (stack)
47398
+ payload.stack = stack;
47399
+ if (opts.extra) {
47400
+ for (const [k, v] of Object.entries(opts.extra)) {
47401
+ payload[k] = v;
47402
+ }
47403
+ }
47404
+ return payload;
47405
+ }
47406
+
47407
+ // ../adapter/dist/error-codeframe.js
47408
+ function buildCodeframe2(src2, line, column, context = 5) {
47409
+ if (typeof src2 !== "string" || src2.length === 0)
47410
+ return null;
47411
+ if (typeof line !== "number" || !Number.isInteger(line))
47412
+ return null;
47413
+ const lines = src2.split("\n");
47414
+ if (line < 1 || line > lines.length)
47415
+ return null;
47416
+ const col = typeof column === "number" && Number.isInteger(column) && column >= 1 ? column : 1;
47417
+ const window2 = typeof context === "number" && Number.isFinite(context) && context >= 0 ? context : 5;
47418
+ const start = Math.max(1, line - window2);
47419
+ const end = Math.min(lines.length, line + window2);
47420
+ const code = [];
47421
+ for (let i = start; i <= end; i++) {
47422
+ code.push({ no: i, text: lines[i - 1] ?? "", isError: i === line });
47423
+ }
47424
+ return { file: "", line, column: col, context: window2, code };
47425
+ }
47426
+
46958
47427
  // src/build-packages.ts
46959
47428
  import { spawnSync } from "node:child_process";
46960
- import { cpSync, existsSync as existsSync30, mkdirSync as mkdirSync13, readFileSync as readFileSync28, readdirSync as readdirSync11, statSync as statSync20, writeFileSync as writeFileSync16 } from "node:fs";
47429
+ import { cpSync, existsSync as existsSync33, mkdirSync as mkdirSync13, readFileSync as readFileSync31, readdirSync as readdirSync11, statSync as statSync20, writeFileSync as writeFileSync17 } from "node:fs";
46961
47430
  import { createRequire as createRequire5 } from "node:module";
46962
- import { dirname as dirname20, join as join17, resolve as resolve30 } from "node:path";
46963
- import { fileURLToPath as fileURLToPath7 } from "node:url";
47431
+ import { dirname as dirname21, join as join17, resolve as resolve33 } from "node:path";
47432
+ import { fileURLToPath as fileURLToPath8 } from "node:url";
46964
47433
  var require2 = createRequire5(import.meta.url);
46965
- var __dirname8 = dirname20(fileURLToPath7(import.meta.url));
46966
- var root2 = resolve30(__dirname8, "..", "..", "..");
47434
+ var __dirname9 = dirname21(fileURLToPath8(import.meta.url));
47435
+ var root2 = resolve33(__dirname9, "..", "..", "..");
46967
47436
  var PACKAGES = {
46968
47437
  // types first — it is a dependency-free leaf that compiler and adapter
46969
47438
  // import for their shared type definitions.
@@ -46995,9 +47464,9 @@ function newestSourceMtime(srcDir) {
46995
47464
  }
46996
47465
  function distStale(pkgDir, entry) {
46997
47466
  const distIndex = join17(pkgDir, "dist", `${entry}.js`);
46998
- if (!existsSync30(distIndex)) return true;
47467
+ if (!existsSync33(distIndex)) return true;
46999
47468
  const distPkg = join17(pkgDir, "dist", "package.json");
47000
- const distStamp = Math.max(statSync20(distIndex).mtimeMs, existsSync30(distPkg) ? statSync20(distPkg).mtimeMs : 0);
47469
+ const distStamp = Math.max(statSync20(distIndex).mtimeMs, existsSync33(distPkg) ? statSync20(distPkg).mtimeMs : 0);
47001
47470
  return newestSourceMtime(join17(pkgDir, "src")) > distStamp;
47002
47471
  }
47003
47472
  function distPackageJson(pkgName, entry, serverEntry, version2) {
@@ -47021,8 +47490,8 @@ function distPackageJson(pkgName, entry, serverEntry, version2) {
47021
47490
  }
47022
47491
  function buildPackages(force = false) {
47023
47492
  for (const [pkg, cfg] of Object.entries(PACKAGES)) {
47024
- const pkgDir = resolve30(root2, "packages", pkg);
47025
- if (!existsSync30(join17(pkgDir, "src"))) continue;
47493
+ const pkgDir = resolve33(root2, "packages", pkg);
47494
+ if (!existsSync33(join17(pkgDir, "src"))) continue;
47026
47495
  if (!force && !distStale(pkgDir, cfg.entry)) continue;
47027
47496
  console.log(`[build] ${cfg.name} -> tsc`);
47028
47497
  const tscBin = require2.resolve("typescript/bin/tsc");
@@ -47035,10 +47504,10 @@ function buildPackages(force = false) {
47035
47504
  const distDir = join17(pkgDir, "dist");
47036
47505
  for (const c of cfg.copy || []) {
47037
47506
  const to = join17(distDir, c.to);
47038
- mkdirSync13(dirname20(to), { recursive: true });
47507
+ mkdirSync13(dirname21(to), { recursive: true });
47039
47508
  cpSync(join17(pkgDir, c.from), to, { recursive: true });
47040
47509
  }
47041
- const srcPkg = JSON.parse(readFileSync28(join17(pkgDir, "package.json"), "utf-8"));
47510
+ const srcPkg = JSON.parse(readFileSync31(join17(pkgDir, "package.json"), "utf-8"));
47042
47511
  if (pkg === "lucide-vesk") {
47043
47512
  const lucideDistPkg = {
47044
47513
  name: srcPkg.name,
@@ -47052,9 +47521,9 @@ function buildPackages(force = false) {
47052
47521
  "./package.json": "./package.json"
47053
47522
  }
47054
47523
  };
47055
- writeFileSync16(join17(distDir, "package.json"), JSON.stringify(lucideDistPkg, null, 2) + "\n");
47524
+ writeFileSync17(join17(distDir, "package.json"), JSON.stringify(lucideDistPkg, null, 2) + "\n");
47056
47525
  } else {
47057
- writeFileSync16(join17(distDir, "package.json"), distPackageJson(cfg.name, cfg.entry, cfg.serverEntry, srcPkg.version || "1.0.0"));
47526
+ writeFileSync17(join17(distDir, "package.json"), distPackageJson(cfg.name, cfg.entry, cfg.serverEntry, srcPkg.version || "1.0.0"));
47058
47527
  }
47059
47528
  console.log(`[build] ${cfg.name} -> dist`);
47060
47529
  }
@@ -47062,13 +47531,13 @@ function buildPackages(force = false) {
47062
47531
  function ensurePackagesBuilt() {
47063
47532
  buildPackages(false);
47064
47533
  }
47065
- if (process.argv[1] && resolve30(process.argv[1]) === fileURLToPath7(import.meta.url)) {
47534
+ if (process.argv[1] && resolve33(process.argv[1]) === fileURLToPath8(import.meta.url)) {
47066
47535
  buildPackages(process.argv.includes("--force"));
47067
47536
  }
47068
47537
 
47069
47538
  // src/action-handler.ts
47070
- import { existsSync as existsSync31, readFileSync as readFileSync29, readdirSync as readdirSync12 } from "node:fs";
47071
- import { resolve as resolve31, join as join18 } from "node:path";
47539
+ import { existsSync as existsSync34, readFileSync as readFileSync32, readdirSync as readdirSync12 } from "node:fs";
47540
+ import { resolve as resolve34, join as join18 } from "node:path";
47072
47541
 
47073
47542
  // ../compiler/dist/server-cookies.js
47074
47543
  function parseCookies3(str3) {
@@ -47101,8 +47570,8 @@ function getAction2(id) {
47101
47570
  function validateActionInput2(def, input) {
47102
47571
  const issues = [];
47103
47572
  for (const [field, ruleOrRules] of Object.entries(def.input || {})) {
47104
- const rules = Array.isArray(ruleOrRules) ? ruleOrRules : [ruleOrRules];
47105
- for (const rule of rules) {
47573
+ const rules2 = Array.isArray(ruleOrRules) ? ruleOrRules : [ruleOrRules];
47574
+ for (const rule of rules2) {
47106
47575
  if (rule && !rule.validate(input[field])) {
47107
47576
  issues.push({ field, message: rule.message });
47108
47577
  break;
@@ -47122,21 +47591,21 @@ function issuesToFieldMap2(issues) {
47122
47591
 
47123
47592
  // src/action-handler.ts
47124
47593
  function actionCssUrls(appDirPath) {
47594
+ let tailwind = true;
47125
47595
  try {
47126
- const veskDir = join18(resolve31(appDirPath, ".."), ".vesk");
47596
+ const veskDir = join18(resolve34(appDirPath, ".."), ".vesk");
47127
47597
  const statePath = join18(veskDir, "plugins.json");
47128
- if (existsSync31(statePath)) {
47129
- const raw2 = readFileSync29(statePath, "utf-8");
47598
+ if (existsSync34(statePath)) {
47599
+ const raw2 = readFileSync32(statePath, "utf-8");
47130
47600
  const state = JSON.parse(raw2);
47131
47601
  const entries = state?.plugins || [];
47132
- const inactiveTailwind = entries.some(
47602
+ tailwind = !entries.some(
47133
47603
  (p) => String(p.name).toLowerCase().includes("tailwind") && p.active === false
47134
47604
  );
47135
- if (inactiveTailwind) return ["/_vesk/static/global.css"];
47136
47605
  }
47137
47606
  } catch {
47138
47607
  }
47139
- return ["/_vesk/static/_tailwind.css", "/_vesk/static/global.css"];
47608
+ return resolveCssUrls2({ tailwind, userCss: hasUserCss2(appDirPath) });
47140
47609
  }
47141
47610
  function actionCssLinkTags(appDirPath) {
47142
47611
  return actionCssUrls(appDirPath).map((u) => ` <link rel="stylesheet" href="${u}" />`).join("\n") + "\n";
@@ -47165,8 +47634,8 @@ function pageSourcesFor(appDirPath, routeTree) {
47165
47634
  const out = [];
47166
47635
  function walk6(nodes) {
47167
47636
  for (const node of nodes) {
47168
- if (node.page) out.push(resolve31(appDirPath, node.sourceDir, "page.vsk"));
47169
- if (node.layout) out.push(resolve31(appDirPath, node.sourceDir, "layout.vsk"));
47637
+ if (node.page) out.push(resolve34(appDirPath, node.sourceDir, "page.vsk"));
47638
+ if (node.layout) out.push(resolve34(appDirPath, node.sourceDir, "layout.vsk"));
47170
47639
  walk6(node.children);
47171
47640
  }
47172
47641
  }
@@ -47174,7 +47643,7 @@ function pageSourcesFor(appDirPath, routeTree) {
47174
47643
  return out;
47175
47644
  }
47176
47645
  function walkVskFiles(dir, out, seen) {
47177
- if (!existsSync31(dir)) return;
47646
+ if (!existsSync34(dir)) return;
47178
47647
  let entries;
47179
47648
  try {
47180
47649
  entries = readdirSync12(dir, { withFileTypes: true });
@@ -47182,7 +47651,7 @@ function walkVskFiles(dir, out, seen) {
47182
47651
  return;
47183
47652
  }
47184
47653
  for (const entry of entries) {
47185
- const full = resolve31(dir, entry.name);
47654
+ const full = resolve34(dir, entry.name);
47186
47655
  if (seen.has(full)) continue;
47187
47656
  seen.add(full);
47188
47657
  if (entry.isDirectory()) {
@@ -47202,16 +47671,16 @@ function candidateSources(appDirPath, routeTree) {
47202
47671
  seen.add(src2);
47203
47672
  out.push(src2);
47204
47673
  }
47205
- const projectRoot = resolve31(appDirPath, "..");
47206
- for (const dir of [resolve31(projectRoot, "components"), appDirPath, projectRoot]) {
47674
+ const projectRoot = resolve34(appDirPath, "..");
47675
+ for (const dir of [resolve34(projectRoot, "components"), appDirPath, projectRoot]) {
47207
47676
  walkVskFiles(dir, out, seen);
47208
47677
  }
47209
47678
  return out;
47210
47679
  }
47211
47680
  function registerSource(sourcePath2) {
47212
- if (!existsSync31(sourcePath2)) return;
47681
+ if (!existsSync34(sourcePath2)) return;
47213
47682
  try {
47214
- compileFile(readFileSync29(sourcePath2, "utf-8"), { sourcePath: sourcePath2 });
47683
+ compileFile(readFileSync32(sourcePath2, "utf-8"), { sourcePath: sourcePath2 });
47215
47684
  } catch {
47216
47685
  }
47217
47686
  }
@@ -47220,8 +47689,8 @@ function ensureActionRegistered(actionId, pagePathname, appDirPath, routeTree) {
47220
47689
  const match = matchUrl(routeTree, pagePathname);
47221
47690
  if (match) {
47222
47691
  for (let i = match.nodes.length - 1; i >= 0; i--) {
47223
- registerSource(resolve31(appDirPath, match.nodes[i].sourceDir, "page.vsk"));
47224
- registerSource(resolve31(appDirPath, match.nodes[i].sourceDir, "layout.vsk"));
47692
+ registerSource(resolve34(appDirPath, match.nodes[i].sourceDir, "page.vsk"));
47693
+ registerSource(resolve34(appDirPath, match.nodes[i].sourceDir, "layout.vsk"));
47225
47694
  }
47226
47695
  }
47227
47696
  if (getAction2(actionId)) return;
@@ -47247,32 +47716,35 @@ async function renderPageHtml(pagePathname, params, ctx2) {
47247
47716
  let head = "";
47248
47717
  for (let i = chain.length - 1; i >= 0; i--) {
47249
47718
  const node = chain[i];
47250
- const pageFilePath = resolve31(ctx2.appDirPath, node.sourceDir, "page.vsk");
47251
- const layoutFilePath = resolve31(ctx2.appDirPath, node.sourceDir, "layout.vsk");
47252
- if (i === chain.length - 1 && node.page && existsSync31(pageFilePath)) {
47253
- const src3 = readFileSync29(pageFilePath, "utf-8");
47719
+ const pageFilePath = resolve34(ctx2.appDirPath, node.sourceDir, "page.vsk");
47720
+ const layoutFilePath = resolve34(ctx2.appDirPath, node.sourceDir, "layout.vsk");
47721
+ if (i === chain.length - 1 && node.page && existsSync34(pageFilePath)) {
47722
+ const src3 = readFileSync32(pageFilePath, "utf-8");
47254
47723
  const compName2 = resolveComponentName(src3) || node.page;
47255
47724
  const result2 = await renderPage(src3, compName2, { params }, /* @__PURE__ */ new Map(), { hydrate: true, sourcePath: pageFilePath });
47256
47725
  body = result2.body;
47257
47726
  head = result2.head || "";
47258
47727
  }
47259
- if (node.layout && existsSync31(layoutFilePath)) {
47260
- const src3 = readFileSync29(layoutFilePath, "utf-8");
47728
+ if (node.layout && existsSync34(layoutFilePath)) {
47729
+ const src3 = readFileSync32(layoutFilePath, "utf-8");
47261
47730
  const compName2 = resolveComponentName(src3) || node.layout;
47262
47731
  const result2 = await renderPage(src3, compName2, { children: body }, /* @__PURE__ */ new Map(), { hydrate: true, sourcePath: layoutFilePath });
47263
47732
  body = result2.body;
47264
47733
  head = (result2.head || "") + head;
47265
47734
  }
47266
47735
  }
47267
- const hasLayout = chain.some((n) => n.layout && existsSync31(resolve31(ctx2.appDirPath, n.sourceDir, "layout.vsk")));
47736
+ const hasLayout = chain.some((n) => n.layout && existsSync34(resolve34(ctx2.appDirPath, n.sourceDir, "layout.vsk")));
47268
47737
  if (hasLayout) {
47269
47738
  const secMeta = securityMeta(ctx2.security);
47270
- return `<!DOCTYPE html>
47739
+ const headBlock = await applyHeadInjects(
47740
+ ' <meta charset="utf-8" />\n <meta name="viewport" content="width=device-width, initial-scale=1" />\n' + actionCssLinkTags(ctx2.appDirPath) + secMeta + (head ? " " + head.split("\n").join("\n ") + "\n" : ""),
47741
+ { plugins: ctx2.plugins },
47742
+ { sourcePath: ctx2.url.pathname }
47743
+ );
47744
+ const fullHtml = `<!DOCTYPE html>
47271
47745
  <html>
47272
47746
  <head>
47273
- <meta charset="utf-8" />
47274
- <meta name="viewport" content="width=device-width, initial-scale=1" />
47275
- ${actionCssLinkTags(ctx2.appDirPath)}${secMeta}${head ? " " + head.split("\n").join("\n ") + "\n" : ""}</head>
47747
+ ${headBlock}</head>
47276
47748
  <body>
47277
47749
  <div id="root">
47278
47750
  ${prettifyHtml(body)}
@@ -47281,13 +47753,14 @@ ${prettifyHtml(body)}
47281
47753
  <script type="module" src="/_vesk/hmr.js"></script>
47282
47754
  </body>
47283
47755
  </html>`;
47756
+ return applyHtmlPlugins(fullHtml, ctx2.plugins, { sourcePath: ctx2.url.pathname });
47284
47757
  }
47285
47758
  const leaf = chain.find((n) => n.page);
47286
47759
  if (!leaf) return null;
47287
- const src2 = readFileSync29(resolve31(ctx2.appDirPath, leaf.sourceDir, "page.vsk"), "utf-8");
47760
+ const src2 = readFileSync32(resolve34(ctx2.appDirPath, leaf.sourceDir, "page.vsk"), "utf-8");
47288
47761
  const compName = resolveComponentName(src2) || leaf.page;
47289
- const html = await renderFullPage(src2, compName, { params }, /* @__PURE__ */ new Map(), { hydrate: true, clientScriptUrl: "/_vesk/client.js", cssUrls: actionCssUrls(ctx2.appDirPath), security: ctx2.security, sourcePath: resolve31(ctx2.appDirPath, leaf.sourceDir, "page.vsk") });
47290
- return html.replace("</body>", ' <script type="module" src="/_vesk/hmr.js"></script>\n</body>');
47762
+ const html = await renderFullPage(src2, compName, { params }, /* @__PURE__ */ new Map(), { hydrate: true, clientScriptUrl: "/_vesk/client.js", cssUrls: actionCssUrls(ctx2.appDirPath), security: ctx2.security, sourcePath: resolve34(ctx2.appDirPath, leaf.sourceDir, "page.vsk"), plugins: ctx2.plugins });
47763
+ return applyHtmlPlugins(html.replace("</body>", ' <script type="module" src="/_vesk/hmr.js"></script>\n</body>'), ctx2.plugins, { sourcePath: ctx2.url.pathname });
47291
47764
  }
47292
47765
  async function handleActionRequest(req, res, ctx2) {
47293
47766
  const { url, appDirPath, routeTree } = ctx2;
@@ -47428,17 +47901,54 @@ async function handleActionRequest(req, res, ctx2) {
47428
47901
 
47429
47902
  // src/dev-server.ts
47430
47903
  var agenticCheckpointManager = new CheckpointManager();
47904
+ function buildDevErrorPayload(input) {
47905
+ const { err, errorMessage, filename, fullPath, appDir, fileExists } = input;
47906
+ const payload = buildErrorPayload(err ?? new Error(errorMessage), filename, { appDir });
47907
+ const errDetails = err && typeof err === "object" ? err : void 0;
47908
+ if (errDetails?.name === "VeskError") {
47909
+ if (Array.isArray(errDetails.suggestions) && errDetails.suggestions.length) {
47910
+ payload.suggestions = errDetails.suggestions;
47911
+ }
47912
+ if (Array.isArray(errDetails.nextSteps) && errDetails.nextSteps.length) {
47913
+ payload.nextSteps = errDetails.nextSteps;
47914
+ }
47915
+ if (typeof errDetails.tip === "string" && errDetails.tip) {
47916
+ payload.tips = [errDetails.tip, ...payload.tips || []];
47917
+ }
47918
+ }
47919
+ if (payload.line === null && payload.column === null) {
47920
+ const lineMatch = errorMessage.match(/(?:line|at\s+line)\s*(\d+)/i);
47921
+ const colMatch = errorMessage.match(/(?:column|col)\s*(\d+)/i);
47922
+ if (lineMatch) {
47923
+ payload.line = parseInt(lineMatch[1], 10);
47924
+ payload.column = colMatch ? parseInt(colMatch[1], 10) : 1;
47925
+ if (fileExists && payload.line > 0) {
47926
+ try {
47927
+ const src2 = readFileSync33(fullPath, "utf-8");
47928
+ const cf = buildCodeframe2(src2, payload.line, payload.column);
47929
+ if (cf) {
47930
+ cf.file = payload.file || filename;
47931
+ payload.codeframe = cf;
47932
+ }
47933
+ } catch {
47934
+ }
47935
+ }
47936
+ }
47937
+ }
47938
+ if (!payload.message) payload.message = errorMessage || "Unknown error";
47939
+ return payload;
47940
+ }
47431
47941
  function resolveRuntimeDir(projectDir2) {
47432
47942
  const candidates = [
47433
47943
  // installed app layout
47434
- resolve32(projectDir2, "node_modules", "@vesk", "runtime"),
47944
+ resolve35(projectDir2, "node_modules", "@vesk", "runtime"),
47435
47945
  // monorepo checkout (tests/probes run from the repo root)
47436
- resolve32(import.meta.dirname ?? ".", "..", "..", "runtime", "dist")
47946
+ resolve35(import.meta.dirname ?? ".", "..", "..", "runtime", "dist")
47437
47947
  ];
47438
47948
  for (const dir of candidates) {
47439
- if (existsSync32(join19(dir, "ripple-runtime.js"))) return dir;
47949
+ if (existsSync35(join19(dir, "ripple-runtime.js"))) return dir;
47440
47950
  const distDir = join19(dir, "dist");
47441
- if (existsSync32(join19(distDir, "ripple-runtime.js"))) return distDir;
47951
+ if (existsSync35(join19(distDir, "ripple-runtime.js"))) return distDir;
47442
47952
  }
47443
47953
  return null;
47444
47954
  }
@@ -47588,7 +48098,7 @@ function collectRoutePaths(nodes, out = []) {
47588
48098
  return out;
47589
48099
  }
47590
48100
  function countFilesNamed(dir, name) {
47591
- if (!existsSync32(dir)) return 0;
48101
+ if (!existsSync35(dir)) return 0;
47592
48102
  let n = 0;
47593
48103
  for (const entry of readdirSync13(dir, { withFileTypes: true })) {
47594
48104
  const p = join19(dir, entry.name);
@@ -47629,13 +48139,13 @@ async function startDevServer(port2, projectDir2, config, host2) {
47629
48139
  }
47630
48140
  }
47631
48141
  function isTailwindActive() {
47632
- return getActiveDevPlugins().some((p) => String(p.name).toLowerCase().includes("tailwind"));
48142
+ return isTailwindPlugin2(getActiveDevPlugins());
47633
48143
  }
47634
48144
  function activeCssUrls() {
47635
- const urls = [];
47636
- if (isTailwindActive()) urls.push("/_vesk/static/_tailwind.css");
47637
- urls.push("/_vesk/static/global.css");
47638
- return urls;
48145
+ return resolveCssUrls2({
48146
+ tailwind: isTailwindActive(),
48147
+ userCss: hasUserCss2(appDirPath)
48148
+ });
47639
48149
  }
47640
48150
  function cssLinkTags() {
47641
48151
  return activeCssUrls().map((u) => ` <link rel="stylesheet" href="${u}" />`).join("\n") + "\n";
@@ -47648,10 +48158,10 @@ async function startDevServer(port2, projectDir2, config, host2) {
47648
48158
  const cssPath = join19(srcDir, "global.css");
47649
48159
  const altCssPath = join19(srcDir, "app.css");
47650
48160
  let rawCss = "";
47651
- if (existsSync32(cssPath)) {
47652
- rawCss = readFileSync30(cssPath, "utf-8");
47653
- } else if (existsSync32(altCssPath)) {
47654
- rawCss = readFileSync30(altCssPath, "utf-8");
48161
+ if (existsSync35(cssPath)) {
48162
+ rawCss = readFileSync33(cssPath, "utf-8");
48163
+ } else if (existsSync35(altCssPath)) {
48164
+ rawCss = readFileSync33(altCssPath, "utf-8");
47655
48165
  }
47656
48166
  if (rawCss) {
47657
48167
  const activeAtStart = getActiveDevPlugins();
@@ -47660,7 +48170,7 @@ async function startDevServer(port2, projectDir2, config, host2) {
47660
48170
  await plugin.onBuildStart();
47661
48171
  }
47662
48172
  }
47663
- devUserCssContent = stripTailwindDirectives(rawCss);
48173
+ devUserCssContent = stripTailwindDirectives2(rawCss);
47664
48174
  if (!isTailwindActive()) {
47665
48175
  devTailwindCssContent = "";
47666
48176
  } else {
@@ -47740,7 +48250,19 @@ async function startDevServer(port2, projectDir2, config, host2) {
47740
48250
  return { err: e, editedSource: null, actualName: null };
47741
48251
  }
47742
48252
  }
47743
- await buildClientBundle();
48253
+ let devLastBuildMs = null;
48254
+ let devLastError = null;
48255
+ const devDiagnostics = [];
48256
+ function recordDiagnostic(finding) {
48257
+ devDiagnostics.unshift(finding);
48258
+ if (devDiagnostics.length > 50) devDiagnostics.length = 50;
48259
+ }
48260
+ try {
48261
+ await buildClientBundle();
48262
+ } catch (e) {
48263
+ devLastError = { file: "", line: null, column: null, message: e.message };
48264
+ LOG.warn(`dev server started with an app compile error: ${e.message}`);
48265
+ }
47744
48266
  await bundleRuntime2();
47745
48267
  const sourceToComponents = /* @__PURE__ */ new Map();
47746
48268
  function updateSourceMapping() {
@@ -47752,13 +48274,6 @@ async function startDevServer(port2, projectDir2, config, host2) {
47752
48274
  }
47753
48275
  }
47754
48276
  updateSourceMapping();
47755
- let devLastBuildMs = null;
47756
- let devLastError = null;
47757
- const devDiagnostics = [];
47758
- function recordDiagnostic(finding) {
47759
- devDiagnostics.unshift(finding);
47760
- if (devDiagnostics.length > 50) devDiagnostics.length = 50;
47761
- }
47762
48277
  async function fullRebuild() {
47763
48278
  const t0 = Date.now();
47764
48279
  try {
@@ -47775,7 +48290,7 @@ async function startDevServer(port2, projectDir2, config, host2) {
47775
48290
  return { ok: true, ms: devLastBuildMs ?? 0 };
47776
48291
  } catch (e) {
47777
48292
  const err = e instanceof Error ? e : new Error(String(e));
47778
- devLastError = { message: err.message };
48293
+ devLastError = { file: "", line: null, column: null, message: err.message };
47779
48294
  recordDiagnostic({ severity: "error", code: "BUILD", file: null, message: err.message, hint: "Fix the failing file; HMR will reload on save." });
47780
48295
  return { ok: false, error: err.message, ms: Date.now() - t0 };
47781
48296
  }
@@ -47866,7 +48381,7 @@ async function startDevServer(port2, projectDir2, config, host2) {
47866
48381
  async function rebuildTailwindCss() {
47867
48382
  if (!rawCss) return false;
47868
48383
  try {
47869
- const nextUser = stripTailwindDirectives(rawCss);
48384
+ const nextUser = stripTailwindDirectives2(rawCss);
47870
48385
  let nextTailwind;
47871
48386
  if (!isTailwindActive()) {
47872
48387
  nextTailwind = "";
@@ -47901,7 +48416,7 @@ async function startDevServer(port2, projectDir2, config, host2) {
47901
48416
  let debounceTimer = null;
47902
48417
  let cssDebounceTimer = null;
47903
48418
  const watchDirs = [appDirPath];
47904
- if (existsSync32(srcDir)) watchDirs.push(srcDir);
48419
+ if (existsSync35(srcDir)) watchDirs.push(srcDir);
47905
48420
  for (const watchDir of watchDirs) {
47906
48421
  watch(watchDir, { recursive: true }, (eventType, filename) => {
47907
48422
  if (!filename) return;
@@ -47910,7 +48425,7 @@ async function startDevServer(port2, projectDir2, config, host2) {
47910
48425
  const isApiRoute = filename.endsWith(".ts") || filename.endsWith(".js") || filename.endsWith(".tsx");
47911
48426
  if (!isVsk && !isCss && !isApiRoute) return;
47912
48427
  const fullPath = filename.startsWith("/") ? filename : join19(watchDir, filename);
47913
- const fileExists = existsSync32(fullPath);
48428
+ const fileExists = existsSync35(fullPath);
47914
48429
  if (isVsk) {
47915
48430
  if (debounceTimer) clearTimeout(debounceTimer);
47916
48431
  debounceTimer = setTimeout(async () => {
@@ -47944,6 +48459,7 @@ async function startDevServer(port2, projectDir2, config, host2) {
47944
48459
  LOG.err(`client build error:`, e.message);
47945
48460
  }
47946
48461
  if (typeof globalThis.__vesk_broadcastHmr === "function") {
48462
+ const hadErrorState = devLastError !== null;
47947
48463
  if (changedComponents.length > 0) {
47948
48464
  let fnSources;
47949
48465
  let errorMessage = bundleError ? bundleError.message : "";
@@ -47959,7 +48475,7 @@ Object.defineProperty(__components, ${JSON.stringify(cname)}, { get: () => __com
47959
48475
  if (compCode.trim()) fnSources = { _raw: compCode };
47960
48476
  } else if (fileExists && !bundleError) {
47961
48477
  try {
47962
- const src2 = readFileSync30(fullPath, "utf-8");
48478
+ const src2 = readFileSync33(fullPath, "utf-8");
47963
48479
  let compCode = buildHmrEvalSnippet2(
47964
48480
  compileClient2(src2, null, { forceClient: true, sourcePath: fullPath, mdRoots: [projectDir2] })
47965
48481
  );
@@ -47974,88 +48490,48 @@ Object.defineProperty(__components, ${JSON.stringify(cname)}, { get: () => __com
47974
48490
  if (compCode.trim()) fnSources = { _raw: compCode };
47975
48491
  } catch (e) {
47976
48492
  errorMessage = e.message;
47977
- LOG.err(`HMR compile error for ${filename}:`, e.message);
48493
+ bundleError = e;
47978
48494
  }
47979
48495
  } else if (!fileExists) {
47980
48496
  LOG.warn(`HMR source not found: ${fullPath}`);
47981
48497
  }
47982
48498
  if (fnSources) {
47983
48499
  devLastError = null;
47984
- globalThis.__vesk_broadcastHmr({
47985
- type: "update",
47986
- time: Date.now() - t0,
47987
- components: Object.fromEntries(changedComponents.map((name) => [name, true])),
47988
- fnSources
47989
- });
47990
- } else if (errorMessage) {
47991
- const err = bundleError;
47992
- let line = 0, col = 0, file = "";
47993
- const suggestions = [];
47994
- const nextSteps = [];
47995
- let tip = "";
47996
- const errDetails = err ? err : void 0;
47997
- if (errDetails?.name === "VeskError") {
47998
- line = errDetails.line || 0;
47999
- col = errDetails.column || 0;
48000
- file = errDetails.file || fullPath.replace(projectDir2, "").replace(/^\//, "") || filename || "";
48001
- if (errDetails.suggestions) suggestions.push(...errDetails.suggestions);
48002
- if (errDetails.nextSteps) nextSteps.push(...errDetails.nextSteps);
48003
- tip = errDetails.tip || "";
48500
+ const bcast = globalThis.__vesk_broadcastHmr;
48501
+ if (hadErrorState) {
48502
+ bcast({ type: "reload" });
48004
48503
  } else {
48005
- const lineMatch = errorMessage.match(/(?:line|at\s+line)\s*(\d+)/i);
48006
- const colMatch = errorMessage.match(/(?:column|col)\s*(\d+)/i);
48007
- const fileMatch = errorMessage.match(/(?:in|at)\s+['"]?([^'":\s]+(?:\.[a-z]+))['"]?/i);
48008
- line = lineMatch ? parseInt(lineMatch[1]) : 0;
48009
- col = colMatch ? parseInt(colMatch[1]) : 0;
48010
- file = fullPath.replace(projectDir2, "").replace(/^\//, "") || filename || "";
48011
- if (fileMatch) file = fileMatch[1];
48012
- }
48013
- let code = "";
48014
- if (errDetails?.code && typeof errDetails.code === "string" && errDetails.code.trim()) {
48015
- code = errDetails.code;
48016
- } else if (line > 0 && fileExists) {
48017
- try {
48018
- const src2 = readFileSync30(fullPath, "utf-8");
48019
- const lines = src2.split("\n");
48020
- const start = Math.max(0, line - 6);
48021
- const end = Math.min(lines.length, line + 5);
48022
- const width = String(end).length;
48023
- const out = [];
48024
- for (let i = start; i < end; i++) {
48025
- const ln = String(i + 1).padStart(width, " ");
48026
- out.push(`${ln} | ${lines[i] ?? ""}`);
48027
- if (i + 1 === line) {
48028
- const pointerCol = Math.max(0, col - 1);
48029
- out.push(`${" ".repeat(width)} | ${" ".repeat(pointerCol)}^`);
48030
- }
48031
- }
48032
- code = out.join("\n");
48033
- } catch {
48034
- }
48504
+ bcast({
48505
+ type: "update",
48506
+ time: Date.now() - t0,
48507
+ components: Object.fromEntries(changedComponents.map((name) => [name, true])),
48508
+ fnSources
48509
+ });
48035
48510
  }
48036
- const tips = [];
48037
- if (tip) tips.push(tip);
48038
- if (errorMessage.toLowerCase().includes("unexpected token")) tips.push("Check for missing or extra brackets, parentheses, or quotes.");
48039
- if (errorMessage.toLowerCase().includes("unexpected identifier")) tips.push("A keyword or identifier is in an unexpected position.");
48040
- if (errorMessage.toLowerCase().includes("expected")) tips.push("Check the syntax around the reported line.");
48041
- if (errorMessage.toLowerCase().includes("not defined") || errorMessage.toLowerCase().includes("is not defined")) tips.push("The variable or component may not be imported or declared.");
48042
- if (errorMessage.toLowerCase().includes("invalid")) tips.push("Check the expression syntax.");
48043
- if (errorMessage.toLowerCase().includes("component") && errorMessage.toLowerCase().includes("not")) tips.push("Ensure the component is properly defined.");
48044
- if (nextSteps.length) tips.push(...nextSteps);
48045
- if (tips.length === 0) tips.push("Review the code around the reported line.");
48046
- devLastError = { message: errorMessage, file, line, column: col };
48047
- recordDiagnostic({ severity: "error", code: "HMR_COMPILE", file: file || null, line: line || null, column: col || null, message: errorMessage, hint: tips[0] || null });
48511
+ } else if (errorMessage) {
48512
+ const payload = buildDevErrorPayload({
48513
+ err: bundleError,
48514
+ errorMessage,
48515
+ filename,
48516
+ fullPath,
48517
+ appDir: appDirPath,
48518
+ fileExists
48519
+ });
48520
+ const displayFile = payload.file || filename || "";
48521
+ LOG.err(`[vsk:error] ${displayFile}${payload.line ? `:${payload.line}:${payload.column || 1}` : ""} \u2014 ${payload.message}`);
48522
+ devLastError = payload;
48523
+ recordDiagnostic({
48524
+ severity: "error",
48525
+ code: "HMR_COMPILE",
48526
+ file: displayFile || null,
48527
+ line: payload.line,
48528
+ column: payload.column,
48529
+ message: payload.message,
48530
+ hint: payload.tips && payload.tips[0] || null
48531
+ });
48048
48532
  globalThis.__vesk_broadcastHmr({
48049
48533
  type: "error",
48050
- message: errorMessage,
48051
- file,
48052
- line,
48053
- column: col,
48054
- code,
48055
- stack: err?.stack || "",
48056
- tips,
48057
- suggestions,
48058
- nextSteps
48534
+ ...payload
48059
48535
  });
48060
48536
  } else {
48061
48537
  devLastError = null;
@@ -48080,7 +48556,7 @@ Object.defineProperty(__components, ${JSON.stringify(cname)}, { get: () => __com
48080
48556
  cssDebounceTimer = setTimeout(async () => {
48081
48557
  try {
48082
48558
  if (fileExists) {
48083
- rawCss = readFileSync30(fullPath, "utf-8");
48559
+ rawCss = readFileSync33(fullPath, "utf-8");
48084
48560
  }
48085
48561
  const cssChanged = await rebuildTailwindCss();
48086
48562
  if (cssChanged && typeof globalThis.__vesk_broadcastHmr === "function") {
@@ -48110,11 +48586,12 @@ Object.defineProperty(__components, ${JSON.stringify(cname)}, { get: () => __com
48110
48586
  ".jpg": "image/jpeg",
48111
48587
  ".ico": "image/x-icon",
48112
48588
  ".html": "text/html",
48113
- ".json": "application/json"
48589
+ ".json": "application/json",
48590
+ ".webmanifest": "application/manifest+json"
48114
48591
  };
48115
48592
  const hmrJsPath = join19(runtimeDir, "hmr-client.js");
48116
48593
  const hmrTsPath = join19(runtimeDir, "hmr-client.ts");
48117
- const hmrClientPath = existsSync32(hmrJsPath) ? hmrJsPath : existsSync32(hmrTsPath) ? hmrTsPath : null;
48594
+ const hmrClientPath = existsSync35(hmrJsPath) ? hmrJsPath : existsSync35(hmrTsPath) ? hmrTsPath : null;
48118
48595
  function extractCompName2(src2) {
48119
48596
  return resolveComponentName(src2);
48120
48597
  }
@@ -48215,7 +48692,7 @@ Object.defineProperty(__components, ${JSON.stringify(cname)}, { get: () => __com
48215
48692
  }
48216
48693
  if (url.pathname === "/_vesk/hmr" || url.pathname === "/_vesk/hmr.js") {
48217
48694
  if (hmrClientPath) {
48218
- let hmrContent = readFileSync30(hmrClientPath, "utf-8");
48695
+ let hmrContent = readFileSync33(hmrClientPath, "utf-8");
48219
48696
  if (hmrClientPath.endsWith(".ts")) {
48220
48697
  hmrContent = stripCodeTypes2(hmrContent);
48221
48698
  }
@@ -48249,21 +48726,21 @@ Object.defineProperty(__components, ${JSON.stringify(cname)}, { get: () => __com
48249
48726
  return;
48250
48727
  }
48251
48728
  }
48252
- if (await handleActionRequest(req, res, { url, appDirPath, routeTree, security, maxBodyBytes: maxBodyBytes2 })) {
48729
+ if (await handleActionRequest(req, res, { url, appDirPath, routeTree, security, maxBodyBytes: maxBodyBytes2, plugins: getActiveDevPlugins() })) {
48253
48730
  return;
48254
48731
  }
48255
48732
  if (url.pathname !== "/") {
48256
48733
  const staticPath = url.pathname.length > 1 ? resolveWithin2(publicDir, url.pathname.slice(1)) : null;
48257
- if (staticPath && existsSync32(staticPath) && statSync21(staticPath).isFile()) {
48734
+ if (staticPath && existsSync35(staticPath) && statSync21(staticPath).isFile()) {
48258
48735
  const ext = extname8(staticPath);
48259
48736
  res.writeHead(200, { "Content-Type": MIME3[ext] || "application/octet-stream" });
48260
- res.end(readFileSync30(staticPath));
48737
+ res.end(readFileSync33(staticPath));
48261
48738
  return;
48262
48739
  }
48263
48740
  }
48264
48741
  const mwChain = collectMiddlewareChain(routeTree, url.pathname, appDirPath);
48265
48742
  const apiDirPath = join19(appDirPath, "api");
48266
- if (url.pathname.startsWith("/api") && existsSync32(apiDirPath)) {
48743
+ if (url.pathname.startsWith("/api") && existsSync35(apiDirPath)) {
48267
48744
  const apiRoutes = await scanApiRoutes(apiDirPath);
48268
48745
  const apiMatch = matchApiUrl(apiRoutes, req.url || url.pathname);
48269
48746
  if (apiMatch) {
@@ -48338,12 +48815,12 @@ Object.defineProperty(__components, ${JSON.stringify(cname)}, { get: () => __com
48338
48815
  const rootNode = routeTree.find((n) => n.fullPath === "/");
48339
48816
  let notFoundHtml = null;
48340
48817
  if (rootNode && rootNode.notFound) {
48341
- const nfPath = resolve32(appDirPath, rootNode.sourceDir, "not-found.vsk");
48342
- if (existsSync32(nfPath)) {
48818
+ const nfPath = resolve35(appDirPath, rootNode.sourceDir, "not-found.vsk");
48819
+ if (existsSync35(nfPath)) {
48343
48820
  try {
48344
- const nfSrc = readFileSync30(nfPath, "utf-8");
48821
+ const nfSrc = readFileSync33(nfPath, "utf-8");
48345
48822
  const nfCompName = extractCompName2(nfSrc) || rootNode.notFound;
48346
- notFoundHtml = await renderFullPage(nfSrc, nfCompName, { params: {}, url: url.pathname }, /* @__PURE__ */ new Map(), { hydrate: true, cssUrls: activeCssUrls(), security, externalDataScript: storeDataScript, sourcePath: nfPath });
48823
+ notFoundHtml = await renderFullPage(nfSrc, nfCompName, { params: {}, url: url.pathname }, /* @__PURE__ */ new Map(), { hydrate: true, cssUrls: activeCssUrls(), security, externalDataScript: storeDataScript, sourcePath: nfPath, plugins: getActiveDevPlugins() });
48347
48824
  } catch {
48348
48825
  }
48349
48826
  }
@@ -48378,18 +48855,18 @@ Object.defineProperty(__components, ${JSON.stringify(cname)}, { get: () => __com
48378
48855
  let props;
48379
48856
  for (let i = chain.length - 1; i >= 0; i--) {
48380
48857
  const node = chain[i];
48381
- const pageFilePath = resolve32(appDirPath, node.sourceDir, "page.vsk");
48382
- const layoutFilePath = resolve32(appDirPath, node.sourceDir, "layout.vsk");
48383
- if (i === chain.length - 1 && node.page && existsSync32(pageFilePath)) {
48384
- const src2 = readFileSync30(pageFilePath, "utf-8");
48858
+ const pageFilePath = resolve35(appDirPath, node.sourceDir, "page.vsk");
48859
+ const layoutFilePath = resolve35(appDirPath, node.sourceDir, "layout.vsk");
48860
+ if (i === chain.length - 1 && node.page && existsSync35(pageFilePath)) {
48861
+ const src2 = readFileSync33(pageFilePath, "utf-8");
48385
48862
  const compName = extractCompName2(src2) || node.page;
48386
48863
  const result2 = await renderPage(src2, compName, { params: matched.params }, /* @__PURE__ */ new Map(), { hydrate: true, sourcePath: pageFilePath });
48387
48864
  body = result2.body;
48388
48865
  head = result2.head || "";
48389
48866
  props = result2.props;
48390
48867
  }
48391
- if (node.layout && existsSync32(layoutFilePath)) {
48392
- const src2 = readFileSync30(layoutFilePath, "utf-8");
48868
+ if (node.layout && existsSync35(layoutFilePath)) {
48869
+ const src2 = readFileSync33(layoutFilePath, "utf-8");
48393
48870
  const compName = extractCompName2(src2) || node.layout;
48394
48871
  const result2 = await renderPage(src2, compName, { children: body }, /* @__PURE__ */ new Map(), { hydrate: true, sourcePath: layoutFilePath });
48395
48872
  body = result2.body;
@@ -48399,7 +48876,7 @@ Object.defineProperty(__components, ${JSON.stringify(cname)}, { get: () => __com
48399
48876
  if (forData) {
48400
48877
  return { html: "", props: props || { params: matched.params }, head };
48401
48878
  }
48402
- const hasLayout = chain.some((n) => n.layout && existsSync32(resolve32(appDirPath, n.sourceDir, "layout.vsk")));
48879
+ const hasLayout = chain.some((n) => n.layout && existsSync35(resolve35(appDirPath, n.sourceDir, "layout.vsk")));
48403
48880
  let html;
48404
48881
  if (hasLayout) {
48405
48882
  const ssrData = ssrSink3.snapshot();
@@ -48413,12 +48890,12 @@ Object.defineProperty(__components, ${JSON.stringify(cname)}, { get: () => __com
48413
48890
  `;
48414
48891
  if (security.autoEscape !== false) secMeta += " <!-- vesk: auto-escape enabled -->\n";
48415
48892
  }
48893
+ let headBlock = ' <meta charset="utf-8" />\n <meta name="viewport" content="width=device-width, initial-scale=1" />\n' + cssLinkTags() + secMeta + (head ? " " + head.split("\n").join("\n ") + "\n" : "");
48894
+ headBlock = await applyHeadInjects(headBlock, { plugins: getActiveDevPlugins() }, { sourcePath: url.pathname });
48416
48895
  html = `<!DOCTYPE html>
48417
48896
  <html>
48418
48897
  <head>
48419
- <meta charset="utf-8" />
48420
- <meta name="viewport" content="width=device-width, initial-scale=1" />
48421
- ${cssLinkTags()}${secMeta}${head ? " " + head.split("\n").join("\n ") + "\n" : ""}</head>
48898
+ ${headBlock}</head>
48422
48899
  <body>
48423
48900
  <div id="root">
48424
48901
  ${prettifyHtml(body)}
@@ -48426,13 +48903,15 @@ ${prettifyHtml(body)}
48426
48903
  </body>
48427
48904
  </html>`;
48428
48905
  html = injectDevScripts(html);
48906
+ html = await applyHtmlPlugins(html, getActiveDevPlugins(), { sourcePath: url.pathname });
48429
48907
  } else {
48430
48908
  const leaf = chain.find((n) => n.page);
48431
48909
  if (leaf) {
48432
- const src2 = readFileSync30(resolve32(appDirPath, leaf.sourceDir, "page.vsk"), "utf-8");
48910
+ const src2 = readFileSync33(resolve35(appDirPath, leaf.sourceDir, "page.vsk"), "utf-8");
48433
48911
  const compName = extractCompName2(src2) || leaf.page;
48434
- html = await renderFullPage(src2, compName, { params: matched.params }, /* @__PURE__ */ new Map(), { hydrate: true, clientScriptUrl: "/_vesk/client.js", cssUrls: activeCssUrls(), security, externalDataScript: storeDataScript, sourcePath: resolve32(appDirPath, leaf.sourceDir, "page.vsk") });
48912
+ html = await renderFullPage(src2, compName, { params: matched.params }, /* @__PURE__ */ new Map(), { hydrate: true, clientScriptUrl: "/_vesk/client.js", cssUrls: activeCssUrls(), security, externalDataScript: storeDataScript, sourcePath: resolve35(appDirPath, leaf.sourceDir, "page.vsk"), plugins: getActiveDevPlugins() });
48435
48913
  html = html.replace("</body>", ' <script type="module" src="/_vesk/hmr.js"></script>\n</body>');
48914
+ html = await applyHtmlPlugins(html, getActiveDevPlugins(), { sourcePath: url.pathname });
48436
48915
  } else {
48437
48916
  throw new Error("No page or layout matched");
48438
48917
  }
@@ -48443,13 +48922,13 @@ ${prettifyHtml(body)}
48443
48922
  function renderSSRStream() {
48444
48923
  async function* raw2() {
48445
48924
  const chain = cleanChain;
48446
- const hasLayout = chain.some((n) => n.layout && existsSync32(resolve32(appDirPath, n.sourceDir, "layout.vsk")));
48925
+ const hasLayout = chain.some((n) => n.layout && existsSync35(resolve35(appDirPath, n.sourceDir, "layout.vsk")));
48447
48926
  if (!hasLayout) {
48448
48927
  const leaf = chain.find((n) => n.page);
48449
48928
  if (leaf) {
48450
- const src2 = readFileSync30(resolve32(appDirPath, leaf.sourceDir, "page.vsk"), "utf-8");
48929
+ const src2 = readFileSync33(resolve35(appDirPath, leaf.sourceDir, "page.vsk"), "utf-8");
48451
48930
  const compName = extractCompName2(src2) || leaf.page;
48452
- yield* renderPageStream(src2, compName, { params: matched.params }, /* @__PURE__ */ new Map(), { hydrate: true, clientScriptUrl: "/_vesk/client.js", cssUrls: activeCssUrls(), security, externalDataScript: storeDataScript, sourcePath: resolve32(appDirPath, leaf.sourceDir, "page.vsk") });
48931
+ yield* renderPageStream(src2, compName, { params: matched.params }, /* @__PURE__ */ new Map(), { hydrate: true, clientScriptUrl: "/_vesk/client.js", cssUrls: activeCssUrls(), security, externalDataScript: storeDataScript, sourcePath: resolve35(appDirPath, leaf.sourceDir, "page.vsk"), plugins: getActiveDevPlugins() });
48453
48932
  } else {
48454
48933
  throw new Error("No page or layout matched");
48455
48934
  }
@@ -48460,33 +48939,35 @@ ${prettifyHtml(body)}
48460
48939
  let props;
48461
48940
  for (let i = chain.length - 1; i >= 0; i--) {
48462
48941
  const node = chain[i];
48463
- const pageFilePath = resolve32(appDirPath, node.sourceDir, "page.vsk");
48464
- const layoutFilePath = resolve32(appDirPath, node.sourceDir, "layout.vsk");
48465
- if (i === chain.length - 1 && node.page && existsSync32(pageFilePath)) {
48466
- const src2 = readFileSync30(pageFilePath, "utf-8");
48942
+ const pageFilePath = resolve35(appDirPath, node.sourceDir, "page.vsk");
48943
+ const layoutFilePath = resolve35(appDirPath, node.sourceDir, "layout.vsk");
48944
+ if (i === chain.length - 1 && node.page && existsSync35(pageFilePath)) {
48945
+ const src2 = readFileSync33(pageFilePath, "utf-8");
48467
48946
  const compName = extractCompName2(src2) || node.page;
48468
48947
  const result2 = await renderPage(src2, compName, { params: matched.params }, /* @__PURE__ */ new Map(), { hydrate: true, sourcePath: pageFilePath });
48469
48948
  body = result2.body;
48470
48949
  head = result2.head || "";
48471
48950
  props = result2.props;
48472
48951
  }
48473
- if (node.layout && existsSync32(layoutFilePath)) {
48474
- const src2 = readFileSync30(layoutFilePath, "utf-8");
48952
+ if (node.layout && existsSync35(layoutFilePath)) {
48953
+ const src2 = readFileSync33(layoutFilePath, "utf-8");
48475
48954
  const compName = extractCompName2(src2) || node.layout;
48476
48955
  const result2 = await renderPage(src2, compName, { children: body }, /* @__PURE__ */ new Map(), { hydrate: true, sourcePath: layoutFilePath });
48477
48956
  body = result2.body;
48478
48957
  head = (result2.head || "") + head;
48479
48958
  }
48480
48959
  }
48481
- yield '<!DOCTYPE html>\n<html>\n<head>\n <meta charset="utf-8" />\n <meta name="viewport" content="width=device-width, initial-scale=1" />\n' + cssLinkTags();
48960
+ const headParts = [' <meta charset="utf-8" />', ' <meta name="viewport" content="width=device-width, initial-scale=1" />'];
48961
+ const cssTags = cssLinkTags();
48962
+ if (cssTags) headParts.push(cssTags.trimEnd());
48482
48963
  if (security) {
48483
- if (security.referrerPolicy !== false) yield ` <meta name="referrer" content="${security.referrerPolicy || "strict-origin-when-cross-origin"}" />
48484
- `;
48485
- if (security.contentSecurityPolicy !== false) yield ` <meta http-equiv="Content-Security-Policy" content="${(security.contentSecurityPolicy || "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; frame-src 'self'; connect-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'").replace(/"/g, "&quot;")}" />
48486
- `;
48487
- if (security.autoEscape !== false) yield " <!-- vesk: auto-escape enabled -->\n";
48964
+ if (security.referrerPolicy !== false) headParts.push(` <meta name="referrer" content="${security.referrerPolicy || "strict-origin-when-cross-origin"}" />`);
48965
+ if (security.contentSecurityPolicy !== false) headParts.push(` <meta http-equiv="Content-Security-Policy" content="${(security.contentSecurityPolicy || "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; frame-src 'self'; connect-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'").replace(/"/g, "&quot;")}" />`);
48966
+ if (security.autoEscape !== false) headParts.push(" <!-- vesk: auto-escape enabled -->");
48488
48967
  }
48489
- if (head) yield " " + head.split("\n").join("\n ") + "\n";
48968
+ if (head) headParts.push(" " + head.split("\n").join("\n "));
48969
+ yield "<!DOCTYPE html>\n<html>\n<head>\n";
48970
+ yield await applyHeadInjects(headParts.join("\n"), { plugins: getActiveDevPlugins() }, { sourcePath: url.pathname }) + "\n";
48490
48971
  yield '</head>\n<body>\n<div id="root">\n';
48491
48972
  yield prettifyHtml(body);
48492
48973
  yield "\n</div>\n";
@@ -48598,12 +49079,12 @@ ${prettifyHtml(body)}
48598
49079
  for (let i = match.nodes.length - 1; i >= 0; i--) {
48599
49080
  const node = match.nodes[i];
48600
49081
  if (node.notFound) {
48601
- const nfPath = resolve32(appDirPath, node.sourceDir, "not-found.vsk");
48602
- if (existsSync32(nfPath)) {
49082
+ const nfPath = resolve35(appDirPath, node.sourceDir, "not-found.vsk");
49083
+ if (existsSync35(nfPath)) {
48603
49084
  try {
48604
- const nfSrc = readFileSync30(nfPath, "utf-8");
49085
+ const nfSrc = readFileSync33(nfPath, "utf-8");
48605
49086
  const nfCompName = extractCompName2(nfSrc) || node.notFound;
48606
- const html = await renderFullPage(nfSrc, nfCompName, { params: match.params, url: url.pathname }, /* @__PURE__ */ new Map(), { hydrate: true, cssUrls: activeCssUrls(), security, externalDataScript: storeDataScript, sourcePath: nfPath });
49087
+ const html = await renderFullPage(nfSrc, nfCompName, { params: match.params, url: url.pathname }, /* @__PURE__ */ new Map(), { hydrate: true, cssUrls: activeCssUrls(), security, externalDataScript: storeDataScript, sourcePath: nfPath, plugins: getActiveDevPlugins() });
48607
49088
  notFoundHtml = injectDevScripts(html);
48608
49089
  } catch {
48609
49090
  }
@@ -48621,13 +49102,13 @@ ${prettifyHtml(body)}
48621
49102
  for (let i = match.nodes.length - 1; i >= 0; i--) {
48622
49103
  const node = match.nodes[i];
48623
49104
  if (node.error) {
48624
- const errPath = resolve32(appDirPath, node.sourceDir, "error.vsk");
48625
- if (existsSync32(errPath)) {
49105
+ const errPath = resolve35(appDirPath, node.sourceDir, "error.vsk");
49106
+ if (existsSync35(errPath)) {
48626
49107
  try {
48627
- const errSrc = readFileSync30(errPath, "utf-8");
49108
+ const errSrc = readFileSync33(errPath, "utf-8");
48628
49109
  const errCompName = extractCompName2(errSrc) || node.error;
48629
49110
  const errProps = { error: err.message, stack: err.stack, statusCode: errorStatusCode(err), url: url.pathname };
48630
- const html = await renderFullPage(errSrc, errCompName, errProps, /* @__PURE__ */ new Map(), { hydrate: true, cssUrls: activeCssUrls(), security, externalDataScript: storeDataScript, sourcePath: errPath });
49111
+ const html = await renderFullPage(errSrc, errCompName, errProps, /* @__PURE__ */ new Map(), { hydrate: true, cssUrls: activeCssUrls(), security, externalDataScript: storeDataScript, sourcePath: errPath, plugins: getActiveDevPlugins() });
48631
49112
  errorHtml = injectDevScripts(html);
48632
49113
  } catch (e2) {
48633
49114
  LOG.err(`error page render failed:`, e2.message);
@@ -48638,10 +49119,12 @@ ${prettifyHtml(body)}
48638
49119
  }
48639
49120
  }
48640
49121
  const errCode = errorStatusCode(err);
49122
+ const fallbackHtml = errorHtml || injectDevScripts(`<!DOCTYPE html><html><body><h1>${errCode}</h1><pre>${err.message}
49123
+ ${err.stack}</pre></body></html>`);
48641
49124
  logRequest(errCode);
49125
+ LOG.err(`[vsk:error] ${url.pathname} \u2014 ${err.message}`);
48642
49126
  res.writeHead(errCode, { "Content-Type": "text/html" });
48643
- res.end(injectSsrErrorMarker(errorHtml || `<!DOCTYPE html><html><body><h1>${errCode}</h1><pre>${err.message}
48644
- ${err.stack}</pre></body></html>`, err));
49127
+ res.end(injectSsrErrorMarker(fallbackHtml, err));
48645
49128
  }
48646
49129
  }
48647
49130
  });
@@ -48664,10 +49147,14 @@ ${err.stack}</pre></body></html>`, err));
48664
49147
  });
48665
49148
  updateSourceMapping();
48666
49149
  const hmrClients = /* @__PURE__ */ new Set();
48667
- const wss = new WebSocketServer({ noServer: true });
49150
+ const wss = new WebSocketServer2({ noServer: true });
48668
49151
  wss.on("connection", (ws) => {
48669
49152
  hmrClients.add(ws);
48670
49153
  ws.on("close", () => hmrClients.delete(ws));
49154
+ if (devLastError) {
49155
+ const msg = JSON.stringify({ type: "error", ...devLastError, nonce: hmrNonce });
49156
+ if (ws.readyState === 1) ws.send(msg);
49157
+ }
48671
49158
  });
48672
49159
  server2.on("upgrade", (req, socket, head) => {
48673
49160
  if (req.url === "/_vesk/hmr" && isAllowedWsUpgrade(req.headers)) {
@@ -48689,7 +49176,6 @@ ${err.stack}</pre></body></html>`, err));
48689
49176
  await new Promise(() => {
48690
49177
  });
48691
49178
  }
48692
- var TAILWIND_BLOCK = /^\s*@(theme\s*\{|layer\s+(components|utilities)\s*\{|utility\s+\w+\s*\{)/;
48693
49179
  function injectSsrErrorMarker(html, err) {
48694
49180
  const msg = err instanceof Error ? err.message : String(err);
48695
49181
  const marker = `<!--vesk-ssr-error:${encodeURIComponent(msg || "Internal Server Error")}-->`;
@@ -48700,35 +49186,6 @@ function injectSsrErrorMarker(html, err) {
48700
49186
  }
48701
49187
  return marker + html;
48702
49188
  }
48703
- function stripTailwindDirectives(css) {
48704
- const lines = css.split("\n");
48705
- const result2 = [];
48706
- let i = 0;
48707
- while (i < lines.length) {
48708
- const line = lines[i].trim();
48709
- if (line.startsWith("@import 'tailwindcss'") || line.startsWith('@import "tailwindcss"')) {
48710
- i++;
48711
- continue;
48712
- }
48713
- if (line.startsWith("@source ")) {
48714
- i++;
48715
- continue;
48716
- }
48717
- if (TAILWIND_BLOCK.test(line)) {
48718
- let braceCount = (lines[i].match(/\{/g) || []).length - (lines[i].match(/\}/g) || []).length;
48719
- i++;
48720
- while (i < lines.length && braceCount > 0) {
48721
- braceCount += (lines[i].match(/\{/g) || []).length;
48722
- braceCount -= (lines[i].match(/\}/g) || []).length;
48723
- i++;
48724
- }
48725
- continue;
48726
- }
48727
- result2.push(lines[i]);
48728
- i++;
48729
- }
48730
- return result2.join("\n").trim();
48731
- }
48732
49189
  function buildRequestContext(req) {
48733
49190
  const headers2 = {};
48734
49191
  for (const [k, v] of Object.entries(req.headers)) {
@@ -48894,8 +49351,8 @@ init_loading_indicator();
48894
49351
  init_action();
48895
49352
 
48896
49353
  // src/index.ts
48897
- var __filename2 = fileURLToPath8(import.meta.url);
48898
- var __dirname9 = resolve34(__filename2, "..");
49354
+ var __filename2 = fileURLToPath9(import.meta.url);
49355
+ var __dirname10 = resolve37(__filename2, "..");
48899
49356
  var args = process.argv.slice(2);
48900
49357
  var cmd = args[0];
48901
49358
  function usage(code = 0) {
@@ -48942,8 +49399,8 @@ function loadEnvFiles(projectDir2) {
48942
49399
  join21(projectDir2, ".env.local")
48943
49400
  ];
48944
49401
  for (const filePath of files) {
48945
- if (!existsSync33(filePath)) continue;
48946
- const content = readFileSync32(filePath, "utf-8");
49402
+ if (!existsSync36(filePath)) continue;
49403
+ const content = readFileSync35(filePath, "utf-8");
48947
49404
  for (const line of content.split("\n")) {
48948
49405
  const trimmed = line.trim();
48949
49406
  if (!trimmed || trimmed.startsWith("#")) continue;
@@ -48965,20 +49422,20 @@ async function loadConfig(projectDir2) {
48965
49422
  const jsPath = join21(projectDir2, "vesk.config.js");
48966
49423
  const tsPath = join21(projectDir2, "vesk.config.ts");
48967
49424
  let configPath3 = null;
48968
- if (existsSync33(jsPath)) configPath3 = jsPath;
48969
- else if (existsSync33(tsPath)) configPath3 = tsPath;
49425
+ if (existsSync36(jsPath)) configPath3 = jsPath;
49426
+ else if (existsSync36(tsPath)) configPath3 = tsPath;
48970
49427
  if (!configPath3) return {};
48971
49428
  let raw2;
48972
49429
  if (configPath3.endsWith(".ts")) {
48973
49430
  const { transpile: transpile2 } = await import("typescript");
48974
- const src2 = readFileSync32(configPath3, "utf-8");
49431
+ const src2 = readFileSync35(configPath3, "utf-8");
48975
49432
  let js = transpile2(src2, { module: 99, target: 99 });
48976
49433
  js = js.replace(/import\s+\{[^}]*\}\s*from\s+['"]@vesk\/compiler['"]\s*;?\s*/g, "");
48977
49434
  js = `const { defineConfig, definePlugin, preset } = globalThis.__vesk_inject;
48978
49435
  ` + js;
48979
49436
  const tmpFile = join21(projectDir2, ".vesk", "config.tmp.js");
48980
- mkdirSync15(dirname22(tmpFile), { recursive: true });
48981
- writeFileSync17(tmpFile, js, "utf-8");
49437
+ mkdirSync15(dirname23(tmpFile), { recursive: true });
49438
+ writeFileSync18(tmpFile, js, "utf-8");
48982
49439
  globalThis.__vesk_inject = { defineConfig, definePlugin, preset };
48983
49440
  raw2 = (await import(tmpFile)).default;
48984
49441
  delete globalThis.__vesk_inject;
@@ -49000,7 +49457,7 @@ if (cmd === "build") {
49000
49457
  const projectDir2 = process.cwd();
49001
49458
  const appDirPath = join21(projectDir2, "app");
49002
49459
  const publicDir = join21(projectDir2, "public");
49003
- if (!existsSync33(appDirPath)) {
49460
+ if (!existsSync36(appDirPath)) {
49004
49461
  console.error(`vesk build: no app/ directory found in ${projectDir2}`);
49005
49462
  process.exit(1);
49006
49463
  }
@@ -49071,7 +49528,7 @@ ${code}`;
49071
49528
  if (cmd === "seo") {
49072
49529
  const projectDir2 = process.cwd();
49073
49530
  const appDirPath = join21(projectDir2, "app");
49074
- if (!existsSync33(appDirPath)) {
49531
+ if (!existsSync36(appDirPath)) {
49075
49532
  console.error(`vesk seo: no app/ directory found in ${projectDir2}`);
49076
49533
  process.exit(1);
49077
49534
  }
@@ -49086,7 +49543,7 @@ if (cmd === "seo") {
49086
49543
  if (cmd === "typecheck") {
49087
49544
  const projectDir2 = process.cwd();
49088
49545
  const appDirPath = join21(projectDir2, "app");
49089
- if (!existsSync33(appDirPath)) {
49546
+ if (!existsSync36(appDirPath)) {
49090
49547
  console.error(`vesk typecheck: no app/ directory found in ${projectDir2}`);
49091
49548
  process.exit(1);
49092
49549
  }
@@ -49121,12 +49578,12 @@ if (cmd === "init") {
49121
49578
  const projectDir2 = process.cwd();
49122
49579
  const srcDir = join21(projectDir2, "src");
49123
49580
  const target = join21(srcDir, "global.css");
49124
- if (existsSync33(target)) {
49581
+ if (existsSync36(target)) {
49125
49582
  console.error(`vesk init: ${target} already exists \u2014 skipping`);
49126
49583
  process.exit(0);
49127
49584
  }
49128
49585
  mkdirSync15(srcDir, { recursive: true });
49129
- writeFileSync17(target, [
49586
+ writeFileSync18(target, [
49130
49587
  `@import 'tailwindcss';`,
49131
49588
  ``,
49132
49589
  `@layer base {`,
@@ -49142,7 +49599,7 @@ if (cmd === "dev") {
49142
49599
  const appDirPath = join21(projectDir2, "app");
49143
49600
  const port2 = parsePortArg(args);
49144
49601
  const host2 = parseHostArg(args);
49145
- if (!existsSync33(appDirPath)) {
49602
+ if (!existsSync36(appDirPath)) {
49146
49603
  console.error(`vesk: no app/ directory found in ${projectDir2}`);
49147
49604
  console.error('Run "npx create-vesk@latest <project-name>" first');
49148
49605
  process.exit(1);