veryfront 0.1.1149 → 0.1.1151
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/cache/config-hash.d.ts +6 -0
- package/esm/src/cache/config-hash.d.ts.map +1 -1
- package/esm/src/cache/config-hash.js +11 -0
- package/esm/src/modules/react-loader/ssr-module-loader/cross-project-import-loader.d.ts +7 -0
- package/esm/src/modules/react-loader/ssr-module-loader/cross-project-import-loader.d.ts.map +1 -1
- package/esm/src/modules/react-loader/ssr-module-loader/cross-project-import-loader.js +13 -3
- package/esm/src/modules/react-loader/ssr-module-loader/ssr-cache-manager.d.ts.map +1 -1
- package/esm/src/modules/react-loader/ssr-module-loader/ssr-cache-manager.js +1 -0
- package/esm/src/rendering/component-handling.d.ts +10 -0
- package/esm/src/rendering/component-handling.d.ts.map +1 -1
- package/esm/src/rendering/component-handling.js +44 -13
- package/esm/src/rendering/layouts/layout-applicator.d.ts.map +1 -1
- package/esm/src/rendering/layouts/layout-applicator.js +10 -9
- package/esm/src/rendering/layouts/layout-collector.d.ts.map +1 -1
- package/esm/src/rendering/layouts/layout-collector.js +10 -12
- package/esm/src/rendering/layouts/utils/component-loader.d.ts +5 -1
- package/esm/src/rendering/layouts/utils/component-loader.d.ts.map +1 -1
- package/esm/src/rendering/layouts/utils/component-loader.js +41 -15
- package/esm/src/rendering/orchestrator/path-helpers.d.ts +13 -2
- package/esm/src/rendering/orchestrator/path-helpers.d.ts.map +1 -1
- package/esm/src/rendering/orchestrator/path-helpers.js +21 -4
- package/esm/src/rendering/orchestrator/pipeline.d.ts.map +1 -1
- package/esm/src/rendering/orchestrator/pipeline.js +10 -2
- package/esm/src/rendering/router-detection.d.ts +12 -0
- package/esm/src/rendering/router-detection.d.ts.map +1 -1
- package/esm/src/rendering/router-detection.js +41 -1
- package/esm/src/transforms/pipeline/index.d.ts.map +1 -1
- package/esm/src/transforms/pipeline/index.js +3 -0
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +5 -5
package/esm/deno.js
CHANGED
|
@@ -12,6 +12,12 @@ interface TransformConfig {
|
|
|
12
12
|
reactVersion?: string;
|
|
13
13
|
/** JSX import source */
|
|
14
14
|
jsxImportSource?: string;
|
|
15
|
+
/** Module server URL for rewritten browser imports */
|
|
16
|
+
moduleServerUrl?: string;
|
|
17
|
+
/** Vendor bundle hash for rewritten vendor imports */
|
|
18
|
+
vendorBundleHash?: string;
|
|
19
|
+
/** API base URL for rewritten cross-project imports */
|
|
20
|
+
apiBaseUrl?: string;
|
|
15
21
|
/** Enable Studio Navigator embed */
|
|
16
22
|
studioEmbed?: boolean;
|
|
17
23
|
/** Development mode */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-hash.d.ts","sourceRoot":"","sources":["../../../src/src/cache/config-hash.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH;;GAEG;AACH,UAAU,eAAe;IACvB,oCAAoC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wBAAwB;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oCAAoC;IACpC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,uBAAuB;IACvB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"config-hash.d.ts","sourceRoot":"","sources":["../../../src/src/cache/config-hash.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH;;GAEG;AACH,UAAU,eAAe;IACvB,oCAAoC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wBAAwB;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sDAAsD;IACtD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sDAAsD;IACtD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oCAAoC;IACpC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,uBAAuB;IACvB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAe1E;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAarE"}
|
|
@@ -17,6 +17,9 @@ export function computeConfigHash(config) {
|
|
|
17
17
|
transformVersion: VERSION,
|
|
18
18
|
reactVersion: config.reactVersion ?? DEFAULT_REACT_VERSION,
|
|
19
19
|
jsxImportSource: config.jsxImportSource ?? "react",
|
|
20
|
+
moduleServerUrl: config.moduleServerUrl ?? null,
|
|
21
|
+
vendorBundleHash: config.vendorBundleHash ?? null,
|
|
22
|
+
apiBaseUrl: config.apiBaseUrl ?? null,
|
|
20
23
|
studioEmbed: config.studioEmbed ?? false,
|
|
21
24
|
dev: config.dev ?? false,
|
|
22
25
|
csstype: CSSTYPE_VERSION,
|
|
@@ -34,8 +37,16 @@ export function computeConfigHashSync(config) {
|
|
|
34
37
|
`v${VERSION}`,
|
|
35
38
|
config.reactVersion ?? DEFAULT_REACT_VERSION,
|
|
36
39
|
config.jsxImportSource ?? "react",
|
|
40
|
+
encodeConfigPart("modules", config.moduleServerUrl),
|
|
41
|
+
encodeConfigPart("vendor", config.vendorBundleHash),
|
|
42
|
+
encodeConfigPart("api", config.apiBaseUrl),
|
|
37
43
|
config.studioEmbed ? "studio" : "",
|
|
38
44
|
config.dev ? "dev" : "",
|
|
39
45
|
].filter(Boolean);
|
|
40
46
|
return parts.join(":");
|
|
41
47
|
}
|
|
48
|
+
function encodeConfigPart(label, value) {
|
|
49
|
+
if (!value)
|
|
50
|
+
return "";
|
|
51
|
+
return `${label}:${value.length}:${value}`;
|
|
52
|
+
}
|
|
@@ -20,6 +20,13 @@ interface TransformCrossProjectImportFlowOptions {
|
|
|
20
20
|
loggerImpl?: Pick<typeof logger, "debug" | "error">;
|
|
21
21
|
fetchTimeoutMs?: number;
|
|
22
22
|
}
|
|
23
|
+
interface CrossProjectImportCacheKeyOptions {
|
|
24
|
+
specifier: string;
|
|
25
|
+
projectId: string;
|
|
26
|
+
reactVersion?: string;
|
|
27
|
+
registryBaseUrl: string;
|
|
28
|
+
}
|
|
29
|
+
export declare function buildCrossProjectImportCacheKey(options: CrossProjectImportCacheKeyOptions): string;
|
|
23
30
|
export declare function transformCrossProjectImportFlow(flowOptions: TransformCrossProjectImportFlowOptions): Promise<string>;
|
|
24
31
|
export {};
|
|
25
32
|
//# sourceMappingURL=cross-project-import-loader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cross-project-import-loader.d.ts","sourceRoot":"","sources":["../../../../../src/src/modules/react-loader/ssr-module-loader/cross-project-import-loader.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,8CAA8C,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAC;AAInF,OAAO,EAAE,cAAc,IAAI,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAEnE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"cross-project-import-loader.d.ts","sourceRoot":"","sources":["../../../../../src/src/modules/react-loader/ssr-module-loader/cross-project-import-loader.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,8CAA8C,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAC;AAInF,OAAO,EAAE,cAAc,IAAI,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAEnE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAIzD,UAAU,uBAAuB;IAC/B,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACnD,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACrE,KAAK,IAAI,UAAU,CAAC;CACrB;AAED,UAAU,sCAAsC;IAC9C,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,OAAO,EAAE,IAAI,CACX,sBAAsB,EACtB,WAAW,GAAG,YAAY,GAAG,KAAK,GAAG,YAAY,GAAG,cAAc,GAAG,SAAS,CAC/E,CAAC;IACF,KAAK,EAAE,uBAAuB,CAAC;IAC/B,qBAAqB,EAAE,CAAC,CAAC,EACvB,iBAAiB,EAAE,MAAM,EACzB,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KACxB,OAAO,CAAC,CAAC,CAAC,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,kBAAkB,CAAC,EAAE,OAAO,cAAc,CAAC;IAC3C,iBAAiB,CAAC,EAAE,OAAO,aAAa,CAAC;IACzC,UAAU,CAAC,EAAE,IAAI,CAAC,OAAO,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC;IACpD,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAOD,UAAU,iCAAiC;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,iCAAiC,GACzC,MAAM,CAIR;AAED,wBAAsB,+BAA+B,CACnD,WAAW,EAAE,sCAAsC,GAClD,OAAO,CAAC,MAAM,CAAC,CA8GjB"}
|
|
@@ -7,19 +7,29 @@ import { writeCacheFile } from "../../../utils/cache-file-ops.js";
|
|
|
7
7
|
import { rendererLogger as logger } from "../../../utils/index.js";
|
|
8
8
|
import { globalCrossProjectCache } from "./cache/index.js";
|
|
9
9
|
import { readLimitedCrossProjectSource } from "../../server/cross-project-source-limit.js";
|
|
10
|
+
import { base64urlEncode } from "../../../utils/base64url.js";
|
|
10
11
|
function getRegistryBaseUrl(apiBaseUrl) {
|
|
11
12
|
const resolvedApiBaseUrl = apiBaseUrl || getApiBaseUrlEnv();
|
|
12
13
|
return resolvedApiBaseUrl.replace(/\/api\/?$/, "");
|
|
13
14
|
}
|
|
15
|
+
export function buildCrossProjectImportCacheKey(options) {
|
|
16
|
+
const reactVersion = options.reactVersion ?? "default";
|
|
17
|
+
const registryKey = base64urlEncode(options.registryBaseUrl);
|
|
18
|
+
return `${options.specifier}:${options.projectId}:${reactVersion}:registry:${registryKey}`;
|
|
19
|
+
}
|
|
14
20
|
export async function transformCrossProjectImportFlow(flowOptions) {
|
|
15
21
|
const { crossProjectImport, options, cache, withTransformCapacity, fetchImpl = fetch, transformToESMImpl = transformToESM, injectContextImpl = injectContext, loggerImpl = logger, fetchTimeoutMs = HTTP_FETCH_TIMEOUT_MS, } = flowOptions;
|
|
16
22
|
const { specifier, projectSlug, version, path } = crossProjectImport;
|
|
17
|
-
const
|
|
18
|
-
const cacheKey =
|
|
23
|
+
const registryBaseUrl = getRegistryBaseUrl(options.apiBaseUrl);
|
|
24
|
+
const cacheKey = buildCrossProjectImportCacheKey({
|
|
25
|
+
specifier,
|
|
26
|
+
projectId: options.projectId,
|
|
27
|
+
reactVersion: options.reactVersion,
|
|
28
|
+
registryBaseUrl,
|
|
29
|
+
});
|
|
19
30
|
const cachedEntry = globalCrossProjectCache.get(cacheKey);
|
|
20
31
|
if (cachedEntry)
|
|
21
32
|
return cachedEntry.tempPath;
|
|
22
|
-
const registryBaseUrl = getRegistryBaseUrl(options.apiBaseUrl);
|
|
23
33
|
const projectRef = `${projectSlug}@${version}`;
|
|
24
34
|
const registryUrl = `${registryBaseUrl}/${projectRef}/@/${path}`;
|
|
25
35
|
loggerImpl.debug("[SSR-MODULE-LOADER] Fetching cross-project import", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssr-cache-manager.d.ts","sourceRoot":"","sources":["../../../../../src/src/modules/react-loader/ssr-module-loader/ssr-cache-manager.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAalE,OAAO,KAAK,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAQ3E;;;;;;;GAOG;AACH,qBAAa,eAAe;IAId,OAAO,CAAC,OAAO;IAH3B,OAAO,CAAC,EAAE,CAAsB;IAChC,OAAO,CAAC,gBAAgB,CAAqB;gBAEzB,OAAO,EAAE,sBAAsB;IAEnD,4DAA4D;IAC5D,aAAa,IAAI,MAAM;
|
|
1
|
+
{"version":3,"file":"ssr-cache-manager.d.ts","sourceRoot":"","sources":["../../../../../src/src/modules/react-loader/ssr-module-loader/ssr-cache-manager.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAalE,OAAO,KAAK,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAQ3E;;;;;;;GAOG;AACH,qBAAa,eAAe;IAId,OAAO,CAAC,OAAO;IAH3B,OAAO,CAAC,EAAE,CAAsB;IAChC,OAAO,CAAC,gBAAgB,CAAqB;gBAEzB,OAAO,EAAE,sBAAsB;IAEnD,4DAA4D;IAC5D,aAAa,IAAI,MAAM;IAWvB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAkB/B,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAiBlD,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAW1E,yBAAyB,IAAI,OAAO;IAoB9B,kBAAkB,CACtB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,cAAc,GAAG,aAAa,EACtC,OAAO,EAAE;QAAE,eAAe,EAAE,OAAO,CAAC;QAAC,qBAAqB,EAAE,OAAO,CAAA;KAAE,GACpE,OAAO,CAAC,OAAO,CAAC;IAgCb,wBAAwB,CAC5B,WAAW,EAAE,gBAAgB,EAC7B,eAAe,EAAE,MAAM,EACvB,gBAAgB,EAAE,MAAM,EACxB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,OAAO,CAAC;IAuBnB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,gBAAgB,GAAG,IAAI;IAQnF,oCAAoC,CAClC,eAAe,EAAE,MAAM,EACvB,gBAAgB,EAAE,MAAM,EACxB,UAAU,CAAC,EAAE,gBAAgB,GAC5B,IAAI;IAQP,OAAO,CAAC,8BAA8B;IAgBtC,wDAAwD;IACxD,KAAK,IAAI,UAAU,CAAC,OAAO,gBAAgB,CAAC;YAI9B,4BAA4B;YAW5B,qBAAqB;YAsBrB,oBAAoB;YAuDpB,YAAY;CA2B3B"}
|
|
@@ -8,6 +8,15 @@ interface ComponentPageResult {
|
|
|
8
8
|
pageElement: BundledReact.ReactElement;
|
|
9
9
|
pageBundle: PageBundle;
|
|
10
10
|
}
|
|
11
|
+
interface BundleComponentForClientDeps {
|
|
12
|
+
transformToESM: (source: string, filePath: string, projectDir: string, adapter: RuntimeAdapter, options: {
|
|
13
|
+
projectId: string;
|
|
14
|
+
dev: boolean;
|
|
15
|
+
jsxImportSource: string;
|
|
16
|
+
moduleServerUrl?: string;
|
|
17
|
+
reactVersion?: string;
|
|
18
|
+
}) => Promise<string>;
|
|
19
|
+
}
|
|
11
20
|
/**
|
|
12
21
|
* Load and render a TSX/JSX component page
|
|
13
22
|
*/
|
|
@@ -26,5 +35,6 @@ export declare function handleComponentPage(pageInfo: EntityInfo, slug: string,
|
|
|
26
35
|
/** React version for transforms (from project config) */
|
|
27
36
|
reactVersion?: string;
|
|
28
37
|
}): Promise<ComponentPageResult>;
|
|
38
|
+
export declare function bundleComponentForClient(source: string, filePath: string, projectDir: string, adapter: RuntimeAdapter, moduleServerUrl?: string, projectId?: string, reactVersion?: string, injectedDeps?: BundleComponentForClientDeps): Promise<string>;
|
|
29
39
|
export {};
|
|
30
40
|
//# sourceMappingURL=component-handling.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component-handling.d.ts","sourceRoot":"","sources":["../../../src/src/rendering/component-handling.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,KAAK,YAAY,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"component-handling.d.ts","sourceRoot":"","sources":["../../../src/src/rendering/component-handling.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,KAAK,YAAY,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAQhE,UAAU,mBAAmB;IAC3B,WAAW,EAAE,YAAY,CAAC,YAAY,CAAC;IACvC,UAAU,EAAE,UAAU,CAAC;CACxB;AAeD,UAAU,4BAA4B;IACpC,cAAc,EAAE,CACd,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE;QACP,SAAS,EAAE,MAAM,CAAC;QAClB,GAAG,EAAE,OAAO,CAAC;QACb,eAAe,EAAE,MAAM,CAAC;QACxB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,KACE,OAAO,CAAC,MAAM,CAAC,CAAC;CACtB;AAyBD;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,UAAU,EACpB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,kBAAkB,EAAE,OAAO,EAC3B,OAAO,EAAE,cAAc,EACvB,OAAO,CAAC,EAAE;IACR,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,yDAAyD;IACzD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GACA,OAAO,CAAC,mBAAmB,CAAC,CAwE9B;AAED,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,cAAc,EACvB,eAAe,CAAC,EAAE,MAAM,EACxB,SAAS,CAAC,EAAE,MAAM,EAClB,YAAY,CAAC,EAAE,MAAM,EACrB,YAAY,CAAC,EAAE,4BAA4B,GAC1C,OAAO,CAAC,MAAM,CAAC,CAqDjB"}
|
|
@@ -7,18 +7,36 @@ import { getProjectReact } from "../react/index.js";
|
|
|
7
7
|
import { buildComponentCacheKey } from "../cache/keys.js";
|
|
8
8
|
import { LRUCache } from "../utils/lru-wrapper.js";
|
|
9
9
|
import { registerLRUCache } from "../cache/index.js";
|
|
10
|
+
import { Singleflight } from "../utils/singleflight.js";
|
|
11
|
+
import { DEFAULT_REACT_VERSION } from "../transforms/import-rewriter/url-builder.js";
|
|
10
12
|
/**
|
|
11
13
|
* Cache for transformed component hydration bundles.
|
|
12
|
-
* Keys are content-addressed
|
|
13
|
-
* Safe for multi-tenant use (project-scoped + content-hashed).
|
|
14
|
+
* Keys are content-addressed and scoped to transform-affecting inputs.
|
|
15
|
+
* Safe for multi-tenant use (project-scoped + content/transform-hashed).
|
|
14
16
|
* Evicted when exceeding MAX_COMPONENT_CACHE_SIZE to prevent unbounded memory growth.
|
|
15
17
|
*/
|
|
16
18
|
const MAX_COMPONENT_CACHE_SIZE = 5_000;
|
|
17
19
|
const componentHydrationCache = new LRUCache({
|
|
18
20
|
maxEntries: MAX_COMPONENT_CACHE_SIZE,
|
|
19
21
|
});
|
|
22
|
+
const componentHydrationFlights = new Singleflight();
|
|
23
|
+
const COMPONENT_HYDRATION_FLIGHT_STALE_EVICTION_MS = 5 * 60_000;
|
|
24
|
+
async function getBundleComponentForClientDeps() {
|
|
25
|
+
const { transformToESM } = await import("../transforms/esm-transform.js");
|
|
26
|
+
return { transformToESM };
|
|
27
|
+
}
|
|
20
28
|
// Register cache for monitoring
|
|
21
29
|
registerLRUCache("component-hydration-cache", componentHydrationCache);
|
|
30
|
+
async function buildComponentHydrationCacheHash(source, moduleServerUrl, reactVersion) {
|
|
31
|
+
const sourceHash = await computeHash(source);
|
|
32
|
+
const effectiveReactVersion = reactVersion ?? DEFAULT_REACT_VERSION;
|
|
33
|
+
const cacheIdentity = JSON.stringify([
|
|
34
|
+
sourceHash,
|
|
35
|
+
moduleServerUrl ?? null,
|
|
36
|
+
effectiveReactVersion,
|
|
37
|
+
]);
|
|
38
|
+
return (await computeHash(cacheIdentity)).slice(0, 16);
|
|
39
|
+
}
|
|
22
40
|
/**
|
|
23
41
|
* Load and render a TSX/JSX component page
|
|
24
42
|
*/
|
|
@@ -70,22 +88,35 @@ export async function handleComponentPage(pageInfo, slug, projectDir, _component
|
|
|
70
88
|
});
|
|
71
89
|
}
|
|
72
90
|
}
|
|
73
|
-
async function bundleComponentForClient(source, filePath, projectDir, adapter, moduleServerUrl, projectId, reactVersion) {
|
|
91
|
+
export async function bundleComponentForClient(source, filePath, projectDir, adapter, moduleServerUrl, projectId, reactVersion, injectedDeps) {
|
|
74
92
|
try {
|
|
75
|
-
const
|
|
76
|
-
const cacheKey = buildComponentCacheKey(projectId ?? projectDir, filePath,
|
|
93
|
+
const cacheHash = await buildComponentHydrationCacheHash(source, moduleServerUrl, reactVersion);
|
|
94
|
+
const cacheKey = buildComponentCacheKey(projectId ?? projectDir, filePath, cacheHash);
|
|
77
95
|
const cached = componentHydrationCache.get(cacheKey);
|
|
78
96
|
if (cached)
|
|
79
97
|
return cached;
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
98
|
+
const transformed = await componentHydrationFlights.do(cacheKey, async (control) => {
|
|
99
|
+
const cachedDuringFlight = componentHydrationCache.get(cacheKey);
|
|
100
|
+
if (cachedDuringFlight)
|
|
101
|
+
return cachedDuringFlight;
|
|
102
|
+
const { transformToESM } = injectedDeps ?? await getBundleComponentForClientDeps();
|
|
103
|
+
const transformed = await transformToESM(source, filePath, projectDir, adapter, {
|
|
104
|
+
projectId: projectId ?? projectDir,
|
|
105
|
+
dev: true,
|
|
106
|
+
jsxImportSource: "react",
|
|
107
|
+
moduleServerUrl,
|
|
108
|
+
reactVersion,
|
|
109
|
+
});
|
|
110
|
+
if (control.isCurrent()) {
|
|
111
|
+
componentHydrationCache.set(cacheKey, transformed);
|
|
112
|
+
}
|
|
113
|
+
return transformed;
|
|
114
|
+
}, {
|
|
115
|
+
staleAfterMs: COMPONENT_HYDRATION_FLIGHT_STALE_EVICTION_MS,
|
|
116
|
+
onStaleEvicted: () => {
|
|
117
|
+
logger.warn("Evicted stale component hydration transform flight", { filePath });
|
|
118
|
+
},
|
|
87
119
|
});
|
|
88
|
-
componentHydrationCache.set(cacheKey, transformed);
|
|
89
120
|
return transformed;
|
|
90
121
|
}
|
|
91
122
|
catch (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout-applicator.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/layouts/layout-applicator.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,YAAY,MAAM,OAAO,CAAC;AACtC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACjF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAKzE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"layout-applicator.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/layouts/layout-applicator.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,7 +7,7 @@ import { resolve as resolveContract } from "../../extensions/contracts.js";
|
|
|
7
7
|
import { applyLayoutsESM, applyLayoutsFunctionBody } from "./utils/applicator.js";
|
|
8
8
|
import { resolveAppComponentPath } from "./utils/app-resolver.js";
|
|
9
9
|
import { collectAncestorDirs, createErrorBoundary, tryLoadReservedInDirs, } from "../app-reserved.js";
|
|
10
|
-
import {
|
|
10
|
+
import { resolveRouterModeForPage } from "../router-detection.js";
|
|
11
11
|
import { getProjectReact } from "../../react/index.js";
|
|
12
12
|
import { extract } from "../../platform/compat/std/front-matter-yaml.js";
|
|
13
13
|
import { createFileSystem } from "../../platform/compat/fs.js";
|
|
@@ -15,6 +15,7 @@ import { resolveFrameworkSourcePath } from "../../platform/compat/framework-sour
|
|
|
15
15
|
import { loadModuleFromSource } from "../../modules/react-loader/index.js";
|
|
16
16
|
import { resolveProjectReactVersion } from "../../transforms/esm/package-registry.js";
|
|
17
17
|
import { CLIENT_PAGE_ISLAND_ID } from "../rsc/page-island.js";
|
|
18
|
+
import { isDotPath } from "../orchestrator/path-helpers.js";
|
|
18
19
|
const logger = rendererLogger.component("layout-applicator");
|
|
19
20
|
export class LayoutApplicator {
|
|
20
21
|
projectDir;
|
|
@@ -75,17 +76,17 @@ export class LayoutApplicator {
|
|
|
75
76
|
else {
|
|
76
77
|
wrappedElement = await this.applyLayoutsOnly(pageElement, layoutBundle, nestedLayouts, layoutDataMap, reactVersion);
|
|
77
78
|
}
|
|
78
|
-
const useAppRouter = await detectAppRouter(this.projectDir, this.config, this.adapter, {
|
|
79
|
-
projectId: this.projectId,
|
|
80
|
-
});
|
|
81
79
|
const pageFilePath = pageInfo.entity.path;
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
80
|
+
const routerMode = resolveRouterModeForPage(this.projectDir, pageFilePath, this.config);
|
|
81
|
+
const dotPath = isDotPath({
|
|
82
|
+
slug: pageInfo.entity.slug ?? "",
|
|
83
|
+
filePath: pageFilePath,
|
|
84
|
+
projectDir: this.projectDir,
|
|
85
|
+
});
|
|
86
|
+
if (routerMode === "app") {
|
|
86
87
|
wrappedElement = await this.wrapWithReservedComponents(wrappedElement, pageFilePath);
|
|
87
88
|
}
|
|
88
|
-
else if (
|
|
89
|
+
else if (dotPath) {
|
|
89
90
|
logger.debug("Skipping wrapWithAppComponent - dot-prefixed path");
|
|
90
91
|
}
|
|
91
92
|
else {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout-collector.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/layouts/layout-collector.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAW7D,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,OAAO,EACrB,MAAM,EAAE,eAAe,GACtB,MAAM,CAKR;
|
|
1
|
+
{"version":3,"file":"layout-collector.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/layouts/layout-collector.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAW7D,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,OAAO,EACrB,MAAM,EAAE,eAAe,GACtB,MAAM,CAKR;AA+BD;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACxC;AAED;;;;;GAKG;AACH,wBAAsB,4BAA4B,CAChD,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQxB;AAUD,MAAM,WAAW,sBAAsB;IACrC,YAAY,EAAE,SAAS,GAAG,SAAS,CAAC;IACpC,aAAa,EAAE,UAAU,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,cAAc,CAAC;IACxB,MAAM,EAAE,eAAe,CAAC;IACxB,UAAU,EAAE,CACV,OAAO,EAAE,MAAM,EACf,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrC,QAAQ,CAAC,EAAE,MAAM,KACd,OAAO,CAAC,SAAS,CAAC,CAAC;CACzB;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAC,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,UAAU,CAIM;gBAEZ,OAAO,EAAE,sBAAsB;IAQrC,cAAc,CAAC,QAAQ,EAAE,UAAU,GAAG,OAAO,CAAC,sBAAsB,CAAC;YAsD7D,mBAAmB;YAyDnB,0BAA0B;IAkExC,OAAO,CAAC,iBAAiB;YAoBX,oBAAoB;YAgBpB,qBAAqB;IA4BnC;;;;;;OAMG;YACW,6BAA6B;IAiC3C;;OAEG;YACW,0BAA0B;CASzC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { join } from "../../platform/compat/path/index.js";
|
|
1
|
+
import { isAbsolute, join, normalize } from "../../platform/compat/path/index.js";
|
|
2
2
|
import { rendererLogger } from "../../utils/index.js";
|
|
3
3
|
import { getLayoutEntity } from "../../types/entities/getEntityInfo.js";
|
|
4
4
|
import { discoverNestedLayouts } from "./utils/discovery.js";
|
|
5
|
-
import {
|
|
5
|
+
import { resolveRouterModeForPage } from "../router-detection.js";
|
|
6
6
|
import { LAYOUT_EXTENSIONS } from "./types.js";
|
|
7
7
|
import { SpanNames } from "../../observability/index.js";
|
|
8
8
|
import { withSpan } from "../../observability/tracing/otlp-setup.js";
|
|
@@ -14,6 +14,9 @@ export function resolveLayoutRouterRootDir(projectDir, useAppRouter, config) {
|
|
|
14
14
|
: config.directories?.pages ?? "pages";
|
|
15
15
|
return join(projectDir, directory);
|
|
16
16
|
}
|
|
17
|
+
function resolvePagePath(pageFilePath, projectDir) {
|
|
18
|
+
return normalize(isAbsolute(pageFilePath) ? pageFilePath : join(projectDir, pageFilePath));
|
|
19
|
+
}
|
|
17
20
|
function getLayoutKind(path) {
|
|
18
21
|
return path.endsWith(".mdx") || path.endsWith(".md") ? "mdx" : "tsx";
|
|
19
22
|
}
|
|
@@ -187,19 +190,14 @@ export class LayoutCollector {
|
|
|
187
190
|
return null;
|
|
188
191
|
}
|
|
189
192
|
async collectNestedLayouts(pageInfo) {
|
|
190
|
-
const pageFilePath = pageInfo.entity.path;
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
// Unified path for ALL adapters - discoverNestedLayouts uses adapter.fs.stat()
|
|
195
|
-
// which works for both filesystem and API adapters
|
|
196
|
-
return this.collectLayoutsUnified(pageFilePath, useAppRouter);
|
|
193
|
+
const pageFilePath = resolvePagePath(pageInfo.entity.path, this.projectDir);
|
|
194
|
+
const routerMode = resolveRouterModeForPage(this.projectDir, pageInfo.entity.path, this.config);
|
|
195
|
+
const rootDir = resolveLayoutRouterRootDir(this.projectDir, routerMode === "app", this.config);
|
|
196
|
+
return this.collectLayoutsUnified(pageFilePath, rootDir);
|
|
197
197
|
}
|
|
198
|
-
async collectLayoutsUnified(pageFilePath,
|
|
199
|
-
const rootDir = resolveLayoutRouterRootDir(this.projectDir, useAppRouter, this.config);
|
|
198
|
+
async collectLayoutsUnified(pageFilePath, rootDir) {
|
|
200
199
|
logger.debug("collectLayoutsUnified", {
|
|
201
200
|
pageFilePath,
|
|
202
|
-
useAppRouter,
|
|
203
201
|
rootDir,
|
|
204
202
|
projectDir: this.projectDir,
|
|
205
203
|
});
|
|
@@ -2,6 +2,7 @@ import * as BundledReact from "react";
|
|
|
2
2
|
import type { RuntimeAdapter } from "../../../platform/adapters/base.js";
|
|
3
3
|
import type { LayoutItem, MdxBundle, MDXComponents } from "../../../types/index.js";
|
|
4
4
|
import type { ImportMapConfig } from "../../../modules/import-map/types.js";
|
|
5
|
+
import { loadComponentFromSource } from "../../../modules/react-loader/component-loader.js";
|
|
5
6
|
type AppRouterDocumentLayoutFunction = (props: {
|
|
6
7
|
children?: BundledReact.ReactNode;
|
|
7
8
|
}) => BundledReact.ReactNode;
|
|
@@ -12,12 +13,15 @@ export interface LayoutComponentCache {
|
|
|
12
13
|
clear(): void;
|
|
13
14
|
clearForProject?(projectId: string): void;
|
|
14
15
|
}
|
|
16
|
+
interface LoadTSXComponentDeps {
|
|
17
|
+
loadComponentFromSource: typeof loadComponentFromSource;
|
|
18
|
+
}
|
|
15
19
|
export declare function createLayoutComponentCache(maxEntries?: number, perProjectMaxEntries?: number): LayoutComponentCache;
|
|
16
20
|
export declare function shouldUnwrapAppRouterDocumentLayout(componentPath: string | undefined, projectDir: string, appDirectory?: string): boolean;
|
|
17
21
|
export declare function unwrapAppRouterDocumentLayout(React: typeof BundledReact, LayoutComponent: AppRouterDocumentLayoutFunction): BundledReact.FunctionComponent<{
|
|
18
22
|
children?: BundledReact.ReactNode;
|
|
19
23
|
}>;
|
|
20
|
-
export declare function loadTSXComponent(componentPath: string, projectDir: string, cache: LayoutComponentCache, adapter: RuntimeAdapter, projectId: string, projectSlug: string, contentSourceId: string, reactVersion?: string): Promise<BundledReact.ComponentType>;
|
|
24
|
+
export declare function loadTSXComponent(componentPath: string, projectDir: string, cache: LayoutComponentCache, adapter: RuntimeAdapter, projectId: string, projectSlug: string, contentSourceId: string, reactVersion?: string, deps?: LoadTSXComponentDeps): Promise<BundledReact.ComponentType>;
|
|
21
25
|
/** Load an MDX layout module from a bundle. */
|
|
22
26
|
export declare function loadMDXLayout(bundle: MdxBundle, projectDir: string, adapter: RuntimeAdapter, projectId: string, projectSlug: string, contentSourceId: string, preloadedImportMap?: ImportMapConfig, reactVersion?: string): Promise<BundledReact.ComponentType<{
|
|
23
27
|
components?: MDXComponents;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component-loader.d.ts","sourceRoot":"","sources":["../../../../../src/src/rendering/layouts/utils/component-loader.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,YAAY,MAAM,OAAO,CAAC;AACtC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAa,MAAM,yBAAyB,CAAC;AAC/F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"component-loader.d.ts","sourceRoot":"","sources":["../../../../../src/src/rendering/layouts/utils/component-loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,10 +10,21 @@ import { getProjectReact } from "../../../react/index.js";
|
|
|
10
10
|
import { ensureValidChild } from "./ensure-valid-child.js";
|
|
11
11
|
import { buildLayoutComponentCacheKey, CacheKeyPrefix } from "../../../cache/keys.js";
|
|
12
12
|
import { LAYOUT_EXTENSIONS } from "../types.js";
|
|
13
|
+
import { Singleflight } from "../../../utils/singleflight.js";
|
|
13
14
|
const loadMdxLayoutLog = logger.component("load-mdx-layout");
|
|
14
15
|
const applyTsxLayoutLog = logger.component("apply-tsx-layout");
|
|
15
16
|
const applyMdxLayoutLog = logger.component("apply-mdx-layout");
|
|
16
17
|
const APP_ROUTER_SCRIPT_LAYOUT_EXTENSIONS = LAYOUT_EXTENSIONS.filter((extension) => extension !== "md" && extension !== "mdx");
|
|
18
|
+
const TSX_COMPONENT_FLIGHT_STALE_EVICTION_MS = 5 * 60_000;
|
|
19
|
+
const tsxComponentFlights = new WeakMap();
|
|
20
|
+
function getTSXComponentFlights(cache) {
|
|
21
|
+
let flights = tsxComponentFlights.get(cache);
|
|
22
|
+
if (!flights) {
|
|
23
|
+
flights = new Singleflight();
|
|
24
|
+
tsxComponentFlights.set(cache, flights);
|
|
25
|
+
}
|
|
26
|
+
return flights;
|
|
27
|
+
}
|
|
17
28
|
class InMemoryLayoutComponentCache {
|
|
18
29
|
maxEntries;
|
|
19
30
|
entries = new Map();
|
|
@@ -159,7 +170,7 @@ export function unwrapAppRouterDocumentLayout(React, LayoutComponent) {
|
|
|
159
170
|
return body?.props?.children ?? props.children ?? null;
|
|
160
171
|
};
|
|
161
172
|
}
|
|
162
|
-
export async function loadTSXComponent(componentPath, projectDir, cache, adapter, projectId, projectSlug, contentSourceId, reactVersion) {
|
|
173
|
+
export async function loadTSXComponent(componentPath, projectDir, cache, adapter, projectId, projectSlug, contentSourceId, reactVersion, deps = { loadComponentFromSource }) {
|
|
163
174
|
const source = await adapter.fs.readFile(componentPath);
|
|
164
175
|
const hash = await computeHash(source);
|
|
165
176
|
const cacheKey = buildLayoutComponentCacheKey(projectId, componentPath, hash, contentSourceId) +
|
|
@@ -167,21 +178,36 @@ export async function loadTSXComponent(componentPath, projectDir, cache, adapter
|
|
|
167
178
|
const cached = cache.get(cacheKey);
|
|
168
179
|
if (cached)
|
|
169
180
|
return cached;
|
|
170
|
-
const loaded = await
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
181
|
+
const loaded = await getTSXComponentFlights(cache).do(cacheKey, async (control) => {
|
|
182
|
+
const cachedDuringFlight = cache.get(cacheKey);
|
|
183
|
+
if (cachedDuringFlight)
|
|
184
|
+
return cachedDuringFlight;
|
|
185
|
+
const loaded = await deps.loadComponentFromSource(source, componentPath, projectDir, adapter, {
|
|
186
|
+
dev: true,
|
|
187
|
+
projectId,
|
|
188
|
+
projectSlug,
|
|
189
|
+
ssr: true,
|
|
190
|
+
contentSourceId,
|
|
191
|
+
reactVersion,
|
|
192
|
+
});
|
|
193
|
+
if (!loaded) {
|
|
194
|
+
throw toError(createError({
|
|
195
|
+
type: "render",
|
|
196
|
+
message: "Component loading failed",
|
|
197
|
+
}));
|
|
198
|
+
}
|
|
199
|
+
if (control.isCurrent()) {
|
|
200
|
+
cache.set(cacheKey, loaded);
|
|
201
|
+
}
|
|
202
|
+
return loaded;
|
|
203
|
+
}, {
|
|
204
|
+
staleAfterMs: TSX_COMPONENT_FLIGHT_STALE_EVICTION_MS,
|
|
205
|
+
onStaleEvicted: () => {
|
|
206
|
+
applyTsxLayoutLog.warn("Evicted stale TSX layout component load flight", {
|
|
207
|
+
componentPath,
|
|
208
|
+
});
|
|
209
|
+
},
|
|
177
210
|
});
|
|
178
|
-
if (!loaded) {
|
|
179
|
-
throw toError(createError({
|
|
180
|
-
type: "render",
|
|
181
|
-
message: "Component loading failed",
|
|
182
|
-
}));
|
|
183
|
-
}
|
|
184
|
-
cache.set(cacheKey, loaded);
|
|
185
211
|
return loaded;
|
|
186
212
|
}
|
|
187
213
|
/** Load an MDX layout module from a bundle. */
|
|
@@ -8,8 +8,19 @@
|
|
|
8
8
|
import type { LayoutItem } from "../../types/index.js";
|
|
9
9
|
/** Check if a path segment is a hidden dot-directory (not . or ..) */
|
|
10
10
|
export declare function isHiddenSegment(segment: string): boolean;
|
|
11
|
-
/**
|
|
12
|
-
export
|
|
11
|
+
/** Inputs used to determine whether a resolved route is hidden. */
|
|
12
|
+
export interface DotPathOptions {
|
|
13
|
+
slug: string;
|
|
14
|
+
filePath?: string;
|
|
15
|
+
projectDir: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Check whether a route contains a dot-prefixed segment.
|
|
19
|
+
*
|
|
20
|
+
* Absolute filesystem ancestors are outside the route namespace and must not
|
|
21
|
+
* make a project hidden (for example, a project checked out under `.worktrees`).
|
|
22
|
+
*/
|
|
23
|
+
export declare function isDotPath({ slug, filePath, projectDir }: DotPathOptions): boolean;
|
|
13
24
|
/** Empty layout result for dot-prefixed paths */
|
|
14
25
|
export declare const EMPTY_LAYOUT_RESULT: {
|
|
15
26
|
layoutBundle: undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path-helpers.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/orchestrator/path-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"path-helpers.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/orchestrator/path-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGvD,sEAAsE;AACtE,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,mEAAmE;AACnE,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAcD;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,cAAc,GAAG,OAAO,CAMjF;AAED,iDAAiD;AACjD,eAAO,MAAM,mBAAmB,EAAE;IAChC,YAAY,EAAE,SAAS,CAAC;IACxB,aAAa,EAAE,UAAU,EAAE,CAAC;CACoB,CAAC"}
|
|
@@ -5,14 +5,31 @@
|
|
|
5
5
|
*
|
|
6
6
|
* @module rendering/orchestrator/path-helpers
|
|
7
7
|
*/
|
|
8
|
+
import { isAbsolute, relative } from "../../platform/compat/path/index.js";
|
|
8
9
|
/** Check if a path segment is a hidden dot-directory (not . or ..) */
|
|
9
10
|
export function isHiddenSegment(segment) {
|
|
10
11
|
return segment.startsWith(".") && segment !== "." && segment !== "..";
|
|
11
12
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
function getProjectPath(filePath, projectDir) {
|
|
14
|
+
if (!filePath || !isAbsolute(filePath))
|
|
15
|
+
return filePath;
|
|
16
|
+
const projectPath = relative(projectDir, filePath);
|
|
17
|
+
const normalizedProjectPath = projectPath.replaceAll("\\", "/");
|
|
18
|
+
const isOutsideProject = normalizedProjectPath === ".." ||
|
|
19
|
+
normalizedProjectPath.startsWith("../") ||
|
|
20
|
+
isAbsolute(projectPath);
|
|
21
|
+
return isOutsideProject ? undefined : projectPath;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Check whether a route contains a dot-prefixed segment.
|
|
25
|
+
*
|
|
26
|
+
* Absolute filesystem ancestors are outside the route namespace and must not
|
|
27
|
+
* make a project hidden (for example, a project checked out under `.worktrees`).
|
|
28
|
+
*/
|
|
29
|
+
export function isDotPath({ slug, filePath, projectDir }) {
|
|
30
|
+
const hasDotSegment = (path) => path.replaceAll("\\", "/").split("/").some(isHiddenSegment);
|
|
31
|
+
const projectPath = getProjectPath(filePath, projectDir);
|
|
32
|
+
return hasDotSegment(slug) || (projectPath ? hasDotSegment(projectPath) : false);
|
|
16
33
|
}
|
|
17
34
|
/** Empty layout result for dot-prefixed paths */
|
|
18
35
|
export const EMPTY_LAYOUT_RESULT = { layoutBundle: undefined, nestedLayouts: [] };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/orchestrator/pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAUH,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,iCAAiC,CAAC;AASzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,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;AA6DhF,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,yEAAyE;IACzE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,wEAAwE;IACxE,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,8EAA8E;IAC9E,iBAAiB,CAAC,EAAE,OAAO,qBAAqB,EAAE,sBAAsB,CAAC;CAC1E;AAqCD,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,mBAAmB,CAAgC;gBAE/C,MAAM,EAAE,oBAAoB;IAcxC,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,oBAAoB;IA0B5B;;;;OAIG;YACW,yBAAyB;IAWvC;;;OAGG;IACH,gBAAgB,IAAI,IAAI;IAKxB,OAAO,CAAC,UAAU;YAOJ,0BAA0B;IAaxC;;;;;;;;;OASG;YACW,qBAAqB;IAiFnC;;;OAGG;YACW,mBAAmB;IAqHjC,OAAO,CAAC,uBAAuB;IAkCzB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/orchestrator/pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAUH,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,iCAAiC,CAAC;AASzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,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;AA6DhF,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,yEAAyE;IACzE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,wEAAwE;IACxE,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,8EAA8E;IAC9E,iBAAiB,CAAC,EAAE,OAAO,qBAAqB,EAAE,sBAAsB,CAAC;CAC1E;AAqCD,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,mBAAmB,CAAgC;gBAE/C,MAAM,EAAE,oBAAoB;IAcxC,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,oBAAoB;IA0B5B;;;;OAIG;YACW,yBAAyB;IAWvC;;;OAGG;IACH,gBAAgB,IAAI,IAAI;IAKxB,OAAO,CAAC,UAAU;YAOJ,0BAA0B;IAaxC;;;;;;;;;OASG;YACW,qBAAqB;IAiFnC;;;OAGG;YACW,mBAAmB;IAqHjC,OAAO,CAAC,uBAAuB;IAkCzB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IA2U9E,+EAA+E;IACzE,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,gBAAgB,CAAC;YA4IzE,kBAAkB;YA2ClB,cAAc;IAW5B,OAAO,CAAC,uBAAuB;YAYjB,kBAAkB;IA6FhC,OAAO,CAAC,kBAAkB;YAQZ,uBAAuB;IAmBrC;;;;;;OAMG;IACH,OAAO,CAAC,aAAa;CAStB"}
|
|
@@ -334,7 +334,11 @@ export class RenderPipeline {
|
|
|
334
334
|
timing.pageResolve = Math.round(performance.now() - pageResolveStart);
|
|
335
335
|
const sourceFile = extractRelativePathShared(pageInfo.entity.path, this.config.projectDir);
|
|
336
336
|
try {
|
|
337
|
-
const skipLayouts = isDotPath(
|
|
337
|
+
const skipLayouts = isDotPath({
|
|
338
|
+
slug,
|
|
339
|
+
filePath: pageInfo.entity.path,
|
|
340
|
+
projectDir: this.config.projectDir,
|
|
341
|
+
});
|
|
338
342
|
const layoutCollectStart = performance.now();
|
|
339
343
|
const layoutResult = skipLayouts ? EMPTY_LAYOUT_RESULT : await profilePhase("render.collect_layouts", () => withSpan("render.collect_layouts", () => this.config.layoutOrchestrator.collectLayouts(pageInfo), { "render.slug": slug }));
|
|
340
344
|
timing.layoutCollect = Math.round(performance.now() - layoutCollectStart);
|
|
@@ -514,7 +518,11 @@ export class RenderPipeline {
|
|
|
514
518
|
clearSSRModuleCacheForProject(projectId, { preserveActiveTransforms: true });
|
|
515
519
|
}
|
|
516
520
|
const pageInfo = await profilePhase("page_data.resolve_page", () => this.config.pageResolver.resolvePage(slug));
|
|
517
|
-
const skipLayouts = isDotPath(
|
|
521
|
+
const skipLayouts = isDotPath({
|
|
522
|
+
slug,
|
|
523
|
+
filePath: pageInfo.entity.path,
|
|
524
|
+
projectDir: this.config.projectDir,
|
|
525
|
+
});
|
|
518
526
|
const layoutResult = skipLayouts ? EMPTY_LAYOUT_RESULT : await profilePhase("page_data.collect_layouts", () => this.config.layoutOrchestrator.collectLayouts(pageInfo));
|
|
519
527
|
const pagePath = extractRelativePathShared(pageInfo.entity.path, this.config.projectDir);
|
|
520
528
|
const fileExtension = getExtensionName(pageInfo.entity.path);
|
|
@@ -26,6 +26,18 @@ export interface DetectAppRouterOptions {
|
|
|
26
26
|
/** Project ID for cache isolation in multi-tenant deployments */
|
|
27
27
|
projectId?: string;
|
|
28
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Resolve the router that owns an already-resolved page.
|
|
31
|
+
*
|
|
32
|
+
* Auto-detection decides which router to try first, but mixed projects can
|
|
33
|
+
* legitimately fall back to the other router. Per-page rendering must follow
|
|
34
|
+
* the route that actually resolved instead of the project-wide preference.
|
|
35
|
+
*
|
|
36
|
+
* Pages routes can also resolve from the project root. App routes cannot
|
|
37
|
+
* resolve outside their configured root, so an unmatched resolved path belongs
|
|
38
|
+
* to the Pages router.
|
|
39
|
+
*/
|
|
40
|
+
export declare function resolveRouterModeForPage(projectDir: string, pagePath: string, config: VeryfrontConfig): "app" | "pages";
|
|
29
41
|
/**
|
|
30
42
|
* Detect if app router should be used based on config and directory structure.
|
|
31
43
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router-detection.d.ts","sourceRoot":"","sources":["../../../src/src/rendering/router-detection.ts"],"names":[],"mappings":"AAAA;;;;;;;4BAO4B;AAK5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAQ1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAY5D;;;GAGG;AACH,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD;AAED;;;;;GAKG;AACH,wBAAgB,mCAAmC,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAE3E;AAED,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,KAAK,GAAG,OAAO,GACpB,IAAI,CAEN;AAED,MAAM,WAAW,sBAAsB;IACrC,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,cAAc,EACvB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,OAAO,CAAC,CA6BlB"}
|
|
1
|
+
{"version":3,"file":"router-detection.d.ts","sourceRoot":"","sources":["../../../src/src/rendering/router-detection.ts"],"names":[],"mappings":"AAAA;;;;;;;4BAO4B;AAK5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAQ1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAY5D;;;GAGG;AACH,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD;AAED;;;;;GAKG;AACH,wBAAgB,mCAAmC,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAE3E;AAED,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,KAAK,GAAG,OAAO,GACpB,IAAI,CAEN;AAED,MAAM,WAAW,sBAAsB;IACrC,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAcD;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,eAAe,GACtB,KAAK,GAAG,OAAO,CA0BjB;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,cAAc,EACvB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,OAAO,CAAC,CA6BlB"}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* - Directory structure analysis
|
|
7
7
|
* - Route file presence detection
|
|
8
8
|
**************************/
|
|
9
|
-
import { join } from "../platform/compat/path/index.js";
|
|
9
|
+
import { isAbsolute, join, normalize, relative } from "../platform/compat/path/index.js";
|
|
10
10
|
import { createFileSystem } from "../platform/compat/fs.js";
|
|
11
11
|
import { rendererLogger } from "../utils/index.js";
|
|
12
12
|
import { LRUCache } from "../utils/lru-wrapper.js";
|
|
@@ -41,6 +41,46 @@ export function clearRouterDetectionCacheForProject(projectId) {
|
|
|
41
41
|
export function primeRouterDetectionCache(projectKey, mode) {
|
|
42
42
|
routerDetectionCache.set(projectKey, mode === "app");
|
|
43
43
|
}
|
|
44
|
+
function isPathInside(path, directory) {
|
|
45
|
+
const relativePath = relative(directory, path).replaceAll("\\", "/");
|
|
46
|
+
return relativePath === "" ||
|
|
47
|
+
(relativePath !== ".." &&
|
|
48
|
+
!relativePath.startsWith("../") &&
|
|
49
|
+
!isAbsolute(relativePath));
|
|
50
|
+
}
|
|
51
|
+
function resolveProjectPath(projectDir, path) {
|
|
52
|
+
return normalize(isAbsolute(path) ? path : join(projectDir, path));
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Resolve the router that owns an already-resolved page.
|
|
56
|
+
*
|
|
57
|
+
* Auto-detection decides which router to try first, but mixed projects can
|
|
58
|
+
* legitimately fall back to the other router. Per-page rendering must follow
|
|
59
|
+
* the route that actually resolved instead of the project-wide preference.
|
|
60
|
+
*
|
|
61
|
+
* Pages routes can also resolve from the project root. App routes cannot
|
|
62
|
+
* resolve outside their configured root, so an unmatched resolved path belongs
|
|
63
|
+
* to the Pages router.
|
|
64
|
+
*/
|
|
65
|
+
export function resolveRouterModeForPage(projectDir, pagePath, config) {
|
|
66
|
+
if (config.router === "app")
|
|
67
|
+
return "app";
|
|
68
|
+
if (config.router === "pages")
|
|
69
|
+
return "pages";
|
|
70
|
+
const resolvedPagePath = resolveProjectPath(projectDir, pagePath);
|
|
71
|
+
const appRoot = resolveProjectPath(projectDir, config.directories?.app ?? "app");
|
|
72
|
+
const pagesRoot = resolveProjectPath(projectDir, config.directories?.pages ?? "pages");
|
|
73
|
+
const isAppRoute = isPathInside(resolvedPagePath, appRoot);
|
|
74
|
+
const isPagesRoute = isPathInside(resolvedPagePath, pagesRoot);
|
|
75
|
+
if (isAppRoute && isPagesRoute) {
|
|
76
|
+
const appDistance = relative(appRoot, resolvedPagePath).split(/[\\/]/).filter(Boolean).length;
|
|
77
|
+
const pagesDistance = relative(pagesRoot, resolvedPagePath).split(/[\\/]/).filter(Boolean).length;
|
|
78
|
+
return pagesDistance < appDistance ? "pages" : "app";
|
|
79
|
+
}
|
|
80
|
+
if (isAppRoute)
|
|
81
|
+
return "app";
|
|
82
|
+
return "pages";
|
|
83
|
+
}
|
|
44
84
|
/**
|
|
45
85
|
* Detect if app router should be used based on config and directory structure.
|
|
46
86
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/pipeline/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAYH,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAEhB,eAAe,EAChB,MAAM,YAAY,CAAC;AAoHpB,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,gBAAgB,EACzB,MAAM,CAAC,EAAE,cAAc,GACtB,OAAO,CAAC,eAAe,CAAC,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/pipeline/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAYH,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAEhB,eAAe,EAChB,MAAM,YAAY,CAAC;AAoHpB,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,gBAAgB,EACzB,MAAM,CAAC,EAAE,cAAc,GACtB,OAAO,CAAC,eAAe,CAAC,CAkJ1B;AAqBD,wBAAsB,cAAc,CAClC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,MAAM,CAAC,CASjB;AAmCD,YAAY,EACV,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,OAAO,EACL,sBAAsB,EACtB,0BAA0B,EAC1B,SAAS,EACT,KAAK,EACL,KAAK,EACL,YAAY,GACb,MAAM,cAAc,CAAC"}
|
|
@@ -107,6 +107,9 @@ export function runPipeline(source, filePath, projectDir, options, config) {
|
|
|
107
107
|
const configHash = await computeConfigHash({
|
|
108
108
|
reactVersion: ctx.reactVersion,
|
|
109
109
|
jsxImportSource: ctx.jsxImportSource,
|
|
110
|
+
moduleServerUrl: ctx.moduleServerUrl,
|
|
111
|
+
vendorBundleHash: ctx.vendorBundleHash,
|
|
112
|
+
apiBaseUrl: ctx.apiBaseUrl,
|
|
110
113
|
studioEmbed: ctx.studioEmbed,
|
|
111
114
|
dev: ctx.dev,
|
|
112
115
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "veryfront",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1151",
|
|
4
4
|
"description": "The simplest way to build AI-powered apps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -332,10 +332,10 @@
|
|
|
332
332
|
"@types/react": "19.2.14",
|
|
333
333
|
"@types/react-dom": "19.2.3",
|
|
334
334
|
"ws": "8.21.0",
|
|
335
|
-
"@veryfront/ext-bundler-esbuild": "0.1.
|
|
336
|
-
"@veryfront/ext-content-mdx": "0.1.
|
|
337
|
-
"@veryfront/ext-css-tailwind": "0.1.
|
|
338
|
-
"@veryfront/ext-parser-babel": "0.1.
|
|
335
|
+
"@veryfront/ext-bundler-esbuild": "0.1.1151",
|
|
336
|
+
"@veryfront/ext-content-mdx": "0.1.1151",
|
|
337
|
+
"@veryfront/ext-css-tailwind": "0.1.1151",
|
|
338
|
+
"@veryfront/ext-parser-babel": "0.1.1151"
|
|
339
339
|
},
|
|
340
340
|
"devDependencies": {
|
|
341
341
|
"@types/node": "20.9.0"
|