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.
- package/README.md +3 -11
- package/esm/cli/app/shell.d.ts.map +1 -1
- package/esm/cli/app/shell.js +9 -5
- package/esm/cli/commands/demo/demo.js +1 -1
- package/esm/cli/commands/init/catalog.d.ts.map +1 -1
- package/esm/cli/commands/init/catalog.js +13 -5
- package/esm/cli/commands/init/command-help.js +4 -4
- package/esm/cli/commands/init/types.d.ts +1 -1
- package/esm/cli/commands/init/types.d.ts.map +1 -1
- package/esm/cli/commands/serve/command.d.ts.map +1 -1
- package/esm/cli/commands/serve/command.js +0 -4
- package/esm/cli/commands/start/command.d.ts.map +1 -1
- package/esm/cli/commands/start/command.js +16 -9
- package/esm/cli/help/tips.js +6 -6
- package/esm/cli/mcp/remote-file-tools.js +1 -1
- package/esm/cli/mcp/tools/catalog-tools.d.ts +3 -3
- package/esm/cli/mcp/tools/catalog-tools.d.ts.map +1 -1
- package/esm/cli/mcp/tools/catalog-tools.js +21 -13
- package/esm/cli/mcp/tools/project-tools.js +1 -1
- package/esm/cli/templates/index.js +11 -11
- package/esm/cli/templates/manifest.d.ts +22 -15
- package/esm/cli/templates/manifest.js +24 -17
- package/esm/cli/templates/types.d.ts +1 -1
- package/esm/cli/templates/types.d.ts.map +1 -1
- package/esm/cli/utils/index.d.ts.map +1 -1
- package/esm/cli/utils/index.js +13 -1
- package/esm/deno.js +1 -1
- package/esm/src/html/html-shell-generator.d.ts.map +1 -1
- package/esm/src/html/html-shell-generator.js +2 -0
- package/esm/src/html/styles-builder/project-css-cache.d.ts +8 -1
- package/esm/src/html/styles-builder/project-css-cache.d.ts.map +1 -1
- package/esm/src/html/styles-builder/project-css-cache.js +13 -2
- package/esm/src/html/styles-builder/tailwind-compiler.d.ts +2 -0
- package/esm/src/html/styles-builder/tailwind-compiler.d.ts.map +1 -1
- package/esm/src/html/styles-builder/tailwind-compiler.js +52 -19
- package/esm/src/modules/react-loader/css-import-collector.d.ts +29 -0
- package/esm/src/modules/react-loader/css-import-collector.d.ts.map +1 -0
- package/esm/src/modules/react-loader/css-import-collector.js +41 -0
- package/esm/src/modules/react-loader/ssr-module-loader/loader.d.ts.map +1 -1
- package/esm/src/modules/react-loader/ssr-module-loader/loader.js +6 -0
- package/esm/src/modules/react-loader/ssr-module-loader/ssr-dependency-validator.d.ts.map +1 -1
- package/esm/src/modules/react-loader/ssr-module-loader/ssr-dependency-validator.js +5 -0
- package/esm/src/platform/adapters/fs/factory.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/factory.js +5 -1
- package/esm/src/platform/adapters/fs/veryfront/websocket-manager.d.ts +1 -0
- package/esm/src/platform/adapters/fs/veryfront/websocket-manager.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/websocket-manager.js +19 -5
- package/esm/src/platform/compat/process.d.ts.map +1 -1
- package/esm/src/platform/compat/process.js +20 -3
- package/esm/src/proxy/main.js +31 -12
- package/esm/src/proxy/token-manager.d.ts +2 -0
- package/esm/src/proxy/token-manager.d.ts.map +1 -1
- package/esm/src/proxy/token-manager.js +47 -8
- package/esm/src/rendering/orchestrator/css-candidate-manifest.d.ts +23 -0
- package/esm/src/rendering/orchestrator/css-candidate-manifest.d.ts.map +1 -0
- package/esm/src/rendering/orchestrator/css-candidate-manifest.js +132 -0
- package/esm/src/rendering/orchestrator/html.d.ts +11 -1
- package/esm/src/rendering/orchestrator/html.d.ts.map +1 -1
- package/esm/src/rendering/orchestrator/html.js +103 -18
- package/esm/src/rendering/orchestrator/pipeline.d.ts.map +1 -1
- package/esm/src/rendering/orchestrator/pipeline.js +14 -2
- package/esm/src/server/bootstrap.d.ts +2 -0
- package/esm/src/server/bootstrap.d.ts.map +1 -1
- package/esm/src/server/bootstrap.js +10 -0
- package/esm/src/server/handlers/preview/markdown-html-generator.d.ts.map +1 -1
- package/esm/src/server/handlers/preview/markdown-html-generator.js +11 -5
- package/esm/src/server/production-server.js +10 -2
- package/esm/src/studio/bridge-template.d.ts +2 -0
- package/esm/src/studio/bridge-template.d.ts.map +1 -1
- package/esm/src/studio/bridge-template.js +3390 -52
- package/esm/src/transforms/css-modules/naming.d.ts +33 -0
- package/esm/src/transforms/css-modules/naming.d.ts.map +1 -0
- package/esm/src/transforms/css-modules/naming.js +128 -0
- package/esm/src/transforms/esm/import-parser.d.ts +1 -0
- package/esm/src/transforms/esm/import-parser.d.ts.map +1 -1
- package/esm/src/transforms/esm/import-parser.js +16 -5
- package/esm/src/transforms/pipeline/index.d.ts.map +1 -1
- package/esm/src/transforms/pipeline/index.js +3 -1
- package/esm/src/transforms/pipeline/stages/index.d.ts +1 -0
- package/esm/src/transforms/pipeline/stages/index.d.ts.map +1 -1
- package/esm/src/transforms/pipeline/stages/index.js +1 -0
- package/esm/src/transforms/pipeline/stages/ssr-css-strip.d.ts +18 -0
- package/esm/src/transforms/pipeline/stages/ssr-css-strip.d.ts.map +1 -0
- package/esm/src/transforms/pipeline/stages/ssr-css-strip.js +168 -0
- package/package.json +1 -1
- package/src/cli/app/shell.ts +9 -5
- package/src/cli/commands/demo/demo.ts +1 -1
- package/src/cli/commands/init/catalog.ts +13 -5
- package/src/cli/commands/init/command-help.ts +4 -4
- package/src/cli/commands/init/types.ts +5 -5
- package/src/cli/commands/serve/command.ts +0 -5
- package/src/cli/commands/start/command.ts +15 -10
- package/src/cli/help/tips.ts +6 -6
- package/src/cli/mcp/remote-file-tools.ts +1 -1
- package/src/cli/mcp/tools/catalog-tools.ts +21 -13
- package/src/cli/mcp/tools/project-tools.ts +1 -1
- package/src/cli/templates/index.ts +11 -11
- package/src/cli/templates/manifest.js +24 -17
- package/src/cli/templates/types.ts +5 -5
- package/src/cli/utils/index.ts +12 -1
- package/src/deno.js +1 -1
- package/src/src/html/html-shell-generator.ts +2 -0
- package/src/src/html/styles-builder/project-css-cache.ts +24 -1
- package/src/src/html/styles-builder/tailwind-compiler.ts +67 -26
- package/src/src/modules/react-loader/css-import-collector.ts +50 -0
- package/src/src/modules/react-loader/ssr-module-loader/loader.ts +7 -0
- package/src/src/modules/react-loader/ssr-module-loader/ssr-dependency-validator.ts +6 -0
- package/src/src/platform/adapters/fs/factory.ts +5 -1
- package/src/src/platform/adapters/fs/veryfront/websocket-manager.ts +21 -5
- package/src/src/platform/compat/process.ts +28 -4
- package/src/src/proxy/main.ts +32 -12
- package/src/src/proxy/token-manager.ts +54 -8
- package/src/src/rendering/orchestrator/css-candidate-manifest.ts +176 -0
- package/src/src/rendering/orchestrator/html.ts +128 -16
- package/src/src/rendering/orchestrator/pipeline.ts +183 -165
- package/src/src/server/bootstrap.ts +16 -0
- package/src/src/server/handlers/preview/markdown-html-generator.ts +12 -5
- package/src/src/server/production-server.ts +12 -2
- package/src/src/studio/bridge-template.ts +3392 -52
- package/src/src/transforms/css-modules/naming.ts +152 -0
- package/src/src/transforms/esm/import-parser.ts +15 -5
- package/src/src/transforms/pipeline/index.ts +3 -0
- package/src/src/transforms/pipeline/stages/index.ts +1 -0
- 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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
-
|
|
38
|
-
suggestion: formatted.suggestion,
|
|
41
|
+
cacheKeySuffix: context.cacheKey.slice(-24),
|
|
39
42
|
});
|
|
40
|
-
|
|
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
|
-
|
|
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;
|
|
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;
|
|
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;
|
|
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:
|
|
35
|
+
clearProjectCSSCache: (projectSlug) => {
|
|
36
|
+
invalidateProjectCSS(projectSlug);
|
|
37
|
+
invalidateProjectCandidateManifests(projectSlug);
|
|
38
|
+
},
|
|
35
39
|
...config.invalidationCallbacks,
|
|
36
40
|
},
|
|
37
41
|
};
|
|
@@ -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;
|
|
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 = (
|
|
87
|
-
logger.warn("WebSocket 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":"AAAA,OAAO,KAAK,OAAO,MAAM,wBAAwB,CAAC;AAmBlD,6EAA6E;AAC7E,wBAAgB,OAAO,IAAI,MAAM,EAAE,CAIlC;AAED,yFAAyF;AACzF,wBAAgB,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,CAIzC;AAED,wBAAgB,GAAG,IAAI,MAAM,CAI5B;AAED,wBAAgB,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAU7C;AAED,wBAAgB,GAAG,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAI5C;AAqCD,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAatD;AAKD,MAAM,WAAW,iBAAiB;IAChC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAUD,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAC9D,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;AAOpE,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAC9D,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;AAUpE,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,EACX,QAAQ,UAAQ,EAChB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAmBT;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAI9C;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAUvD;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAU3C;AAED,KAAK,iBAAiB,GAAG;IACvB,QAAQ,EAAE,MAAM,OAAO,CAAC;IACxB,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5C,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACtC,CAAC;AAEF;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,iBAAiB,GAAG,IAAI,CAS/D;AAED,wBAAgB,GAAG,IAAI,MAAM,CAI5B;AAED,wBAAgB,IAAI,IAAI,MAAM,CAI7B;AAED,wBAAgB,WAAW,IAAI;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAUA;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAIvC;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,OAAO,CAIrC;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAmBnE;AAED;;GAEG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CACnD,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAAC,CAClE,CA+BA;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAO1C;AAED;;;GAGG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAQlC;AAED;;GAEG;AACH,wBAAgB,QAAQ,CACtB,MAAM,EAAE,QAAQ,GAAG,SAAS,EAC5B,OAAO,EAAE,MAAM,IAAI,GAClB,IAAI,CAMN;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,mBAAmB,GAAG,oBAAoB,KAAK,OAAO,GAAG,IAAI,GAC1F,IAAI,CA+CN;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI,CAShF;AAED;;GAEG;AACH,wBAAgB,QAAQ,IAAI,MAAM,CAIjC;AAED;;;GAGG;AACH,wBAAgB,MAAM,IAAI,MAAM,CAU/B;AAED;;;GAGG;AACH,wBAAgB,SAAS,IAAI;IAAE,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,GAAG,IAAI,CASpE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAE9C;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAaxE;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG1D;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,IAAI,CAkBjD;AAMD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,gDAAgD;IAChD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,mEAAmE;IACnE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,sEAAsE;IACtE,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAwBD;;;;;;;;;GASG;AACH,wBAAsB,UAAU,CAC9B,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,aAAa,CAAC,CA6HxB"}
|
|
@@ -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
|
-
|
|
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
|
-
|
|
372
|
+
handleNodeGlobalError(error, "unhandledRejection");
|
|
356
373
|
});
|
|
357
374
|
}
|
|
358
375
|
/**
|
package/esm/src/proxy/main.js
CHANGED
|
@@ -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
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
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
|
-
|
|
496
|
-
|
|
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
|
-
//
|
|
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;
|
|
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
|
-
|
|
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
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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"}
|