veryfront 0.1.89 → 0.1.90

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/esm/cli/commands/knowledge/command.d.ts +3 -0
  2. package/esm/cli/commands/knowledge/command.d.ts.map +1 -1
  3. package/esm/cli/commands/knowledge/command.js +27 -2
  4. package/esm/deno.js +1 -1
  5. package/esm/src/html/styles-builder/candidate-extractor.d.ts +5 -1
  6. package/esm/src/html/styles-builder/candidate-extractor.d.ts.map +1 -1
  7. package/esm/src/html/styles-builder/candidate-extractor.js +6 -1
  8. package/esm/src/html/styles-builder/content-version.d.ts +9 -0
  9. package/esm/src/html/styles-builder/content-version.d.ts.map +1 -0
  10. package/esm/src/html/styles-builder/content-version.js +15 -0
  11. package/esm/src/html/styles-builder/css-pregeneration.d.ts +11 -0
  12. package/esm/src/html/styles-builder/css-pregeneration.d.ts.map +1 -1
  13. package/esm/src/html/styles-builder/css-pregeneration.js +15 -10
  14. package/esm/src/html/styles-builder/prepared-project-css-cache.d.ts +31 -0
  15. package/esm/src/html/styles-builder/prepared-project-css-cache.d.ts.map +1 -0
  16. package/esm/src/html/styles-builder/prepared-project-css-cache.js +165 -0
  17. package/esm/src/html/styles-builder/style-scope-profile.d.ts +14 -0
  18. package/esm/src/html/styles-builder/style-scope-profile.d.ts.map +1 -0
  19. package/esm/src/html/styles-builder/style-scope-profile.js +121 -0
  20. package/esm/src/platform/adapters/fs/factory.d.ts.map +1 -1
  21. package/esm/src/platform/adapters/fs/factory.js +2 -21
  22. package/esm/src/platform/adapters/fs/veryfront/adapter.d.ts.map +1 -1
  23. package/esm/src/platform/adapters/fs/veryfront/adapter.js +44 -19
  24. package/esm/src/platform/adapters/fs/veryfront/default-invalidation-callbacks.d.ts +3 -0
  25. package/esm/src/platform/adapters/fs/veryfront/default-invalidation-callbacks.d.ts.map +1 -0
  26. package/esm/src/platform/adapters/fs/veryfront/default-invalidation-callbacks.js +25 -0
  27. package/esm/src/platform/adapters/fs/veryfront/proxy-manager.d.ts.map +1 -1
  28. package/esm/src/platform/adapters/fs/veryfront/proxy-manager.js +2 -15
  29. package/esm/src/platform/adapters/fs/veryfront/websocket-manager.d.ts +4 -0
  30. package/esm/src/platform/adapters/fs/veryfront/websocket-manager.d.ts.map +1 -1
  31. package/esm/src/platform/adapters/fs/veryfront/websocket-manager.js +2 -0
  32. package/esm/src/rendering/orchestrator/css-candidate-manifest.d.ts +3 -0
  33. package/esm/src/rendering/orchestrator/css-candidate-manifest.d.ts.map +1 -1
  34. package/esm/src/rendering/orchestrator/css-candidate-manifest.js +10 -5
  35. package/esm/src/rendering/orchestrator/html.d.ts.map +1 -1
  36. package/esm/src/rendering/orchestrator/html.js +8 -0
  37. package/esm/src/server/handlers/dev/styles-candidate-scanner.d.ts.map +1 -1
  38. package/esm/src/server/handlers/dev/styles-candidate-scanner.js +14 -16
  39. package/esm/src/server/handlers/dev/styles-css.handler.d.ts +2 -0
  40. package/esm/src/server/handlers/dev/styles-css.handler.d.ts.map +1 -1
  41. package/esm/src/server/handlers/dev/styles-css.handler.js +55 -8
  42. package/package.json +1 -1
  43. package/src/cli/commands/knowledge/command.ts +30 -2
  44. package/src/deno.js +1 -1
  45. package/src/src/html/styles-builder/candidate-extractor.ts +13 -0
  46. package/src/src/html/styles-builder/content-version.ts +20 -0
  47. package/src/src/html/styles-builder/css-pregeneration.ts +49 -12
  48. package/src/src/html/styles-builder/prepared-project-css-cache.ts +228 -0
  49. package/src/src/html/styles-builder/style-scope-profile.ts +164 -0
  50. package/src/src/platform/adapters/fs/factory.ts +2 -27
  51. package/src/src/platform/adapters/fs/veryfront/adapter.ts +49 -20
  52. package/src/src/platform/adapters/fs/veryfront/default-invalidation-callbacks.ts +35 -0
  53. package/src/src/platform/adapters/fs/veryfront/proxy-manager.ts +4 -21
  54. package/src/src/platform/adapters/fs/veryfront/websocket-manager.ts +3 -0
  55. package/src/src/rendering/orchestrator/css-candidate-manifest.ts +28 -6
  56. package/src/src/rendering/orchestrator/html.ts +11 -0
  57. package/src/src/server/handlers/dev/styles-candidate-scanner.ts +18 -15
  58. package/src/src/server/handlers/dev/styles-css.handler.ts +88 -16
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/adapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/adapter.ts"],"names":[],"mappings":"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"}
@@ -164,6 +164,7 @@ export class VeryfrontFSAdapter {
164
164
  },
165
165
  clearFileListIndex: () => this.readOps.clearFileListIndex(),
166
166
  setFileListCache: (cacheKey, files) => this.cache.setAsync(cacheKey, files),
167
+ pregenerateStyles: (files) => this.triggerCSSPregeneration(files),
167
168
  });
168
169
  logger.debug("Created", {
169
170
  apiBaseUrl: this.apiBaseUrl,
@@ -245,10 +246,10 @@ export class VeryfrontFSAdapter {
245
246
  sourceFiles: fileSummary.sourceFiles,
246
247
  sourceFilesWithContent: fileSummary.sourceFilesWithContent,
247
248
  });
248
- // Trigger CSS pre-generation for non-branch environments (fire-and-forget)
249
- // This runs in parallel with the rest of initialization
250
- if (this.contentContext.sourceType !== "branch" &&
251
- fileSummary.sourceFilesWithContent > 0) {
249
+ // Trigger CSS pre-generation after the initial file snapshot is ready.
250
+ // This keeps stylesheet generation off the first styles request for both
251
+ // preview branches and published content.
252
+ if (fileSummary.sourceFilesWithContent > 0) {
252
253
  this.triggerCSSPregeneration(files).catch(() => {
253
254
  // Error already logged in triggerCSSPregeneration
254
255
  });
@@ -326,6 +327,12 @@ export class VeryfrontFSAdapter {
326
327
  });
327
328
  const files = await fetchFileListForContext(this.client, warmupContext);
328
329
  await this.cache.setAsync(effectiveCacheKey, files);
330
+ const fileSummary = summarizeFileList(files);
331
+ if (fileSummary.sourceFilesWithContent > 0) {
332
+ this.triggerCSSPregeneration(files).catch(() => {
333
+ // Error already logged in triggerCSSPregeneration
334
+ });
335
+ }
329
336
  logger.debug("File list warmup complete", {
330
337
  reason,
331
338
  cacheKey: effectiveCacheKey,
@@ -542,31 +549,49 @@ export class VeryfrontFSAdapter {
542
549
  async triggerCSSPregeneration(files) {
543
550
  try {
544
551
  const { pregenerateCSSFromFiles, findStylesheetFromFiles } = await import("../../../../html/styles-builder/css-pregeneration.js");
552
+ const { resolveStyleContentVersion } = await import("../../../../html/styles-builder/content-version.js");
553
+ const { createStyleScopeProfile } = await import("../../../../html/styles-builder/style-scope-profile.js");
545
554
  let stylesheetPath;
555
+ let styleProfile = createStyleScopeProfile();
546
556
  const projectDir = this.normalizer.getProjectDir();
547
- if (projectDir) {
548
- try {
549
- const { runtime } = await import("../../registry.js");
550
- const { getConfig } = await import("../../../../config/index.js");
551
- const adapter = await runtime.get();
552
- const cacheKey = this.client.getProjectId() || this.projectSlug;
553
- const config = await getConfig(projectDir, adapter, { cacheKey });
554
- stylesheetPath = config?.tailwind?.stylesheet;
555
- }
556
- catch (error) {
557
- logger.debug("Failed to load config for CSS pre-generation", {
558
- projectSlug: this.projectSlug,
559
- error: error instanceof Error ? error.message : String(error),
560
- });
561
- }
557
+ if (!projectDir) {
558
+ logger.debug("Skipping CSS pre-generation without projectDir", {
559
+ projectSlug: this.projectSlug,
560
+ });
561
+ return;
562
+ }
563
+ try {
564
+ const { runtime } = await import("../../registry.js");
565
+ const { getConfig } = await import("../../../../config/index.js");
566
+ const adapter = await runtime.get();
567
+ const cacheKey = this.client.getProjectId() || this.projectSlug;
568
+ const config = await getConfig(projectDir, adapter, { cacheKey });
569
+ stylesheetPath = config?.tailwind?.stylesheet;
570
+ styleProfile = createStyleScopeProfile(config);
571
+ }
572
+ catch (error) {
573
+ logger.debug("Failed to load config for CSS pre-generation", {
574
+ projectSlug: this.projectSlug,
575
+ error: error instanceof Error ? error.message : String(error),
576
+ });
562
577
  }
563
578
  const stylesheet = findStylesheetFromFiles(files, stylesheetPath);
579
+ const projectVersion = resolveStyleContentVersion(this.contentContext, {
580
+ branch: this.contentContext?.branch ?? null,
581
+ releaseId: this.contentContext?.releaseId ?? null,
582
+ environmentName: this.contentContext?.environmentName ?? null,
583
+ });
564
584
  await pregenerateCSSFromFiles({
565
585
  projectSlug: this.projectSlug,
586
+ projectVersion,
587
+ projectDir,
566
588
  files,
589
+ styleProfile,
567
590
  stylesheet,
568
591
  stylesheetPath,
569
592
  minify: true,
593
+ environment: "preview",
594
+ buildMode: "production",
570
595
  });
571
596
  }
572
597
  catch (error) {
@@ -0,0 +1,3 @@
1
+ import type { InvalidationCallbacks } from "./types.js";
2
+ export declare function createDefaultInvalidationCallbacks(callbacks?: InvalidationCallbacks): InvalidationCallbacks;
3
+ //# sourceMappingURL=default-invalidation-callbacks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-invalidation-callbacks.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/default-invalidation-callbacks.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAExD,wBAAgB,kCAAkC,CAChD,SAAS,CAAC,EAAE,qBAAqB,GAChC,qBAAqB,CAgBvB"}
@@ -0,0 +1,25 @@
1
+ import { clearSSRModuleCache, clearSSRModuleCacheForProject, } from "../../../../modules/react-loader/ssr-module-loader/cache/index.js";
2
+ import { clearRouterDetectionCacheForProject } from "../../../../rendering/router-detection.js";
3
+ import { clearModulePathCache, invalidateModulePaths, } from "../../../../transforms/mdx/esm-module-loader/cache/index.js";
4
+ import { clearSnippetCacheForProject } from "../../../../rendering/snippet-renderer.js";
5
+ import { clearRendererCacheForProject } from "../../../../rendering/renderer.js";
6
+ import { invalidateProjectCSS } from "../../../../html/styles-builder/tailwind-compiler.js";
7
+ import { invalidatePreparedProjectCSS } from "../../../../html/styles-builder/prepared-project-css-cache.js";
8
+ import { invalidateProjectCandidateManifests } from "../../../../rendering/orchestrator/css-candidate-manifest.js";
9
+ export function createDefaultInvalidationCallbacks(callbacks) {
10
+ return {
11
+ clearSSRModuleCache,
12
+ clearModulePathCache,
13
+ invalidateModulePaths,
14
+ clearSSRModuleCacheForProject,
15
+ clearRouterDetectionCacheForProject,
16
+ clearSnippetCacheForProject,
17
+ clearRendererCacheForProject,
18
+ clearProjectCSSCache: (projectSlug) => {
19
+ invalidateProjectCSS(projectSlug);
20
+ invalidatePreparedProjectCSS(projectSlug);
21
+ invalidateProjectCandidateManifests(projectSlug);
22
+ },
23
+ ...callbacks,
24
+ };
25
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"proxy-manager.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/proxy-manager.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAA0B,MAAM,YAAY,CAAC;AAyBtF,UAAU,2BAA2B;IACnC,UAAU,EAAE,eAAe,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAqC;IACrD,OAAO,CAAC,eAAe,CAAkD;IACzE,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,YAAY,CAAC,CAAyC;gBAElD,MAAM,EAAE,2BAA2B;IAkBzC,UAAU,CACd,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,MAAM,EAClB,cAAc,CAAC,EAAE,OAAO,EACxB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,EACzB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,EAC/B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GACrB,OAAO,CAAC,kBAAkB,CAAC;IA+H9B,OAAO,CAAC,oBAAoB;IAuC5B,OAAO,CAAC,wBAAwB;IAyChC,OAAO,CAAC,aAAa;IA4GrB,OAAO,CAAC,sBAAsB;IAsB9B,OAAO,CAAC,mBAAmB;IAY3B,UAAU,CACR,WAAW,EAAE,MAAM,EACnB,cAAc,CAAC,EAAE,OAAO,EACxB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,EACzB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GACrB,OAAO;IAUV,QAAQ,IAAI;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;KAAE;IAUnE,OAAO,IAAI,IAAI;CAchB"}
1
+ {"version":3,"file":"proxy-manager.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/proxy-manager.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAA0B,MAAM,YAAY,CAAC;AAetF,UAAU,2BAA2B;IACnC,UAAU,EAAE,eAAe,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAqC;IACrD,OAAO,CAAC,eAAe,CAAkD;IACzE,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,YAAY,CAAC,CAAyC;gBAElD,MAAM,EAAE,2BAA2B;IAkBzC,UAAU,CACd,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,MAAM,EAClB,cAAc,CAAC,EAAE,OAAO,EACxB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,EACzB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,EAC/B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GACrB,OAAO,CAAC,kBAAkB,CAAC;IA+H9B,OAAO,CAAC,oBAAoB;IAuC5B,OAAO,CAAC,wBAAwB;IAyChC,OAAO,CAAC,aAAa;IAqGrB,OAAO,CAAC,sBAAsB;IAsB9B,OAAO,CAAC,mBAAmB;IAY3B,UAAU,CACR,WAAW,EAAE,MAAM,EACnB,cAAc,CAAC,EAAE,OAAO,EACxB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,EACzB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GACrB,OAAO;IAUV,QAAQ,IAAI;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;KAAE;IAUnE,OAAO,IAAI,IAAI;CAchB"}
@@ -3,12 +3,8 @@ import { logger as baseLogger } from "../../../../utils/index.js";
3
3
  import { CACHE_INVARIANT_VIOLATION, INVALID_ARGUMENT } from "../../../../errors/index.js";
4
4
  import { buildProxyManagerCacheKey } from "../../../../cache/index.js";
5
5
  import { VeryfrontFSAdapter } from "./index.js";
6
- import { clearSSRModuleCache, clearSSRModuleCacheForProject, } from "../../../../modules/react-loader/ssr-module-loader/cache/index.js";
7
- import { clearRouterDetectionCacheForProject } from "../../../../rendering/router-detection.js";
8
- import { clearModulePathCache, invalidateModulePaths, } from "../../../../transforms/mdx/esm-module-loader/cache/index.js";
9
- import { clearSnippetCacheForProject } from "../../../../rendering/snippet-renderer.js";
10
- import { clearRendererCacheForProject } from "../../../../rendering/renderer.js";
11
6
  import { GetAdapterParamsSchema } from "./schemas/index.js";
7
+ import { createDefaultInvalidationCallbacks } from "./default-invalidation-callbacks.js";
12
8
  const logger = baseLogger.component("proxy-fs-adapter-manager");
13
9
  const DEFAULT_MAX_ADAPTERS = 100;
14
10
  const DEFAULT_MAX_IDLE_MS = 30 * 60 * 1_000;
@@ -193,16 +189,7 @@ export class ProxyFSAdapterManager {
193
189
  projectId,
194
190
  apiToken: effectiveToken,
195
191
  },
196
- invalidationCallbacks: {
197
- clearSSRModuleCache,
198
- clearModulePathCache,
199
- invalidateModulePaths,
200
- clearSSRModuleCacheForProject,
201
- clearRouterDetectionCacheForProject,
202
- clearSnippetCacheForProject,
203
- clearRendererCacheForProject,
204
- ...this.baseConfig.invalidationCallbacks,
205
- },
192
+ invalidationCallbacks: createDefaultInvalidationCallbacks(this.baseConfig.invalidationCallbacks),
206
193
  };
207
194
  const adapter = new VeryfrontFSAdapter(config);
208
195
  let context;
@@ -17,6 +17,10 @@ interface WebSocketDeps {
17
17
  path: string;
18
18
  content?: string;
19
19
  }>) => Promise<void>;
20
+ pregenerateStyles?: (files: Array<{
21
+ path: string;
22
+ content?: string;
23
+ }>) => Promise<void>;
20
24
  }
21
25
  export declare class WebSocketManager {
22
26
  private readonly deps;
@@ -1 +1 @@
1
- {"version":3,"file":"websocket-manager.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/websocket-manager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAwB/F,UAAU,aAAa;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,qBAAqB,EAAE,qBAAqB,CAAC;IAE7C,iBAAiB,EAAE,MAAM,sBAAsB,GAAG,IAAI,CAAC;IACvD,gBAAgB,EAAE,MAAM,aAAa,CAAC;IACtC,aAAa,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IACxC,iBAAiB,EAAE,MAAM,IAAI,CAAC;IAC9B,kBAAkB,EAAE,MAAM,IAAI,CAAC;IAC/B,gBAAgB,EAAE,CAChB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,KAC7C,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB;AAED,qBAAa,gBAAgB;IAqBf,OAAO,CAAC,QAAQ,CAAC,IAAI;IApBjC,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,gBAAgB,CAAsD;IAC9E,OAAO,CAAC,gBAAgB,CAAuD;IAC/E,OAAO,CAAC,UAAU,CAAc;IAChC,OAAO,CAAC,iBAAiB,CAAsD;IAC/E,OAAO,CAAC,0BAA0B,CAAsD;IACxF,OAAO,CAAC,mBAAmB,CAAqB;IAEhD,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,qBAAqB,CAAK;IAClC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,0BAA0B,CAAK;IACvC,OAAO,CAAC,iCAAiC,CAAqB;IAC9D,OAAO,CAAC,WAAW,CAIjB;gBAE2B,IAAI,EAAE,aAAa;IAEhD,OAAO,CAAC,uBAAuB;IAK/B,OAAO,CAAC,8BAA8B;IAOtC,OAAO,CAAC,wBAAwB;IAahC,OAAO,CAAC,2BAA2B;IAUnC,cAAc,IAAI;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,sBAAsB,EAAE,MAAM,CAAC;QAC/B,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;KAC7B;IAID,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IA+GhC,OAAO,CAAC,iBAAiB;IAMzB,OAAO,IAAI,IAAI;IA8Bf,OAAO,CAAC,iBAAiB;IAyJzB,OAAO,CAAC,8BAA8B;IA0GtC,OAAO,CAAC,oBAAoB;IAa5B,OAAO,CAAC,6BAA6B;YAiBvB,4BAA4B;YAwI5B,mBAAmB;IA2IjC,OAAO,CAAC,cAAc;IA+BtB,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,WAAW;CAyBpB"}
1
+ {"version":3,"file":"websocket-manager.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/websocket-manager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAwB/F,UAAU,aAAa;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,qBAAqB,EAAE,qBAAqB,CAAC;IAE7C,iBAAiB,EAAE,MAAM,sBAAsB,GAAG,IAAI,CAAC;IACvD,gBAAgB,EAAE,MAAM,aAAa,CAAC;IACtC,aAAa,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IACxC,iBAAiB,EAAE,MAAM,IAAI,CAAC;IAC9B,kBAAkB,EAAE,MAAM,IAAI,CAAC;IAC/B,gBAAgB,EAAE,CAChB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,KAC7C,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACzF;AAED,qBAAa,gBAAgB;IAqBf,OAAO,CAAC,QAAQ,CAAC,IAAI;IApBjC,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,gBAAgB,CAAsD;IAC9E,OAAO,CAAC,gBAAgB,CAAuD;IAC/E,OAAO,CAAC,UAAU,CAAc;IAChC,OAAO,CAAC,iBAAiB,CAAsD;IAC/E,OAAO,CAAC,0BAA0B,CAAsD;IACxF,OAAO,CAAC,mBAAmB,CAAqB;IAEhD,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,qBAAqB,CAAK;IAClC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,0BAA0B,CAAK;IACvC,OAAO,CAAC,iCAAiC,CAAqB;IAC9D,OAAO,CAAC,WAAW,CAIjB;gBAE2B,IAAI,EAAE,aAAa;IAEhD,OAAO,CAAC,uBAAuB;IAK/B,OAAO,CAAC,8BAA8B;IAOtC,OAAO,CAAC,wBAAwB;IAahC,OAAO,CAAC,2BAA2B;IAUnC,cAAc,IAAI;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,sBAAsB,EAAE,MAAM,CAAC;QAC/B,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;KAC7B;IAID,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IA+GhC,OAAO,CAAC,iBAAiB;IAMzB,OAAO,IAAI,IAAI;IA8Bf,OAAO,CAAC,iBAAiB;IAyJzB,OAAO,CAAC,8BAA8B;IA0GtC,OAAO,CAAC,oBAAoB;IAa5B,OAAO,CAAC,6BAA6B;YAiBvB,4BAA4B;YAyI5B,mBAAmB;IA4IjC,OAAO,CAAC,cAAc;IA+BtB,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,WAAW;CAyBpB"}
@@ -481,6 +481,7 @@ export class WebSocketManager {
481
481
  const cacheKey = buildFileListCacheKey(contentContext);
482
482
  await this.deps.setFileListCache(cacheKey, files);
483
483
  this.deps.clearFileListIndex();
484
+ await this.deps.pregenerateStyles?.(files);
484
485
  logger.debug("Fresh files cached (memory + Redis)", {
485
486
  cacheKey,
486
487
  fileCount: files.length,
@@ -586,6 +587,7 @@ export class WebSocketManager {
586
587
  const cacheKey = buildFileListCacheKey(contentContext);
587
588
  await this.deps.setFileListCache(cacheKey, files);
588
589
  this.deps.clearFileListIndex();
590
+ await this.deps.pregenerateStyles?.(files);
589
591
  logger.debug("FRESH FILES FETCHED", {
590
592
  cacheKey,
591
593
  fileCount: files.length,
@@ -1,3 +1,4 @@
1
+ import { type StyleScopeProfile } from "../../html/styles-builder/style-scope-profile.js";
1
2
  interface SourceFileLike {
2
3
  path: string;
3
4
  content?: string;
@@ -6,6 +7,7 @@ interface RouteCandidateOptions {
6
7
  projectScope: string;
7
8
  projectVersion: string;
8
9
  projectDir: string;
10
+ styleProfile?: StyleScopeProfile;
9
11
  routeKey: string;
10
12
  routeFilePaths: string[];
11
13
  files: SourceFileLike[];
@@ -15,6 +17,7 @@ interface ProjectCandidateOptions {
15
17
  projectScope: string;
16
18
  projectVersion: string;
17
19
  projectDir: string;
20
+ styleProfile?: StyleScopeProfile;
18
21
  files: SourceFileLike[];
19
22
  developmentMode: boolean;
20
23
  }
@@ -1 +1 @@
1
- {"version":3,"file":"css-candidate-manifest.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/orchestrator/css-candidate-manifest.ts"],"names":[],"mappings":"AAIA,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAQD,UAAU,qBAAqB;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,UAAU,uBAAuB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,eAAe,EAAE,OAAO,CAAC;CAC1B;AA0GD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,qBAAqB,GAAG,GAAG,CAAC,MAAM,CAAC,CAkC9E;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,uBAAuB,GAAG,GAAG,CAAC,MAAM,CAAC,CAGlF;AAED;;GAEG;AACH,wBAAgB,mCAAmC,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAc/E"}
1
+ {"version":3,"file":"css-candidate-manifest.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/orchestrator/css-candidate-manifest.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,kDAAkD,CAAC;AAI1D,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAQD,UAAU,qBAAqB;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,iBAAiB,CAAC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,UAAU,uBAAuB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,iBAAiB,CAAC;IACjC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAqHD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,qBAAqB,GAAG,GAAG,CAAC,MAAM,CAAC,CAuC9E;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,uBAAuB,GAAG,GAAG,CAAC,MAAM,CAAC,CAGlF;AAED;;GAEG;AACH,wBAAgB,mCAAmC,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAc/E"}
@@ -1,4 +1,5 @@
1
1
  import { extractCandidates } from "../../html/styles-builder/tailwind-compiler.js";
2
+ import { filterFilesForStyleScope, } from "../../html/styles-builder/style-scope-profile.js";
2
3
  import { getRouteModulePaths } from "../../modules/manifest/route-module-manifest.js";
3
4
  import { rendererLogger } from "../../utils/index.js";
4
5
  const logger = rendererLogger.component("css-candidate-manifest");
@@ -17,8 +18,8 @@ function toRelativeProjectPath(path, projectDir) {
17
18
  }
18
19
  return normalized.replace(/^\/+/, "");
19
20
  }
20
- function buildManifestCacheKey(projectScope, projectVersion) {
21
- return `${projectScope}:${projectVersion}`;
21
+ function buildManifestCacheKey(projectScope, projectVersion, styleProfileHash) {
22
+ return `${projectScope}:${projectVersion}:${styleProfileHash ?? "default"}`;
22
23
  }
23
24
  function shouldRebuildManifest(existing, developmentMode) {
24
25
  if (!existing)
@@ -59,10 +60,13 @@ function buildCandidateManifest(files, projectDir) {
59
60
  return { fileCandidates, allCandidates, builtAt: Date.now() };
60
61
  }
61
62
  function getOrBuildManifest(options) {
62
- const manifestKey = buildManifestCacheKey(options.projectScope, options.projectVersion);
63
+ const manifestKey = buildManifestCacheKey(options.projectScope, options.projectVersion, options.styleProfile?.hash);
63
64
  const existingManifest = manifestCache.get(manifestKey);
65
+ const scopedFiles = options.styleProfile
66
+ ? filterFilesForStyleScope(options.files, options.styleProfile, options.projectDir)
67
+ : options.files;
64
68
  const manifest = shouldRebuildManifest(existingManifest, options.developmentMode)
65
- ? buildCandidateManifest(options.files, options.projectDir)
69
+ ? buildCandidateManifest(scopedFiles, options.projectDir)
66
70
  : existingManifest;
67
71
  if (manifest !== existingManifest) {
68
72
  manifestCache.set(manifestKey, manifest);
@@ -87,7 +91,7 @@ function addCandidatesForPath(target, manifest, path, projectDir) {
87
91
  * Resolve route-scoped Tailwind candidates from a precomputed per-project manifest.
88
92
  */
89
93
  export function getRouteCandidates(options) {
90
- const manifestKey = buildManifestCacheKey(options.projectScope, options.projectVersion);
94
+ const manifestKey = buildManifestCacheKey(options.projectScope, options.projectVersion, options.styleProfile?.hash);
91
95
  const manifest = getOrBuildManifest(options);
92
96
  const routeCacheKey = `${manifestKey}:${options.routeKey}`;
93
97
  const cachedRoute = routeCandidateCache.get(routeCacheKey);
@@ -111,6 +115,7 @@ export function getRouteCandidates(options) {
111
115
  logger.debug("Resolved route candidates", {
112
116
  projectScope: options.projectScope,
113
117
  projectVersion: options.projectVersion,
118
+ styleProfileHash: options.styleProfile?.hash,
114
119
  route: options.routeKey,
115
120
  count: routeCandidates.size,
116
121
  });
@@ -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;AAQ7D,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;AAE9B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAchD,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;IAWjE,kBAAkB,CACtB,WAAW,EAAE,cAAc,EAC3B,OAAO,EAAE,IAAI,CAAC,qBAAqB,EAAE,MAAM,CAAC,GAC3C,OAAO,CAAC,cAAc,CAAC;YAmCZ,sBAAsB;YAsBtB,wBAAwB;YAmBxB,gBAAgB;YAehB,kBAAkB;IAsDhC,OAAO,CAAC,iBAAiB;IA4DzB,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,cAAc;YAQR,eAAe;YAaf,gBAAgB;IAwE9B;;;;OAIG;YACW,gBAAgB;IA2D9B,OAAO,CAAC,wBAAwB;IAchC,OAAO,CAAC,qBAAqB;YAOf,6BAA6B;CAwD5C"}
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;AAQ7D,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;AAE9B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAiBhD,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;IAWjE,kBAAkB,CACtB,WAAW,EAAE,cAAc,EAC3B,OAAO,EAAE,IAAI,CAAC,qBAAqB,EAAE,MAAM,CAAC,GAC3C,OAAO,CAAC,cAAc,CAAC;YAmCZ,sBAAsB;YAsBtB,wBAAwB;YAmBxB,gBAAgB;YAehB,kBAAkB;IAsDhC,OAAO,CAAC,iBAAiB;IA4DzB,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,cAAc;YAQR,eAAe;YAaf,gBAAgB;IAwE9B;;;;OAIG;YACW,gBAAgB;IA2D9B,OAAO,CAAC,wBAAwB;IAqBhC,OAAO,CAAC,qBAAqB;YAOf,6BAA6B;CAyD5C"}
@@ -9,6 +9,8 @@ import { resolveAppComponentPath } from "../layouts/utils/app-resolver.js";
9
9
  import { StreamTimeoutError, streamToString } from "../utils/stream-utils.js";
10
10
  import { normalizeCssModuleKey, rewriteCssModuleContent, } from "../../transforms/css-modules/naming.js";
11
11
  import { getRouteCandidates } from "./css-candidate-manifest.js";
12
+ import { resolveStyleContentVersion } from "../../html/styles-builder/content-version.js";
13
+ import { createStyleScopeProfile } from "../../html/styles-builder/style-scope-profile.js";
12
14
  const logger = rendererLogger.component("html-generator");
13
15
  export class HTMLGenerator {
14
16
  config;
@@ -317,6 +319,11 @@ export class HTMLGenerator {
317
319
  if (typeof wrappedFs.getUnderlyingAdapter !== "function")
318
320
  return undefined;
319
321
  const fsAdapter = wrappedFs.getUnderlyingAdapter();
322
+ const contentContext = typeof fsAdapter.getContentContext === "function"
323
+ ? fsAdapter.getContentContext()
324
+ : null;
325
+ if (contentContext)
326
+ return resolveStyleContentVersion(contentContext);
320
327
  return fsAdapter.getProjectData?.()?.updated_at;
321
328
  }
322
329
  buildRouteManifestKey(pagePath) {
@@ -351,6 +358,7 @@ export class HTMLGenerator {
351
358
  projectScope,
352
359
  projectVersion,
353
360
  projectDir: this.config.projectDir,
361
+ styleProfile: createStyleScopeProfile(this.config.config),
354
362
  routeKey,
355
363
  routeFilePaths,
356
364
  files,
@@ -1 +1 @@
1
- {"version":3,"file":"styles-candidate-scanner.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/dev/styles-candidate-scanner.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAQH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AA8BlD;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CA0CxF"}
1
+ {"version":3,"file":"styles-candidate-scanner.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/dev/styles-candidate-scanner.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAcH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAiBlD;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAgDxF"}
@@ -8,6 +8,8 @@
8
8
  * @module server/handlers/dev/styles-candidate-scanner
9
9
  */
10
10
  import { extractCandidates } from "../../../html/styles-builder/tailwind-compiler.js";
11
+ import { resolveStyleContentVersion } from "../../../html/styles-builder/content-version.js";
12
+ import { createStyleScopeProfile, shouldIncludeStylePath, shouldTraverseStyleDirectory, } from "../../../html/styles-builder/style-scope-profile.js";
11
13
  import { serverLogger } from "../../../utils/index.js";
12
14
  import { createFileSystem } from "../../../platform/compat/fs.js";
13
15
  import { join } from "../../../platform/compat/path/index.js";
@@ -15,22 +17,8 @@ import { getProjectCandidates } from "../../../rendering/orchestrator/css-candid
15
17
  import { FRAMEWORK_CANDIDATES } from "./framework-candidates.generated.js";
16
18
  const logger = serverLogger.component("styles-candidate-scanner");
17
19
  const SOURCE_EXTENSIONS = [".tsx", ".jsx", ".mdx", ".ts", ".js"];
18
- const SKIP_DIRS = new Set(["node_modules", ".cache", ".git", "dist", "build", ".vscode"]);
19
20
  /** De-duplicated set of framework candidates, computed once at import time. */
20
21
  const frameworkCandidates = new Set(FRAMEWORK_CANDIDATES);
21
- function resolveProjectVersion(ctx, contentContext) {
22
- if (contentContext?.releaseId)
23
- return `release:${contentContext.releaseId}`;
24
- if (contentContext?.branch)
25
- return `branch:${contentContext.branch}`;
26
- if (contentContext?.environmentName)
27
- return `environment:${contentContext.environmentName}`;
28
- if (ctx.releaseId)
29
- return `release:${ctx.releaseId}`;
30
- if (ctx.parsedDomain?.branch)
31
- return `branch:${ctx.parsedDomain.branch}`;
32
- return "live";
33
- }
34
22
  /**
35
23
  * Extract Tailwind CSS candidate class names from all project source files.
36
24
  *
@@ -39,6 +27,7 @@ function resolveProjectVersion(ctx, contentContext) {
39
27
  * method is available (local dev mode).
40
28
  */
41
29
  export async function extractProjectCandidates(ctx) {
30
+ const styleProfile = createStyleScopeProfile(ctx.config);
42
31
  const wrappedFs = ctx.adapter.fs;
43
32
  if (typeof wrappedFs.getUnderlyingAdapter !== "function") {
44
33
  logger.debug("[StylesCandidateScanner] No FS adapter wrapper, falling back to local file scanning");
@@ -57,8 +46,13 @@ export async function extractProjectCandidates(ctx) {
57
46
  : null;
58
47
  for (const cls of getProjectCandidates({
59
48
  projectScope: ctx.projectSlug ?? contentContext?.projectSlug ?? ctx.projectDir,
60
- projectVersion: resolveProjectVersion(ctx, contentContext),
49
+ projectVersion: resolveStyleContentVersion(contentContext, {
50
+ releaseId: ctx.releaseId,
51
+ branch: ctx.parsedDomain?.branch,
52
+ environmentName: ctx.environmentName,
53
+ }),
61
54
  projectDir: ctx.projectDir,
55
+ styleProfile,
62
56
  files,
63
57
  developmentMode: contentContext?.sourceType === "branch",
64
58
  })) {
@@ -71,6 +65,7 @@ export async function extractProjectCandidates(ctx) {
71
65
  * Used in local development mode where projects are read directly from disk.
72
66
  */
73
67
  async function scanLocalFiles(projectDir, ctx) {
68
+ const styleProfile = createStyleScopeProfile(ctx.config);
74
69
  const candidates = new Set(frameworkCandidates);
75
70
  const fs = createFileSystem();
76
71
  const scanDir = async (dir) => {
@@ -85,12 +80,15 @@ async function scanLocalFiles(projectDir, ctx) {
85
80
  for await (const entry of entries) {
86
81
  const fullPath = join(dir, entry.name);
87
82
  if (entry.isDirectory) {
88
- if (!SKIP_DIRS.has(entry.name))
83
+ if (shouldTraverseStyleDirectory(styleProfile, fullPath, projectDir)) {
89
84
  await scanDir(fullPath);
85
+ }
90
86
  continue;
91
87
  }
92
88
  if (!entry.isFile)
93
89
  continue;
90
+ if (!shouldIncludeStylePath(styleProfile, fullPath, projectDir))
91
+ continue;
94
92
  if (!SOURCE_EXTENSIONS.some((ext) => entry.name.endsWith(ext)))
95
93
  continue;
96
94
  try {
@@ -12,5 +12,7 @@ export declare class StylesCSSHandler extends BaseHandler {
12
12
  handle(req: dntShim.Request, ctx: HandlerContext): Promise<HandlerResult>;
13
13
  private loadStylesheet;
14
14
  private generateStylesheet;
15
+ private getContentContext;
16
+ private createPreparedCSSContext;
15
17
  }
16
18
  //# sourceMappingURL=styles-css.handler.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"styles-css.handler.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/dev/styles-css.handler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,OAAO,MAAM,2BAA2B,CAAC;AAGrD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAmB,aAAa,EAAE,MAAM,aAAa,CAAC;AAkBnG,qBAAa,gBAAiB,SAAQ,WAAW;IAC/C,QAAQ,EAAE,eAAe,CAKvB;IAEI,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;YAkGjE,cAAc;IAkB5B,OAAO,CAAC,kBAAkB;CAe3B"}
1
+ {"version":3,"file":"styles-css.handler.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/dev/styles-css.handler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,OAAO,MAAM,2BAA2B,CAAC;AAGrD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAmB,aAAa,EAAE,MAAM,aAAa,CAAC;AAoBnG,qBAAa,gBAAiB,SAAQ,WAAW;IAC/C,QAAQ,EAAE,eAAe,CAKvB;IAEI,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;YAqIjE,cAAc;IAkB5B,OAAO,CAAC,kBAAkB;IAc1B,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,wBAAwB;CAyBjC"}
@@ -1,8 +1,11 @@
1
1
  import { BaseHandler } from "../response/base.js";
2
2
  import { HTTP_OK, PRIORITY_HIGH_DEV } from "../../../utils/constants/index.js";
3
3
  import { joinPath } from "../../../utils/path-utils.js";
4
- import { formatCSSError, generateTailwindCSS, getProjectCSS, } from "../../../html/styles-builder/tailwind-compiler.js";
4
+ import { formatCSSError, getProjectCSS } from "../../../html/styles-builder/tailwind-compiler.js";
5
5
  import { DEFAULT_STYLESHEET } from "../../../html/styles-builder/css-hash-cache.js";
6
+ import { resolveStyleContentVersion } from "../../../html/styles-builder/content-version.js";
7
+ import { createPreparedProjectCSSContext, storePreparedProjectCSS, tryGetPreparedProjectCSS, } from "../../../html/styles-builder/prepared-project-css-cache.js";
8
+ import { createStyleScopeProfile } from "../../../html/styles-builder/style-scope-profile.js";
6
9
  import { serverLogger } from "../../../utils/index.js";
7
10
  import { extractProjectCandidates } from "./styles-candidate-scanner.js";
8
11
  const logger = serverLogger.component("styles-css-handler");
@@ -19,6 +22,9 @@ export class StylesCSSHandler extends BaseHandler {
19
22
  try {
20
23
  return await this.withProxyContext(ctx, async () => {
21
24
  const responseBuilder = this.createResponseBuilder(ctx).withCache("no-cache");
25
+ const projectScope = ctx.projectSlug ?? ctx.projectDir;
26
+ const styleProfile = createStyleScopeProfile(ctx.config);
27
+ const contentContext = this.getContentContext(ctx);
22
28
  let rawCss;
23
29
  try {
24
30
  rawCss = await this.loadStylesheet(ctx);
@@ -29,6 +35,19 @@ export class StylesCSSHandler extends BaseHandler {
29
35
  });
30
36
  rawCss = DEFAULT_STYLESHEET;
31
37
  }
38
+ const preparedContext = this.createPreparedCSSContext(projectScope, rawCss, styleProfile.hash, contentContext, ctx);
39
+ if (preparedContext) {
40
+ const prepared = await tryGetPreparedProjectCSS(preparedContext);
41
+ if (prepared) {
42
+ logger.debug("Prepared CSS cache hit", {
43
+ projectScope,
44
+ projectVersion: preparedContext.projectVersion,
45
+ styleProfileHash: styleProfile.hash,
46
+ cssHash: prepared.hash,
47
+ });
48
+ return this.respond(responseBuilder.withContentType("text/css; charset=utf-8", prepared.css, HTTP_OK));
49
+ }
50
+ }
32
51
  let candidates;
33
52
  try {
34
53
  candidates = await extractProjectCandidates(ctx);
@@ -39,9 +58,12 @@ export class StylesCSSHandler extends BaseHandler {
39
58
  });
40
59
  candidates = new Set();
41
60
  }
42
- const result = await this.generateStylesheet(ctx, rawCss, candidates);
43
- if ("error" in result && result.error) {
44
- const formatted = formatCSSError(result.error);
61
+ let result;
62
+ try {
63
+ result = await this.generateStylesheet(ctx, rawCss, candidates);
64
+ }
65
+ catch (error) {
66
+ const formatted = formatCSSError(error instanceof Error ? error : String(error));
45
67
  logger.error("Tailwind error", {
46
68
  error: formatted.message,
47
69
  suggestion: formatted.suggestion,
@@ -78,11 +100,18 @@ body::before {
78
100
  });
79
101
  }
80
102
  logger.debug("CSS generated", {
103
+ projectScope,
81
104
  candidates: candidates.size,
82
105
  cssLength: result.css.length,
83
106
  fromCache: "fromCache" in result ? result.fromCache : false,
84
107
  cssHash: "hash" in result ? result.hash : undefined,
85
108
  });
109
+ if (preparedContext && "hash" in result) {
110
+ await storePreparedProjectCSS(preparedContext, {
111
+ css: result.css,
112
+ hash: result.hash,
113
+ });
114
+ }
86
115
  return this.respond(responseBuilder.withContentType("text/css; charset=utf-8", result.css, HTTP_OK));
87
116
  });
88
117
  }
@@ -115,10 +144,28 @@ body::before {
115
144
  }
116
145
  }
117
146
  generateStylesheet(ctx, rawCss, candidates) {
118
- if (!ctx.projectSlug) {
119
- return generateTailwindCSS(rawCss, candidates);
120
- }
121
- return getProjectCSS(ctx.projectSlug, rawCss, candidates, {
147
+ const projectScope = ctx.projectSlug ?? ctx.projectDir;
148
+ return getProjectCSS(projectScope, rawCss, candidates, {
149
+ minify: true,
150
+ environment: "preview",
151
+ buildMode: "production",
152
+ });
153
+ }
154
+ getContentContext(ctx) {
155
+ const wrappedFs = ctx.adapter.fs;
156
+ if (typeof wrappedFs.getUnderlyingAdapter !== "function")
157
+ return null;
158
+ const fsAdapter = wrappedFs.getUnderlyingAdapter();
159
+ return typeof fsAdapter.getContentContext === "function" ? fsAdapter.getContentContext() : null;
160
+ }
161
+ createPreparedCSSContext(projectScope, rawCss, styleProfileHash, contentContext, ctx) {
162
+ if (!projectScope)
163
+ return undefined;
164
+ return createPreparedProjectCSSContext(projectScope, resolveStyleContentVersion(contentContext, {
165
+ releaseId: ctx.releaseId,
166
+ branch: ctx.parsedDomain?.branch,
167
+ environmentName: ctx.environmentName,
168
+ }), rawCss, styleProfileHash, {
122
169
  minify: true,
123
170
  environment: "preview",
124
171
  buildMode: "production",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "veryfront",
3
- "version": "0.1.89",
3
+ "version": "0.1.90",
4
4
  "description": "The simplest way to build AI-powered apps",
5
5
  "keywords": [
6
6
  "react",
@@ -219,6 +219,23 @@ function slugify(value: string): string {
219
219
  return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "document";
220
220
  }
221
221
 
222
+ /**
223
+ * Strip the chat-upload prefix that Studio prepends to uploaded files.
224
+ *
225
+ * Studio stores uploads with a generated prefix like:
226
+ * chat-<uuid>-<timestamp>-<shortid>-<original-filename>
227
+ *
228
+ * This function removes the prefix so knowledge files use the clean
229
+ * original filename (e.g. "agents" instead of
230
+ * "chat-909d3dbc-5a9a-4156-97e4-bcceb5c2ec0d-1773942180291-fv1qg5-agents").
231
+ */
232
+ const CHAT_UPLOAD_PREFIX_RE =
233
+ /^chat-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}-\d+-[a-z0-9]+-/i;
234
+
235
+ export function stripChatUploadPrefix(name: string): string {
236
+ return name.replace(CHAT_UPLOAD_PREFIX_RE, "");
237
+ }
238
+
222
239
  function defaultOutputRoot(): Promise<string> {
223
240
  return dntShim.Deno.makeTempDir({ prefix: "veryfront-knowledge-" });
224
241
  }
@@ -361,7 +378,7 @@ function buildSourceReference(source: KnowledgeSource): string {
361
378
  : source.localPath;
362
379
  }
363
380
 
364
- function buildSuggestedSlug(source: KnowledgeSource, index: number): string {
381
+ export function buildSuggestedSlug(source: KnowledgeSource, index: number): string {
365
382
  const normalized = normalize(
366
383
  source.kind === "upload" ? source.uploadPath : source.localPath,
367
384
  ).replace(/\\/g, "/");
@@ -383,9 +400,20 @@ function buildSuggestedSlug(source: KnowledgeSource, index: number): string {
383
400
  stripped = normalized.replace(/\.[^.]+$/, "");
384
401
  }
385
402
 
403
+ // Strip Studio's chat-upload prefix from the filename portion so that
404
+ // knowledge files use the original clean filename.
405
+ const lastSlash = stripped.lastIndexOf("/");
406
+ if (lastSlash >= 0) {
407
+ const dir = stripped.slice(0, lastSlash + 1);
408
+ const file = stripChatUploadPrefix(stripped.slice(lastSlash + 1));
409
+ stripped = file ? `${dir}${file}` : stripped;
410
+ } else {
411
+ stripped = stripChatUploadPrefix(stripped) || stripped;
412
+ }
413
+
386
414
  return slugify(stripped || basename(normalized, extname(normalized)) || `document-${index + 1}`);
387
415
  }
388
- function ensureUniqueSlugs(sources: KnowledgeSource[]): string[] {
416
+ export function ensureUniqueSlugs(sources: KnowledgeSource[]): string[] {
389
417
  const counts = new Map<string, number>();
390
418
  return sources.map((source, index) => {
391
419
  const baseSlug = buildSuggestedSlug(source, index);