veryfront 0.1.178 → 0.1.180
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/deno.js +1 -1
- package/esm/src/rendering/orchestrator/pipeline.d.ts +3 -0
- package/esm/src/rendering/orchestrator/pipeline.d.ts.map +1 -1
- package/esm/src/rendering/orchestrator/pipeline.js +70 -60
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +1 -1
- package/src/deno.js +1 -1
- package/src/src/rendering/orchestrator/pipeline.ts +104 -73
- package/src/src/utils/version-constant.ts +1 -1
package/esm/deno.js
CHANGED
|
@@ -76,6 +76,9 @@ export declare class RenderPipeline {
|
|
|
76
76
|
/** Resolve page data for SPA client-side navigation without rendering HTML. */
|
|
77
77
|
resolvePageData(slug: string, options?: RenderOptions): Promise<PageDataResponse>;
|
|
78
78
|
private extractMdxMetadata;
|
|
79
|
+
private resolveAppPath;
|
|
80
|
+
private resolvePageDataCss;
|
|
81
|
+
private generatePageCssFromHtml;
|
|
79
82
|
/**
|
|
80
83
|
* Build a cache key that is safe for multi-tenant + query-param aware caching.
|
|
81
84
|
* Returns null when request contains sensitive headers (Authorization/Cookie) and
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/orchestrator/pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAgBH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AA6ChF,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAE1D;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACxE,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACrF;AAED,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,YAAY,CAAC;IAC3B,gBAAgB,EAAE,wBAAwB,CAAC;IAC3C,YAAY,EAAE,YAAY,CAAC;IAC3B,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,eAAe,EAAE,eAAe,CAAC;IACjC,OAAO,EAAE,cAAc,CAAC;IACxB,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,8EAA8E;IAC9E,iBAAiB,CAAC,EAAE,OAAO,qBAAqB,EAAE,sBAAsB,CAAC;CAC1E;
|
|
1
|
+
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/orchestrator/pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAgBH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AA6ChF,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAE1D;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACxE,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACrF;AAED,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,YAAY,CAAC;IAC3B,gBAAgB,EAAE,wBAAwB,CAAC;IAC3C,YAAY,EAAE,YAAY,CAAC;IAC3B,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,eAAe,EAAE,eAAe,CAAC;IACjC,OAAO,EAAE,cAAc,CAAC;IACxB,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,8EAA8E;IAC9E,iBAAiB,CAAC,EAAE,OAAO,qBAAqB,EAAE,sBAAsB,CAAC;CAC1E;AAyBD,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,kBAAkB,CAAqB;gBAEnC,MAAM,EAAE,oBAAoB;IAaxC;;;OAGG;IACH,gBAAgB,IAAI,IAAI;IAKxB,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,sBAAsB;YAIhB,0BAA0B;IAaxC;;;;;;;;;OASG;YACW,qBAAqB;IAyDnC;;;OAGG;YACW,mBAAmB;IAiGjC,OAAO,CAAC,uBAAuB;IAkCzB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IA+P9E,+EAA+E;IACzE,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,gBAAgB,CAAC;YA+FzE,kBAAkB;YA2ClB,cAAc;YAWd,kBAAkB;YAmElB,uBAAuB;IAmBrC;;;;;;OAMG;IACH,OAAO,CAAC,aAAa;CAetB"}
|
|
@@ -425,66 +425,8 @@ export class RenderPipeline {
|
|
|
425
425
|
const wrappedAdapter = fs.getUnderlyingAdapter();
|
|
426
426
|
projectUpdatedAt = wrappedAdapter.getProjectData?.()?.updated_at;
|
|
427
427
|
}
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
const candidatePath = join(this.config.projectDir, `components/app.${ext}`);
|
|
431
|
-
if (await this.config.adapter.fs.exists(candidatePath)) {
|
|
432
|
-
appPath = extractRelativePathShared(candidatePath, this.config.projectDir);
|
|
433
|
-
break;
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
let css;
|
|
437
|
-
let cssError;
|
|
438
|
-
const cssCacheKey = getPageCssCacheKey(options?.projectId, options?.environment, slug, projectUpdatedAt);
|
|
439
|
-
const cachedCss = getCachedPageCss(cssCacheKey);
|
|
440
|
-
if (cachedCss) {
|
|
441
|
-
css = cachedCss;
|
|
442
|
-
resolvePageDataLog.debug("CSS cache hit", { slug, cssLength: css.length });
|
|
443
|
-
}
|
|
444
|
-
else {
|
|
445
|
-
try {
|
|
446
|
-
const renderResult = await withTimeout(this.renderPage(slug, {
|
|
447
|
-
...options,
|
|
448
|
-
delivery: "string",
|
|
449
|
-
skipCacheCheck: true,
|
|
450
|
-
skipCachePersist: true,
|
|
451
|
-
}), CSS_SSR_TIMEOUT_MS, `CSS SSR for ${slug}`);
|
|
452
|
-
if (renderResult?.html) {
|
|
453
|
-
css = await this.resolveCssFromRenderedHtml(renderResult.html, options?.projectSlug ?? options?.projectId);
|
|
454
|
-
if (css) {
|
|
455
|
-
resolvePageDataLog.debug("Reused SSR CSS for page data", {
|
|
456
|
-
slug,
|
|
457
|
-
cssLength: css.length,
|
|
458
|
-
source: "rendered-html-hash",
|
|
459
|
-
});
|
|
460
|
-
}
|
|
461
|
-
else {
|
|
462
|
-
const candidates = extractCandidates(renderResult.html);
|
|
463
|
-
css = (await generateTailwindCSS(undefined, candidates, {
|
|
464
|
-
projectSlug: options?.projectSlug,
|
|
465
|
-
})).css;
|
|
466
|
-
resolvePageDataLog.debug("Fell back to HTML candidate CSS generation", {
|
|
467
|
-
slug,
|
|
468
|
-
htmlLength: renderResult.html.length,
|
|
469
|
-
cssLength: css?.length || 0,
|
|
470
|
-
});
|
|
471
|
-
}
|
|
472
|
-
if (css)
|
|
473
|
-
cachePageCss(cssCacheKey, css);
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
catch (error) {
|
|
477
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
478
|
-
// Surface CSS generation failures instead of silently swallowing them.
|
|
479
|
-
// This allows clients to show a warning or fall back gracefully.
|
|
480
|
-
cssError = `CSS generation failed: ${errorMessage}`;
|
|
481
|
-
resolvePageDataLog.error("CSS generation failed", {
|
|
482
|
-
slug,
|
|
483
|
-
error: errorMessage,
|
|
484
|
-
projectId: options?.projectId,
|
|
485
|
-
});
|
|
486
|
-
}
|
|
487
|
-
}
|
|
428
|
+
const appPath = await this.resolveAppPath();
|
|
429
|
+
const { css, cssError } = await this.resolvePageDataCss(slug, options, projectUpdatedAt);
|
|
488
430
|
resolvePageDataLog.debug("Resolved page data", {
|
|
489
431
|
slug,
|
|
490
432
|
pagePath,
|
|
@@ -540,6 +482,74 @@ export class RenderPipeline {
|
|
|
540
482
|
return { frontmatter: {}, headings: [] };
|
|
541
483
|
}
|
|
542
484
|
}
|
|
485
|
+
async resolveAppPath() {
|
|
486
|
+
for (const ext of LAYOUT_EXTENSIONS) {
|
|
487
|
+
const candidatePath = join(this.config.projectDir, `components/app.${ext}`);
|
|
488
|
+
if (await this.config.adapter.fs.exists(candidatePath)) {
|
|
489
|
+
return extractRelativePathShared(candidatePath, this.config.projectDir);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
return undefined;
|
|
493
|
+
}
|
|
494
|
+
async resolvePageDataCss(slug, options, projectUpdatedAt) {
|
|
495
|
+
const cssCacheKey = getPageCssCacheKey(options?.projectId, options?.environment, slug, projectUpdatedAt);
|
|
496
|
+
const cachedCss = getCachedPageCss(cssCacheKey);
|
|
497
|
+
if (cachedCss) {
|
|
498
|
+
resolvePageDataLog.debug("CSS cache hit", { slug, cssLength: cachedCss.length });
|
|
499
|
+
return { css: cachedCss, cssError: undefined };
|
|
500
|
+
}
|
|
501
|
+
try {
|
|
502
|
+
const renderResult = await withTimeout(this.renderPage(slug, {
|
|
503
|
+
...options,
|
|
504
|
+
delivery: "string",
|
|
505
|
+
skipCacheCheck: true,
|
|
506
|
+
skipCachePersist: true,
|
|
507
|
+
}), CSS_SSR_TIMEOUT_MS, `CSS SSR for ${slug}`);
|
|
508
|
+
if (!renderResult?.html) {
|
|
509
|
+
return { css: undefined, cssError: undefined };
|
|
510
|
+
}
|
|
511
|
+
let css = await this.resolveCssFromRenderedHtml(renderResult.html, options?.projectSlug ?? options?.projectId);
|
|
512
|
+
if (css) {
|
|
513
|
+
resolvePageDataLog.debug("Reused SSR CSS for page data", {
|
|
514
|
+
slug,
|
|
515
|
+
cssLength: css.length,
|
|
516
|
+
source: "rendered-html-hash",
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
else {
|
|
520
|
+
css = await this.generatePageCssFromHtml(slug, renderResult.html, options);
|
|
521
|
+
}
|
|
522
|
+
if (css)
|
|
523
|
+
cachePageCss(cssCacheKey, css);
|
|
524
|
+
return { css, cssError: undefined };
|
|
525
|
+
}
|
|
526
|
+
catch (error) {
|
|
527
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
528
|
+
// Surface CSS generation failures instead of silently swallowing them.
|
|
529
|
+
// This allows clients to show a warning or fall back gracefully.
|
|
530
|
+
resolvePageDataLog.error("CSS generation failed", {
|
|
531
|
+
slug,
|
|
532
|
+
error: errorMessage,
|
|
533
|
+
projectId: options?.projectId,
|
|
534
|
+
});
|
|
535
|
+
return {
|
|
536
|
+
css: undefined,
|
|
537
|
+
cssError: `CSS generation failed: ${errorMessage}`,
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
async generatePageCssFromHtml(slug, html, options) {
|
|
542
|
+
const candidates = extractCandidates(html);
|
|
543
|
+
const generatedCss = (await generateTailwindCSS(undefined, candidates, {
|
|
544
|
+
projectSlug: options?.projectSlug,
|
|
545
|
+
})).css;
|
|
546
|
+
resolvePageDataLog.debug("Fell back to HTML candidate CSS generation", {
|
|
547
|
+
slug,
|
|
548
|
+
htmlLength: html.length,
|
|
549
|
+
cssLength: generatedCss?.length || 0,
|
|
550
|
+
});
|
|
551
|
+
return generatedCss;
|
|
552
|
+
}
|
|
543
553
|
/**
|
|
544
554
|
* Build a cache key that is safe for multi-tenant + query-param aware caching.
|
|
545
555
|
* Returns null when request contains sensitive headers (Authorization/Cookie) and
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "0.1.
|
|
1
|
+
export declare const VERSION = "0.1.180";
|
|
2
2
|
//# sourceMappingURL=version-constant.d.ts.map
|
package/package.json
CHANGED
package/src/deno.js
CHANGED
|
@@ -116,6 +116,11 @@ interface MdxMetadataResult {
|
|
|
116
116
|
headings: Array<{ id: string; text: string; level: number }>;
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
interface PageCssResult {
|
|
120
|
+
css: string | undefined;
|
|
121
|
+
cssError: string | undefined;
|
|
122
|
+
}
|
|
123
|
+
|
|
119
124
|
interface FetchedDataResult {
|
|
120
125
|
type: "page" | "layout";
|
|
121
126
|
id: string;
|
|
@@ -691,80 +696,9 @@ export class RenderPipeline {
|
|
|
691
696
|
projectUpdatedAt = wrappedAdapter.getProjectData?.()?.updated_at;
|
|
692
697
|
}
|
|
693
698
|
|
|
694
|
-
|
|
695
|
-
for (const ext of LAYOUT_EXTENSIONS) {
|
|
696
|
-
const candidatePath = join(this.config.projectDir, `components/app.${ext}`);
|
|
697
|
-
if (await this.config.adapter.fs.exists(candidatePath)) {
|
|
698
|
-
appPath = extractRelativePathShared(candidatePath, this.config.projectDir);
|
|
699
|
-
break;
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
let css: string | undefined;
|
|
704
|
-
let cssError: string | undefined;
|
|
705
|
-
const cssCacheKey = getPageCssCacheKey(
|
|
706
|
-
options?.projectId,
|
|
707
|
-
options?.environment,
|
|
708
|
-
slug,
|
|
709
|
-
projectUpdatedAt,
|
|
710
|
-
);
|
|
711
|
-
|
|
712
|
-
const cachedCss = getCachedPageCss(cssCacheKey);
|
|
713
|
-
if (cachedCss) {
|
|
714
|
-
css = cachedCss;
|
|
715
|
-
resolvePageDataLog.debug("CSS cache hit", { slug, cssLength: css.length });
|
|
716
|
-
} else {
|
|
717
|
-
try {
|
|
718
|
-
const renderResult = await withTimeout(
|
|
719
|
-
this.renderPage(slug, {
|
|
720
|
-
...options,
|
|
721
|
-
delivery: "string",
|
|
722
|
-
skipCacheCheck: true,
|
|
723
|
-
skipCachePersist: true,
|
|
724
|
-
}),
|
|
725
|
-
CSS_SSR_TIMEOUT_MS,
|
|
726
|
-
`CSS SSR for ${slug}`,
|
|
727
|
-
);
|
|
728
|
-
|
|
729
|
-
if (renderResult?.html) {
|
|
730
|
-
css = await this.resolveCssFromRenderedHtml(
|
|
731
|
-
renderResult.html,
|
|
732
|
-
options?.projectSlug ?? options?.projectId,
|
|
733
|
-
);
|
|
734
|
-
|
|
735
|
-
if (css) {
|
|
736
|
-
resolvePageDataLog.debug("Reused SSR CSS for page data", {
|
|
737
|
-
slug,
|
|
738
|
-
cssLength: css.length,
|
|
739
|
-
source: "rendered-html-hash",
|
|
740
|
-
});
|
|
741
|
-
} else {
|
|
742
|
-
const candidates = extractCandidates(renderResult.html);
|
|
743
|
-
css = (await generateTailwindCSS(undefined, candidates, {
|
|
744
|
-
projectSlug: options?.projectSlug,
|
|
745
|
-
})).css;
|
|
746
|
-
|
|
747
|
-
resolvePageDataLog.debug("Fell back to HTML candidate CSS generation", {
|
|
748
|
-
slug,
|
|
749
|
-
htmlLength: renderResult.html.length,
|
|
750
|
-
cssLength: css?.length || 0,
|
|
751
|
-
});
|
|
752
|
-
}
|
|
699
|
+
const appPath = await this.resolveAppPath();
|
|
753
700
|
|
|
754
|
-
|
|
755
|
-
}
|
|
756
|
-
} catch (error) {
|
|
757
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
758
|
-
// Surface CSS generation failures instead of silently swallowing them.
|
|
759
|
-
// This allows clients to show a warning or fall back gracefully.
|
|
760
|
-
cssError = `CSS generation failed: ${errorMessage}`;
|
|
761
|
-
resolvePageDataLog.error("CSS generation failed", {
|
|
762
|
-
slug,
|
|
763
|
-
error: errorMessage,
|
|
764
|
-
projectId: options?.projectId,
|
|
765
|
-
});
|
|
766
|
-
}
|
|
767
|
-
}
|
|
701
|
+
const { css, cssError } = await this.resolvePageDataCss(slug, options, projectUpdatedAt);
|
|
768
702
|
|
|
769
703
|
resolvePageDataLog.debug("Resolved page data", {
|
|
770
704
|
slug,
|
|
@@ -838,6 +772,103 @@ export class RenderPipeline {
|
|
|
838
772
|
}
|
|
839
773
|
}
|
|
840
774
|
|
|
775
|
+
private async resolveAppPath(): Promise<string | undefined> {
|
|
776
|
+
for (const ext of LAYOUT_EXTENSIONS) {
|
|
777
|
+
const candidatePath = join(this.config.projectDir, `components/app.${ext}`);
|
|
778
|
+
if (await this.config.adapter.fs.exists(candidatePath)) {
|
|
779
|
+
return extractRelativePathShared(candidatePath, this.config.projectDir);
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
return undefined;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
private async resolvePageDataCss(
|
|
787
|
+
slug: string,
|
|
788
|
+
options: RenderOptions | undefined,
|
|
789
|
+
projectUpdatedAt: string | undefined,
|
|
790
|
+
): Promise<PageCssResult> {
|
|
791
|
+
const cssCacheKey = getPageCssCacheKey(
|
|
792
|
+
options?.projectId,
|
|
793
|
+
options?.environment,
|
|
794
|
+
slug,
|
|
795
|
+
projectUpdatedAt,
|
|
796
|
+
);
|
|
797
|
+
|
|
798
|
+
const cachedCss = getCachedPageCss(cssCacheKey);
|
|
799
|
+
if (cachedCss) {
|
|
800
|
+
resolvePageDataLog.debug("CSS cache hit", { slug, cssLength: cachedCss.length });
|
|
801
|
+
return { css: cachedCss, cssError: undefined };
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
try {
|
|
805
|
+
const renderResult = await withTimeout(
|
|
806
|
+
this.renderPage(slug, {
|
|
807
|
+
...options,
|
|
808
|
+
delivery: "string",
|
|
809
|
+
skipCacheCheck: true,
|
|
810
|
+
skipCachePersist: true,
|
|
811
|
+
}),
|
|
812
|
+
CSS_SSR_TIMEOUT_MS,
|
|
813
|
+
`CSS SSR for ${slug}`,
|
|
814
|
+
);
|
|
815
|
+
|
|
816
|
+
if (!renderResult?.html) {
|
|
817
|
+
return { css: undefined, cssError: undefined };
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
let css = await this.resolveCssFromRenderedHtml(
|
|
821
|
+
renderResult.html,
|
|
822
|
+
options?.projectSlug ?? options?.projectId,
|
|
823
|
+
);
|
|
824
|
+
|
|
825
|
+
if (css) {
|
|
826
|
+
resolvePageDataLog.debug("Reused SSR CSS for page data", {
|
|
827
|
+
slug,
|
|
828
|
+
cssLength: css.length,
|
|
829
|
+
source: "rendered-html-hash",
|
|
830
|
+
});
|
|
831
|
+
} else {
|
|
832
|
+
css = await this.generatePageCssFromHtml(slug, renderResult.html, options);
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
if (css) cachePageCss(cssCacheKey, css);
|
|
836
|
+
return { css, cssError: undefined };
|
|
837
|
+
} catch (error) {
|
|
838
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
839
|
+
// Surface CSS generation failures instead of silently swallowing them.
|
|
840
|
+
// This allows clients to show a warning or fall back gracefully.
|
|
841
|
+
resolvePageDataLog.error("CSS generation failed", {
|
|
842
|
+
slug,
|
|
843
|
+
error: errorMessage,
|
|
844
|
+
projectId: options?.projectId,
|
|
845
|
+
});
|
|
846
|
+
return {
|
|
847
|
+
css: undefined,
|
|
848
|
+
cssError: `CSS generation failed: ${errorMessage}`,
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
private async generatePageCssFromHtml(
|
|
854
|
+
slug: string,
|
|
855
|
+
html: string,
|
|
856
|
+
options: RenderOptions | undefined,
|
|
857
|
+
): Promise<string | undefined> {
|
|
858
|
+
const candidates = extractCandidates(html);
|
|
859
|
+
const generatedCss = (await generateTailwindCSS(undefined, candidates, {
|
|
860
|
+
projectSlug: options?.projectSlug,
|
|
861
|
+
})).css;
|
|
862
|
+
|
|
863
|
+
resolvePageDataLog.debug("Fell back to HTML candidate CSS generation", {
|
|
864
|
+
slug,
|
|
865
|
+
htmlLength: html.length,
|
|
866
|
+
cssLength: generatedCss?.length || 0,
|
|
867
|
+
});
|
|
868
|
+
|
|
869
|
+
return generatedCss;
|
|
870
|
+
}
|
|
871
|
+
|
|
841
872
|
/**
|
|
842
873
|
* Build a cache key that is safe for multi-tenant + query-param aware caching.
|
|
843
874
|
* Returns null when request contains sensitive headers (Authorization/Cookie) and
|