@vesk/adapter 0.2.12 → 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.
@@ -1 +1 @@
1
- {"version":3,"file":"client-bundle.d.ts","sourceRoot":"","sources":["../src/client-bundle.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,SAAS,EAAE,mBAAmB,EAAE,kBAAkB,EAAqC,MAAM,yBAAyB,CAAC;AAoCrI;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CA8BhE;AAoLD;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAkBxD;AAmCD,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,SAAS,EAAE,EACtB,MAAM,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAClC,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,kBAAkB,CAAC,CA0S7B;AAMD,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CA+B3D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAUlE;AAYD;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAuCrG"}
1
+ {"version":3,"file":"client-bundle.d.ts","sourceRoot":"","sources":["../src/client-bundle.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,SAAS,EAAE,mBAAmB,EAAE,kBAAkB,EAAqC,MAAM,yBAAyB,CAAC;AAoCrI;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CA8BhE;AAoLD;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAkBxD;AAmCD,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,SAAS,EAAE,EACtB,MAAM,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAClC,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,kBAAkB,CAAC,CA4T7B;AAMD,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CA+B3D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAUlE;AAYD;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAuCrG"}
@@ -459,6 +459,21 @@ export async function generateClientBundle(routeTree, appDir, componentMap, opti
459
459
  return slug.replace(/[\[\]]/g, '_');
460
460
  }
461
461
  const codeSplit = !!(options?.codeSplit);
462
+ const transformPlugins = options?.plugins || [];
463
+ /** Run every active plugin's `onTransformJS` over an emitted bundle/chunk source. */
464
+ async function applyTransformPlugins(code, filePath) {
465
+ if (transformPlugins.length === 0)
466
+ return code;
467
+ let out = code;
468
+ for (const plugin of transformPlugins) {
469
+ if (typeof plugin.onTransformJS === 'function') {
470
+ const result = await plugin.onTransformJS(out, filePath);
471
+ if (typeof result === 'string')
472
+ out = result;
473
+ }
474
+ }
475
+ return out;
476
+ }
462
477
  if (codeSplit) {
463
478
  const chunkEntries = [];
464
479
  function walkSplit(nodes, _chain) {
@@ -537,7 +552,11 @@ export async function generateClientBundle(routeTree, appDir, componentMap, opti
537
552
  if (cache)
538
553
  cache.mainBundle = { key: mainKey, code: main };
539
554
  }
540
- return { main, chunks, cachedFileHits, compiledFiles, mainFromCache, editedSources, editedNames };
555
+ const transformedChunks = [];
556
+ for (const chunk of chunks) {
557
+ transformedChunks.push({ ...chunk, code: await applyTransformPlugins(chunk.code, chunk.name) });
558
+ }
559
+ return { main: await applyTransformPlugins(main, 'client.js'), chunks: transformedChunks, cachedFileHits, compiledFiles, mainFromCache, editedSources, editedNames };
541
560
  }
542
561
  else {
543
562
  let componentLines = [];
@@ -603,7 +622,7 @@ export async function generateClientBundle(routeTree, appDir, componentMap, opti
603
622
  componentLines, hydratorLines, aliasLines, hydratorAliasLines,
604
623
  }, !!options?.hmr, !!options?.importRuntime, runtimeImportNames, options?.routeDataCache);
605
624
  // Mono (non-codeSplit) builds are the production path — no incremental cache.
606
- return { main, chunks: [] };
625
+ return { main: await applyTransformPlugins(main, 'client.js'), chunks: [] };
607
626
  }
608
627
  }
609
628
  function stripTypes(code) {
package/dist/css.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ export declare const TAILWIND_CSS_URL = "/_vesk/static/_tailwind.css";
2
+ export declare const GLOBAL_CSS_URL = "/_vesk/static/global.css";
3
+ /** Resolve the project's user stylesheet source (`src/global.css`, then `src/app.css`). */
4
+ export declare function resolveUserCssPath(appDir: string): string | null;
5
+ /** True when the project has a user stylesheet source (`src/global.css` or `src/app.css`). */
6
+ export declare function hasUserCss(appDir: string): boolean;
7
+ /** True when a non-empty `_tailwind.css` was produced for the build (prod disk output). */
8
+ export declare function hasBuiltTailwindCss(outDir: string): boolean;
9
+ /** True when the active plugin pipeline includes the tailwind plugin. */
10
+ export declare function isTailwindPlugin(plugins: Array<{
11
+ name?: string;
12
+ }> | undefined | null): boolean;
13
+ /**
14
+ * Single source of truth for the `/_vesk/static/*.css` link list. Callers
15
+ * supply environment facts — `tailwind`: tailwind output is available
16
+ * (built-file present + non-empty in prod, active plugin in dev);
17
+ * `userCss`: a user stylesheet exists — so build, request, dev, and prod
18
+ * paths share one ordering.
19
+ */
20
+ export declare function resolveCssUrls(opts: {
21
+ tailwind?: boolean;
22
+ userCss?: boolean;
23
+ }): string[];
24
+ /** Drop tailwind framework directives from user CSS, keeping hand-written rules. */
25
+ export declare function stripTailwindDirectives(css: string): string;
26
+ //# sourceMappingURL=css.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"css.d.ts","sourceRoot":"","sources":["../src/css.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,gBAAgB,gCAAgC,CAAC;AAC9D,eAAO,MAAM,cAAc,6BAA6B,CAAC;AAEzD,2FAA2F;AAC3F,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMhE;AAED,8FAA8F;AAC9F,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAElD;AAED,2FAA2F;AAC3F,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAG3D;AAED,yEAAyE;AACzE,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAE9F;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,EAAE,CAKxF;AAED,oFAAoF;AACpF,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAkB3D"}
package/dist/css.js ADDED
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Shared stylesheet resolution for the adapter build, prod server, generated
3
+ * SSR functions, dev server, and action handler. Each environment feeds its
4
+ * facts (`tailwind` output available, user stylesheet present) into
5
+ * `resolveCssUrls`, so the `/_vesk/static/*.css` link list and its ordering
6
+ * come from one place instead of six ad-hoc copies.
7
+ */
8
+ import { readFileSync, existsSync } from 'node:fs';
9
+ import { resolve } from 'node:path';
10
+ import { cssBlockEnd } from '@vesk/compiler/src/scan';
11
+ export const TAILWIND_CSS_URL = '/_vesk/static/_tailwind.css';
12
+ export const GLOBAL_CSS_URL = '/_vesk/static/global.css';
13
+ /** Resolve the project's user stylesheet source (`src/global.css`, then `src/app.css`). */
14
+ export function resolveUserCssPath(appDir) {
15
+ const cssSrc = resolve(appDir, '..', 'src', 'global.css');
16
+ if (existsSync(cssSrc))
17
+ return cssSrc;
18
+ const altCssSrc = resolve(appDir, '..', 'src', 'app.css');
19
+ if (existsSync(altCssSrc))
20
+ return altCssSrc;
21
+ return null;
22
+ }
23
+ /** True when the project has a user stylesheet source (`src/global.css` or `src/app.css`). */
24
+ export function hasUserCss(appDir) {
25
+ return resolveUserCssPath(appDir) !== null;
26
+ }
27
+ /** True when a non-empty `_tailwind.css` was produced for the build (prod disk output). */
28
+ export function hasBuiltTailwindCss(outDir) {
29
+ const p = resolve(outDir, 'static', '_tailwind.css');
30
+ return existsSync(p) && readFileSync(p, 'utf-8').trim().length > 0;
31
+ }
32
+ /** True when the active plugin pipeline includes the tailwind plugin. */
33
+ export function isTailwindPlugin(plugins) {
34
+ return (plugins || []).some((p) => String(p && p.name).toLowerCase().includes('tailwind'));
35
+ }
36
+ /**
37
+ * Single source of truth for the `/_vesk/static/*.css` link list. Callers
38
+ * supply environment facts — `tailwind`: tailwind output is available
39
+ * (built-file present + non-empty in prod, active plugin in dev);
40
+ * `userCss`: a user stylesheet exists — so build, request, dev, and prod
41
+ * paths share one ordering.
42
+ */
43
+ export function resolveCssUrls(opts) {
44
+ const urls = [];
45
+ if (opts.tailwind)
46
+ urls.push(TAILWIND_CSS_URL);
47
+ if (opts.userCss)
48
+ urls.push(GLOBAL_CSS_URL);
49
+ return urls;
50
+ }
51
+ /** Drop tailwind framework directives from user CSS, keeping hand-written rules. */
52
+ export function stripTailwindDirectives(css) {
53
+ const blockStart = /^\s*@(theme\s*\{|layer\s+(components|utilities)\s*\{|utility\s+[\w-]+\s*\{)/;
54
+ let result = css.replace(/^\s*@import\s+['"]tailwindcss['"]\s*;?\s*$/gm, '');
55
+ result = result.replace(/^\s*@source\s+['"][^'"]+['"]\s*;?\s*$/gm, '');
56
+ const output = [];
57
+ let pos = 0;
58
+ while (pos < result.length) {
59
+ const lineEnd = result.indexOf('\n', pos) === -1 ? result.length : result.indexOf('\n', pos) + 1;
60
+ const line = result.slice(pos, lineEnd);
61
+ if (blockStart.test(line.trim())) {
62
+ const end = cssBlockEnd(result, pos);
63
+ pos = end;
64
+ continue;
65
+ }
66
+ output.push(line);
67
+ pos = lineEnd;
68
+ }
69
+ return output.join('').trim();
70
+ }
@@ -1,4 +1,5 @@
1
1
  import { type Server } from 'node:http';
2
+ import type { HmrErrorPayload } from './hmr';
2
3
  import type { DevServerOptions } from '@vesk/adapter/src/types';
3
4
  /**
4
5
  * Shape returned by the dev HMR state endpoint. Mirrors what the parallel
@@ -9,7 +10,7 @@ import type { DevServerOptions } from '@vesk/adapter/src/types';
9
10
  export interface DevHmrState {
10
11
  status: 'up' | 'compiling' | 'error' | 'down';
11
12
  lastCompileMs: number | null;
12
- error: Record<string, unknown> | null;
13
+ error: HmrErrorPayload | Record<string, unknown> | null;
13
14
  hasError: boolean;
14
15
  componentCount: number;
15
16
  /** Whether the @vesk/agentic plugin is installed and active (mirrors the
@@ -1 +1 @@
1
- {"version":3,"file":"dev-server.d.ts","sourceRoot":"","sources":["../src/dev-server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,MAAM,EAA6C,MAAM,WAAW,CAAC;AAUjG,OAAO,KAAK,EAAa,gBAAgB,EAAwB,MAAM,yBAAyB,CAAC;AAgBjG;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,IAAI,GAAG,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC;IAC9C,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACtC,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB;+EAC2E;IAC3E,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,mEAAmE;AACnE,wBAAgB,kBAAkB,IAAI,WAAW,CAEhD;AAuCD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAIzE;AAkBD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,mHAAmH;IACnH,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC7B;;8BAE0B;IAC1B,MAAM,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,UAAU,GAAG,YAAY,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;IACrE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,WAAW,CAAC;IAChC,8EAA8E;IAC9E,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3E;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,wBAAwB,GAAG;IACvE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;CAChH,CAUA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAa3C;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIrD;AA6CD,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAuevG"}
1
+ {"version":3,"file":"dev-server.d.ts","sourceRoot":"","sources":["../src/dev-server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,MAAM,EAA6C,MAAM,WAAW,CAAC;AAOjG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;AAI7C,OAAO,KAAK,EAAa,gBAAgB,EAAwB,MAAM,yBAAyB,CAAC;AAgBjG;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,IAAI,GAAG,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC;IAC9C,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACxD,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB;+EAC2E;IAC3E,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,mEAAmE;AACnE,wBAAgB,kBAAkB,IAAI,WAAW,CAEhD;AAuCD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAIzE;AAkBD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,mHAAmH;IACnH,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC7B;;8BAE0B;IAC1B,MAAM,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,UAAU,GAAG,YAAY,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;IACrE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,WAAW,CAAC;IAChC,8EAA8E;IAC9E,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3E;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,wBAAwB,GAAG;IACvE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;CAChH,CAUA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAa3C;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIrD;AA8CD,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAuevG"}
@@ -192,6 +192,7 @@ const MIME = {
192
192
  '.svg': 'image/svg+xml', '.css': 'text/css', '.js': 'application/javascript',
193
193
  '.png': 'image/png', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg',
194
194
  '.ico': 'image/x-icon', '.html': 'text/html', '.json': 'application/json',
195
+ '.webmanifest': 'application/manifest+json',
195
196
  '.woff': 'font/woff', '.woff2': 'font/woff2', '.wasm': 'application/wasm',
196
197
  };
197
198
  export async function startDevServer(appDir, options) {
package/dist/hmr.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"hmr.d.ts","sourceRoot":"","sources":["../src/hmr.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AASxC,OAAO,EAAsC,KAAK,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAEvG,OAAO,KAAK,EAAE,SAAS,EAAkB,MAAM,yBAAyB,CAAC;AAIzE;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAaD,wBAAgB,WAAW,IAAI;IAC7B,MAAM,EAAE,IAAI,GAAG,QAAQ,CAAC;IACxB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAQA;AAED,MAAM,WAAW,wBAAwB;IACvC,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,wBAA6B,GAClC,eAAe,CA4DjB;AA2RD,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GACjC;IACD,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAClE,gBAAgB,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvH,WAAW,EAAE,MAAM,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;CACnD,CAyJA"}
1
+ {"version":3,"file":"hmr.d.ts","sourceRoot":"","sources":["../src/hmr.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAUxC,OAAO,EAAsC,KAAK,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAEvG,OAAO,KAAK,EAAE,SAAS,EAAkB,MAAM,yBAAyB,CAAC;AAIzE;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAaD,wBAAgB,WAAW,IAAI;IAC7B,MAAM,EAAE,IAAI,GAAG,QAAQ,CAAC;IACxB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAQA;AAED,MAAM,WAAW,wBAAwB;IACvC,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,wBAA6B,GAClC,eAAe,CAsEjB;AA0RD,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GACjC;IACD,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAClE,gBAAgB,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvH,WAAW,EAAE,MAAM,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;CACnD,CAyJA"}
package/dist/hmr.js CHANGED
@@ -6,6 +6,7 @@ import { compileClient } from '@vesk/compiler/src/client-codegen';
6
6
  import { buildHmrEvalSnippet } from './client-bundle';
7
7
  import { resolveComponentName, randomToken } from '@vesk/compiler/src/server-codegen';
8
8
  import { resolveErrorFile } from '@vesk/adapter/src/ssr-function';
9
+ import { resolveCssUrls, hasUserCss, hasBuiltTailwindCss } from '@vesk/adapter/src/css';
9
10
  import { isAllowedWsUpgrade } from '@vesk/adapter/src/paths';
10
11
  import { parseCompilerError, buildCodeframe } from '@vesk/adapter/src/error-codeframe';
11
12
  import { suggestFor } from '@vesk/adapter/src/error-tips';
@@ -78,11 +79,19 @@ export function buildErrorPayload(error, filename, opts = {}) {
78
79
  const filePath = typeof opts.appDir === 'string'
79
80
  ? resolve(opts.appDir, file)
80
81
  : undefined;
82
+ // The file header already shows the location; strip the redundant
83
+ // " in <file>" suffix compilers append to messages (e.g. acorn's
84
+ // "Unexpected token in /abs/app/page.vsk").
85
+ const cleanMessage = filePath && message.endsWith(` in ${filePath}`)
86
+ ? message.slice(0, -` in ${filePath}`.length).trim()
87
+ : message.endsWith(` in ${file}`)
88
+ ? message.slice(0, -` in ${file}`.length).trim()
89
+ : message;
81
90
  const payload = {
82
91
  file,
83
92
  line,
84
93
  column,
85
- message,
94
+ message: cleanMessage,
86
95
  };
87
96
  if (filePath)
88
97
  payload.filePath = filePath;
@@ -232,19 +241,16 @@ function buildParamExtraction(node, urlParts) {
232
241
  }
233
242
  function regenerateSsrFunction(routeNode, appDir, outDir, componentMap, options) {
234
243
  const ancestorLayouts = options?.ancestorLayouts || [];
244
+ const headExtra = options?.headExtra || null;
235
245
  const pagePath = resolve(appDir, routeNode.sourceDir, 'page.vsk');
236
246
  const layoutPath = resolve(appDir, routeNode.sourceDir, 'layout.vsk');
237
- const tailwindPath = resolve(outDir, 'static', '_tailwind.css');
238
- const globalCssPath = resolve(appDir, '..', 'src', 'global.css');
239
- const altCssPath = resolve(appDir, '..', 'src', 'app.css');
240
- const hasGlobalCss = existsSync(globalCssPath) || existsSync(altCssPath);
241
- const hasTailwind = existsSync(tailwindPath) && readFileSync(tailwindPath, 'utf-8').trim().length > 0;
242
- const cssUrls = [];
243
- if (hasTailwind)
244
- cssUrls.push('/_vesk/static/_tailwind.css');
245
- if (hasGlobalCss)
246
- cssUrls.push('/_vesk/static/global.css');
247
+ const cssUrls = resolveCssUrls({
248
+ tailwind: hasBuiltTailwindCss(outDir),
249
+ userCss: hasUserCss(appDir),
250
+ });
247
251
  const cssOption = cssUrls.length > 0 ? `, cssUrls: ${JSON.stringify(cssUrls)}` : '';
252
+ const headExtraOption = headExtra ? `, headExtra: ${JSON.stringify(headExtra)}` : '';
253
+ const bakedOptions = cssOption + headExtraOption;
248
254
  const parts = routeNode.fullPath.split('/').filter(Boolean);
249
255
  const name = routeName(parts);
250
256
  const funcDir = resolve(outDir, 'server', 'functions');
@@ -323,7 +329,7 @@ function regenerateSsrFunction(routeNode, appDir, outDir, componentMap, options)
323
329
  " const stack = err && typeof err === 'object' && 'stack' in err ? String(err.stack) : '';",
324
330
  " page = { body: await __renderErrorBody({ params, statusCode: 500, error: message, stack, url: url.href }), head: '' };",
325
331
  ' }',
326
- ' const html = await renderFullPage(_layoutSrc, _layoutComp, { params, children: (caughtError ? \'<!--vesk-ssr-error:\' + (caughtError && typeof caughtError === \'object\' && \'message\' in caughtError ? encodeURIComponent(String(caughtError.message)) : \'\') + \'-->\' : \'\') + page.body }, __componentRegistry, { hydrate: true, cached: _layoutCompiled' + cssOption + clientScriptOption + dataScriptOption + ', pageHead: page.head, sourcePath: _layoutPath });',
332
+ ' const html = await renderFullPage(_layoutSrc, _layoutComp, { params, children: (caughtError ? \'<!--vesk-ssr-error:\' + (caughtError && typeof caughtError === \'object\' && \'message\' in caughtError ? encodeURIComponent(String(caughtError.message)) : \'\') + \'-->\' : \'\') + page.body }, __componentRegistry, { hydrate: true, cached: _layoutCompiled' + bakedOptions + clientScriptOption + dataScriptOption + ', pageHead: page.head, sourcePath: _layoutPath });',
327
333
  " return new Response(html, { headers: { 'Content-Type': 'text/html' }, status: caughtError ? 500 : 200 });",
328
334
  ].join('\n');
329
335
  }
@@ -340,7 +346,7 @@ function regenerateSsrFunction(routeNode, appDir, outDir, componentMap, options)
340
346
  " const stack = err && typeof err === 'object' && 'stack' in err ? String(err.stack) : '';",
341
347
  " page = { body: await __renderErrorBody({ params, statusCode: 500, error: message, stack, url: url.href }), head: '' };",
342
348
  ' }',
343
- ' const html = await renderFullPage(_layoutSrc, _layoutComp, { params, children: (caughtError ? \'<!--vesk-ssr-error:\' + (caughtError && typeof caughtError === \'object\' && \'message\' in caughtError ? encodeURIComponent(String(caughtError.message)) : \'\') + \'-->\' : \'\') + page.body }, __componentRegistry, { hydrate: true, cached: _layoutCompiled' + cssOption + clientScriptOption + dataScriptOption + ', pageHead: page.head, sourcePath: _layoutPath });',
349
+ ' const html = await renderFullPage(_layoutSrc, _layoutComp, { params, children: (caughtError ? \'<!--vesk-ssr-error:\' + (caughtError && typeof caughtError === \'object\' && \'message\' in caughtError ? encodeURIComponent(String(caughtError.message)) : \'\') + \'-->\' : \'\') + page.body }, __componentRegistry, { hydrate: true, cached: _layoutCompiled' + bakedOptions + clientScriptOption + dataScriptOption + ', pageHead: page.head, sourcePath: _layoutPath });',
344
350
  " return new Response(html, { headers: { 'Content-Type': 'text/html' }, status: caughtError ? 500 : 200 });",
345
351
  ].join('\n');
346
352
  }
@@ -348,13 +354,13 @@ function regenerateSsrFunction(routeNode, appDir, outDir, componentMap, options)
348
354
  renderCode = [
349
355
  ' let stream;',
350
356
  ' try {',
351
- ' stream = renderPageStream(_src, _comp, { params }, __componentRegistry, { hydrate: true, cached: _srcCompiled' + cssOption + clientScriptOption + dataScriptOption + ", sourcePath: _srcPath });",
357
+ ' stream = renderPageStream(_src, _comp, { params }, __componentRegistry, { hydrate: true, cached: _srcCompiled' + bakedOptions + clientScriptOption + dataScriptOption + ", sourcePath: _srcPath });",
352
358
  ' } catch (err) {',
353
359
  ' if (err && (err.name === \'NotFoundError\' || err.name === \'Redirect\')) throw err;',
354
360
  ' if (!_errorSrc) throw err;',
355
361
  " const message = err && typeof err === 'object' && 'message' in err ? String(err.message) : String(err);",
356
362
  " const stack = err && typeof err === 'object' && 'stack' in err ? String(err.stack) : '';",
357
- " const html = await renderFullPage(_errorSrc, _errorComp, { params, statusCode: 500, error: message, stack, url: url.href }, __componentRegistry, { hydrate: true, cached: _errorCompiled" + cssOption + clientScriptOption + dataScriptOption + ', sourcePath: _errorPath });',
363
+ " const html = await renderFullPage(_errorSrc, _errorComp, { params, statusCode: 500, error: message, stack, url: url.href }, __componentRegistry, { hydrate: true, cached: _errorCompiled" + bakedOptions + clientScriptOption + dataScriptOption + ', sourcePath: _errorPath });',
358
364
  " return new Response(html, { headers: { 'Content-Type': 'text/html' }, status: 500 });",
359
365
  ' }',
360
366
  ' return new Response(new ReadableStream({',
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACe,YAAY,EAAE,WAAW,EAC7B,UAAU,EAChC,MAAM,yBAAyB,CAAC;AAiBjC;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;CACjB;AACD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,iBAAiB,EAAE,CAAC;CAC9B;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,UAAU,EAAE,EACrB,OAAO,EAAE,iBAAiB,EAAE,GAAG,IAAI,GAAG,SAAS,GAC9C,UAAU,EAAE,CAQd;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,UAAU,EAAE,EACrB,KAAK,EAAE,eAAe,GAAG,IAAI,GAAG,SAAS,GACxC,UAAU,EAAE,CAGd;AAWD,wBAAsB,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAyVpG;AAED,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAIhE,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,yBAAyB,EACzB,eAAe,GAChB,MAAM,2BAA2B,CAAC;AACnC,YAAY,EACV,mBAAmB,EACnB,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,aAAa,GACd,MAAM,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACe,YAAY,EAAE,WAAW,EAC7B,UAAU,EAChC,MAAM,yBAAyB,CAAC;AAiBjC;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;CACjB;AACD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,iBAAiB,EAAE,CAAC;CAC9B;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,UAAU,EAAE,EACrB,OAAO,EAAE,iBAAiB,EAAE,GAAG,IAAI,GAAG,SAAS,GAC9C,UAAU,EAAE,CAQd;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,UAAU,EAAE,EACrB,KAAK,EAAE,eAAe,GAAG,IAAI,GAAG,SAAS,GACxC,UAAU,EAAE,CAGd;AA+BD,wBAAsB,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAqUpG;AAED,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAIhE,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,yBAAyB,EACzB,eAAe,GAChB,MAAM,2BAA2B,CAAC;AACnC,YAAY,EACV,mBAAmB,EACnB,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,aAAa,GACd,MAAM,2BAA2B,CAAC"}
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { mkdirSync, writeFileSync, existsSync, readFileSync } from 'node:fs';
2
2
  import { resolve, dirname, relative, basename } from 'node:path';
3
3
  import { fileURLToPath } from 'node:url';
4
- import { cssBlockEnd } from '@vesk/compiler/src/scan';
5
4
  import { bundleRuntime } from '@vesk/adapter/src/runtime-bundle';
6
5
  import { generateSsrFunction } from '@vesk/adapter/src/ssr-function';
6
+ import { resolveUserCssPath, stripTailwindDirectives, isTailwindPlugin, resolveCssUrls, hasUserCss, hasBuiltTailwindCss } from '@vesk/adapter/src/css';
7
7
  import { collectActionIds } from '@vesk/compiler/src/actions';
8
8
  import { generateApiFunction } from '@vesk/adapter/src/api-function';
9
9
  import { compileMiddleware, compileMiddlewareCode } from '@vesk/adapter/src/middleware';
@@ -61,6 +61,28 @@ function veskDirFromOutDir(outDir) {
61
61
  return dirname(outDir);
62
62
  return outDir;
63
63
  }
64
+ /**
65
+ * Invoke every active plugin's `onHead` once with an empty head to capture its
66
+ * static head contribution. The result is baked into generated SSR functions
67
+ * and `config.json` (`headExtra`) for the prod path, where plugin objects are
68
+ * not available at request time.
69
+ */
70
+ async function collectPluginHeadExtra(pluginsPipelines) {
71
+ const parts = [];
72
+ for (const plugin of pluginsPipelines) {
73
+ if (typeof plugin.onHead !== 'function')
74
+ continue;
75
+ try {
76
+ const result = await plugin.onHead('', { sourcePath: 'build' });
77
+ if (typeof result === 'string' && result.trim())
78
+ parts.push(result);
79
+ }
80
+ catch {
81
+ // a failing onHead at bake time must not break the build
82
+ }
83
+ }
84
+ return parts.join('\n');
85
+ }
64
86
  export async function build(appDir, options) {
65
87
  appDir = resolve(appDir);
66
88
  const outDir = resolve(options?.outDir || resolve(appDir, '..', '.vesk'));
@@ -111,6 +133,13 @@ export async function build(appDir, options) {
111
133
  await plugin.onBuildStart();
112
134
  }
113
135
  }
136
+ // Bake the active `onHead` plugins' static head contribution for the prod
137
+ // SSR path (generated SSR functions + prod-server not-found/error pages have
138
+ // no in-process plugin objects, so their head snippets ship build-time).
139
+ // Live hooks still run in dev / build / SSG where plugin objects exist.
140
+ const pluginHeadExtra = await collectPluginHeadExtra(pluginsPipelines);
141
+ if (pluginHeadExtra)
142
+ console.error('vesk build: baked plugin head → config.json + SSR functions');
114
143
  console.error(`vesk build: output → ${outDir}`);
115
144
  const dirs = [
116
145
  resolve(outDir, 'server', 'functions'),
@@ -120,6 +149,48 @@ export async function build(appDir, options) {
120
149
  ];
121
150
  for (const d of dirs)
122
151
  mkdirSync(d, { recursive: true });
152
+ const cssSourcePath = resolveUserCssPath(appDir);
153
+ if (cssSourcePath !== null) {
154
+ const cssContent = readFileSync(cssSourcePath, 'utf-8');
155
+ const userCss = stripTailwindDirectives(cssContent);
156
+ const userCssTarget = resolve(outDir, 'static', 'global.css');
157
+ writeFileSync(userCssTarget, userCss, 'utf-8');
158
+ console.error(`vesk build: css → static/global.css (${userCss.length} bytes)`);
159
+ const twCssTarget = resolve(outDir, 'static', '_tailwind.css');
160
+ const tailwindActive = isTailwindPlugin(pluginsPipelines);
161
+ if (!tailwindActive) {
162
+ writeFileSync(twCssTarget, '', 'utf-8');
163
+ console.error('vesk build: css → static/_tailwind.css (empty, tailwind plugin inactive)');
164
+ }
165
+ else {
166
+ let twCss = cssContent;
167
+ for (const plugin of pluginsPipelines) {
168
+ if (typeof plugin.onCSS === 'function') {
169
+ const result = await plugin.onCSS(twCss, cssSourcePath);
170
+ if (result !== null && typeof result === 'string') {
171
+ twCss = result;
172
+ }
173
+ }
174
+ }
175
+ const hasUnresolvedTailwindImport = /@import\s+['"]tailwindcss['"]/.test(twCss);
176
+ if (hasUnresolvedTailwindImport) {
177
+ const lines = twCss.split('\n').filter(l => !/^\s*@import\s+['"]tailwindcss['"]/.test(l));
178
+ twCss = lines.join('\n').trim();
179
+ if (twCss.length === 0) {
180
+ writeFileSync(twCssTarget, '', 'utf-8');
181
+ console.error('vesk build: css → static/_tailwind.css (empty, tailwind unresolved)');
182
+ }
183
+ else {
184
+ writeFileSync(twCssTarget, twCss, 'utf-8');
185
+ console.error(`vesk build: css → static/_tailwind.css (${twCss.length} bytes, tailwind partially unresolved)`);
186
+ }
187
+ }
188
+ else {
189
+ writeFileSync(twCssTarget, twCss, 'utf-8');
190
+ console.error(`vesk build: css → static/_tailwind.css (${twCss.length} bytes)`);
191
+ }
192
+ }
193
+ }
123
194
  const { scanRoutes, scanComponents } = await resolveCompilerApi('router.js');
124
195
  const { scanApiRoutes } = await resolveCompilerApi('api-routes.js');
125
196
  const { collectMiddlewareChain } = await resolveCompilerApi('middleware.js');
@@ -153,7 +224,7 @@ export async function build(appDir, options) {
153
224
  const mwSources = mwChain.map((m) => readFileSync(m.sourcePath, 'utf-8'));
154
225
  mwCode = compileMiddlewareCode(mwSources);
155
226
  }
156
- const { funcPath, funcCode, name } = generateSsrFunction(node, appDir, outDir, componentMap, { ancestorLayouts, middlewareCode: mwCode });
227
+ const { funcPath, funcCode, name } = generateSsrFunction(node, appDir, outDir, componentMap, { ancestorLayouts, middlewareCode: mwCode, headExtra: pluginHeadExtra });
157
228
  writeFileSync(funcPath, funcCode, 'utf-8');
158
229
  const pagePath = resolve(appDir, node.sourceDir, 'page.vsk');
159
230
  if (existsSync(pagePath)) {
@@ -217,6 +288,8 @@ export async function build(appDir, options) {
217
288
  bundleOpts.hmr = true;
218
289
  if (options?.routeDataCache !== undefined)
219
290
  bundleOpts.routeDataCache = options.routeDataCache;
291
+ if (pluginsPipelines.length > 0)
292
+ bundleOpts.plugins = pluginsPipelines;
220
293
  const { main, chunks } = await generateClientBundle(routeTree, appDir, componentMap, bundleOpts);
221
294
  writeFileSync(resolve(outDir, 'static', 'client.js'), main, 'utf-8');
222
295
  const mode = chunks.length > 0 ? 'code-split' : 'monolithic';
@@ -230,82 +303,14 @@ export async function build(appDir, options) {
230
303
  }
231
304
  copyStaticAssets(publicDir, outDir);
232
305
  console.error('vesk build: static → static/public/');
233
- const srcDir = resolve(appDir, '..', 'src');
234
- const cssSrc = resolve(srcDir, 'global.css');
235
- const altCssSrc = resolve(srcDir, 'app.css');
236
- let cssContent = null;
237
- let cssSourcePath = null;
238
- if (existsSync(cssSrc)) {
239
- cssContent = readFileSync(cssSrc, 'utf-8');
240
- cssSourcePath = cssSrc;
241
- }
242
- else if (existsSync(altCssSrc)) {
243
- cssContent = readFileSync(altCssSrc, 'utf-8');
244
- cssSourcePath = altCssSrc;
245
- }
246
- function stripTailwindDirectives(css) {
247
- const blockStart = /^\s*@(theme\s*\{|layer\s+(components|utilities)\s*\{|utility\s+\w+\s*\{)/;
248
- let result = css.replace(/^\s*@import\s+['"]tailwindcss['"]\s*;?\s*$/gm, '');
249
- result = result.replace(/^\s*@source\s+['"][^'"]+['"]\s*;?\s*$/gm, '');
250
- const output = [];
251
- let pos = 0;
252
- while (pos < result.length) {
253
- const lineEnd = result.indexOf('\n', pos) === -1 ? result.length : result.indexOf('\n', pos) + 1;
254
- const line = result.slice(pos, lineEnd);
255
- if (blockStart.test(line.trim())) {
256
- const end = cssBlockEnd(result, pos);
257
- pos = end;
258
- continue;
259
- }
260
- output.push(line);
261
- pos = lineEnd;
262
- }
263
- return output.join('').trim();
264
- }
265
- if (cssContent !== null) {
266
- const userCss = stripTailwindDirectives(cssContent);
267
- const userCssTarget = resolve(outDir, 'static', 'global.css');
268
- writeFileSync(userCssTarget, userCss, 'utf-8');
269
- console.error(`vesk build: css → static/global.css (${userCss.length} bytes)`);
270
- const twCssTarget = resolve(outDir, 'static', '_tailwind.css');
271
- const isTailwindActive = pluginsPipelines.some((p) => String(p.name).toLowerCase().includes('tailwind'));
272
- if (!isTailwindActive) {
273
- writeFileSync(twCssTarget, '', 'utf-8');
274
- console.error('vesk build: css → static/_tailwind.css (empty, tailwind plugin inactive)');
275
- }
276
- else {
277
- let twCss = cssContent;
278
- for (const plugin of pluginsPipelines) {
279
- if (typeof plugin.onCSS === 'function') {
280
- const result = await plugin.onCSS(twCss, cssSourcePath);
281
- if (result !== null && typeof result === 'string') {
282
- twCss = result;
283
- }
284
- }
285
- }
286
- const hasUnresolvedTailwindImport = /@import\s+['"]tailwindcss['"]/.test(twCss);
287
- if (hasUnresolvedTailwindImport) {
288
- const lines = twCss.split('\n').filter(l => !/^\s*@import\s+['"]tailwindcss['"]/.test(l));
289
- twCss = lines.join('\n').trim();
290
- if (twCss.length === 0) {
291
- writeFileSync(twCssTarget, '', 'utf-8');
292
- console.error('vesk build: css → static/_tailwind.css (empty, tailwind unresolved)');
293
- }
294
- else {
295
- writeFileSync(twCssTarget, twCss, 'utf-8');
296
- console.error(`vesk build: css → static/_tailwind.css (${twCss.length} bytes, tailwind partially unresolved)`);
297
- }
298
- }
299
- else {
300
- writeFileSync(twCssTarget, twCss, 'utf-8');
301
- console.error(`vesk build: css → static/_tailwind.css (${twCss.length} bytes)`);
302
- }
303
- }
304
- }
305
306
  let prerenderedRoutes = [];
306
307
  if (options?.ssg) {
307
308
  const { generateSsgRoutes } = await import('./static.js');
308
- prerenderedRoutes = await generateSsgRoutes(routeTree, appDir, outDir);
309
+ const cssUrls = resolveCssUrls({
310
+ tailwind: hasBuiltTailwindCss(outDir),
311
+ userCss: hasUserCss(appDir),
312
+ });
313
+ prerenderedRoutes = await generateSsgRoutes(routeTree, appDir, outDir, pluginsPipelines, pluginHeadExtra, cssUrls);
309
314
  console.error(`vesk build: ssg → prerendered/ (${prerenderedRoutes.length} pages)`);
310
315
  }
311
316
  {
@@ -340,7 +345,7 @@ export async function build(appDir, options) {
340
345
  console.error(`vesk build: seo → static/public/robots.txt (${robots.length} bytes)`);
341
346
  }
342
347
  }
343
- const manifest = generateManifest(routeTree, ssrRoutes, apiRoutes, prerenderedRoutes, middlewareEnabled, actionMap);
348
+ const manifest = generateManifest(routeTree, ssrRoutes, apiRoutes, prerenderedRoutes, middlewareEnabled, actionMap, pluginHeadExtra);
344
349
  writeFileSync(resolve(outDir, 'config.json'), JSON.stringify(manifest, null, 2) + '\n', 'utf-8');
345
350
  console.error('vesk build: config → config.json');
346
351
  {
@@ -1,3 +1,3 @@
1
1
  import type { RouteNode, ApiRouteNode, Manifest, SsgRouteResult } from '@vesk/adapter/src/types';
2
- export declare function generateManifest(routes: RouteNode[], ssrRoutes: RouteNode[], apiRoutes: ApiRouteNode[], staticRoutes: SsgRouteResult[], middlewareEnabled: boolean, actionMap?: Record<string, string>): Manifest;
2
+ export declare function generateManifest(routes: RouteNode[], ssrRoutes: RouteNode[], apiRoutes: ApiRouteNode[], staticRoutes: SsgRouteResult[], middlewareEnabled: boolean, actionMap?: Record<string, string>, headExtra?: string): Manifest;
3
3
  //# sourceMappingURL=manifest.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAqE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEpK,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,SAAS,EAAE,EACnB,SAAS,EAAE,SAAS,EAAE,EACtB,SAAS,EAAE,YAAY,EAAE,EACzB,YAAY,EAAE,cAAc,EAAE,EAC9B,iBAAiB,EAAE,OAAO,EAC1B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACjC,QAAQ,CAiDV"}
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAqE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEpK,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,SAAS,EAAE,EACnB,SAAS,EAAE,SAAS,EAAE,EACtB,SAAS,EAAE,YAAY,EAAE,EACzB,YAAY,EAAE,cAAc,EAAE,EAC9B,iBAAiB,EAAE,OAAO,EAC1B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAClC,SAAS,CAAC,EAAE,MAAM,GACjB,QAAQ,CAkDV"}
package/dist/manifest.js CHANGED
@@ -1,4 +1,4 @@
1
- export function generateManifest(routes, ssrRoutes, apiRoutes, staticRoutes, middlewareEnabled, actionMap) {
1
+ export function generateManifest(routes, ssrRoutes, apiRoutes, staticRoutes, middlewareEnabled, actionMap, headExtra) {
2
2
  const routeEntries = [];
3
3
  for (const r of ssrRoutes) {
4
4
  const urlParts = r.fullPath.split('/').filter(Boolean);
@@ -43,5 +43,6 @@ export function generateManifest(routes, ssrRoutes, apiRoutes, staticRoutes, mid
43
43
  dir: 'static',
44
44
  },
45
45
  ...(actionEntries.length > 0 ? { actions: actionEntries } : {}),
46
+ ...(headExtra ? { headExtra } : {}),
46
47
  };
47
48
  }
@@ -1 +1 @@
1
- {"version":3,"file":"prod-server.d.ts","sourceRoot":"","sources":["../src/prod-server.ts"],"names":[],"mappings":"AAEA,OAAO,EAA2D,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AA8CjG,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAIzE;AA4FD,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAiZxI"}
1
+ {"version":3,"file":"prod-server.d.ts","sourceRoot":"","sources":["../src/prod-server.ts"],"names":[],"mappings":"AAEA,OAAO,EAA2D,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AA+CjG,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAIzE;AA+FD,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA+YxI"}
@@ -6,6 +6,7 @@ import { fileURLToPath } from 'node:url';
6
6
  import { createRateLimiter, resolveComponentName, safeJsonForScript, getClientProtocol, DEFAULT_MAX_BODY_BYTES } from '@vesk/compiler/src/server-codegen';
7
7
  import { securityHeaders } from '@vesk/compiler/src/server-utils';
8
8
  import { resolveWithin, installMdReadHook } from '@vesk/adapter/src/paths';
9
+ import { resolveCssUrls, hasUserCss, hasBuiltTailwindCss } from '@vesk/adapter/src/css';
9
10
  const _require = createRequire(import.meta.url);
10
11
  const __dirname = dirname(fileURLToPath(import.meta.url));
11
12
  async function readBody(req, maxBytes = DEFAULT_MAX_BODY_BYTES) {
@@ -111,6 +112,7 @@ const MIME = {
111
112
  '.svg': 'image/svg+xml', '.css': 'text/css', '.js': 'application/javascript',
112
113
  '.png': 'image/png', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg',
113
114
  '.ico': 'image/x-icon', '.html': 'text/html', '.json': 'application/json',
115
+ '.webmanifest': 'application/manifest+json',
114
116
  '.woff': 'font/woff', '.woff2': 'font/woff2', '.wasm': 'application/wasm',
115
117
  };
116
118
  export async function startProdServer(outDir, options) {
@@ -129,6 +131,10 @@ export async function startProdServer(outDir, options) {
129
131
  process.exit(1);
130
132
  }
131
133
  const buildConfig = JSON.parse(readFileSync(configPath, 'utf-8'));
134
+ // Baked onHead-plugin head snippet (config.json `headExtra`) — applied to
135
+ // pages that render directly here (not-found / error) where no SSR function
136
+ // and no in-process plugin objects exist.
137
+ const bakedHeadExtra = buildConfig.headExtra || '';
132
138
  console.error(`vesk start: serving from ${outDir}`);
133
139
  const projectDir = resolve(outDir, '..');
134
140
  let securityConfig = {};
@@ -408,6 +414,10 @@ export async function startProdServer(outDir, options) {
408
414
  }
409
415
  }
410
416
  const appDir = resolve(projectDir, 'app');
417
+ const pageCssUrls = resolveCssUrls({
418
+ tailwind: hasBuiltTailwindCss(outDir),
419
+ userCss: hasUserCss(appDir),
420
+ });
411
421
  const nfPath = resolve(appDir, 'not-found.vsk');
412
422
  let notFoundHtml = null;
413
423
  if (existsSync(nfPath)) {
@@ -416,13 +426,7 @@ export async function startProdServer(outDir, options) {
416
426
  const { renderFullPage, storeDataScriptGlobal } = await import(runtimePath);
417
427
  const src = readFileSync(nfPath, 'utf-8');
418
428
  const compName = resolveComponentName(src) || 'NotFound';
419
- const tailwindPathNF = resolve(outDir, 'static', '_tailwind.css');
420
- const hasTailwindNF = existsSync(tailwindPathNF) && readFileSync(tailwindPathNF, 'utf-8').trim().length > 0;
421
- const cssUrlsNF = [];
422
- if (hasTailwindNF)
423
- cssUrlsNF.push('/_vesk/static/_tailwind.css');
424
- cssUrlsNF.push('/_vesk/static/global.css');
425
- notFoundHtml = await renderFullPage(src, compName, { params: {}, url: url.pathname }, new Map(), { hydrate: true, cssUrls: cssUrlsNF, security: securityConfig?.security || {}, externalDataScript: storeDataScriptGlobal, sourcePath: nfPath });
429
+ notFoundHtml = await renderFullPage(src, compName, { params: {}, url: url.pathname }, new Map(), { hydrate: true, cssUrls: pageCssUrls, security: securityConfig?.security || {}, externalDataScript: storeDataScriptGlobal, sourcePath: nfPath, headExtra: bakedHeadExtra });
426
430
  }
427
431
  catch { }
428
432
  }
@@ -491,13 +495,7 @@ export async function startProdServer(outDir, options) {
491
495
  const compName = resolveComponentName(src) || 'Error';
492
496
  // never leak stack traces / internal messages to prod error pages
493
497
  const expose = process.env.NODE_ENV !== 'production';
494
- const tailwindPathErr = resolve(outDir, 'static', '_tailwind.css');
495
- const hasTailwindErr = existsSync(tailwindPathErr) && readFileSync(tailwindPathErr, 'utf-8').trim().length > 0;
496
- const cssUrlsErr = [];
497
- if (hasTailwindErr)
498
- cssUrlsErr.push('/_vesk/static/_tailwind.css');
499
- cssUrlsErr.push('/_vesk/static/global.css');
500
- errorHtml = await renderFullPage(src, compName, { error: expose ? err.message : 'Internal Server Error', stack: expose ? err.stack : '', statusCode: 500, url: url.pathname }, new Map(), { hydrate: true, cssUrls: cssUrlsErr, clientScriptUrl: '/_vesk/static/client.js', security: securityConfig?.security || {}, externalDataScript: storeDataScriptGlobal, sourcePath: errPath });
498
+ errorHtml = await renderFullPage(src, compName, { error: expose ? err.message : 'Internal Server Error', stack: expose ? err.stack : '', statusCode: 500, url: url.pathname }, new Map(), { hydrate: true, cssUrls: pageCssUrls, clientScriptUrl: '/_vesk/static/client.js', security: securityConfig?.security || {}, externalDataScript: storeDataScriptGlobal, sourcePath: errPath, headExtra: bakedHeadExtra });
501
499
  }
502
500
  catch { }
503
501
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ssr-function.d.ts","sourceRoot":"","sources":["../src/ssr-function.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAkB,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAW7F,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQjF;AAiDD,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAClC,OAAO,CAAC,EAAE,kBAAkB,GAC3B;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAqXtD"}
1
+ {"version":3,"file":"ssr-function.d.ts","sourceRoot":"","sources":["../src/ssr-function.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAkB,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAW7F,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQjF;AAiDD,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAClC,OAAO,CAAC,EAAE,kBAAkB,GAC3B;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAsXtD"}
@@ -1,6 +1,7 @@
1
1
  import { readFileSync, existsSync } from 'node:fs';
2
2
  import { resolve, relative, join } from 'node:path';
3
3
  import { resolveComponentName } from '@vesk/compiler/src/server-codegen';
4
+ import { resolveCssUrls, hasUserCss, hasBuiltTailwindCss } from '@vesk/adapter/src/css';
4
5
  function escapeSource(src) {
5
6
  return src
6
7
  .replace(/\\/g, '\\\\')
@@ -72,23 +73,22 @@ function buildParamExtraction(node, urlParts) {
72
73
  export function generateSsrFunction(routeNode, appDir, outDir, componentMap, options) {
73
74
  const ancestorLayouts = options?.ancestorLayouts || [];
74
75
  const middlewareCode = options?.middlewareCode || null;
76
+ const headExtra = options?.headExtra || null;
75
77
  const pagePath = resolve(appDir, routeNode.sourceDir, 'page.vsk');
76
78
  const layoutPath = resolve(appDir, routeNode.sourceDir, 'layout.vsk');
77
79
  const parts = routeNode.fullPath.split('/').filter(Boolean);
78
80
  const name = routeName(parts);
79
81
  const funcDir = resolve(outDir, 'server', 'functions');
80
82
  const funcPath = resolve(funcDir, `${name}.js`);
81
- const tailwindPath = resolve(outDir, 'static', '_tailwind.css');
82
- const globalCssPath = resolve(appDir, '..', 'src', 'global.css');
83
- const altCssPath = resolve(appDir, '..', 'src', 'app.css');
84
- const hasGlobalCss = existsSync(globalCssPath) || existsSync(altCssPath);
85
- const hasTailwind = existsSync(tailwindPath) && readFileSync(tailwindPath, 'utf-8').trim().length > 0;
86
- const cssUrls = [];
87
- if (hasTailwind)
88
- cssUrls.push('/_vesk/static/_tailwind.css');
89
- if (hasGlobalCss)
90
- cssUrls.push('/_vesk/static/global.css');
83
+ const cssUrls = resolveCssUrls({
84
+ tailwind: hasBuiltTailwindCss(outDir),
85
+ userCss: hasUserCss(appDir),
86
+ });
91
87
  const cssOption = cssUrls.length > 0 ? `, cssUrls: ${JSON.stringify(cssUrls)}` : '';
88
+ // Static head snippet baked from the active onHead plugins — merged into
89
+ // every rendered head at request time (page tags win via mergeHeadHtml).
90
+ const headExtraOption = headExtra ? `, headExtra: ${JSON.stringify(headExtra)}` : '';
91
+ const bakedOptions = cssOption + headExtraOption;
92
92
  const hasLayout = !!routeNode.layout;
93
93
  const hasAncestorLayout = ancestorLayouts.length > 0;
94
94
  const pageSrc = readFileSync(pagePath, 'utf-8');
@@ -176,7 +176,7 @@ export function generateSsrFunction(routeNode, appDir, outDir, componentMap, opt
176
176
  " const stack = err && typeof err === 'object' && 'stack' in err ? String(err.stack) : '';",
177
177
  " page = { body: await __renderErrorBody({ params, statusCode: 500, error: __expose ? message : 'Internal Server Error', stack: __expose ? stack : '', url: requestUrl || '' }), head: '' };",
178
178
  ' }',
179
- " 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 });',
179
+ " 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 });',
180
180
  " return new Response(html, { headers: { 'Content-Type': 'text/html' }, status: caughtError ? 500 : 200 });",
181
181
  ' });',
182
182
  '}',
@@ -191,14 +191,14 @@ export function generateSsrFunction(routeNode, appDir, outDir, componentMap, opt
191
191
  " const message = err && typeof err === 'object' && 'message' in err ? String(err.message) : String(err);",
192
192
  " const stack = err && typeof err === 'object' && 'stack' in err ? String(err.stack) : '';",
193
193
  " const props = { params, statusCode: 500, error: __expose ? message : 'Internal Server Error', stack: __expose ? stack : '', url: requestUrl || '' };",
194
- ' return renderFullPage(_errorSrc, _errorComp, props, __componentRegistry, { hydrate: true, cached: _errorCompiled' + cssOption + clientScriptOption + dataScriptOption + ', sourcePath: _errorPath });',
194
+ ' return renderFullPage(_errorSrc, _errorComp, props, __componentRegistry, { hydrate: true, cached: _errorCompiled' + bakedOptions + clientScriptOption + dataScriptOption + ', sourcePath: _errorPath });',
195
195
  '}',
196
196
  '',
197
197
  'async function __renderHtml(params, requestUrl) {',
198
198
  ' return withSsrStore(async () => {',
199
199
  ' let stream;',
200
200
  ' try {',
201
- ' stream = renderPageStream(_src, _comp, { params }, __componentRegistry, { hydrate: true, cached: _srcCompiled' + cssOption + clientScriptOption + dataScriptOption + ', sourcePath: _srcPath });',
201
+ ' stream = renderPageStream(_src, _comp, { params }, __componentRegistry, { hydrate: true, cached: _srcCompiled' + bakedOptions + clientScriptOption + dataScriptOption + ', sourcePath: _srcPath });',
202
202
  ' } catch (err) {',
203
203
  ' if (err && (err.name === \'NotFoundError\' || err.name === \'Redirect\')) throw err;',
204
204
  ' const html = await __renderErrorFullPage(params, requestUrl, err);',
package/dist/static.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { RouteNode, SsgRouteResult } from '@vesk/adapter/src/types';
2
2
  export declare function copyStaticAssets(publicDir: string, outDir: string): void;
3
- export declare function generateSsgRoutes(routeTree: RouteNode[], appDir: string, outDir: string): Promise<SsgRouteResult[]>;
3
+ export declare function generateSsgRoutes(routeTree: RouteNode[], appDir: string, outDir: string, plugins?: import('@vesk/types').VeskPlugin[], headExtra?: string, cssUrls?: string[]): Promise<SsgRouteResult[]>;
4
4
  export declare function generateSitemap(_routeTree: RouteNode[], ssrRoutes: RouteNode[], prerenderedRoutes: SsgRouteResult[], { siteUrl }?: {
5
5
  siteUrl?: string;
6
6
  }): string;
@@ -1 +1 @@
1
- {"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../src/static.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEzE,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAsBxE;AAED,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAwEzH;AAED,wBAAgB,eAAe,CAC7B,UAAU,EAAE,SAAS,EAAE,EACvB,SAAS,EAAE,SAAS,EAAE,EACtB,iBAAiB,EAAE,cAAc,EAAE,EACnC,EAAE,OAAiC,EAAE,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/D,MAAM,CAoCR;AAED,wBAAgB,iBAAiB,CAAC,OAAO,SAA0B,GAAG,MAAM,CAK3E"}
1
+ {"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../src/static.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEzE,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAsBxE;AAED,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,SAAS,EAAE,EACtB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,OAAO,aAAa,EAAE,UAAU,EAAE,EAC5C,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,cAAc,EAAE,CAAC,CA0E3B;AAED,wBAAgB,eAAe,CAC7B,UAAU,EAAE,SAAS,EAAE,EACvB,SAAS,EAAE,SAAS,EAAE,EACtB,iBAAiB,EAAE,cAAc,EAAE,EACnC,EAAE,OAAiC,EAAE,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/D,MAAM,CAoCR;AAED,wBAAgB,iBAAiB,CAAC,OAAO,SAA0B,GAAG,MAAM,CAK3E"}
package/dist/static.js CHANGED
@@ -23,10 +23,11 @@ export function copyStaticAssets(publicDir, outDir) {
23
23
  }
24
24
  copyDir(publicDir, targetDir);
25
25
  }
26
- export async function generateSsgRoutes(routeTree, appDir, outDir) {
26
+ export async function generateSsgRoutes(routeTree, appDir, outDir, plugins, headExtra, cssUrls) {
27
27
  const { ssg } = await import('@vesk/compiler/src/server-render');
28
28
  const prerenderDir = resolve(outDir, 'prerendered');
29
29
  mkdirSync(prerenderDir, { recursive: true });
30
+ const ssgOptions = { plugins, headExtra, cssUrls };
30
31
  const results = [];
31
32
  async function evaluateExport(src, exportName) {
32
33
  try {
@@ -55,7 +56,7 @@ export async function generateSsgRoutes(routeTree, appDir, outDir) {
55
56
  for (const entry of paths) {
56
57
  try {
57
58
  const params = entry.params || {};
58
- const result = await ssg(src, null, params, {});
59
+ const result = await ssg(src, null, params, ssgOptions);
59
60
  const urlPath = entry.path || node.fullPath;
60
61
  // getStaticPaths output is app-controlled but must never write
61
62
  // outside the prerender output dir
@@ -78,7 +79,7 @@ export async function generateSsgRoutes(routeTree, appDir, outDir) {
78
79
  }
79
80
  else if (hasStaticProps) {
80
81
  try {
81
- const result = await ssg(src, null, undefined, {});
82
+ const result = await ssg(src, null, undefined, ssgOptions);
82
83
  const htmlPath = resolve(prerenderDir, node.fullPath === '/' ? 'index.html' : `${node.fullPath.slice(1)}.html`);
83
84
  mkdirSync(resolve(htmlPath, '..'), { recursive: true });
84
85
  writeFileSync(htmlPath, result.html);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vesk/adapter",
3
- "version": "0.2.12",
3
+ "version": "0.2.15",
4
4
  "type": "module",
5
5
  "description": "Vesk adapter — builds deployable .vesk/ output for Deno and Node serverless",
6
6
  "main": "./dist/index.js",
@@ -23,9 +23,9 @@
23
23
  "sharp": "^0.35.3"
24
24
  },
25
25
  "dependencies": {
26
- "@vesk/compiler": "^0.2.12",
27
- "@vesk/runtime": "^0.2.12",
28
- "@vesk/types": "^0.2.12"
26
+ "@vesk/compiler": "^0.2.15",
27
+ "@vesk/runtime": "^0.2.15",
28
+ "@vesk/types": "^0.2.15"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@types/ws": "^8.18.1",