veryfront 0.1.742 → 0.1.744
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/hash.d.ts +33 -0
- package/esm/src/cache/hash.d.ts.map +1 -0
- package/esm/src/cache/hash.js +59 -0
- package/esm/src/modules/server/module-batch-handler.d.ts.map +1 -1
- package/esm/src/modules/server/module-batch-handler.js +68 -5
- package/esm/src/modules/server/module-server.d.ts.map +1 -1
- package/esm/src/modules/server/module-server.js +60 -4
- package/esm/src/modules/server/ssr-import-rewriter.d.ts +14 -2
- package/esm/src/modules/server/ssr-import-rewriter.d.ts.map +1 -1
- package/esm/src/modules/server/ssr-import-rewriter.js +134 -12
- package/esm/src/rendering/context/render-context.d.ts.map +1 -1
- package/esm/src/rendering/context/render-context.js +7 -1
- package/esm/src/server/context/enriched-context.d.ts.map +1 -1
- package/esm/src/server/context/enriched-context.js +15 -3
- package/esm/src/server/handlers/request/api/project-discovery.js +2 -2
- package/esm/src/skill/executor.d.ts.map +1 -1
- package/esm/src/skill/executor.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 +1 -1
package/esm/deno.js
CHANGED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**************************
|
|
2
|
+
* Standardized Cache Hashing Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides consistent hashing for cache keys across the codebase.
|
|
5
|
+
* All cache keys should use these utilities to ensure:
|
|
6
|
+
* - Consistent format with type prefixes
|
|
7
|
+
* - Collision resistance between different cache types
|
|
8
|
+
* - Easy debugging and key parsing
|
|
9
|
+
*
|
|
10
|
+
* Key format: `{type}:{hash}` or `{type}:{version}:{hash}`
|
|
11
|
+
*
|
|
12
|
+
* @module cache/hash
|
|
13
|
+
**************************/
|
|
14
|
+
import { computeHash } from "../utils/hash-utils.js";
|
|
15
|
+
type CacheKeyType = "http" | "mod" | "esm" | "render" | "mdx" | "css" | "file" | "config";
|
|
16
|
+
export declare function fastHash(input: string): number;
|
|
17
|
+
export declare function hashToString(hash: number): string;
|
|
18
|
+
export declare function hashString(input: string): string;
|
|
19
|
+
export declare function getCacheKey(type: CacheKeyType, input: string): string;
|
|
20
|
+
export declare function getVersionedCacheKey(type: CacheKeyType, version: number | string, input: string): string;
|
|
21
|
+
export declare function getCompoundCacheKey(type: CacheKeyType, components: string[]): string;
|
|
22
|
+
export declare function parseCacheKey(key: string): {
|
|
23
|
+
type: string;
|
|
24
|
+
hash: string;
|
|
25
|
+
version?: string;
|
|
26
|
+
} | null;
|
|
27
|
+
export declare const sha256Hash: typeof computeHash;
|
|
28
|
+
export declare function sha256Short(input: string): Promise<string>;
|
|
29
|
+
export declare function getHttpBundleFilename(normalizedUrl: string): string;
|
|
30
|
+
export declare function parseHttpBundleFilename(filename: string): string | null;
|
|
31
|
+
export declare function isCacheKey(value: string): boolean;
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=hash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../../src/src/cache/hash.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;4BAY4B;AAE5B,OAAO,EAAE,WAAW,EAAc,MAAM,wBAAwB,CAAC;AAEjE,KAAK,YAAY,GACb,MAAM,GACN,KAAK,GACL,KAAK,GACL,QAAQ,GACR,KAAK,GACL,KAAK,GACL,MAAM,GACN,QAAQ,CAAC;AAEb,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQ9C;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAErE;AAED,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,YAAY,EAClB,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,KAAK,EAAE,MAAM,GACZ,MAAM,CAER;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,CAEpF;AAED,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,GACV;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAWzD;AAED,eAAO,MAAM,UAAU,oBAAc,CAAC;AAEtC,wBAAsB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEhE;AAED,wBAAgB,qBAAqB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAEnE;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEvE;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEjD"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**************************
|
|
2
|
+
* Standardized Cache Hashing Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides consistent hashing for cache keys across the codebase.
|
|
5
|
+
* All cache keys should use these utilities to ensure:
|
|
6
|
+
* - Consistent format with type prefixes
|
|
7
|
+
* - Collision resistance between different cache types
|
|
8
|
+
* - Easy debugging and key parsing
|
|
9
|
+
*
|
|
10
|
+
* Key format: `{type}:{hash}` or `{type}:{version}:{hash}`
|
|
11
|
+
*
|
|
12
|
+
* @module cache/hash
|
|
13
|
+
**************************/
|
|
14
|
+
import { computeHash, simpleHash } from "../utils/hash-utils.js";
|
|
15
|
+
export function fastHash(input) {
|
|
16
|
+
let hash = 5381;
|
|
17
|
+
for (let i = 0; i < input.length; i++) {
|
|
18
|
+
hash = ((hash << 5) + hash) ^ input.charCodeAt(i);
|
|
19
|
+
}
|
|
20
|
+
return hash >>> 0;
|
|
21
|
+
}
|
|
22
|
+
export function hashToString(hash) {
|
|
23
|
+
return hash.toString(36);
|
|
24
|
+
}
|
|
25
|
+
export function hashString(input) {
|
|
26
|
+
return hashToString(fastHash(input));
|
|
27
|
+
}
|
|
28
|
+
export function getCacheKey(type, input) {
|
|
29
|
+
return `${type}:${hashString(input)}`;
|
|
30
|
+
}
|
|
31
|
+
export function getVersionedCacheKey(type, version, input) {
|
|
32
|
+
return `${type}:v${version}:${hashString(input)}`;
|
|
33
|
+
}
|
|
34
|
+
export function getCompoundCacheKey(type, components) {
|
|
35
|
+
return getCacheKey(type, components.join(":"));
|
|
36
|
+
}
|
|
37
|
+
export function parseCacheKey(key) {
|
|
38
|
+
const [type, ...rest] = key.split(":");
|
|
39
|
+
if (!type || rest.length === 0)
|
|
40
|
+
return null;
|
|
41
|
+
const [maybeVersion, ...hashParts] = rest;
|
|
42
|
+
if (maybeVersion?.startsWith("v") && /^v\d+$/.test(maybeVersion)) {
|
|
43
|
+
return { type, version: maybeVersion.slice(1), hash: hashParts.join(":") };
|
|
44
|
+
}
|
|
45
|
+
return { type, hash: rest.join(":") };
|
|
46
|
+
}
|
|
47
|
+
export const sha256Hash = computeHash;
|
|
48
|
+
export async function sha256Short(input) {
|
|
49
|
+
return (await sha256Hash(input)).slice(0, 8);
|
|
50
|
+
}
|
|
51
|
+
export function getHttpBundleFilename(normalizedUrl) {
|
|
52
|
+
return `http-${simpleHash(normalizedUrl)}.mjs`;
|
|
53
|
+
}
|
|
54
|
+
export function parseHttpBundleFilename(filename) {
|
|
55
|
+
return filename.match(/^http-(\d+)\.mjs$/)?.[1] ?? null;
|
|
56
|
+
}
|
|
57
|
+
export function isCacheKey(value) {
|
|
58
|
+
return /^[a-z]+:[a-z0-9]+/.test(value);
|
|
59
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-batch-handler.d.ts","sourceRoot":"","sources":["../../../../src/src/modules/server/module-batch-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AASH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"module-batch-handler.d.ts","sourceRoot":"","sources":["../../../../src/src/modules/server/module-batch-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AASH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AA2DtE,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,cAAc,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,yDAAyD;IACzD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC,CA2K/F;AAkPD;;GAEG;AACH,wBAAgB,eAAe,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAY1D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAKrE"}
|
|
@@ -20,12 +20,13 @@ import { createSecureFs } from "../../security/index.js";
|
|
|
20
20
|
import { transformToESM } from "../../transforms/esm-transform.js";
|
|
21
21
|
import { createFileSystem } from "../../platform/compat/fs.js";
|
|
22
22
|
import { join } from "../../platform/compat/path/index.js";
|
|
23
|
-
import {
|
|
23
|
+
import { applySSRImportRewritesAsync, resolveSSRImportTargetModulePath, stripSSRModuleJsExtension, } from "./ssr-import-rewriter.js";
|
|
24
24
|
import { buildModuleTransformCacheKey } from "../../cache/keys.js";
|
|
25
25
|
import { withSpan } from "../../observability/tracing/otlp-setup.js";
|
|
26
26
|
import { getFrameworkRootFromMeta } from "../../platform/compat/vfs-paths.js";
|
|
27
27
|
import { LRUCache } from "../../utils/lru-wrapper.js";
|
|
28
28
|
import { registerLRUCache } from "../../cache/index.js";
|
|
29
|
+
import { sha256Short } from "../../cache/hash.js";
|
|
29
30
|
const logger = serverLogger.component("module-batch");
|
|
30
31
|
/** Slow request threshold in milliseconds */
|
|
31
32
|
const SLOW_REQUEST_THRESHOLD_MS = 500;
|
|
@@ -202,7 +203,7 @@ async function loadAndTransformModule(modulePath, projectDir, adapter, secureFs,
|
|
|
202
203
|
if (!stat.isFile)
|
|
203
204
|
continue;
|
|
204
205
|
const source = await secureFs.readFile(fullPath);
|
|
205
|
-
return transformModule(source, fullPath, projectDir, adapter, options);
|
|
206
|
+
return transformModule(source, fullPath, modulePath, projectDir, adapter, secureFs, options);
|
|
206
207
|
}
|
|
207
208
|
catch (_) {
|
|
208
209
|
/* expected: file may not exist at this extension */
|
|
@@ -224,7 +225,7 @@ async function loadAndTransformModule(modulePath, projectDir, adapter, secureFs,
|
|
|
224
225
|
if (!stat.isFile)
|
|
225
226
|
continue;
|
|
226
227
|
const source = await platformFs.readTextFile(frameworkPath);
|
|
227
|
-
return transformModule(source, frameworkPath, projectDir, adapter, options);
|
|
228
|
+
return transformModule(source, frameworkPath, modulePath, projectDir, adapter, secureFs, options);
|
|
228
229
|
}
|
|
229
230
|
catch (_) {
|
|
230
231
|
/* expected: framework file may not exist at this extension */
|
|
@@ -233,7 +234,7 @@ async function loadAndTransformModule(modulePath, projectDir, adapter, secureFs,
|
|
|
233
234
|
}
|
|
234
235
|
return null;
|
|
235
236
|
}
|
|
236
|
-
async function transformModule(source, sourceFile, projectDir, adapter, options) {
|
|
237
|
+
async function transformModule(source, sourceFile, modulePath, projectDir, adapter, secureFs, options) {
|
|
237
238
|
let code = await transformToESM(source, sourceFile, projectDir, adapter, {
|
|
238
239
|
projectId: options.projectId ?? projectDir,
|
|
239
240
|
dev: options.dev,
|
|
@@ -241,13 +242,75 @@ async function transformModule(source, sourceFile, projectDir, adapter, options)
|
|
|
241
242
|
reactVersion: options.reactVersion,
|
|
242
243
|
});
|
|
243
244
|
if (options.ssr) {
|
|
244
|
-
code =
|
|
245
|
+
code = await applySSRImportRewritesAsync(code, {
|
|
245
246
|
projectSlug: options.projectSlug,
|
|
246
247
|
branch: options.branch,
|
|
248
|
+
resolveCacheBuster: createBatchSSRTargetCacheBusterResolver({
|
|
249
|
+
projectDir,
|
|
250
|
+
secureFs,
|
|
251
|
+
currentModulePath: modulePath,
|
|
252
|
+
}),
|
|
247
253
|
});
|
|
248
254
|
}
|
|
249
255
|
return code;
|
|
250
256
|
}
|
|
257
|
+
async function readBatchTargetSource(projectDir, secureFs, modulePath) {
|
|
258
|
+
const basePath = stripSSRModuleJsExtension(modulePath);
|
|
259
|
+
for (const ext of EXTENSIONS) {
|
|
260
|
+
const fullPath = join(projectDir, basePath + ext);
|
|
261
|
+
try {
|
|
262
|
+
const stat = await secureFs.stat(fullPath);
|
|
263
|
+
if (!stat.isFile)
|
|
264
|
+
continue;
|
|
265
|
+
return {
|
|
266
|
+
path: fullPath,
|
|
267
|
+
source: await secureFs.readFile(fullPath),
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
catch (_) {
|
|
271
|
+
/* expected: file may not exist at this extension */
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
if (!basePath.startsWith("lib/"))
|
|
275
|
+
return null;
|
|
276
|
+
const frameworkLookupDirs = [EMBEDDED_SRC_DIR, join(FRAMEWORK_ROOT, "src")];
|
|
277
|
+
const platformFs = createFileSystem();
|
|
278
|
+
for (const lookupDir of frameworkLookupDirs) {
|
|
279
|
+
for (const ext of FRAMEWORK_EXTENSIONS) {
|
|
280
|
+
const frameworkPath = join(lookupDir, basePath + ext);
|
|
281
|
+
try {
|
|
282
|
+
const stat = await platformFs.stat(frameworkPath);
|
|
283
|
+
if (!stat.isFile)
|
|
284
|
+
continue;
|
|
285
|
+
return {
|
|
286
|
+
path: frameworkPath,
|
|
287
|
+
source: await platformFs.readTextFile(frameworkPath),
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
catch (_) {
|
|
291
|
+
/* expected: framework file may not exist at this extension */
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
return null;
|
|
296
|
+
}
|
|
297
|
+
function createBatchSSRTargetCacheBusterResolver(options) {
|
|
298
|
+
const versions = new Map();
|
|
299
|
+
return (target) => {
|
|
300
|
+
const targetPath = resolveSSRImportTargetModulePath(target, options.currentModulePath);
|
|
301
|
+
let promise = versions.get(targetPath);
|
|
302
|
+
if (!promise) {
|
|
303
|
+
promise = (async () => {
|
|
304
|
+
const resolved = await readBatchTargetSource(options.projectDir, options.secureFs, targetPath);
|
|
305
|
+
if (!resolved)
|
|
306
|
+
return undefined;
|
|
307
|
+
return await sha256Short(`${resolved.path}\0${resolved.source}`);
|
|
308
|
+
})();
|
|
309
|
+
versions.set(targetPath, promise);
|
|
310
|
+
}
|
|
311
|
+
return promise;
|
|
312
|
+
};
|
|
313
|
+
}
|
|
251
314
|
/**
|
|
252
315
|
* Generate the batch bundle code
|
|
253
316
|
* Creates a module that exports all loaded modules by path
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-server.d.ts","sourceRoot":"","sources":["../../../../src/src/modules/server/module-server.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAG5E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"module-server.d.ts","sourceRoot":"","sources":["../../../../src/src/modules/server/module-server.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAG5E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AA6BtE;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAsDrD,CAAC;AAQF,MAAM,WAAW,mBAAmB;IAClC,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,6BAA6B;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,sBAAsB;IACtB,OAAO,EAAE,cAAc,CAAC;IACxB,uBAAuB;IACvB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,yDAAyD;IACzD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sFAAsF;IACtF,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,sDAAsD;AACtD,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAkVzF;AAgTD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAGrD"}
|
|
@@ -11,11 +11,12 @@ import { getApiBaseUrlEnv } from "../../config/env.js";
|
|
|
11
11
|
import { injectContext, withSpan } from "../../observability/tracing/otlp-setup.js";
|
|
12
12
|
import { injectNodePositions } from "../../transforms/plugins/babel-node-positions.js";
|
|
13
13
|
import { parseProjectDomain } from "../../server/utils/domain-parser.js";
|
|
14
|
-
import {
|
|
14
|
+
import { applySSRImportRewritesAsync, resolveSSRImportTargetModulePath, stripSSRModuleJsExtension, } from "./ssr-import-rewriter.js";
|
|
15
15
|
import { addHMRTimestamps } from "../../transforms/esm/import-rewriter.js";
|
|
16
16
|
import { FRAMEWORK_ROOT, resolveFrameworkSourcePath, } from "../../platform/compat/framework-source-resolver.js";
|
|
17
17
|
import { getReactUrls, REACT_DEFAULT_VERSION } from "../../utils/constants/cdn.js";
|
|
18
18
|
import { readLimitedCrossProjectSource } from "./cross-project-source-limit.js";
|
|
19
|
+
import { sha256Short } from "../../cache/hash.js";
|
|
19
20
|
const logger = serverLogger.component("module-server");
|
|
20
21
|
/**
|
|
21
22
|
* Embedded polyfills for compiled Deno binaries.
|
|
@@ -153,9 +154,15 @@ export function serveModule(req, options) {
|
|
|
153
154
|
try {
|
|
154
155
|
let transformedCode = await transformToESM(snippetCode, `_snippets/${hash}.tsx`, projectDir, adapter, { projectId: effectiveProjectId, dev, ssr: isSSR, reactVersion });
|
|
155
156
|
if (isSSR) {
|
|
156
|
-
transformedCode =
|
|
157
|
+
transformedCode = await applySSRImportRewritesAsync(transformedCode, {
|
|
157
158
|
projectSlug: snippetProjectSlug,
|
|
158
159
|
branch: snippetBranch,
|
|
160
|
+
resolveCacheBuster: createSSRTargetCacheBusterResolver({
|
|
161
|
+
secureFs,
|
|
162
|
+
projectDir,
|
|
163
|
+
currentModulePath: `_snippets/${hash}.js`,
|
|
164
|
+
reactVersion,
|
|
165
|
+
}),
|
|
159
166
|
});
|
|
160
167
|
}
|
|
161
168
|
logger.debug("Snippet transformed", {
|
|
@@ -215,7 +222,16 @@ export function serveModule(req, options) {
|
|
|
215
222
|
reactVersion,
|
|
216
223
|
});
|
|
217
224
|
if (isSSR) {
|
|
218
|
-
code =
|
|
225
|
+
code = await applySSRImportRewritesAsync(code, {
|
|
226
|
+
crossProjectRef: projectRef,
|
|
227
|
+
resolveCacheBuster: createSSRTargetCacheBusterResolver({
|
|
228
|
+
secureFs,
|
|
229
|
+
projectDir,
|
|
230
|
+
currentModulePath: crossPath,
|
|
231
|
+
crossProjectRef: projectRef,
|
|
232
|
+
reactVersion,
|
|
233
|
+
}),
|
|
234
|
+
});
|
|
219
235
|
}
|
|
220
236
|
return createModuleResponse(method, code, HTTP_OK, {
|
|
221
237
|
"Content-Type": "application/javascript; charset=utf-8",
|
|
@@ -303,7 +319,16 @@ export function serveModule(req, options) {
|
|
|
303
319
|
};
|
|
304
320
|
code = await transformToESM(source, sourceFile, projectDir, adapter, transformOpts);
|
|
305
321
|
if (isSSR) {
|
|
306
|
-
code =
|
|
322
|
+
code = await applySSRImportRewritesAsync(code, {
|
|
323
|
+
projectSlug,
|
|
324
|
+
branch,
|
|
325
|
+
resolveCacheBuster: createSSRTargetCacheBusterResolver({
|
|
326
|
+
secureFs,
|
|
327
|
+
projectDir,
|
|
328
|
+
currentModulePath: modulePath,
|
|
329
|
+
reactVersion,
|
|
330
|
+
}),
|
|
331
|
+
});
|
|
307
332
|
}
|
|
308
333
|
const hmrTimestamp = url.searchParams.get("t");
|
|
309
334
|
if (hmrTimestamp) {
|
|
@@ -330,6 +355,37 @@ export function serveModule(req, options) {
|
|
|
330
355
|
}
|
|
331
356
|
}, { "modules.path": url.pathname, "modules.projectSlug": options.projectSlug || "unknown" });
|
|
332
357
|
}
|
|
358
|
+
async function readSourceFileForVersion(secureFs, findResult) {
|
|
359
|
+
if (findResult.embeddedContent !== undefined)
|
|
360
|
+
return findResult.embeddedContent;
|
|
361
|
+
const platformFs = createFileSystem();
|
|
362
|
+
return findResult.isFrameworkFile
|
|
363
|
+
? await platformFs.readTextFile(findResult.path)
|
|
364
|
+
: await secureFs.readFile(findResult.path);
|
|
365
|
+
}
|
|
366
|
+
function createSSRTargetCacheBusterResolver(options) {
|
|
367
|
+
const versions = new Map();
|
|
368
|
+
return (target) => {
|
|
369
|
+
const targetPath = resolveSSRImportTargetModulePath(target, options.currentModulePath);
|
|
370
|
+
const key = `${options.crossProjectRef ?? "local"}\0${targetPath}`;
|
|
371
|
+
let promise = versions.get(key);
|
|
372
|
+
if (!promise) {
|
|
373
|
+
promise = (async () => {
|
|
374
|
+
if (options.crossProjectRef) {
|
|
375
|
+
const source = await fetchCrossProjectSource(options.crossProjectRef, targetPath);
|
|
376
|
+
return source === null ? undefined : await sha256Short(`${targetPath}\0${source}`);
|
|
377
|
+
}
|
|
378
|
+
const findResult = await findSourceFile(options.secureFs, options.projectDir, stripSSRModuleJsExtension(targetPath), options.reactVersion);
|
|
379
|
+
if (!findResult)
|
|
380
|
+
return undefined;
|
|
381
|
+
const source = await readSourceFileForVersion(options.secureFs, findResult);
|
|
382
|
+
return await sha256Short(`${findResult.path}\0${source}`);
|
|
383
|
+
})();
|
|
384
|
+
versions.set(key, promise);
|
|
385
|
+
}
|
|
386
|
+
return promise;
|
|
387
|
+
};
|
|
388
|
+
}
|
|
333
389
|
const REACT_PACKAGE_ASSET_SPECIFIERS = {
|
|
334
390
|
"react/react": "react",
|
|
335
391
|
"react/react-dom": "react-dom",
|
|
@@ -1,15 +1,27 @@
|
|
|
1
|
+
type CacheBuster = number | string;
|
|
2
|
+
export interface SSRImportRewriteTarget {
|
|
3
|
+
specifier: string;
|
|
4
|
+
kind: "alias" | "relative";
|
|
5
|
+
modulePath: string;
|
|
6
|
+
rewrittenPath: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function stripSSRModuleJsExtension(path: string): string;
|
|
9
|
+
export declare function resolveSSRImportTargetModulePath(target: SSRImportRewriteTarget, currentModulePath: string): string;
|
|
1
10
|
interface SSRRewriteOptions {
|
|
2
11
|
/** Project slug for multi-project routing */
|
|
3
12
|
projectSlug?: string | null;
|
|
4
13
|
/** Branch name for branch-aware routing */
|
|
5
14
|
branch?: string | null;
|
|
6
|
-
/** Cache buster
|
|
7
|
-
cacheBuster?:
|
|
15
|
+
/** Cache buster token. When omitted, each rewritten target gets a stable token. */
|
|
16
|
+
cacheBuster?: CacheBuster;
|
|
17
|
+
/** Resolve a cache buster token for each rewritten target. */
|
|
18
|
+
resolveCacheBuster?: (target: SSRImportRewriteTarget) => CacheBuster | null | undefined | Promise<CacheBuster | null | undefined>;
|
|
8
19
|
/** Cross-project reference (e.g., "demo@0.0") for @/ path rewrites */
|
|
9
20
|
crossProjectRef?: string;
|
|
10
21
|
/** React version to use for import rewrites */
|
|
11
22
|
reactVersion?: string;
|
|
12
23
|
}
|
|
13
24
|
export declare function applySSRImportRewrites(code: string, options?: SSRRewriteOptions): string;
|
|
25
|
+
export declare function applySSRImportRewritesAsync(code: string, options?: SSRRewriteOptions): Promise<string>;
|
|
14
26
|
export {};
|
|
15
27
|
//# sourceMappingURL=ssr-import-rewriter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssr-import-rewriter.d.ts","sourceRoot":"","sources":["../../../../src/src/modules/server/ssr-import-rewriter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ssr-import-rewriter.d.ts","sourceRoot":"","sources":["../../../../src/src/modules/server/ssr-import-rewriter.ts"],"names":[],"mappings":"AAQA,KAAK,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC;AAEnC,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,OAAO,GAAG,UAAU,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9D;AAWD,wBAAgB,gCAAgC,CAC9C,MAAM,EAAE,sBAAsB,EAC9B,iBAAiB,EAAE,MAAM,GACxB,MAAM,CAWR;AAED,UAAU,iBAAiB;IACzB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,2CAA2C;IAC3C,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,mFAAmF;IACnF,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,8DAA8D;IAC9D,kBAAkB,CAAC,EAAE,CACnB,MAAM,EAAE,sBAAsB,KAC3B,WAAW,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAC9E,sEAAsE;IACtE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,+CAA+C;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAwKD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,MAAM,CAK5F;AA+CD,wBAAsB,2BAA2B,CAC/C,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,MAAM,CAAC,CAKjB"}
|
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
import { DEFAULT_REACT_VERSION, getReactImportMap, } from "../../transforms/esm/package-registry.js";
|
|
2
2
|
import { isDeno, isNode } from "../../platform/compat/runtime.js";
|
|
3
3
|
import { getLocalReactPaths } from "../../platform/compat/react-paths.js";
|
|
4
|
+
import { hashString } from "../../cache/hash.js";
|
|
5
|
+
export function stripSSRModuleJsExtension(path) {
|
|
6
|
+
return path.replace(/\.(?:mjs|js)$/i, "");
|
|
7
|
+
}
|
|
8
|
+
function normalizeSSRModulePath(path) {
|
|
9
|
+
let normalized = path.replace(/^\/+/, "");
|
|
10
|
+
if (normalized.startsWith("_vf_modules/")) {
|
|
11
|
+
normalized = normalized.slice("_vf_modules/".length);
|
|
12
|
+
}
|
|
13
|
+
if (normalized.startsWith("@/"))
|
|
14
|
+
normalized = normalized.slice(2);
|
|
15
|
+
return normalized;
|
|
16
|
+
}
|
|
17
|
+
export function resolveSSRImportTargetModulePath(target, currentModulePath) {
|
|
18
|
+
if (target.kind === "alias")
|
|
19
|
+
return normalizeSSRModulePath(target.modulePath);
|
|
20
|
+
const currentPath = normalizeSSRModulePath(currentModulePath);
|
|
21
|
+
if (target.specifier.startsWith("/")) {
|
|
22
|
+
return normalizeSSRModulePath(target.specifier);
|
|
23
|
+
}
|
|
24
|
+
const basePath = currentPath.startsWith("/") ? currentPath : `/${currentPath}`;
|
|
25
|
+
const resolved = new URL(target.specifier, `http://veryfront.local${basePath}`).pathname;
|
|
26
|
+
return normalizeSSRModulePath(resolved);
|
|
27
|
+
}
|
|
4
28
|
function shouldKeepBareSpecifier(specifier) {
|
|
5
29
|
// npm: specifiers are only supported in Deno, not Node.js
|
|
6
30
|
// In Node.js, we need to convert them to esm.sh URLs (handled in rewriteBareImports)
|
|
@@ -56,24 +80,86 @@ function rewriteBareImports(code, version) {
|
|
|
56
80
|
return `from "https://esm.sh/${bareSpecifier}?external=react&target=es2022"`;
|
|
57
81
|
});
|
|
58
82
|
}
|
|
83
|
+
function getDefaultCacheBuster(target, options) {
|
|
84
|
+
return hashString([
|
|
85
|
+
target.kind,
|
|
86
|
+
target.modulePath,
|
|
87
|
+
target.rewrittenPath,
|
|
88
|
+
options.projectSlug ?? "",
|
|
89
|
+
options.branch ?? "",
|
|
90
|
+
options.crossProjectRef ?? "",
|
|
91
|
+
options.reactVersion ?? "",
|
|
92
|
+
].join("\0"));
|
|
93
|
+
}
|
|
94
|
+
function getCacheBusterSync(target, options) {
|
|
95
|
+
if (options.cacheBuster !== undefined)
|
|
96
|
+
return String(options.cacheBuster);
|
|
97
|
+
return getDefaultCacheBuster(target, options);
|
|
98
|
+
}
|
|
99
|
+
async function getCacheBusterAsync(target, options) {
|
|
100
|
+
if (options.cacheBuster !== undefined)
|
|
101
|
+
return String(options.cacheBuster);
|
|
102
|
+
const resolved = await options.resolveCacheBuster?.(target);
|
|
103
|
+
if (resolved !== undefined && resolved !== null)
|
|
104
|
+
return String(resolved);
|
|
105
|
+
return getDefaultCacheBuster(target, options);
|
|
106
|
+
}
|
|
107
|
+
function buildAliasRewrite(specifierPath, options) {
|
|
108
|
+
const { crossProjectRef } = options;
|
|
109
|
+
const jsPath = specifierPath.endsWith(".js") ? specifierPath : `${specifierPath}.js`;
|
|
110
|
+
if (crossProjectRef) {
|
|
111
|
+
const rewrittenPath = `/_vf_modules/_cross/${crossProjectRef}/@/${jsPath}`;
|
|
112
|
+
return {
|
|
113
|
+
target: {
|
|
114
|
+
specifier: `@/${specifierPath}`,
|
|
115
|
+
kind: "alias",
|
|
116
|
+
modulePath: jsPath,
|
|
117
|
+
rewrittenPath,
|
|
118
|
+
},
|
|
119
|
+
prefix: `${rewrittenPath}?ssr=true`,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
const rewrittenPath = `/_vf_modules/${jsPath}`;
|
|
123
|
+
return {
|
|
124
|
+
target: {
|
|
125
|
+
specifier: `@/${specifierPath}`,
|
|
126
|
+
kind: "alias",
|
|
127
|
+
modulePath: jsPath,
|
|
128
|
+
rewrittenPath,
|
|
129
|
+
},
|
|
130
|
+
prefix: `${rewrittenPath}?ssr=true`,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
function buildRelativeRewrite(specifier) {
|
|
134
|
+
return {
|
|
135
|
+
target: {
|
|
136
|
+
specifier,
|
|
137
|
+
kind: "relative",
|
|
138
|
+
modulePath: specifier,
|
|
139
|
+
rewrittenPath: specifier,
|
|
140
|
+
},
|
|
141
|
+
prefix: `${specifier}?ssr=true`,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function buildScopedParams(options) {
|
|
145
|
+
const projectParam = options.projectSlug ? `&project=${options.projectSlug}` : "";
|
|
146
|
+
const branchParam = options.branch ? `&branch=${options.branch}` : "";
|
|
147
|
+
return `${projectParam}${branchParam}`;
|
|
148
|
+
}
|
|
59
149
|
function rewritePathAliases(code, options) {
|
|
60
|
-
const
|
|
61
|
-
const projectParam = projectSlug ? `&project=${projectSlug}` : "";
|
|
62
|
-
const branchParam = branch ? `&branch=${branch}` : "";
|
|
150
|
+
const scopedParams = buildScopedParams(options);
|
|
63
151
|
return code.replace(/from\s+["']@\/([^"']+)["']/g, (_match, path) => {
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
return `from "/_vf_modules/${jsPath}?ssr=true${projectParam}${branchParam}&v=${cacheBuster}"`;
|
|
152
|
+
const { target, prefix } = buildAliasRewrite(path, options);
|
|
153
|
+
const cacheBuster = getCacheBusterSync(target, options);
|
|
154
|
+
return `from "${prefix}${scopedParams}&v=${cacheBuster}"`;
|
|
69
155
|
});
|
|
70
156
|
}
|
|
71
157
|
function rewriteRelativeImports(code, options) {
|
|
72
|
-
const
|
|
73
|
-
const projectParam = projectSlug ? `&project=${projectSlug}` : "";
|
|
74
|
-
const branchParam = branch ? `&branch=${branch}` : "";
|
|
158
|
+
const scopedParams = buildScopedParams(options);
|
|
75
159
|
return code.replace(/from\s+["']((?:\.\.?\/|\/)[^"']+\.js)["']/g, (_match, path) => {
|
|
76
|
-
|
|
160
|
+
const { target, prefix } = buildRelativeRewrite(path);
|
|
161
|
+
const cacheBuster = getCacheBusterSync(target, options);
|
|
162
|
+
return `from "${prefix}${scopedParams}&v=${cacheBuster}"`;
|
|
77
163
|
});
|
|
78
164
|
}
|
|
79
165
|
export function applySSRImportRewrites(code, options = {}) {
|
|
@@ -82,3 +168,39 @@ export function applySSRImportRewrites(code, options = {}) {
|
|
|
82
168
|
result = rewriteRelativeImports(result, options);
|
|
83
169
|
return result;
|
|
84
170
|
}
|
|
171
|
+
async function replaceAsync(code, pattern, replacer) {
|
|
172
|
+
const chunks = [];
|
|
173
|
+
let lastIndex = 0;
|
|
174
|
+
pattern.lastIndex = 0;
|
|
175
|
+
for (let match = pattern.exec(code); match; match = pattern.exec(code)) {
|
|
176
|
+
chunks.push(code.slice(lastIndex, match.index));
|
|
177
|
+
chunks.push(await replacer(match));
|
|
178
|
+
lastIndex = match.index + match[0].length;
|
|
179
|
+
}
|
|
180
|
+
chunks.push(code.slice(lastIndex));
|
|
181
|
+
return chunks.join("");
|
|
182
|
+
}
|
|
183
|
+
async function rewritePathAliasesAsync(code, options) {
|
|
184
|
+
const scopedParams = buildScopedParams(options);
|
|
185
|
+
return await replaceAsync(code, /from\s+["']@\/([^"']+)["']/g, async (match) => {
|
|
186
|
+
const path = match[1] ?? "";
|
|
187
|
+
const { target, prefix } = buildAliasRewrite(path, options);
|
|
188
|
+
const cacheBuster = await getCacheBusterAsync(target, options);
|
|
189
|
+
return `from "${prefix}${scopedParams}&v=${cacheBuster}"`;
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
async function rewriteRelativeImportsAsync(code, options) {
|
|
193
|
+
const scopedParams = buildScopedParams(options);
|
|
194
|
+
return await replaceAsync(code, /from\s+["']((?:\.\.?\/|\/)[^"']+\.js)["']/g, async (match) => {
|
|
195
|
+
const path = match[1] ?? "";
|
|
196
|
+
const { target, prefix } = buildRelativeRewrite(path);
|
|
197
|
+
const cacheBuster = await getCacheBusterAsync(target, options);
|
|
198
|
+
return `from "${prefix}${scopedParams}&v=${cacheBuster}"`;
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
export async function applySSRImportRewritesAsync(code, options = {}) {
|
|
202
|
+
let result = rewriteBareImports(code, options.reactVersion);
|
|
203
|
+
result = await rewritePathAliasesAsync(result, options);
|
|
204
|
+
result = await rewriteRelativeImportsAsync(result, options);
|
|
205
|
+
return result;
|
|
206
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-context.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/context/render-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0CAA0C,CAAC;AAEhF,OAAO,EAIL,mBAAmB,EACpB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,YAAY,CAAC;AAEzD,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,eAAe,CAAC;IACxB,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;IACnC,OAAO,EAAE,cAAc,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,iBAAiB,CAAC;IAC/B,2GAA2G;IAC3G,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,0BAA0B;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,cAAc,EACnB,OAAO,CAAC,EAAE,0BAA0B,GACnC,aAAa,CA4Cf;
|
|
1
|
+
{"version":3,"file":"render-context.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/context/render-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0CAA0C,CAAC;AAEhF,OAAO,EAIL,mBAAmB,EACpB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,YAAY,CAAC;AAEzD,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,eAAe,CAAC;IACxB,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;IACnC,OAAO,EAAE,cAAc,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,iBAAiB,CAAC;IAC/B,2GAA2G;IAC3G,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,0BAA0B;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,cAAc,EACnB,OAAO,CAAC,EAAE,0BAA0B,GACnC,aAAa,CA4Cf;AAoBD,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,eAAe,EACzB,OAAO,CAAC,EAAE,0BAA0B,GACnC,aAAa,CA8Bf;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAE7E;AAED,eAAO,MAAM,aAAa,4BAAsB,CAAC;AAEjD,wBAAgB,YAAY,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,aAAa,GAAG,OAAO,CAExE"}
|
|
@@ -40,8 +40,14 @@ export function createRenderContext(ctx, options) {
|
|
|
40
40
|
function getReleaseKey(isLocal, environment, branch, releaseId) {
|
|
41
41
|
if (isLocal)
|
|
42
42
|
return branch ?? "main";
|
|
43
|
-
if (environment === "production")
|
|
43
|
+
if (environment === "production") {
|
|
44
|
+
if (!releaseId) {
|
|
45
|
+
throw INVALID_ARGUMENT.create({
|
|
46
|
+
detail: "Production requires releaseId for cache isolation",
|
|
47
|
+
});
|
|
48
|
+
}
|
|
44
49
|
return releaseId;
|
|
50
|
+
}
|
|
45
51
|
return branch ?? "main";
|
|
46
52
|
}
|
|
47
53
|
export function createRenderContextFromEnriched(enriched, options) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"enriched-context.d.ts","sourceRoot":"","sources":["../../../../src/src/server/context/enriched-context.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,2BAA2B,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAChG,YAAY,EACV,2BAA2B,EAC3B,eAAe,EACf,WAAW,GACZ,MAAM,6BAA6B,CAAC;AAErC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,2BAA2B,GAAG,eAAe,
|
|
1
|
+
{"version":3,"file":"enriched-context.d.ts","sourceRoot":"","sources":["../../../../src/src/server/context/enriched-context.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,2BAA2B,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAChG,YAAY,EACV,2BAA2B,EAC3B,eAAe,EACf,WAAW,GACZ,MAAM,6BAA6B,CAAC;AAErC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,2BAA2B,GAAG,eAAe,CA8C1F;AAMD,wBAAgB,kCAAkC,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAK/E"}
|
|
@@ -4,9 +4,21 @@ export function buildEnrichedContext(options) {
|
|
|
4
4
|
if (!options.contentSourceId) {
|
|
5
5
|
throw INVALID_ARGUMENT.create({ detail: `Missing contentSourceId for ${options.projectSlug}` });
|
|
6
6
|
}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
let releaseKey;
|
|
8
|
+
if (options.isLocalProject) {
|
|
9
|
+
releaseKey = options.branch ?? "main";
|
|
10
|
+
}
|
|
11
|
+
else if (options.environment === "production") {
|
|
12
|
+
if (!options.releaseId) {
|
|
13
|
+
throw INVALID_ARGUMENT.create({
|
|
14
|
+
detail: "Production requires releaseId for cache isolation",
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
releaseKey = options.releaseId;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
releaseKey = options.branch ?? "main";
|
|
21
|
+
}
|
|
10
22
|
return {
|
|
11
23
|
projectId: options.projectId,
|
|
12
24
|
projectSlug: options.projectSlug,
|
|
@@ -13,7 +13,7 @@ function discoveryKey(ctx) {
|
|
|
13
13
|
const environment = ctx.enriched?.environment ?? ctx.resolvedEnvironment ??
|
|
14
14
|
(ctx.releaseId ? "production" : "preview");
|
|
15
15
|
if (environment === "production") {
|
|
16
|
-
return `${slug}:release:${ctx.releaseId
|
|
16
|
+
return ctx.releaseId ? `${slug}:release:${ctx.releaseId}` : `${slug}:production:unreleased`;
|
|
17
17
|
}
|
|
18
18
|
const branch = ctx.requestContext?.branch ?? ctx.enriched?.branch ?? ctx.parsedDomain?.branch ??
|
|
19
19
|
"main";
|
|
@@ -26,7 +26,7 @@ function shouldCacheCompletedDiscovery(ctx) {
|
|
|
26
26
|
}
|
|
27
27
|
const environment = ctx.enriched?.environment ?? ctx.resolvedEnvironment ??
|
|
28
28
|
(ctx.releaseId ? "production" : "preview");
|
|
29
|
-
return environment === "production";
|
|
29
|
+
return environment === "production" && !!ctx.releaseId;
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
32
32
|
* Run primitive discovery (agents, tools) for a project if not already done.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../../src/src/skill/executor.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AA4EnG;;GAEG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAqBrF;AAED;;GAEG;AACH,qBAAa,mBAAoB,YAAW,mBAAmB;IACvD,OAAO,CAAC,KAAK,EAAE,wBAAwB,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAsB3E;
|
|
1
|
+
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../../src/src/skill/executor.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AA4EnG;;GAEG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAqBrF;AAED;;GAEG;AACH,qBAAa,mBAAoB,YAAW,mBAAmB;IACvD,OAAO,CAAC,KAAK,EAAE,wBAAwB,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAsB3E;AAgED;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,mBAAmB,CAE5D"}
|
|
@@ -149,6 +149,9 @@ class CloudScriptExecutor {
|
|
|
149
149
|
const commandPromise = sandbox.executeCommand(cmdString);
|
|
150
150
|
const result = await withTimeout(commandPromise, timeoutMs);
|
|
151
151
|
if (result === TIMEOUT_SENTINEL) {
|
|
152
|
+
commandPromise.catch(() => {
|
|
153
|
+
// The command may reject after the timeout path has already returned.
|
|
154
|
+
});
|
|
152
155
|
// Kill any running processes before returning — withTimeout only
|
|
153
156
|
// races the timer, it doesn't terminate the sandbox command.
|
|
154
157
|
try {
|