veryfront 0.1.162 → 0.1.163

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/esm/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.1.162",
3
+ "version": "0.1.163",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "exclude": [
@@ -0,0 +1,31 @@
1
+ import type { VeryfrontConfig } from "../../config/index.js";
2
+ import type { HTMLGenerationOptions } from "../../html/index.js";
3
+ import { getProjectCSS } from "../../html/styles-builder/index.js";
4
+ import { warmPreparedCSSArtifactFromFiles } from "../../html/styles-builder/css-pregeneration.js";
5
+ import { resolveStyleContentVersion } from "../../html/styles-builder/content-version.js";
6
+ import { createStyleScopeProfile } from "../../html/styles-builder/style-scope-profile.js";
7
+ import type { RuntimeAdapter } from "../../platform/adapters/base.js";
8
+ import { getRouteCandidates } from "./css-candidate-manifest.js";
9
+ import type { HTMLGenerationContext } from "./html.js";
10
+ export type ProjectCSSResult = Awaited<ReturnType<typeof getProjectCSS>> | null;
11
+ interface ProjectCssConfig {
12
+ projectDir: string;
13
+ adapter: RuntimeAdapter;
14
+ config: VeryfrontConfig;
15
+ mode: "development" | "production";
16
+ }
17
+ interface ProjectCssDeps {
18
+ createStyleScopeProfile?: typeof createStyleScopeProfile;
19
+ getProjectCSS?: typeof getProjectCSS;
20
+ getProjectContentVersion?: (config: Pick<ProjectCssConfig, "adapter" | "mode">) => string | undefined;
21
+ getRouteCandidates?: typeof getRouteCandidates;
22
+ resolveStyleContentVersion?: typeof resolveStyleContentVersion;
23
+ warmPreparedCSSArtifactFromFiles?: typeof warmPreparedCSSArtifactFromFiles;
24
+ }
25
+ export declare function buildRouteManifestKey(pagePath: string, projectDir: string): string;
26
+ export declare function getProjectContentVersion(config: Pick<ProjectCssConfig, "adapter" | "mode">, deps?: Pick<ProjectCssDeps, "resolveStyleContentVersion">): string | undefined;
27
+ export declare function startProjectCSSPreparation(context: HTMLGenerationContext, htmlOptions: HTMLGenerationOptions, deps?: Pick<ProjectCssDeps, "getProjectCSS">): Promise<ProjectCSSResult> | undefined;
28
+ export declare function startPreparedCSSWarmup(config: ProjectCssConfig, context: HTMLGenerationContext, htmlOptions: HTMLGenerationOptions, deps?: Pick<ProjectCssDeps, "createStyleScopeProfile" | "getProjectContentVersion" | "warmPreparedCSSArtifactFromFiles">): void;
29
+ export declare function extractProjectClassesForRoute(config: ProjectCssConfig, context: HTMLGenerationContext, appComponentPath?: string, deps?: Pick<ProjectCssDeps, "createStyleScopeProfile" | "getProjectContentVersion" | "getRouteCandidates">): Promise<Set<string>>;
30
+ export {};
31
+ //# sourceMappingURL=html-project-css.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-project-css.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/orchestrator/html-project-css.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,gCAAgC,EAAE,MAAM,gDAAgD,CAAC;AAClG,OAAO,EAAE,0BAA0B,EAAE,MAAM,8CAA8C,CAAC;AAC1F,OAAO,EAAE,uBAAuB,EAAE,MAAM,kDAAkD,CAAC;AAC3F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAItE,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAIvD,MAAM,MAAM,gBAAgB,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC,GAAG,IAAI,CAAC;AAEhF,UAAU,gBAAgB;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,cAAc,CAAC;IACxB,MAAM,EAAE,eAAe,CAAC;IACxB,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;CACpC;AAED,UAAU,cAAc;IACtB,uBAAuB,CAAC,EAAE,OAAO,uBAAuB,CAAC;IACzD,aAAa,CAAC,EAAE,OAAO,aAAa,CAAC;IACrC,wBAAwB,CAAC,EAAE,CACzB,MAAM,EAAE,IAAI,CAAC,gBAAgB,EAAE,SAAS,GAAG,MAAM,CAAC,KAC/C,MAAM,GAAG,SAAS,CAAC;IACxB,kBAAkB,CAAC,EAAE,OAAO,kBAAkB,CAAC;IAC/C,0BAA0B,CAAC,EAAE,OAAO,0BAA0B,CAAC;IAC/D,gCAAgC,CAAC,EAAE,OAAO,gCAAgC,CAAC;CAC5E;AAUD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAKlF;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,IAAI,CAAC,gBAAgB,EAAE,SAAS,GAAG,MAAM,CAAC,EAClD,IAAI,GAAE,IAAI,CAAC,cAAc,EAAE,4BAA4B,CAAM,GAC5D,MAAM,GAAG,SAAS,CAiBpB;AAED,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,qBAAqB,EAC9B,WAAW,EAAE,qBAAqB,EAClC,IAAI,GAAE,IAAI,CAAC,cAAc,EAAE,eAAe,CAAM,GAC/C,OAAO,CAAC,gBAAgB,CAAC,GAAG,SAAS,CAkBvC;AAED,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,qBAAqB,EAC9B,WAAW,EAAE,qBAAqB,EAClC,IAAI,GAAE,IAAI,CACR,cAAc,EACd,yBAAyB,GAAG,0BAA0B,GAAG,kCAAkC,CACvF,GACL,IAAI,CAyCN;AAED,wBAAsB,6BAA6B,CACjD,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,qBAAqB,EAC9B,gBAAgB,CAAC,EAAE,MAAM,EACzB,IAAI,GAAE,IAAI,CACR,cAAc,EACd,yBAAyB,GAAG,0BAA0B,GAAG,oBAAoB,CACzE,GACL,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CA+CtB"}
@@ -0,0 +1,126 @@
1
+ import { getProjectCSS } from "../../html/styles-builder/index.js";
2
+ import { warmPreparedCSSArtifactFromFiles } from "../../html/styles-builder/css-pregeneration.js";
3
+ import { resolveStyleContentVersion } from "../../html/styles-builder/content-version.js";
4
+ import { createStyleScopeProfile } from "../../html/styles-builder/style-scope-profile.js";
5
+ import { rendererLogger } from "../../utils/index.js";
6
+ import { extractRelativePath } from "../../utils/route-path-utils.js";
7
+ import { getRouteCandidates } from "./css-candidate-manifest.js";
8
+ const logger = rendererLogger.component("html-project-css");
9
+ function getUnderlyingFsAdapter(adapter) {
10
+ const wrappedFs = adapter.fs;
11
+ if (typeof wrappedFs.getUnderlyingAdapter !== "function")
12
+ return undefined;
13
+ return wrappedFs.getUnderlyingAdapter();
14
+ }
15
+ export function buildRouteManifestKey(pagePath, projectDir) {
16
+ const relativePagePath = extractRelativePath(pagePath, projectDir);
17
+ return relativePagePath
18
+ .replace(/\.(tsx|ts|jsx|mdx|md|js)$/, "")
19
+ .replace(/^pages\//, "");
20
+ }
21
+ export function getProjectContentVersion(config, deps = {}) {
22
+ const fsAdapter = getUnderlyingFsAdapter(config.adapter);
23
+ if (!fsAdapter)
24
+ return undefined;
25
+ const contentContext = typeof fsAdapter.getContentContext === "function"
26
+ ? fsAdapter.getContentContext()
27
+ : null;
28
+ if (contentContext) {
29
+ const resolveContentVersion = deps.resolveStyleContentVersion ?? resolveStyleContentVersion;
30
+ return resolveContentVersion(contentContext);
31
+ }
32
+ return fsAdapter.getProjectData?.()?.updated_at;
33
+ }
34
+ export function startProjectCSSPreparation(context, htmlOptions, deps = {}) {
35
+ const isLocalProject = htmlOptions.isLocalProject ?? false;
36
+ if (isLocalProject || htmlOptions.environment !== "production")
37
+ return undefined;
38
+ const projectScope = htmlOptions.projectSlug || htmlOptions.projectId || context.slug;
39
+ if (!projectScope || projectScope === "default")
40
+ return undefined;
41
+ const getProjectCss = deps.getProjectCSS ?? getProjectCSS;
42
+ return getProjectCss(projectScope, htmlOptions.globalCSS, new Set([...(htmlOptions.projectClasses ?? [])]), {
43
+ minify: true,
44
+ environment: htmlOptions.environment,
45
+ buildMode: htmlOptions.mode,
46
+ });
47
+ }
48
+ export function startPreparedCSSWarmup(config, context, htmlOptions, deps = {}) {
49
+ const isLocalProject = htmlOptions.isLocalProject ?? false;
50
+ const usesPreviewStylesheet = isLocalProject || htmlOptions.environment !== "production";
51
+ if (!usesPreviewStylesheet)
52
+ return;
53
+ const fsAdapter = getUnderlyingFsAdapter(config.adapter);
54
+ if (typeof fsAdapter?.getAllSourceFiles !== "function")
55
+ return;
56
+ const projectScope = htmlOptions.projectSlug || htmlOptions.projectId || context.slug;
57
+ if (!projectScope || projectScope === "default")
58
+ return;
59
+ const resolveProjectContentVersion = deps.getProjectContentVersion ?? getProjectContentVersion;
60
+ const projectVersion = resolveProjectContentVersion(config) ??
61
+ (config.mode === "development" ? "dev" : "unknown");
62
+ const createStyleProfile = deps.createStyleScopeProfile ?? createStyleScopeProfile;
63
+ const warmPreparedCss = deps.warmPreparedCSSArtifactFromFiles ?? warmPreparedCSSArtifactFromFiles;
64
+ const styleProfile = createStyleProfile(config.config);
65
+ const stylesheetPath = config.config?.tailwind?.stylesheet;
66
+ Promise.resolve(fsAdapter.getAllSourceFiles())
67
+ .then((files) => warmPreparedCss({
68
+ projectSlug: projectScope,
69
+ projectVersion,
70
+ projectDir: config.projectDir,
71
+ files,
72
+ styleProfile,
73
+ stylesheetPath,
74
+ minify: true,
75
+ environment: "preview",
76
+ buildMode: "production",
77
+ }))
78
+ .catch((error) => {
79
+ logger.debug("Prepared CSS warmup skipped after source scan failure", {
80
+ projectScope,
81
+ error: error instanceof Error ? error.message : String(error),
82
+ });
83
+ });
84
+ }
85
+ export async function extractProjectClassesForRoute(config, context, appComponentPath, deps = {}) {
86
+ const classes = new Set();
87
+ const fsAdapter = getUnderlyingFsAdapter(config.adapter);
88
+ if (typeof fsAdapter?.getAllSourceFiles !== "function")
89
+ return classes;
90
+ const files = await fsAdapter.getAllSourceFiles();
91
+ const projectScope = context.options?.projectSlug || context.options?.projectId ||
92
+ config.projectDir;
93
+ const resolveProjectContentVersion = deps.getProjectContentVersion ?? getProjectContentVersion;
94
+ const projectVersion = resolveProjectContentVersion(config) ??
95
+ (config.mode === "development" ? "dev" : "unknown");
96
+ const routeKey = buildRouteManifestKey(context.pageInfo.entity.path, config.projectDir);
97
+ const routeLayoutPaths = context.nestedLayouts
98
+ .map((layout) => layout.componentPath || layout.path)
99
+ .filter((path) => Boolean(path));
100
+ const routeFilePaths = [
101
+ context.pageInfo.entity.path,
102
+ ...routeLayoutPaths,
103
+ ...(appComponentPath ? [appComponentPath] : []),
104
+ ];
105
+ const createStyleProfile = deps.createStyleScopeProfile ?? createStyleScopeProfile;
106
+ const getRouteCssCandidates = deps.getRouteCandidates ?? getRouteCandidates;
107
+ const routeCandidates = getRouteCssCandidates({
108
+ projectScope,
109
+ projectVersion,
110
+ projectDir: config.projectDir,
111
+ styleProfile: createStyleProfile(config.config),
112
+ routeKey,
113
+ routeFilePaths,
114
+ files,
115
+ developmentMode: config.mode === "development",
116
+ });
117
+ for (const cls of routeCandidates)
118
+ classes.add(cls);
119
+ logger.debug("extractProjectClasses", {
120
+ filesProcessed: files.length,
121
+ routeKey,
122
+ routeFileCount: routeFilePaths.length,
123
+ totalClasses: classes.size,
124
+ });
125
+ return classes;
126
+ }
@@ -33,8 +33,6 @@ export declare class HTMLGenerator {
33
33
  private detectUseClientDirective;
34
34
  private wrapHTMLFragment;
35
35
  private generateShellParts;
36
- private startProjectCSSPreparation;
37
- private startPreparedCSSWarmup;
38
36
  private buildHeadElements;
39
37
  private mergeFrontmatter;
40
38
  private resolveAppPath;
@@ -46,8 +44,5 @@ export declare class HTMLGenerator {
46
44
  * double-loading globals.css when it's both auto-discovered and explicitly imported.
47
45
  */
48
46
  private mergeImportedCSS;
49
- private getProjectContentVersion;
50
- private buildRouteManifestKey;
51
- private extractProjectClassesForRoute;
52
47
  }
53
48
  //# sourceMappingURL=html.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/orchestrator/html.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAS7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EACV,SAAS,EAET,UAAU,EACX,MAAM,sBAAsB,CAAC;AAG9B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AA6EhD,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,cAAc,CAAC;IACxB,MAAM,EAAE,eAAe,CAAC;IACxB,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;CACpC;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,UAAU,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;IACvB,YAAY,EAAE,SAAS,GAAG,SAAS,CAAC;IACpC,aAAa,EAAE,UAAU,EAAE,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,2FAA2F;IAC3F,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAsB;gBAExB,MAAM,EAAE,mBAAmB;IAIjC,gBAAgB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC;IA0BjE,kBAAkB,CACtB,WAAW,EAAE,cAAc,EAC3B,OAAO,EAAE,IAAI,CAAC,qBAAqB,EAAE,MAAM,CAAC,GAC3C,OAAO,CAAC,cAAc,CAAC;YAqEZ,sBAAsB;YAqDtB,4BAA4B;YAiB5B,wBAAwB;YAmBxB,gBAAgB;YAyBhB,kBAAkB;IAwDhC,OAAO,CAAC,0BAA0B;IAsBlC,OAAO,CAAC,sBAAsB;IAgD9B,OAAO,CAAC,iBAAiB;IA4DzB,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,cAAc;YAQR,eAAe;YAaf,gBAAgB;IAgF9B;;;;OAIG;YACW,gBAAgB;IA2D9B,OAAO,CAAC,wBAAwB;IAqBhC,OAAO,CAAC,qBAAqB;YAOf,6BAA6B;CAyD5C"}
1
+ {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/orchestrator/html.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAS7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EACV,SAAS,EAET,UAAU,EACX,MAAM,sBAAsB,CAAC;AAG9B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AA4EhD,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,cAAc,CAAC;IACxB,MAAM,EAAE,eAAe,CAAC;IACxB,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;CACpC;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,UAAU,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;IACvB,YAAY,EAAE,SAAS,GAAG,SAAS,CAAC;IACpC,aAAa,EAAE,UAAU,EAAE,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,2FAA2F;IAC3F,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAsB;gBAExB,MAAM,EAAE,mBAAmB;IAIjC,gBAAgB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC;IA0BjE,kBAAkB,CACtB,WAAW,EAAE,cAAc,EAC3B,OAAO,EAAE,IAAI,CAAC,qBAAqB,EAAE,MAAM,CAAC,GAC3C,OAAO,CAAC,cAAc,CAAC;YAqEZ,sBAAsB;YAqDtB,4BAA4B;YAiB5B,wBAAwB;YAmBxB,gBAAgB;YAyBhB,kBAAkB;IAwDhC,OAAO,CAAC,iBAAiB;IA4DzB,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,cAAc;YAQR,eAAe;YAaf,gBAAgB;IAgF9B;;;;OAIG;YACW,gBAAgB;CA0D/B"}
@@ -10,11 +10,7 @@ import { resolveAppComponentPath } from "../layouts/utils/app-resolver.js";
10
10
  import { StreamTimeoutError, streamToString } from "../utils/stream-utils.js";
11
11
  import { profilePhase, profileSyncPhase } from "../../observability/request-profiler.js";
12
12
  import { normalizeCssModuleKey, rewriteCssModuleContent, } from "../../transforms/css-modules/naming.js";
13
- import { getProjectCSS } from "../../html/styles-builder/index.js";
14
- import { warmPreparedCSSArtifactFromFiles } from "../../html/styles-builder/css-pregeneration.js";
15
- import { getRouteCandidates } from "./css-candidate-manifest.js";
16
- import { resolveStyleContentVersion } from "../../html/styles-builder/content-version.js";
17
- import { createStyleScopeProfile } from "../../html/styles-builder/style-scope-profile.js";
13
+ import { extractProjectClassesForRoute, startPreparedCSSWarmup, startProjectCSSPreparation, } from "./html-project-css.js";
18
14
  const logger = rendererLogger.component("html-generator");
19
15
  function applyExplicitThemeToDocument(html, colorScheme, enabled) {
20
16
  if (!enabled || !colorScheme)
@@ -67,7 +63,7 @@ export class HTMLGenerator {
67
63
  if (this.config.mode === "production" && context.options?.environment === "production") {
68
64
  const mergedFrontmatter = this.mergeFrontmatter(context);
69
65
  const htmlOptions = await profilePhase("html.build_options", () => this.buildHTMLOptions(context, mergedFrontmatter));
70
- projectCSSPromise = this.startProjectCSSPreparation(context, htmlOptions);
66
+ projectCSSPromise = startProjectCSSPreparation(context, htmlOptions);
71
67
  }
72
68
  html = await this.handleFullHTMLDocument(context, projectCSSPromise);
73
69
  }
@@ -84,8 +80,8 @@ export class HTMLGenerator {
84
80
  const fullContext = context;
85
81
  const mergedFrontmatter = this.mergeFrontmatter(fullContext);
86
82
  const htmlOptions = await profilePhase("html.build_options", () => this.buildHTMLOptions(fullContext, mergedFrontmatter));
87
- const projectCSSPromise = this.startProjectCSSPreparation(fullContext, htmlOptions);
88
- this.startPreparedCSSWarmup(fullContext, htmlOptions);
83
+ const projectCSSPromise = startProjectCSSPreparation(fullContext, htmlOptions);
84
+ startPreparedCSSWarmup(this.config, fullContext, htmlOptions);
89
85
  let reactContent;
90
86
  try {
91
87
  reactContent = (await streamToString(reactStream)).trim();
@@ -181,8 +177,8 @@ export class HTMLGenerator {
181
177
  async wrapHTMLFragment(context) {
182
178
  const mergedFrontmatter = this.mergeFrontmatter(context);
183
179
  const htmlOptions = await profilePhase("html.build_options", () => this.buildHTMLOptions(context, mergedFrontmatter));
184
- const projectCSSPromise = this.startProjectCSSPreparation(context, htmlOptions);
185
- this.startPreparedCSSWarmup(context, htmlOptions);
180
+ const projectCSSPromise = startProjectCSSPreparation(context, htmlOptions);
181
+ startPreparedCSSWarmup(this.config, context, htmlOptions);
186
182
  const reactContent = context.html.trim();
187
183
  const { start, end } = await profilePhase("html.generate_shell_parts", () => this.generateShellParts(context, mergedFrontmatter, htmlOptions, reactContent, projectCSSPromise));
188
184
  return `${start}${reactContent}${end}`;
@@ -224,54 +220,6 @@ export class HTMLGenerator {
224
220
  }
225
221
  return { start: modifiedStart, end };
226
222
  }
227
- startProjectCSSPreparation(context, htmlOptions) {
228
- const isLocalProject = htmlOptions.isLocalProject ?? false;
229
- if (isLocalProject || htmlOptions.environment !== "production")
230
- return undefined;
231
- const projectScope = htmlOptions.projectSlug || htmlOptions.projectId || context.slug;
232
- if (!projectScope || projectScope === "default")
233
- return undefined;
234
- return getProjectCSS(projectScope, htmlOptions.globalCSS, new Set([...(htmlOptions.projectClasses ?? [])]), {
235
- minify: true,
236
- environment: htmlOptions.environment,
237
- buildMode: htmlOptions.mode,
238
- });
239
- }
240
- startPreparedCSSWarmup(context, htmlOptions) {
241
- const isLocalProject = htmlOptions.isLocalProject ?? false;
242
- const usesPreviewStylesheet = isLocalProject || htmlOptions.environment !== "production";
243
- if (!usesPreviewStylesheet)
244
- return;
245
- const wrappedFs = this.config.adapter.fs;
246
- if (typeof wrappedFs.getUnderlyingAdapter !== "function")
247
- return;
248
- const fsAdapter = wrappedFs.getUnderlyingAdapter();
249
- if (typeof fsAdapter.getAllSourceFiles !== "function")
250
- return;
251
- const projectScope = htmlOptions.projectSlug || htmlOptions.projectId || context.slug;
252
- if (!projectScope || projectScope === "default")
253
- return;
254
- const projectVersion = this.getProjectContentVersion() ??
255
- (this.config.mode === "development" ? "dev" : "unknown");
256
- const styleProfile = createStyleScopeProfile(this.config.config);
257
- const stylesheetPath = this.config.config?.tailwind?.stylesheet;
258
- Promise.resolve(fsAdapter.getAllSourceFiles()).then((files) => warmPreparedCSSArtifactFromFiles({
259
- projectSlug: projectScope,
260
- projectVersion,
261
- projectDir: this.config.projectDir,
262
- files,
263
- styleProfile,
264
- stylesheetPath,
265
- minify: true,
266
- environment: "preview",
267
- buildMode: "production",
268
- })).catch((error) => {
269
- logger.debug("Prepared CSS warmup skipped after source scan failure", {
270
- projectScope,
271
- error: error instanceof Error ? error.message : String(error),
272
- });
273
- });
274
- }
275
223
  buildHeadElements(head) {
276
224
  if (!head)
277
225
  return { scripts: "", other: "" };
@@ -360,7 +308,7 @@ export class HTMLGenerator {
360
308
  profilePhase("html.load_global_css", () => this.loadProjectFile(stylesheetPath)),
361
309
  ]);
362
310
  const appComponentPath = appComponentPathOrNull ?? undefined;
363
- const projectClasses = await profilePhase("html.route_candidates", () => this.extractProjectClassesForRoute(context, appComponentPath));
311
+ const projectClasses = await profilePhase("html.route_candidates", () => extractProjectClassesForRoute(this.config, context, appComponentPath));
364
312
  // Load CSS imported by components and merge with globalCSS.
365
313
  // Deduplicate against the configured stylesheet to avoid double-loading.
366
314
  const combinedCSS = await profilePhase("html.merge_imported_css", () => this.mergeImportedCSS(globalCSS, context.cssImports, stylesheetPath));
@@ -462,64 +410,4 @@ export class HTMLGenerator {
462
410
  });
463
411
  return combined;
464
412
  }
465
- getProjectContentVersion() {
466
- const wrappedFs = this.config.adapter.fs;
467
- if (typeof wrappedFs.getUnderlyingAdapter !== "function")
468
- return undefined;
469
- const fsAdapter = wrappedFs.getUnderlyingAdapter();
470
- const contentContext = typeof fsAdapter.getContentContext === "function"
471
- ? fsAdapter.getContentContext()
472
- : null;
473
- if (contentContext)
474
- return resolveStyleContentVersion(contentContext);
475
- return fsAdapter.getProjectData?.()?.updated_at;
476
- }
477
- buildRouteManifestKey(pagePath) {
478
- const relativePagePath = extractRelativePath(pagePath, this.config.projectDir);
479
- return relativePagePath
480
- .replace(/\.(tsx|ts|jsx|mdx|md|js)$/, "")
481
- .replace(/^pages\//, "");
482
- }
483
- async extractProjectClassesForRoute(context, appComponentPath) {
484
- const classes = new Set();
485
- const wrappedFs = this.config.adapter.fs;
486
- if (typeof wrappedFs.getUnderlyingAdapter !== "function")
487
- return classes;
488
- const fsAdapter = wrappedFs.getUnderlyingAdapter();
489
- if (typeof fsAdapter.getAllSourceFiles !== "function")
490
- return classes;
491
- const files = await fsAdapter.getAllSourceFiles();
492
- const projectScope = context.options?.projectSlug || context.options?.projectId ||
493
- this.config.projectDir;
494
- const projectVersion = this.getProjectContentVersion() ??
495
- (this.config.mode === "development" ? "dev" : "unknown");
496
- const routeKey = this.buildRouteManifestKey(context.pageInfo.entity.path);
497
- const routeLayoutPaths = context.nestedLayouts
498
- .map((layout) => layout.componentPath || layout.path)
499
- .filter((path) => Boolean(path));
500
- const routeFilePaths = [
501
- context.pageInfo.entity.path,
502
- ...routeLayoutPaths,
503
- ...(appComponentPath ? [appComponentPath] : []),
504
- ];
505
- const routeCandidates = getRouteCandidates({
506
- projectScope,
507
- projectVersion,
508
- projectDir: this.config.projectDir,
509
- styleProfile: createStyleScopeProfile(this.config.config),
510
- routeKey,
511
- routeFilePaths,
512
- files,
513
- developmentMode: this.config.mode === "development",
514
- });
515
- for (const cls of routeCandidates)
516
- classes.add(cls);
517
- logger.debug("extractProjectClasses", {
518
- filesProcessed: files.length,
519
- routeKey,
520
- routeFileCount: routeFilePaths.length,
521
- totalClasses: classes.size,
522
- });
523
- return classes;
524
- }
525
413
  }
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.1.162";
1
+ export declare const VERSION = "0.1.163";
2
2
  //# sourceMappingURL=version-constant.d.ts.map
@@ -1,3 +1,3 @@
1
1
  // Keep in sync with deno.json version.
2
2
  // scripts/release.ts updates this constant during releases.
3
- export const VERSION = "0.1.162";
3
+ export const VERSION = "0.1.163";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "veryfront",
3
- "version": "0.1.162",
3
+ "version": "0.1.163",
4
4
  "description": "The simplest way to build AI-powered apps",
5
5
  "keywords": [
6
6
  "react",
package/src/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.1.162",
3
+ "version": "0.1.163",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "exclude": [
@@ -0,0 +1,203 @@
1
+ import type { VeryfrontConfig } from "../../config/index.js";
2
+ import type { HTMLGenerationOptions } from "../../html/index.js";
3
+ import { getProjectCSS } from "../../html/styles-builder/index.js";
4
+ import { warmPreparedCSSArtifactFromFiles } from "../../html/styles-builder/css-pregeneration.js";
5
+ import { resolveStyleContentVersion } from "../../html/styles-builder/content-version.js";
6
+ import { createStyleScopeProfile } from "../../html/styles-builder/style-scope-profile.js";
7
+ import type { RuntimeAdapter } from "../../platform/adapters/base.js";
8
+ import type { ResolvedContentContext } from "../../platform/adapters/fs/veryfront/types.js";
9
+ import { rendererLogger } from "../../utils/index.js";
10
+ import { extractRelativePath } from "../../utils/route-path-utils.js";
11
+ import { getRouteCandidates } from "./css-candidate-manifest.js";
12
+ import type { HTMLGenerationContext } from "./html.js";
13
+
14
+ const logger = rendererLogger.component("html-project-css");
15
+
16
+ export type ProjectCSSResult = Awaited<ReturnType<typeof getProjectCSS>> | null;
17
+
18
+ interface ProjectCssConfig {
19
+ projectDir: string;
20
+ adapter: RuntimeAdapter;
21
+ config: VeryfrontConfig;
22
+ mode: "development" | "production";
23
+ }
24
+
25
+ interface ProjectCssDeps {
26
+ createStyleScopeProfile?: typeof createStyleScopeProfile;
27
+ getProjectCSS?: typeof getProjectCSS;
28
+ getProjectContentVersion?: (
29
+ config: Pick<ProjectCssConfig, "adapter" | "mode">,
30
+ ) => string | undefined;
31
+ getRouteCandidates?: typeof getRouteCandidates;
32
+ resolveStyleContentVersion?: typeof resolveStyleContentVersion;
33
+ warmPreparedCSSArtifactFromFiles?: typeof warmPreparedCSSArtifactFromFiles;
34
+ }
35
+
36
+ type SourceFileEntry = { path: string; content?: string };
37
+
38
+ function getUnderlyingFsAdapter(adapter: RuntimeAdapter): unknown {
39
+ const wrappedFs = adapter.fs as unknown as { getUnderlyingAdapter?: () => unknown };
40
+ if (typeof wrappedFs.getUnderlyingAdapter !== "function") return undefined;
41
+ return wrappedFs.getUnderlyingAdapter();
42
+ }
43
+
44
+ export function buildRouteManifestKey(pagePath: string, projectDir: string): string {
45
+ const relativePagePath = extractRelativePath(pagePath, projectDir);
46
+ return relativePagePath
47
+ .replace(/\.(tsx|ts|jsx|mdx|md|js)$/, "")
48
+ .replace(/^pages\//, "");
49
+ }
50
+
51
+ export function getProjectContentVersion(
52
+ config: Pick<ProjectCssConfig, "adapter" | "mode">,
53
+ deps: Pick<ProjectCssDeps, "resolveStyleContentVersion"> = {},
54
+ ): string | undefined {
55
+ const fsAdapter = getUnderlyingFsAdapter(config.adapter) as {
56
+ getContentContext?: () => ResolvedContentContext | null;
57
+ getProjectData?: () => { updated_at?: string } | undefined;
58
+ } | undefined;
59
+
60
+ if (!fsAdapter) return undefined;
61
+
62
+ const contentContext = typeof fsAdapter.getContentContext === "function"
63
+ ? fsAdapter.getContentContext()
64
+ : null;
65
+ if (contentContext) {
66
+ const resolveContentVersion = deps.resolveStyleContentVersion ?? resolveStyleContentVersion;
67
+ return resolveContentVersion(contentContext);
68
+ }
69
+
70
+ return fsAdapter.getProjectData?.()?.updated_at;
71
+ }
72
+
73
+ export function startProjectCSSPreparation(
74
+ context: HTMLGenerationContext,
75
+ htmlOptions: HTMLGenerationOptions,
76
+ deps: Pick<ProjectCssDeps, "getProjectCSS"> = {},
77
+ ): Promise<ProjectCSSResult> | undefined {
78
+ const isLocalProject = htmlOptions.isLocalProject ?? false;
79
+ if (isLocalProject || htmlOptions.environment !== "production") return undefined;
80
+
81
+ const projectScope = htmlOptions.projectSlug || htmlOptions.projectId || context.slug;
82
+ if (!projectScope || projectScope === "default") return undefined;
83
+
84
+ const getProjectCss = deps.getProjectCSS ?? getProjectCSS;
85
+ return getProjectCss(
86
+ projectScope,
87
+ htmlOptions.globalCSS,
88
+ new Set([...(htmlOptions.projectClasses ?? [])]),
89
+ {
90
+ minify: true,
91
+ environment: htmlOptions.environment,
92
+ buildMode: htmlOptions.mode,
93
+ },
94
+ );
95
+ }
96
+
97
+ export function startPreparedCSSWarmup(
98
+ config: ProjectCssConfig,
99
+ context: HTMLGenerationContext,
100
+ htmlOptions: HTMLGenerationOptions,
101
+ deps: Pick<
102
+ ProjectCssDeps,
103
+ "createStyleScopeProfile" | "getProjectContentVersion" | "warmPreparedCSSArtifactFromFiles"
104
+ > = {},
105
+ ): void {
106
+ const isLocalProject = htmlOptions.isLocalProject ?? false;
107
+ const usesPreviewStylesheet = isLocalProject || htmlOptions.environment !== "production";
108
+ if (!usesPreviewStylesheet) return;
109
+
110
+ const fsAdapter = getUnderlyingFsAdapter(config.adapter) as {
111
+ getAllSourceFiles?: () => SourceFileEntry[] | Promise<SourceFileEntry[]>;
112
+ } | undefined;
113
+ if (typeof fsAdapter?.getAllSourceFiles !== "function") return;
114
+
115
+ const projectScope = htmlOptions.projectSlug || htmlOptions.projectId || context.slug;
116
+ if (!projectScope || projectScope === "default") return;
117
+
118
+ const resolveProjectContentVersion = deps.getProjectContentVersion ?? getProjectContentVersion;
119
+ const projectVersion = resolveProjectContentVersion(config) ??
120
+ (config.mode === "development" ? "dev" : "unknown");
121
+ const createStyleProfile = deps.createStyleScopeProfile ?? createStyleScopeProfile;
122
+ const warmPreparedCss = deps.warmPreparedCSSArtifactFromFiles ?? warmPreparedCSSArtifactFromFiles;
123
+ const styleProfile = createStyleProfile(config.config);
124
+ const stylesheetPath = config.config?.tailwind?.stylesheet;
125
+
126
+ Promise.resolve(fsAdapter.getAllSourceFiles())
127
+ .then((files) =>
128
+ warmPreparedCss({
129
+ projectSlug: projectScope,
130
+ projectVersion,
131
+ projectDir: config.projectDir,
132
+ files,
133
+ styleProfile,
134
+ stylesheetPath,
135
+ minify: true,
136
+ environment: "preview",
137
+ buildMode: "production",
138
+ })
139
+ )
140
+ .catch((error) => {
141
+ logger.debug("Prepared CSS warmup skipped after source scan failure", {
142
+ projectScope,
143
+ error: error instanceof Error ? error.message : String(error),
144
+ });
145
+ });
146
+ }
147
+
148
+ export async function extractProjectClassesForRoute(
149
+ config: ProjectCssConfig,
150
+ context: HTMLGenerationContext,
151
+ appComponentPath?: string,
152
+ deps: Pick<
153
+ ProjectCssDeps,
154
+ "createStyleScopeProfile" | "getProjectContentVersion" | "getRouteCandidates"
155
+ > = {},
156
+ ): Promise<Set<string>> {
157
+ const classes = new Set<string>();
158
+ const fsAdapter = getUnderlyingFsAdapter(config.adapter) as {
159
+ getAllSourceFiles?: () => SourceFileEntry[] | Promise<SourceFileEntry[]>;
160
+ } | undefined;
161
+
162
+ if (typeof fsAdapter?.getAllSourceFiles !== "function") return classes;
163
+
164
+ const files = await fsAdapter.getAllSourceFiles();
165
+ const projectScope = context.options?.projectSlug || context.options?.projectId ||
166
+ config.projectDir;
167
+ const resolveProjectContentVersion = deps.getProjectContentVersion ?? getProjectContentVersion;
168
+ const projectVersion = resolveProjectContentVersion(config) ??
169
+ (config.mode === "development" ? "dev" : "unknown");
170
+ const routeKey = buildRouteManifestKey(context.pageInfo.entity.path, config.projectDir);
171
+ const routeLayoutPaths = context.nestedLayouts
172
+ .map((layout) => layout.componentPath || layout.path)
173
+ .filter((path): path is string => Boolean(path));
174
+ const routeFilePaths = [
175
+ context.pageInfo.entity.path,
176
+ ...routeLayoutPaths,
177
+ ...(appComponentPath ? [appComponentPath] : []),
178
+ ];
179
+
180
+ const createStyleProfile = deps.createStyleScopeProfile ?? createStyleScopeProfile;
181
+ const getRouteCssCandidates = deps.getRouteCandidates ?? getRouteCandidates;
182
+ const routeCandidates = getRouteCssCandidates({
183
+ projectScope,
184
+ projectVersion,
185
+ projectDir: config.projectDir,
186
+ styleProfile: createStyleProfile(config.config),
187
+ routeKey,
188
+ routeFilePaths,
189
+ files,
190
+ developmentMode: config.mode === "development",
191
+ });
192
+
193
+ for (const cls of routeCandidates) classes.add(cls);
194
+
195
+ logger.debug("extractProjectClasses", {
196
+ filesProcessed: files.length,
197
+ routeKey,
198
+ routeFileCount: routeFilePaths.length,
199
+ totalClasses: classes.size,
200
+ });
201
+
202
+ return classes;
203
+ }
@@ -31,15 +31,14 @@ import {
31
31
  normalizeCssModuleKey,
32
32
  rewriteCssModuleContent,
33
33
  } from "../../transforms/css-modules/naming.js";
34
- import { getProjectCSS } from "../../html/styles-builder/index.js";
35
- import { warmPreparedCSSArtifactFromFiles } from "../../html/styles-builder/css-pregeneration.js";
36
- import { getRouteCandidates } from "./css-candidate-manifest.js";
37
- import { resolveStyleContentVersion } from "../../html/styles-builder/content-version.js";
38
- import { createStyleScopeProfile } from "../../html/styles-builder/style-scope-profile.js";
39
- import type { ResolvedContentContext } from "../../platform/adapters/fs/veryfront/types.js";
34
+ import {
35
+ extractProjectClassesForRoute,
36
+ type ProjectCSSResult,
37
+ startPreparedCSSWarmup,
38
+ startProjectCSSPreparation,
39
+ } from "./html-project-css.js";
40
40
 
41
41
  const logger = rendererLogger.component("html-generator");
42
- type ProjectCSSResult = Awaited<ReturnType<typeof getProjectCSS>> | null;
43
42
 
44
43
  function applyExplicitThemeToDocument(
45
44
  html: string,
@@ -136,7 +135,7 @@ export class HTMLGenerator {
136
135
  "html.build_options",
137
136
  () => this.buildHTMLOptions(context, mergedFrontmatter),
138
137
  );
139
- projectCSSPromise = this.startProjectCSSPreparation(context, htmlOptions);
138
+ projectCSSPromise = startProjectCSSPreparation(context, htmlOptions);
140
139
  }
141
140
 
142
141
  html = await this.handleFullHTMLDocument(context, projectCSSPromise);
@@ -162,8 +161,8 @@ export class HTMLGenerator {
162
161
  "html.build_options",
163
162
  () => this.buildHTMLOptions(fullContext, mergedFrontmatter),
164
163
  );
165
- const projectCSSPromise = this.startProjectCSSPreparation(fullContext, htmlOptions);
166
- this.startPreparedCSSWarmup(fullContext, htmlOptions);
164
+ const projectCSSPromise = startProjectCSSPreparation(fullContext, htmlOptions);
165
+ startPreparedCSSWarmup(this.config, fullContext, htmlOptions);
167
166
 
168
167
  let reactContent: string;
169
168
  try {
@@ -319,8 +318,8 @@ export class HTMLGenerator {
319
318
  "html.build_options",
320
319
  () => this.buildHTMLOptions(context, mergedFrontmatter),
321
320
  );
322
- const projectCSSPromise = this.startProjectCSSPreparation(context, htmlOptions);
323
- this.startPreparedCSSWarmup(context, htmlOptions);
321
+ const projectCSSPromise = startProjectCSSPreparation(context, htmlOptions);
322
+ startPreparedCSSWarmup(this.config, context, htmlOptions);
324
323
  const reactContent = context.html.trim();
325
324
 
326
325
  const { start, end } = await profilePhase(
@@ -394,76 +393,6 @@ export class HTMLGenerator {
394
393
  return { start: modifiedStart, end };
395
394
  }
396
395
 
397
- private startProjectCSSPreparation(
398
- context: HTMLGenerationContext,
399
- htmlOptions: HTMLGenerationOptions,
400
- ): Promise<ProjectCSSResult> | undefined {
401
- const isLocalProject = htmlOptions.isLocalProject ?? false;
402
- if (isLocalProject || htmlOptions.environment !== "production") return undefined;
403
-
404
- const projectScope = htmlOptions.projectSlug || htmlOptions.projectId || context.slug;
405
- if (!projectScope || projectScope === "default") return undefined;
406
-
407
- return getProjectCSS(
408
- projectScope,
409
- htmlOptions.globalCSS,
410
- new Set([...(htmlOptions.projectClasses ?? [])]),
411
- {
412
- minify: true,
413
- environment: htmlOptions.environment,
414
- buildMode: htmlOptions.mode,
415
- },
416
- );
417
- }
418
-
419
- private startPreparedCSSWarmup(
420
- context: HTMLGenerationContext,
421
- htmlOptions: HTMLGenerationOptions,
422
- ): void {
423
- const isLocalProject = htmlOptions.isLocalProject ?? false;
424
- const usesPreviewStylesheet = isLocalProject || htmlOptions.environment !== "production";
425
- if (!usesPreviewStylesheet) return;
426
-
427
- const wrappedFs = this.config.adapter.fs as unknown as {
428
- getUnderlyingAdapter?: () => unknown;
429
- };
430
- if (typeof wrappedFs.getUnderlyingAdapter !== "function") return;
431
-
432
- const fsAdapter = wrappedFs.getUnderlyingAdapter() as {
433
- getAllSourceFiles?: () =>
434
- | Array<{ path: string; content?: string }>
435
- | Promise<Array<{ path: string; content?: string }>>;
436
- };
437
- if (typeof fsAdapter.getAllSourceFiles !== "function") return;
438
-
439
- const projectScope = htmlOptions.projectSlug || htmlOptions.projectId || context.slug;
440
- if (!projectScope || projectScope === "default") return;
441
-
442
- const projectVersion = this.getProjectContentVersion() ??
443
- (this.config.mode === "development" ? "dev" : "unknown");
444
- const styleProfile = createStyleScopeProfile(this.config.config);
445
- const stylesheetPath = this.config.config?.tailwind?.stylesheet;
446
-
447
- Promise.resolve(fsAdapter.getAllSourceFiles()).then((files) =>
448
- warmPreparedCSSArtifactFromFiles({
449
- projectSlug: projectScope,
450
- projectVersion,
451
- projectDir: this.config.projectDir,
452
- files,
453
- styleProfile,
454
- stylesheetPath,
455
- minify: true,
456
- environment: "preview",
457
- buildMode: "production",
458
- })
459
- ).catch((error) => {
460
- logger.debug("Prepared CSS warmup skipped after source scan failure", {
461
- projectScope,
462
- error: error instanceof Error ? error.message : String(error),
463
- });
464
- });
465
- }
466
-
467
396
  private buildHeadElements(head?: CollectedHead): { scripts: string; other: string } {
468
397
  if (!head) return { scripts: "", other: "" };
469
398
 
@@ -565,7 +494,7 @@ export class HTMLGenerator {
565
494
  const appComponentPath = appComponentPathOrNull ?? undefined;
566
495
  const projectClasses = await profilePhase(
567
496
  "html.route_candidates",
568
- () => this.extractProjectClassesForRoute(context, appComponentPath),
497
+ () => extractProjectClassesForRoute(this.config, context, appComponentPath),
569
498
  );
570
499
 
571
500
  // Load CSS imported by components and merge with globalCSS.
@@ -696,90 +625,4 @@ export class HTMLGenerator {
696
625
  });
697
626
  return combined;
698
627
  }
699
-
700
- private getProjectContentVersion(): string | undefined {
701
- const wrappedFs = this.config.adapter.fs as unknown as {
702
- getUnderlyingAdapter?: () => unknown;
703
- };
704
-
705
- if (typeof wrappedFs.getUnderlyingAdapter !== "function") return undefined;
706
-
707
- const fsAdapter = wrappedFs.getUnderlyingAdapter() as {
708
- getContentContext?: () => ResolvedContentContext | null;
709
- getProjectData?: () => { updated_at?: string } | undefined;
710
- };
711
-
712
- const contentContext = typeof fsAdapter.getContentContext === "function"
713
- ? fsAdapter.getContentContext()
714
- : null;
715
-
716
- if (contentContext) return resolveStyleContentVersion(contentContext);
717
-
718
- return fsAdapter.getProjectData?.()?.updated_at;
719
- }
720
-
721
- private buildRouteManifestKey(pagePath: string): string {
722
- const relativePagePath = extractRelativePath(pagePath, this.config.projectDir);
723
- return relativePagePath
724
- .replace(/\.(tsx|ts|jsx|mdx|md|js)$/, "")
725
- .replace(/^pages\//, "");
726
- }
727
-
728
- private async extractProjectClassesForRoute(
729
- context: HTMLGenerationContext,
730
- appComponentPath?: string,
731
- ): Promise<Set<string>> {
732
- const classes = new Set<string>();
733
-
734
- const wrappedFs = this.config.adapter.fs as unknown as {
735
- getUnderlyingAdapter?: () => unknown;
736
- };
737
-
738
- if (typeof wrappedFs.getUnderlyingAdapter !== "function") return classes;
739
-
740
- const fsAdapter = wrappedFs.getUnderlyingAdapter() as {
741
- getAllSourceFiles?: () =>
742
- | Array<{ path: string; content?: string }>
743
- | Promise<Array<{ path: string; content?: string }>>;
744
- };
745
-
746
- if (typeof fsAdapter.getAllSourceFiles !== "function") return classes;
747
-
748
- const files = await fsAdapter.getAllSourceFiles();
749
- const projectScope = context.options?.projectSlug || context.options?.projectId ||
750
- this.config.projectDir;
751
- const projectVersion = this.getProjectContentVersion() ??
752
- (this.config.mode === "development" ? "dev" : "unknown");
753
- const routeKey = this.buildRouteManifestKey(context.pageInfo.entity.path);
754
- const routeLayoutPaths = context.nestedLayouts
755
- .map((layout) => layout.componentPath || layout.path)
756
- .filter((path): path is string => Boolean(path));
757
- const routeFilePaths = [
758
- context.pageInfo.entity.path,
759
- ...routeLayoutPaths,
760
- ...(appComponentPath ? [appComponentPath] : []),
761
- ];
762
-
763
- const routeCandidates = getRouteCandidates({
764
- projectScope,
765
- projectVersion,
766
- projectDir: this.config.projectDir,
767
- styleProfile: createStyleScopeProfile(this.config.config),
768
- routeKey,
769
- routeFilePaths,
770
- files,
771
- developmentMode: this.config.mode === "development",
772
- });
773
-
774
- for (const cls of routeCandidates) classes.add(cls);
775
-
776
- logger.debug("extractProjectClasses", {
777
- filesProcessed: files.length,
778
- routeKey,
779
- routeFileCount: routeFilePaths.length,
780
- totalClasses: classes.size,
781
- });
782
-
783
- return classes;
784
- }
785
628
  }
@@ -1,3 +1,3 @@
1
1
  // Keep in sync with deno.json version.
2
2
  // scripts/release.ts updates this constant during releases.
3
- export const VERSION = "0.1.162";
3
+ export const VERSION = "0.1.163";