veryfront 0.1.26 → 0.1.28

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 (124) hide show
  1. package/README.md +3 -11
  2. package/esm/cli/app/shell.d.ts.map +1 -1
  3. package/esm/cli/app/shell.js +9 -5
  4. package/esm/cli/commands/demo/demo.js +1 -1
  5. package/esm/cli/commands/init/catalog.d.ts.map +1 -1
  6. package/esm/cli/commands/init/catalog.js +13 -5
  7. package/esm/cli/commands/init/command-help.js +4 -4
  8. package/esm/cli/commands/init/types.d.ts +1 -1
  9. package/esm/cli/commands/init/types.d.ts.map +1 -1
  10. package/esm/cli/commands/serve/command.d.ts.map +1 -1
  11. package/esm/cli/commands/serve/command.js +0 -4
  12. package/esm/cli/commands/start/command.d.ts.map +1 -1
  13. package/esm/cli/commands/start/command.js +16 -9
  14. package/esm/cli/help/tips.js +6 -6
  15. package/esm/cli/mcp/remote-file-tools.js +1 -1
  16. package/esm/cli/mcp/tools/catalog-tools.d.ts +3 -3
  17. package/esm/cli/mcp/tools/catalog-tools.d.ts.map +1 -1
  18. package/esm/cli/mcp/tools/catalog-tools.js +21 -13
  19. package/esm/cli/mcp/tools/project-tools.js +1 -1
  20. package/esm/cli/templates/index.js +11 -11
  21. package/esm/cli/templates/manifest.d.ts +22 -15
  22. package/esm/cli/templates/manifest.js +24 -17
  23. package/esm/cli/templates/types.d.ts +1 -1
  24. package/esm/cli/templates/types.d.ts.map +1 -1
  25. package/esm/cli/utils/index.d.ts.map +1 -1
  26. package/esm/cli/utils/index.js +13 -1
  27. package/esm/deno.js +1 -1
  28. package/esm/src/html/html-shell-generator.d.ts.map +1 -1
  29. package/esm/src/html/html-shell-generator.js +2 -0
  30. package/esm/src/html/styles-builder/project-css-cache.d.ts +8 -1
  31. package/esm/src/html/styles-builder/project-css-cache.d.ts.map +1 -1
  32. package/esm/src/html/styles-builder/project-css-cache.js +13 -2
  33. package/esm/src/html/styles-builder/tailwind-compiler.d.ts +2 -0
  34. package/esm/src/html/styles-builder/tailwind-compiler.d.ts.map +1 -1
  35. package/esm/src/html/styles-builder/tailwind-compiler.js +52 -19
  36. package/esm/src/modules/react-loader/css-import-collector.d.ts +29 -0
  37. package/esm/src/modules/react-loader/css-import-collector.d.ts.map +1 -0
  38. package/esm/src/modules/react-loader/css-import-collector.js +41 -0
  39. package/esm/src/modules/react-loader/ssr-module-loader/loader.d.ts.map +1 -1
  40. package/esm/src/modules/react-loader/ssr-module-loader/loader.js +6 -0
  41. package/esm/src/modules/react-loader/ssr-module-loader/ssr-dependency-validator.d.ts.map +1 -1
  42. package/esm/src/modules/react-loader/ssr-module-loader/ssr-dependency-validator.js +5 -0
  43. package/esm/src/platform/adapters/fs/factory.d.ts.map +1 -1
  44. package/esm/src/platform/adapters/fs/factory.js +5 -1
  45. package/esm/src/platform/adapters/fs/veryfront/websocket-manager.d.ts +1 -0
  46. package/esm/src/platform/adapters/fs/veryfront/websocket-manager.d.ts.map +1 -1
  47. package/esm/src/platform/adapters/fs/veryfront/websocket-manager.js +19 -5
  48. package/esm/src/platform/compat/process.d.ts.map +1 -1
  49. package/esm/src/platform/compat/process.js +20 -3
  50. package/esm/src/proxy/main.js +31 -12
  51. package/esm/src/proxy/token-manager.d.ts +2 -0
  52. package/esm/src/proxy/token-manager.d.ts.map +1 -1
  53. package/esm/src/proxy/token-manager.js +47 -8
  54. package/esm/src/rendering/orchestrator/css-candidate-manifest.d.ts +23 -0
  55. package/esm/src/rendering/orchestrator/css-candidate-manifest.d.ts.map +1 -0
  56. package/esm/src/rendering/orchestrator/css-candidate-manifest.js +132 -0
  57. package/esm/src/rendering/orchestrator/html.d.ts +11 -1
  58. package/esm/src/rendering/orchestrator/html.d.ts.map +1 -1
  59. package/esm/src/rendering/orchestrator/html.js +103 -18
  60. package/esm/src/rendering/orchestrator/pipeline.d.ts.map +1 -1
  61. package/esm/src/rendering/orchestrator/pipeline.js +14 -2
  62. package/esm/src/server/bootstrap.d.ts +2 -0
  63. package/esm/src/server/bootstrap.d.ts.map +1 -1
  64. package/esm/src/server/bootstrap.js +10 -0
  65. package/esm/src/server/handlers/preview/markdown-html-generator.d.ts.map +1 -1
  66. package/esm/src/server/handlers/preview/markdown-html-generator.js +11 -5
  67. package/esm/src/server/production-server.js +10 -2
  68. package/esm/src/studio/bridge-template.d.ts +2 -0
  69. package/esm/src/studio/bridge-template.d.ts.map +1 -1
  70. package/esm/src/studio/bridge-template.js +3390 -52
  71. package/esm/src/transforms/css-modules/naming.d.ts +33 -0
  72. package/esm/src/transforms/css-modules/naming.d.ts.map +1 -0
  73. package/esm/src/transforms/css-modules/naming.js +128 -0
  74. package/esm/src/transforms/esm/import-parser.d.ts +1 -0
  75. package/esm/src/transforms/esm/import-parser.d.ts.map +1 -1
  76. package/esm/src/transforms/esm/import-parser.js +16 -5
  77. package/esm/src/transforms/pipeline/index.d.ts.map +1 -1
  78. package/esm/src/transforms/pipeline/index.js +3 -1
  79. package/esm/src/transforms/pipeline/stages/index.d.ts +1 -0
  80. package/esm/src/transforms/pipeline/stages/index.d.ts.map +1 -1
  81. package/esm/src/transforms/pipeline/stages/index.js +1 -0
  82. package/esm/src/transforms/pipeline/stages/ssr-css-strip.d.ts +18 -0
  83. package/esm/src/transforms/pipeline/stages/ssr-css-strip.d.ts.map +1 -0
  84. package/esm/src/transforms/pipeline/stages/ssr-css-strip.js +168 -0
  85. package/package.json +1 -1
  86. package/src/cli/app/shell.ts +9 -5
  87. package/src/cli/commands/demo/demo.ts +1 -1
  88. package/src/cli/commands/init/catalog.ts +13 -5
  89. package/src/cli/commands/init/command-help.ts +4 -4
  90. package/src/cli/commands/init/types.ts +5 -5
  91. package/src/cli/commands/serve/command.ts +0 -5
  92. package/src/cli/commands/start/command.ts +15 -10
  93. package/src/cli/help/tips.ts +6 -6
  94. package/src/cli/mcp/remote-file-tools.ts +1 -1
  95. package/src/cli/mcp/tools/catalog-tools.ts +21 -13
  96. package/src/cli/mcp/tools/project-tools.ts +1 -1
  97. package/src/cli/templates/index.ts +11 -11
  98. package/src/cli/templates/manifest.js +24 -17
  99. package/src/cli/templates/types.ts +5 -5
  100. package/src/cli/utils/index.ts +12 -1
  101. package/src/deno.js +1 -1
  102. package/src/src/html/html-shell-generator.ts +2 -0
  103. package/src/src/html/styles-builder/project-css-cache.ts +24 -1
  104. package/src/src/html/styles-builder/tailwind-compiler.ts +67 -26
  105. package/src/src/modules/react-loader/css-import-collector.ts +50 -0
  106. package/src/src/modules/react-loader/ssr-module-loader/loader.ts +7 -0
  107. package/src/src/modules/react-loader/ssr-module-loader/ssr-dependency-validator.ts +6 -0
  108. package/src/src/platform/adapters/fs/factory.ts +5 -1
  109. package/src/src/platform/adapters/fs/veryfront/websocket-manager.ts +21 -5
  110. package/src/src/platform/compat/process.ts +28 -4
  111. package/src/src/proxy/main.ts +32 -12
  112. package/src/src/proxy/token-manager.ts +54 -8
  113. package/src/src/rendering/orchestrator/css-candidate-manifest.ts +176 -0
  114. package/src/src/rendering/orchestrator/html.ts +128 -16
  115. package/src/src/rendering/orchestrator/pipeline.ts +183 -165
  116. package/src/src/server/bootstrap.ts +16 -0
  117. package/src/src/server/handlers/preview/markdown-html-generator.ts +12 -5
  118. package/src/src/server/production-server.ts +12 -2
  119. package/src/src/studio/bridge-template.ts +3392 -52
  120. package/src/src/transforms/css-modules/naming.ts +152 -0
  121. package/src/src/transforms/esm/import-parser.ts +15 -5
  122. package/src/src/transforms/pipeline/index.ts +3 -0
  123. package/src/src/transforms/pipeline/stages/index.ts +1 -0
  124. package/src/src/transforms/pipeline/stages/ssr-css-strip.ts +201 -0
@@ -14,11 +14,17 @@ export { clearPluginCache, getCompilerCacheStats, invalidateCompiler, } from "./
14
14
  export { cacheCSSAsync, cacheCSSInputsAsync, clearCSSCache, getCSSByHash, getCSSByHashAsync, } from "./css-hash-cache.js";
15
15
  export { initializeProjectCSSCache, invalidateProjectCSS, invalidateProjectCSSAsync, isProjectCSSCacheDistributed, } from "./project-css-cache.js";
16
16
  const logger = serverLogger.component("tailwind");
17
+ const inFlightProjectCSS = new Map();
18
+ const inFlightRegeneration = new Map();
17
19
  // ============================================================================
18
20
  // Project CSS orchestration
19
21
  // ============================================================================
20
22
  export async function getProjectCSS(projectSlug, stylesheet, candidates, options) {
21
- const context = createProjectCSSRequestContext(projectSlug, stylesheet, candidates);
23
+ const context = createProjectCSSRequestContext(projectSlug, stylesheet, candidates, {
24
+ minify: options?.minify,
25
+ environment: options?.environment,
26
+ buildMode: options?.buildMode,
27
+ });
22
28
  const localHit = await tryGetProjectCSSFromLocalFallback(context, candidates);
23
29
  if (localHit)
24
30
  return localHit;
@@ -28,26 +34,43 @@ export async function getProjectCSS(projectSlug, stylesheet, candidates, options
28
34
  const distributedHit = await tryGetProjectCSSFromDistributedCache(context, candidates);
29
35
  if (distributedHit)
30
36
  return distributedHit;
31
- // Generate fresh CSS
32
- const result = await generateTailwindCSS(context.stylesheet, candidates, options);
33
- if (result.error) {
34
- const formatted = formatCSSError(result.error);
35
- logger.error("Project CSS generation failed", {
37
+ const inFlight = inFlightProjectCSS.get(context.cacheKey);
38
+ if (inFlight) {
39
+ logger.debug("Project CSS compile single-flight hit", {
36
40
  projectSlug: context.projectSlug,
37
- error: formatted.message,
38
- suggestion: formatted.suggestion,
41
+ cacheKeySuffix: context.cacheKey.slice(-24),
39
42
  });
40
- throw new Error(`[tailwind] ${formatted.title}: ${formatted.message} Suggestion: ${formatted.suggestion}`);
43
+ return inFlight;
44
+ }
45
+ const generationPromise = (async () => {
46
+ // Generate fresh CSS
47
+ const result = await generateTailwindCSS(context.stylesheet, candidates, options);
48
+ if (result.error) {
49
+ const formatted = formatCSSError(result.error);
50
+ logger.error("Project CSS generation failed", {
51
+ projectSlug: context.projectSlug,
52
+ error: formatted.message,
53
+ suggestion: formatted.suggestion,
54
+ });
55
+ throw new Error(`[tailwind] ${formatted.title}: ${formatted.message} Suggestion: ${formatted.suggestion}`);
56
+ }
57
+ const hash = hashCSS(result.css);
58
+ await storeProjectCSS(context, { css: result.css, hash, candidatesHash: context.candidatesHash }, candidates);
59
+ logger.debug("Project CSS generated", {
60
+ projectSlug: context.projectSlug,
61
+ hash,
62
+ cssLength: result.css.length,
63
+ candidateCount: candidates.size,
64
+ });
65
+ return { css: result.css, hash, fromCache: false };
66
+ })();
67
+ inFlightProjectCSS.set(context.cacheKey, generationPromise);
68
+ try {
69
+ return await generationPromise;
70
+ }
71
+ finally {
72
+ inFlightProjectCSS.delete(context.cacheKey);
41
73
  }
42
- const hash = hashCSS(result.css);
43
- await storeProjectCSS(context, { css: result.css, hash, candidatesHash: context.candidatesHash }, candidates);
44
- logger.debug("Project CSS generated", {
45
- projectSlug: context.projectSlug,
46
- hash,
47
- cssLength: result.css.length,
48
- candidateCount: candidates.size,
49
- });
50
- return { css: result.css, hash, fromCache: false };
51
74
  }
52
75
  // ============================================================================
53
76
  // CSS JIT regeneration
@@ -63,7 +86,10 @@ export async function getProjectCSS(projectSlug, stylesheet, candidates, options
63
86
  * @returns The regenerated CSS if inputs are cached and hash matches, undefined otherwise
64
87
  */
65
88
  export async function regenerateCSSByHash(expectedHash) {
66
- return await withSpan(SpanNames.HTML_REGENERATE_CSS_BY_HASH, async () => {
89
+ const inFlight = inFlightRegeneration.get(expectedHash);
90
+ if (inFlight)
91
+ return await inFlight;
92
+ const regenerationPromise = withSpan(SpanNames.HTML_REGENERATE_CSS_BY_HASH, async () => {
67
93
  const inputs = await resolveRegenerationInputs(expectedHash);
68
94
  if (!inputs || inputs.candidates.length === 0) {
69
95
  logger.debug("Cannot regenerate CSS - no cached inputs", { hash: expectedHash });
@@ -100,6 +126,13 @@ export async function regenerateCSSByHash(expectedHash) {
100
126
  });
101
127
  return result.css;
102
128
  }, { "css.hash": expectedHash });
129
+ inFlightRegeneration.set(expectedHash, regenerationPromise);
130
+ try {
131
+ return await regenerationPromise;
132
+ }
133
+ finally {
134
+ inFlightRegeneration.delete(expectedHash);
135
+ }
103
136
  }
104
137
  // ============================================================================
105
138
  // Core Tailwind CSS generation
@@ -0,0 +1,29 @@
1
+ /**
2
+ * CSS Import Collector - Request-scoped CSS import tracking for SSR
3
+ *
4
+ * Collects CSS import paths discovered during module loading using
5
+ * AsyncLocalStorage for proper isolation between concurrent requests.
6
+ *
7
+ * Usage:
8
+ * const { result, cssImports } = await runWithCSSCollector(() => loadModules(...));
9
+ * // cssImports contains absolute paths to CSS files discovered during loading
10
+ */
11
+ /**
12
+ * Run a function with CSS import collection enabled.
13
+ * Returns the function result and all collected CSS import paths.
14
+ */
15
+ export declare function runWithCSSCollector<T>(fn: () => T | Promise<T>): Promise<{
16
+ result: T;
17
+ cssImports: string[];
18
+ }>;
19
+ /**
20
+ * Register a CSS import path discovered during module loading.
21
+ * No-op if called outside of a runWithCSSCollector context.
22
+ */
23
+ export declare function registerCSSImport(absolutePath: string): void;
24
+ /**
25
+ * Get all CSS imports collected so far in the current context.
26
+ * Returns empty array if called outside of a runWithCSSCollector context.
27
+ */
28
+ export declare function getCSSImports(): string[];
29
+ //# sourceMappingURL=css-import-collector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"css-import-collector.d.ts","sourceRoot":"","sources":["../../../../src/src/modules/react-loader/css-import-collector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAUH;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,CAAC,EACzC,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GACvB,OAAO,CAAC;IAAE,MAAM,EAAE,CAAC,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAI9C;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAI5D;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,MAAM,EAAE,CAIxC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * CSS Import Collector - Request-scoped CSS import tracking for SSR
3
+ *
4
+ * Collects CSS import paths discovered during module loading using
5
+ * AsyncLocalStorage for proper isolation between concurrent requests.
6
+ *
7
+ * Usage:
8
+ * const { result, cssImports } = await runWithCSSCollector(() => loadModules(...));
9
+ * // cssImports contains absolute paths to CSS files discovered during loading
10
+ */
11
+ import { AsyncLocalStorage } from "node:async_hooks";
12
+ const cssStorage = new AsyncLocalStorage();
13
+ /**
14
+ * Run a function with CSS import collection enabled.
15
+ * Returns the function result and all collected CSS import paths.
16
+ */
17
+ export async function runWithCSSCollector(fn) {
18
+ const store = { imports: new Set() };
19
+ const result = await cssStorage.run(store, fn);
20
+ return { result, cssImports: [...store.imports] };
21
+ }
22
+ /**
23
+ * Register a CSS import path discovered during module loading.
24
+ * No-op if called outside of a runWithCSSCollector context.
25
+ */
26
+ export function registerCSSImport(absolutePath) {
27
+ const store = cssStorage.getStore();
28
+ if (!store)
29
+ return;
30
+ store.imports.add(absolutePath);
31
+ }
32
+ /**
33
+ * Get all CSS imports collected so far in the current context.
34
+ * Returns empty array if called outside of a runWithCSSCollector context.
35
+ */
36
+ export function getCSSImports() {
37
+ const store = cssStorage.getStore();
38
+ if (!store)
39
+ return [];
40
+ return [...store.imports];
41
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../../../src/src/modules/react-loader/ssr-module-loader/loader.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAiCpC,OAAO,KAAK,EAAoB,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAwB3E;;;;;GAKG;AACH,qBAAa,eAAe;IAKd,OAAO,CAAC,OAAO;IAJ3B,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,cAAc,CAA2B;IACjD,OAAO,CAAC,YAAY,CAAyB;gBAEzB,OAAO,EAAE,sBAAsB;IAWnD,OAAO,CAAC,mBAAmB;IAY3B,OAAO,CAAC,4BAA4B;YAetB,qBAAqB;YAuCrB,0BAA0B;IA2FxC,UAAU,CACR,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;YA+C1C,2BAA2B;IAYzC,OAAO,CAAC,yBAAyB;YAiBnB,2BAA2B;CAqU1C"}
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../../../src/src/modules/react-loader/ssr-module-loader/loader.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAiCpC,OAAO,KAAK,EAAoB,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAyB3E;;;;;GAKG;AACH,qBAAa,eAAe;IAKd,OAAO,CAAC,OAAO;IAJ3B,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,cAAc,CAA2B;IACjD,OAAO,CAAC,YAAY,CAAyB;gBAEzB,OAAO,EAAE,sBAAsB;IAWnD,OAAO,CAAC,mBAAmB;IAY3B,OAAO,CAAC,4BAA4B;YAetB,qBAAqB;YAuCrB,0BAA0B;IA2FxC,UAAU,CACR,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;YA+C1C,2BAA2B;IAYzC,OAAO,CAAC,yBAAyB;YAiBnB,2BAA2B;CA2U1C"}
@@ -30,6 +30,7 @@ import { SSRCircuitBreaker } from "./ssr-circuit-breaker.js";
30
30
  import { SSRDependencyValidator } from "./ssr-dependency-validator.js";
31
31
  import { preflightLocalImports } from "./preflight-imports.js";
32
32
  import { resolveVfModuleImports } from "./vf-module-resolver.js";
33
+ import { registerCSSImport } from "../css-import-collector.js";
33
34
  const logger = rendererLogger.component("ssr-module-loader");
34
35
  const MISSING_HTTP_BUNDLE_PATTERN = /veryfront-http-bundle\/http-([a-f0-9]+)\.mjs/;
35
36
  /**
@@ -302,6 +303,11 @@ export class SSRModuleLoader {
302
303
  globalInProgress.set(inProgressKey, transformPromise);
303
304
  try {
304
305
  let parseResult = await parseLocalImports(code, filePath, this.options.projectDir, this.options.adapter);
306
+ // Register CSS imports for later inclusion in HTML output.
307
+ // CSS files are not JS modules — skip them in the dependency graph.
308
+ for (const cssImport of parseResult.cssImports) {
309
+ registerCSSImport(cssImport.absolutePath);
310
+ }
305
311
  if (parseResult.missing.length > 0) {
306
312
  this.depValidator.missingDependencies.push(...parseResult.missing);
307
313
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ssr-dependency-validator.d.ts","sourceRoot":"","sources":["../../../../../src/src/modules/react-loader/ssr-module-loader/ssr-dependency-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,0CAA0C,CAAC;AAElG,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAGlE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAMzE;;;;;GAKG;AACH,qBAAa,sBAAsB;IAK/B,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,yBAAyB;IAKjC,OAAO,CAAC,2BAA2B;IAGnC,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,UAAU;IAdpB,kEAAkE;IAClE,mBAAmB,EAAE,aAAa,EAAE,CAAM;gBAGhC,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,EACzC,yBAAyB,EAAE,CACjC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,KAAK,EAAE,MAAM,KACV,OAAO,CAAC,IAAI,CAAC,EACV,2BAA2B,EAAE,CACnC,kBAAkB,EAAE,kBAAkB,KACnC,OAAO,CAAC,MAAM,CAAC,EACZ,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,MAAM;IAG5B,uDAAuD;IACvD,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK;IAwBjD;;;OAGG;IACG,uBAAuB,CAC3B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,KAAK,GAAE,MAAU,GAChB,OAAO,CAAC,IAAI,CAAC;IAqChB;;;OAGG;IACG,mBAAmB,CACvB,OAAO,EAAE,KAAK,CAAC;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,EAC3D,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,GAC3C,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAmChC"}
1
+ {"version":3,"file":"ssr-dependency-validator.d.ts","sourceRoot":"","sources":["../../../../../src/src/modules/react-loader/ssr-module-loader/ssr-dependency-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,0CAA0C,CAAC;AAGlG,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAGlE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAMzE;;;;;GAKG;AACH,qBAAa,sBAAsB;IAK/B,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,yBAAyB;IAKjC,OAAO,CAAC,2BAA2B;IAGnC,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,UAAU;IAdpB,kEAAkE;IAClE,mBAAmB,EAAE,aAAa,EAAE,CAAM;gBAGhC,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,EACzC,yBAAyB,EAAE,CACjC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,KAAK,EAAE,MAAM,KACV,OAAO,CAAC,IAAI,CAAC,EACV,2BAA2B,EAAE,CACnC,kBAAkB,EAAE,kBAAkB,KACnC,OAAO,CAAC,MAAM,CAAC,EACZ,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,MAAM;IAG5B,uDAAuD;IACvD,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK;IAwBjD;;;OAGG;IACG,uBAAuB,CAC3B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,KAAK,GAAE,MAAU,GAChB,OAAO,CAAC,IAAI,CAAC;IA0ChB;;;OAGG;IACG,mBAAmB,CACvB,OAAO,EAAE,KAAK,CAAC;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,EAC3D,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,GAC3C,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAmChC"}
@@ -7,6 +7,7 @@
7
7
  * @module module-system/react-loader/ssr-module-loader/ssr-dependency-validator
8
8
  */
9
9
  import { parseLocalImports } from "../../../transforms/esm/import-parser.js";
10
+ import { registerCSSImport } from "../css-import-collector.js";
10
11
  import { createFileSystem } from "../../../platform/compat/fs.js";
11
12
  import { createError, toError } from "../../../errors/veryfront-error.js";
12
13
  import { rendererLogger } from "../../../utils/index.js";
@@ -68,6 +69,10 @@ export class SSRDependencyValidator {
68
69
  if (depth > MAX_TRANSFORM_DEPTH)
69
70
  return;
70
71
  const parseResult = await parseLocalImports(code, filePath, this.projectDir, this.adapter);
72
+ // Register CSS imports from cached modules for HTML inclusion
73
+ for (const cssImport of parseResult.cssImports) {
74
+ registerCSSImport(cssImport.absolutePath);
75
+ }
71
76
  if (parseResult.missing.length > 0) {
72
77
  this.missingDependencies.push(...parseResult.missing);
73
78
  }
@@ -1 +1 @@
1
- {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../../../src/src/platform/adapters/fs/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAsBvE,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,CAAC,CA4E3E"}
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../../../src/src/platform/adapters/fs/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAuBvE,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,CAAC,CA+E3E"}
@@ -6,6 +6,7 @@ import { clearModulePathCache, invalidateModulePaths, } from "../../../transform
6
6
  import { clearSnippetCache, clearSnippetCacheForProject, } from "../../../rendering/snippet-renderer.js";
7
7
  import { clearRendererCacheForProject } from "../../../rendering/renderer.js";
8
8
  import { invalidateProjectCSS } from "../../../html/styles-builder/tailwind-compiler.js";
9
+ import { invalidateProjectCandidateManifests } from "../../../rendering/orchestrator/css-candidate-manifest.js";
9
10
  export function createFSAdapter(config) {
10
11
  const type = config.type ?? "local";
11
12
  const proxyMode = config.veryfront?.proxyMode ?? false;
@@ -31,7 +32,10 @@ export function createFSAdapter(config) {
31
32
  clearRouterDetectionCacheForProject,
32
33
  clearSnippetCacheForProject,
33
34
  clearRendererCacheForProject,
34
- clearProjectCSSCache: invalidateProjectCSS,
35
+ clearProjectCSSCache: (projectSlug) => {
36
+ invalidateProjectCSS(projectSlug);
37
+ invalidateProjectCandidateManifests(projectSlug);
38
+ },
35
39
  ...config.invalidationCallbacks,
36
40
  },
37
41
  };
@@ -29,6 +29,7 @@ export declare class WebSocketManager {
29
29
  private pendingChangedPaths;
30
30
  private wsConnectionId;
31
31
  private wsConsecutiveFailures;
32
+ private disposed;
32
33
  private pokeMetrics;
33
34
  constructor(deps: WebSocketDeps);
34
35
  getPokeMetrics(): {
@@ -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;AAsB/F,MAAM,WAAW,aAAa;IAC5B,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;IAiBf,OAAO,CAAC,QAAQ,CAAC,IAAI;IAhBjC,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,WAAW,CAIjB;gBAE2B,IAAI,EAAE,aAAa;IAEhD,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;IA0EhC,OAAO,CAAC,iBAAiB;IAMzB,OAAO,IAAI,IAAI;IAwBf,OAAO,CAAC,iBAAiB;IAkJzB,OAAO,CAAC,8BAA8B;IA0GtC,OAAO,CAAC,oBAAoB;IAa5B,OAAO,CAAC,6BAA6B;YAiBvB,4BAA4B;YA2H5B,mBAAmB;IAmIjC,OAAO,CAAC,cAAc;IA4BtB,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;AAsB/F,MAAM,WAAW,aAAa;IAC5B,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;IAkBf,OAAO,CAAC,QAAQ,CAAC,IAAI;IAjBjC,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,QAAQ,CAAS;IACzB,OAAO,CAAC,WAAW,CAIjB;gBAE2B,IAAI,EAAE,aAAa;IAEhD,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;IAmFhC,OAAO,CAAC,iBAAiB;IAMzB,OAAO,IAAI,IAAI;IA8Bf,OAAO,CAAC,iBAAiB;IAkJzB,OAAO,CAAC,8BAA8B;IA0GtC,OAAO,CAAC,oBAAoB;IAa5B,OAAO,CAAC,6BAA6B;YAiBvB,4BAA4B;YA2H5B,mBAAmB;IAmIjC,OAAO,CAAC,cAAc;IA4BtB,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,WAAW;CAyBpB"}
@@ -20,6 +20,7 @@ export class WebSocketManager {
20
20
  pendingChangedPaths = new Set();
21
21
  wsConnectionId = null;
22
22
  wsConsecutiveFailures = 0;
23
+ disposed = false;
23
24
  pokeMetrics = {
24
25
  received: 0,
25
26
  invalidationsTriggered: 0,
@@ -32,6 +33,8 @@ export class WebSocketManager {
32
33
  return { ...this.pokeMetrics, connectionId: this.wsConnectionId };
33
34
  }
34
35
  connect(projectId) {
36
+ if (this.disposed)
37
+ return;
35
38
  this.cleanupTimers();
36
39
  if (this.wsConsecutiveFailures >= WS_RECONNECT_MAX_FAILURES) {
37
40
  logger.warn("WebSocket reconnect failure cap reached, resetting failure counter", {
@@ -71,20 +74,26 @@ export class WebSocketManager {
71
74
  this.handlePokeMessage(event);
72
75
  };
73
76
  this.ws.onclose = () => {
77
+ this.wsConnectionId = null;
78
+ this.cleanupTimers();
79
+ if (this.disposed)
80
+ return;
74
81
  this.wsConsecutiveFailures++;
75
82
  const delay = this.getReconnectDelay();
76
83
  logger.debug("WebSocket closed, reconnecting", {
77
84
  delayMs: delay,
78
- connectionId: this.wsConnectionId,
79
85
  totalPokesReceived: this.pokeMetrics.received,
80
86
  consecutiveFailures: this.wsConsecutiveFailures,
81
87
  });
82
- this.wsConnectionId = null;
83
- this.cleanupTimers();
84
88
  this.wsReconnectTimer = dntShim.setTimeout(() => this.connect(projectId), delay);
85
89
  };
86
- this.ws.onerror = (error) => {
87
- logger.warn("WebSocket error", { error });
90
+ this.ws.onerror = (event) => {
91
+ logger.warn("WebSocket error", {
92
+ type: event.type,
93
+ url: event.target?.url?.replace(/token=[^&]+/, "token=***"),
94
+ readyState: event.target?.readyState,
95
+ consecutiveFailures: this.wsConsecutiveFailures,
96
+ });
88
97
  };
89
98
  }
90
99
  catch (error) {
@@ -103,6 +112,7 @@ export class WebSocketManager {
103
112
  return Math.min(delay, WS_RECONNECT_MAX_DELAY_MS);
104
113
  }
105
114
  dispose() {
115
+ this.disposed = true;
106
116
  this.cleanupTimers();
107
117
  if (this.invalidationTimer) {
108
118
  clearTimeout(this.invalidationTimer);
@@ -114,6 +124,10 @@ export class WebSocketManager {
114
124
  }
115
125
  if (!this.ws)
116
126
  return;
127
+ // Detach handlers before closing to prevent onclose from scheduling a reconnect
128
+ this.ws.onclose = null;
129
+ this.ws.onerror = null;
130
+ this.ws.onmessage = null;
117
131
  try {
118
132
  this.ws.close();
119
133
  }
@@ -1 +1 @@
1
- {"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../../../src/src/platform/compat/process.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../../../src/src/platform/compat/process.ts"],"names":[],"mappings":"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"}
@@ -346,13 +346,30 @@ export function onGlobalError(onError) {
346
346
  }
347
347
  if (!hasNodeProcess)
348
348
  return;
349
+ const handleNodeGlobalError = (error, type) => {
350
+ let shouldPreventExit = false;
351
+ try {
352
+ shouldPreventExit = onError(error, type) === true;
353
+ }
354
+ catch (handlerError) {
355
+ const handlerException = handlerError instanceof Error
356
+ ? handlerError
357
+ : new Error(String(handlerError));
358
+ console.error("Global error handler threw while processing", type, handlerException);
359
+ }
360
+ if (shouldPreventExit)
361
+ return;
362
+ // Node/Bun suppress default fatal behavior when a listener is registered.
363
+ // If the callback did not explicitly handle the error, exit to preserve
364
+ // expected fatal semantics for uncaught exceptions and unhandled rejections.
365
+ nodeProcess.exit(1);
366
+ };
349
367
  nodeProcess.on("uncaughtException", (error) => {
350
- onError(error, "uncaughtException");
351
- // Note: In Node.js, uncaughtException doesn't exit by default if handler is registered
368
+ handleNodeGlobalError(error, "uncaughtException");
352
369
  });
353
370
  nodeProcess.on("unhandledRejection", (reason) => {
354
371
  const error = reason instanceof Error ? reason : new Error(String(reason));
355
- onError(error, "unhandledRejection");
372
+ handleNodeGlobalError(error, "unhandledRejection");
356
373
  });
357
374
  }
358
375
  /**
@@ -482,18 +482,38 @@ function router(req) {
482
482
  return handleApiProxy(req);
483
483
  return forwardToServer(req);
484
484
  }
485
+ // Create server before signal registration so early SIGTERM/SIGINT can close it safely.
486
+ const server = createHttpServer();
485
487
  // Graceful shutdown
486
- async function shutdown() {
487
- proxyLogger.info("Shutting down");
488
- rendererRouter?.close();
489
- serverResolver.close();
490
- await proxyHandler.close();
491
- await shutdownOTLP();
492
- proxyLogger.info("Closed connections");
493
- exit(0);
488
+ let shuttingDown = false;
489
+ async function shutdown(signal) {
490
+ if (shuttingDown)
491
+ return;
492
+ shuttingDown = true;
493
+ proxyLogger.info(`Received ${signal}, shutting down`);
494
+ try {
495
+ await server.close();
496
+ rendererRouter?.close();
497
+ serverResolver.close();
498
+ await proxyHandler.close();
499
+ await shutdownOTLP();
500
+ proxyLogger.info("Closed connections");
501
+ }
502
+ catch (error) {
503
+ proxyLogger.error("Error while shutting down proxy", error);
504
+ }
505
+ finally {
506
+ exit(0);
507
+ }
494
508
  }
495
- onSignal("SIGINT", shutdown);
496
- onSignal("SIGTERM", shutdown);
509
+ const handleSignal = (signal) => {
510
+ void shutdown(signal).catch((error) => {
511
+ proxyLogger.error("Unhandled shutdown error", { signal }, error);
512
+ exit(1);
513
+ });
514
+ };
515
+ onSignal("SIGINT", () => handleSignal("SIGINT"));
516
+ onSignal("SIGTERM", () => handleSignal("SIGTERM"));
497
517
  // Wait for sticky-session router to resolve initial target list
498
518
  await rendererRouter?.ready();
499
519
  // Initialize tracing and start server
@@ -503,6 +523,5 @@ proxyLogger.debug("Starting proxy server (split mode)", {
503
523
  serverUrl: PRODUCTION_SERVER_URL,
504
524
  apiBaseUrl: config.apiBaseUrl,
505
525
  });
506
- // Create and start the HTTP server
507
- const server = createHttpServer();
526
+ // Start the HTTP server
508
527
  await server.serve(router, { port: PORT, hostname: HOST });
@@ -15,6 +15,7 @@ export declare class TokenManager {
15
15
  private config;
16
16
  private cache;
17
17
  private pendingRequests;
18
+ private negativeCache;
18
19
  private refreshBuffer;
19
20
  constructor(config: OAuthConfig, options?: TokenManagerOptions);
20
21
  getToken(scope: TokenScope, projectSlug?: string, customDomain?: string): Promise<string>;
@@ -30,6 +31,7 @@ export declare class TokenManager {
30
31
  private getCacheKey;
31
32
  private isTokenValid;
32
33
  private fetchAndCacheToken;
34
+ private parseStatusFromError;
33
35
  private calculateExpiresAt;
34
36
  }
35
37
  //# sourceMappingURL=token-manager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"token-manager.d.ts","sourceRoot":"","sources":["../../../src/src/proxy/token-manager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAmB,MAAM,kBAAkB,CAAC;AAIpE,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,YAAY,CAAC;AAElD,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,YAAY;IAMrB,OAAO,CAAC,MAAM;IALhB,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,eAAe,CAAsC;IAC7D,OAAO,CAAC,aAAa,CAAS;gBAGpB,MAAM,EAAE,WAAW,EAC3B,OAAO,GAAE,mBAAwB;IAM7B,QAAQ,CACZ,KAAK,EAAE,UAAU,EACjB,WAAW,CAAC,EAAE,MAAM,EACpB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,MAAM,CAAC;IA+BZ,eAAe,CAAC,KAAK,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvE,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,QAAQ,IAAI,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAIjF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,YAAY;YAIN,kBAAkB;IA+BhC,OAAO,CAAC,kBAAkB;CAe3B"}
1
+ {"version":3,"file":"token-manager.d.ts","sourceRoot":"","sources":["../../../src/src/proxy/token-manager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAmB,MAAM,kBAAkB,CAAC;AAIpE,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,YAAY,CAAC;AAWlD,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,YAAY;IAOrB,OAAO,CAAC,MAAM;IANhB,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,eAAe,CAAsC;IAC7D,OAAO,CAAC,aAAa,CAAyC;IAC9D,OAAO,CAAC,aAAa,CAAS;gBAGpB,MAAM,EAAE,WAAW,EAC3B,OAAO,GAAE,mBAAwB;IAM7B,QAAQ,CACZ,KAAK,EAAE,UAAU,EACjB,WAAW,CAAC,EAAE,MAAM,EACpB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,MAAM,CAAC;IAuCZ,eAAe,CAAC,KAAK,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMvE,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3B,QAAQ,IAAI,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAIjF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,YAAY;YAIN,kBAAkB;IAkDhC,OAAO,CAAC,oBAAoB;IAM5B,OAAO,CAAC,kBAAkB;CAe3B"}
@@ -1,10 +1,13 @@
1
1
  import { fetchOAuthToken } from "./oauth-client.js";
2
2
  import { MemoryCache } from "./cache/memory-cache.js";
3
3
  import { ProxySpanNames, withSpan } from "./tracing.js";
4
+ const NEGATIVE_CACHE_TTL = 5 * 60 * 1000; // 5 minutes
5
+ const NEGATIVE_CACHE_MAX_SIZE = 1000;
4
6
  export class TokenManager {
5
7
  config;
6
8
  cache;
7
9
  pendingRequests = new Map();
10
+ negativeCache = new Map();
8
11
  refreshBuffer;
9
12
  constructor(config, options = {}) {
10
13
  this.config = config;
@@ -15,6 +18,13 @@ export class TokenManager {
15
18
  const projectKey = projectSlug || customDomain;
16
19
  const cacheKey = this.getCacheKey(scope, projectKey);
17
20
  return withSpan(ProxySpanNames.PROXY_TOKEN_FETCH, async () => {
21
+ const negEntry = this.negativeCache.get(cacheKey);
22
+ if (negEntry) {
23
+ if (Date.now() - negEntry.cachedAt < NEGATIVE_CACHE_TTL) {
24
+ throw new Error(negEntry.message);
25
+ }
26
+ this.negativeCache.delete(cacheKey);
27
+ }
18
28
  const cached = await this.cache.get(cacheKey);
19
29
  if (cached && this.isTokenValid(cached))
20
30
  return cached.token;
@@ -37,9 +47,12 @@ export class TokenManager {
37
47
  });
38
48
  }
39
49
  async invalidateToken(scope, projectSlug) {
40
- await this.cache.delete(this.getCacheKey(scope, projectSlug));
50
+ const cacheKey = this.getCacheKey(scope, projectSlug);
51
+ this.negativeCache.delete(cacheKey);
52
+ await this.cache.delete(cacheKey);
41
53
  }
42
54
  async clearCache() {
55
+ this.negativeCache.clear();
43
56
  await this.cache.clear();
44
57
  }
45
58
  async getStats() {
@@ -60,13 +73,34 @@ export class TokenManager {
60
73
  const apiClientSecret = isPreview
61
74
  ? this.config.previewApiClientSecret
62
75
  : this.config.apiClientSecret;
63
- const response = await fetchOAuthToken({
64
- apiBaseUrl: this.config.apiBaseUrl,
65
- apiClientId,
66
- apiClientSecret,
67
- projectSlug,
68
- customDomain,
69
- });
76
+ let response;
77
+ try {
78
+ response = await fetchOAuthToken({
79
+ apiBaseUrl: this.config.apiBaseUrl,
80
+ apiClientId,
81
+ apiClientSecret,
82
+ projectSlug,
83
+ customDomain,
84
+ });
85
+ }
86
+ catch (error) {
87
+ const status = this.parseStatusFromError(error);
88
+ if (status === 400 || status === 404) {
89
+ const projectKey = projectSlug || customDomain;
90
+ const cacheKey = this.getCacheKey(scope, projectKey);
91
+ if (this.negativeCache.size >= NEGATIVE_CACHE_MAX_SIZE) {
92
+ const oldest = this.negativeCache.keys().next().value;
93
+ if (oldest !== undefined)
94
+ this.negativeCache.delete(oldest);
95
+ }
96
+ this.negativeCache.set(cacheKey, {
97
+ status,
98
+ message: error instanceof Error ? error.message : String(error),
99
+ cachedAt: Date.now(),
100
+ });
101
+ }
102
+ throw error;
103
+ }
70
104
  const projectKey = projectSlug || customDomain;
71
105
  await this.cache.set(this.getCacheKey(scope, projectKey), {
72
106
  token: response.access_token,
@@ -76,6 +110,11 @@ export class TokenManager {
76
110
  });
77
111
  return response.access_token;
78
112
  }
113
+ parseStatusFromError(error) {
114
+ const message = error instanceof Error ? error.message : String(error);
115
+ const match = message.match(/failed: (\d+)/);
116
+ return match ? Number(match[1]) : null;
117
+ }
79
118
  calculateExpiresAt(response) {
80
119
  if (response.expires_in)
81
120
  return Date.now() + response.expires_in * 1000;
@@ -0,0 +1,23 @@
1
+ interface SourceFileLike {
2
+ path: string;
3
+ content?: string;
4
+ }
5
+ interface RouteCandidateOptions {
6
+ projectScope: string;
7
+ projectVersion: string;
8
+ projectDir: string;
9
+ routeKey: string;
10
+ routeFilePaths: string[];
11
+ files: SourceFileLike[];
12
+ developmentMode: boolean;
13
+ }
14
+ /**
15
+ * Resolve route-scoped Tailwind candidates from a precomputed per-project manifest.
16
+ */
17
+ export declare function getRouteCandidates(options: RouteCandidateOptions): Set<string>;
18
+ /**
19
+ * Invalidate cached candidate manifests for one project scope (or all scopes).
20
+ */
21
+ export declare function invalidateProjectCandidateManifests(projectScope?: string): void;
22
+ export {};
23
+ //# sourceMappingURL=css-candidate-manifest.d.ts.map
@@ -0,0 +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;AAmFD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,qBAAqB,GAAG,GAAG,CAAC,MAAM,CAAC,CA+C9E;AAED;;GAEG;AACH,wBAAgB,mCAAmC,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAc/E"}