veryfront 0.1.1152 → 0.1.1153
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/platform/adapters/base.d.ts +10 -0
- package/esm/src/platform/adapters/base.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/adapter.d.ts +15 -0
- package/esm/src/platform/adapters/fs/veryfront/adapter.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/adapter.js +181 -17
- package/esm/src/platform/adapters/fs/veryfront/default-invalidation-callbacks.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/default-invalidation-callbacks.js +12 -7
- package/esm/src/platform/adapters/fs/veryfront/multi-project-adapter.d.ts +2 -0
- package/esm/src/platform/adapters/fs/veryfront/multi-project-adapter.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/multi-project-adapter.js +28 -0
- package/esm/src/platform/adapters/fs/veryfront/types.d.ts +10 -7
- package/esm/src/platform/adapters/fs/veryfront/types.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/websocket-manager.d.ts +3 -10
- package/esm/src/platform/adapters/fs/veryfront/websocket-manager.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/websocket-manager.js +39 -17
- package/esm/src/platform/adapters/fs/wrapper.d.ts +2 -0
- package/esm/src/platform/adapters/fs/wrapper.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/wrapper.js +8 -0
- package/esm/src/rendering/app-route-resolver.js +17 -19
- package/esm/src/rendering/router-detection.js +41 -10
- package/esm/src/server/handlers/request/agent-stream.handler.d.ts.map +1 -1
- package/esm/src/server/handlers/request/agent-stream.handler.js +1 -0
- package/esm/src/server/handlers/request/api/api-handler-wrapper.d.ts +1 -0
- package/esm/src/server/handlers/request/api/api-handler-wrapper.d.ts.map +1 -1
- package/esm/src/server/handlers/request/api/api-handler-wrapper.js +37 -3
- package/esm/src/server/handlers/request/api/pages-api-handler.d.ts +7 -1
- package/esm/src/server/handlers/request/api/pages-api-handler.d.ts.map +1 -1
- package/esm/src/server/handlers/request/api/pages-api-handler.js +26 -10
- package/esm/src/server/handlers/request/api/project-discovery.d.ts +6 -0
- package/esm/src/server/handlers/request/api/project-discovery.d.ts.map +1 -1
- package/esm/src/server/handlers/request/api/project-discovery.js +43 -11
- package/esm/src/server/runtime-handler/adapter-factory.d.ts.map +1 -1
- package/esm/src/server/runtime-handler/adapter-factory.js +10 -8
- package/esm/src/types/entities/getEntityInfo.js +0 -15
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +5 -5
|
@@ -506,32 +506,45 @@ export class WebSocketManager {
|
|
|
506
506
|
parentDirs: Array.from(parentDirs),
|
|
507
507
|
prefixes: ["file:", "stat:", "dir:"],
|
|
508
508
|
});
|
|
509
|
-
this.deps.invalidationCallbacks.invalidateModulePaths?.(changedPaths);
|
|
510
509
|
const projectId = this.deps.client.getProjectId();
|
|
510
|
+
const invalidations = [
|
|
511
|
+
this.deps.invalidationCallbacks.invalidateModulePaths?.(changedPaths),
|
|
512
|
+
];
|
|
511
513
|
logger.debug("Clearing SSR module cache for HMR", {
|
|
512
514
|
changedPaths,
|
|
513
515
|
projectId,
|
|
514
516
|
usePerProject: !!this.deps.invalidationCallbacks.clearSSRModuleCacheForProject,
|
|
515
517
|
});
|
|
516
518
|
if (this.deps.invalidationCallbacks.clearSSRModuleCacheForProject && projectId) {
|
|
517
|
-
this.deps.invalidationCallbacks.clearSSRModuleCacheForProject(projectId);
|
|
519
|
+
invalidations.push(this.deps.invalidationCallbacks.clearSSRModuleCacheForProject(projectId));
|
|
518
520
|
}
|
|
519
521
|
else {
|
|
520
|
-
this.deps.invalidationCallbacks.clearSSRModuleCache?.();
|
|
522
|
+
invalidations.push(this.deps.invalidationCallbacks.clearSSRModuleCache?.());
|
|
523
|
+
}
|
|
524
|
+
if (projectId) {
|
|
525
|
+
if (this.deps.invalidationCallbacks.clearRouterDetectionCacheForProject) {
|
|
526
|
+
invalidations.push(this.deps.invalidationCallbacks.clearRouterDetectionCacheForProject(projectId));
|
|
527
|
+
}
|
|
528
|
+
if (this.deps.invalidationCallbacks.clearProjectDiscoveryCacheForProject) {
|
|
529
|
+
invalidations.push(this.deps.invalidationCallbacks.clearProjectDiscoveryCacheForProject(projectId));
|
|
530
|
+
}
|
|
521
531
|
}
|
|
522
532
|
if (this.deps.invalidationCallbacks.clearRendererCacheForProject && projectId) {
|
|
523
|
-
|
|
533
|
+
invalidations.push(this.deps.invalidationCallbacks.clearRendererCacheForProject(projectId));
|
|
524
534
|
}
|
|
525
535
|
if (this.deps.invalidationCallbacks.clearProjectCSSCache && this.deps.projectSlug) {
|
|
526
|
-
this.deps.invalidationCallbacks.clearProjectCSSCache(this.deps.projectSlug);
|
|
536
|
+
invalidations.push(this.deps.invalidationCallbacks.clearProjectCSSCache(this.deps.projectSlug));
|
|
537
|
+
}
|
|
538
|
+
const pendingInvalidations = invalidations.filter((invalidation) => invalidation !== undefined);
|
|
539
|
+
if (pendingInvalidations.length > 0) {
|
|
540
|
+
await Promise.all(pendingInvalidations);
|
|
527
541
|
}
|
|
528
542
|
if (contentContext?.sourceType === "branch") {
|
|
529
543
|
await this.deps.cache.deleteByPrefixAsync("files:branch:");
|
|
530
544
|
try {
|
|
531
545
|
const files = await this.deps.client.listAllFiles();
|
|
532
546
|
const cacheKey = buildFileListCacheKey(contentContext);
|
|
533
|
-
await this.deps.
|
|
534
|
-
this.deps.clearFileListIndex();
|
|
547
|
+
await this.deps.replaceSourceSnapshot(cacheKey, files);
|
|
535
548
|
preparedStyleArtifact = await this.deps.pregenerateStyles?.(files);
|
|
536
549
|
logger.debug("Fresh files cached (memory + Redis)", {
|
|
537
550
|
cacheKey,
|
|
@@ -597,24 +610,34 @@ export class WebSocketManager {
|
|
|
597
610
|
this.deps.clearMemoryCaches();
|
|
598
611
|
this.deps.invalidationCallbacks.clearDomainCache?.();
|
|
599
612
|
const projectId = this.deps.client.getProjectId();
|
|
613
|
+
const invalidations = [];
|
|
600
614
|
if (this.deps.invalidationCallbacks.clearSSRModuleCacheForProject && projectId) {
|
|
601
|
-
this.deps.invalidationCallbacks.clearSSRModuleCacheForProject(projectId);
|
|
615
|
+
invalidations.push(this.deps.invalidationCallbacks.clearSSRModuleCacheForProject(projectId));
|
|
602
616
|
}
|
|
603
617
|
else {
|
|
604
|
-
this.deps.invalidationCallbacks.clearSSRModuleCache?.();
|
|
618
|
+
invalidations.push(this.deps.invalidationCallbacks.clearSSRModuleCache?.());
|
|
605
619
|
}
|
|
606
|
-
if (
|
|
607
|
-
this.deps.invalidationCallbacks.clearRouterDetectionCacheForProject
|
|
620
|
+
if (projectId) {
|
|
621
|
+
if (this.deps.invalidationCallbacks.clearRouterDetectionCacheForProject) {
|
|
622
|
+
invalidations.push(this.deps.invalidationCallbacks.clearRouterDetectionCacheForProject(projectId));
|
|
623
|
+
}
|
|
624
|
+
if (this.deps.invalidationCallbacks.clearProjectDiscoveryCacheForProject) {
|
|
625
|
+
invalidations.push(this.deps.invalidationCallbacks.clearProjectDiscoveryCacheForProject(projectId));
|
|
626
|
+
}
|
|
608
627
|
}
|
|
609
|
-
this.deps.invalidationCallbacks.clearModulePathCache?.();
|
|
628
|
+
invalidations.push(this.deps.invalidationCallbacks.clearModulePathCache?.());
|
|
610
629
|
if (this.deps.invalidationCallbacks.clearSnippetCacheForProject && this.deps.projectSlug) {
|
|
611
|
-
this.deps.invalidationCallbacks.clearSnippetCacheForProject(this.deps.projectSlug);
|
|
630
|
+
invalidations.push(this.deps.invalidationCallbacks.clearSnippetCacheForProject(this.deps.projectSlug));
|
|
612
631
|
}
|
|
613
632
|
if (this.deps.invalidationCallbacks.clearRendererCacheForProject && projectId) {
|
|
614
|
-
|
|
633
|
+
invalidations.push(this.deps.invalidationCallbacks.clearRendererCacheForProject(projectId));
|
|
615
634
|
}
|
|
616
635
|
if (this.deps.invalidationCallbacks.clearProjectCSSCache && this.deps.projectSlug) {
|
|
617
|
-
this.deps.invalidationCallbacks.clearProjectCSSCache(this.deps.projectSlug);
|
|
636
|
+
invalidations.push(this.deps.invalidationCallbacks.clearProjectCSSCache(this.deps.projectSlug));
|
|
637
|
+
}
|
|
638
|
+
const pendingInvalidations = invalidations.filter((invalidation) => invalidation !== undefined);
|
|
639
|
+
if (pendingInvalidations.length > 0) {
|
|
640
|
+
await Promise.all(pendingInvalidations);
|
|
618
641
|
}
|
|
619
642
|
const totalFileCount = fileBranchCount + fileReleaseCount + fileEnvCount;
|
|
620
643
|
const totalStatCount = statBranchCount + statReleaseCount + statEnvCount;
|
|
@@ -630,8 +653,7 @@ export class WebSocketManager {
|
|
|
630
653
|
try {
|
|
631
654
|
const files = await this.deps.client.listAllFiles();
|
|
632
655
|
const cacheKey = buildFileListCacheKey(contentContext);
|
|
633
|
-
await this.deps.
|
|
634
|
-
this.deps.clearFileListIndex();
|
|
656
|
+
await this.deps.replaceSourceSnapshot(cacheKey, files);
|
|
635
657
|
preparedStyleArtifact = await this.deps.pregenerateStyles?.(files);
|
|
636
658
|
logger.debug("FRESH FILES FETCHED", {
|
|
637
659
|
cacheKey,
|
|
@@ -35,6 +35,8 @@ export declare class NotSupportedError extends Error {
|
|
|
35
35
|
export declare class FSAdapterWrapper implements ExtendedFileSystemAdapter {
|
|
36
36
|
private readonly _fsAdapter;
|
|
37
37
|
readonly refreshSourceSnapshot?: (reason?: string) => Promise<void>;
|
|
38
|
+
readonly ensureSourceSnapshotFresh?: (reason?: string) => Promise<void>;
|
|
39
|
+
readonly getSourceSnapshotVersion?: () => number | undefined | Promise<number | undefined>;
|
|
38
40
|
constructor(fsAdapter: FSAdapter);
|
|
39
41
|
getUnderlyingAdapter(): FSAdapter;
|
|
40
42
|
getAdapterType(): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrapper.d.ts","sourceRoot":"","sources":["../../../../../src/src/platform/adapters/fs/wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,QAAQ,EACR,QAAQ,EACR,iBAAiB,EACjB,WAAW,EACX,kBAAkB,EAClB,YAAY,EACb,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAuB,cAAc,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE3F,MAAM,WAAW,yBAA0B,SAAQ,iBAAiB;IAClE,oBAAoB,IAAI,SAAS,CAAC;IAClC,cAAc,IAAI,MAAM,CAAC;IACzB,kBAAkB,IAAI,OAAO,CAAC;IAC9B,kBAAkB,IAAI,OAAO,CAAC;IAC9B,gBAAgB,IAAI,OAAO,CAAC;IAC5B,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,iBAAiB,IAAI,IAAI,CAAC;IAC1B,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;IAC9C,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAAC;IAClC,kBAAkB,IAAI,IAAI,CAAC;IAC3B,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;IACrE,cAAc,CAAC,CAAC,EACd,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE;QACR,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KACjC,GACA,OAAO,CAAC,CAAC,CAAC,CAAC;IACd,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACjD,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IACjD,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,iBAAiB,GAAG,EAAE,IAAI,yBAAyB,CAE1F;AAYD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,iBAAiB,GAAG,OAAO,CAKlE;AAED,qBAAa,iBAAkB,SAAQ,KAAK;gBAC9B,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM;CAQpD;AAMD,qBAAa,gBAAiB,YAAW,yBAAyB;IAChE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAY;IACvC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"wrapper.d.ts","sourceRoot":"","sources":["../../../../../src/src/platform/adapters/fs/wrapper.ts"],"names":[],"mappings":"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"}
|
|
@@ -37,11 +37,19 @@ function isContextualAdapter(adapter) {
|
|
|
37
37
|
export class FSAdapterWrapper {
|
|
38
38
|
_fsAdapter;
|
|
39
39
|
refreshSourceSnapshot;
|
|
40
|
+
ensureSourceSnapshotFresh;
|
|
41
|
+
getSourceSnapshotVersion;
|
|
40
42
|
constructor(fsAdapter) {
|
|
41
43
|
this._fsAdapter = fsAdapter;
|
|
42
44
|
if (typeof fsAdapter.refreshSourceSnapshot === "function") {
|
|
43
45
|
this.refreshSourceSnapshot = (reason) => fsAdapter.refreshSourceSnapshot.call(fsAdapter, reason);
|
|
44
46
|
}
|
|
47
|
+
if (typeof fsAdapter.ensureSourceSnapshotFresh === "function") {
|
|
48
|
+
this.ensureSourceSnapshotFresh = (reason) => fsAdapter.ensureSourceSnapshotFresh.call(fsAdapter, reason);
|
|
49
|
+
}
|
|
50
|
+
if (typeof fsAdapter.getSourceSnapshotVersion === "function") {
|
|
51
|
+
this.getSourceSnapshotVersion = () => fsAdapter.getSourceSnapshotVersion.call(fsAdapter);
|
|
52
|
+
}
|
|
45
53
|
}
|
|
46
54
|
getUnderlyingAdapter() {
|
|
47
55
|
return this._fsAdapter;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* - Dynamic segment matching ([id], [...slug], etc.)
|
|
7
7
|
* - Page file loading with frontmatter extraction
|
|
8
8
|
*/
|
|
9
|
-
import { isDynamicSegment } from "../utils/route-path-utils.js";
|
|
9
|
+
import { isCatchAllSegment, isDynamicSegment } from "../utils/route-path-utils.js";
|
|
10
10
|
import { join } from "../platform/compat/path/index.js";
|
|
11
11
|
import { extract } from "../platform/compat/std/front-matter-yaml.js";
|
|
12
12
|
export async function getAppRouteEntity(projectDir, slug, adapter, appDirName = "app") {
|
|
@@ -53,22 +53,11 @@ async function tryDynamicMatch(projectDir, slug, adapter, appDirName) {
|
|
|
53
53
|
const segments = slug ? slug.split("/").filter(Boolean) : [];
|
|
54
54
|
let currentDir = join(projectDir, appDirName);
|
|
55
55
|
for (const segment of segments) {
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
const stat = await adapter.fs.stat(exactPath);
|
|
59
|
-
if (stat.isDirectory) {
|
|
60
|
-
currentDir = exactPath;
|
|
61
|
-
continue;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
catch (_) {
|
|
65
|
-
/* expected: exact path may not exist, try dynamic segments */
|
|
66
|
-
}
|
|
67
|
-
const dynamic = await findDynamicDir(currentDir, adapter);
|
|
68
|
-
if (!dynamic)
|
|
56
|
+
const routeDirectory = await findRouteDirectory(currentDir, segment, adapter);
|
|
57
|
+
if (!routeDirectory)
|
|
69
58
|
return null;
|
|
70
|
-
currentDir = join(currentDir,
|
|
71
|
-
if (
|
|
59
|
+
currentDir = join(currentDir, routeDirectory.name);
|
|
60
|
+
if (routeDirectory.isCatchAll)
|
|
72
61
|
break;
|
|
73
62
|
}
|
|
74
63
|
for (const ext of [".mdx", ".md", ".tsx", ".jsx", ".ts", ".js"]) {
|
|
@@ -79,14 +68,23 @@ async function tryDynamicMatch(projectDir, slug, adapter, appDirName) {
|
|
|
79
68
|
}
|
|
80
69
|
return null;
|
|
81
70
|
}
|
|
82
|
-
async function
|
|
71
|
+
async function findRouteDirectory(dir, segment, adapter) {
|
|
83
72
|
try {
|
|
84
73
|
const entries = await adapter.fs.readDir(dir);
|
|
74
|
+
let dynamic = null;
|
|
85
75
|
for await (const entry of entries) {
|
|
86
|
-
if (!entry.isDirectory
|
|
76
|
+
if (!entry.isDirectory && !entry.isSymlink)
|
|
87
77
|
continue;
|
|
88
|
-
|
|
78
|
+
if (entry.name === segment)
|
|
79
|
+
return { name: entry.name, isCatchAll: false };
|
|
80
|
+
if (!dynamic && isDynamicSegment(entry.name)) {
|
|
81
|
+
dynamic = {
|
|
82
|
+
name: entry.name,
|
|
83
|
+
isCatchAll: isCatchAllSegment(entry.name),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
89
86
|
}
|
|
87
|
+
return dynamic;
|
|
90
88
|
}
|
|
91
89
|
catch (_) {
|
|
92
90
|
/* expected: adapter.fs.readDir may fail for npm compatibility */
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* - Directory structure analysis
|
|
7
7
|
* - Route file presence detection
|
|
8
8
|
**************************/
|
|
9
|
-
import { isAbsolute, join, normalize, relative } from "../platform/compat/path/index.js";
|
|
9
|
+
import { basename, dirname, 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";
|
|
@@ -113,14 +113,12 @@ export async function detectAppRouter(projectDir, config, adapter, options) {
|
|
|
113
113
|
async function detectAppRouterImpl(projectDir, config, adapter) {
|
|
114
114
|
const appDirName = config?.directories?.app ?? "app";
|
|
115
115
|
const pagesDirName = config?.directories?.pages ?? "pages";
|
|
116
|
-
const appDir = join(projectDir, appDirName);
|
|
117
|
-
const pagesDir = join(projectDir, pagesDirName);
|
|
118
|
-
const [
|
|
119
|
-
|
|
120
|
-
|
|
116
|
+
const appDir = normalize(join(projectDir, appDirName));
|
|
117
|
+
const pagesDir = normalize(join(projectDir, pagesDirName));
|
|
118
|
+
const [hasAppDir, hasPagesDir] = await Promise.all([
|
|
119
|
+
directoryExists(appDir, projectDir, adapter),
|
|
120
|
+
directoryExists(pagesDir, projectDir, adapter),
|
|
121
121
|
]);
|
|
122
|
-
const hasAppDir = Boolean(appStat?.isDirectory);
|
|
123
|
-
const hasPagesDir = Boolean(pagesStat?.isDirectory);
|
|
124
122
|
if (hasAppDir && (await hasRouteFiles(appDir, adapter)))
|
|
125
123
|
return true;
|
|
126
124
|
if (hasPagesDir && (await hasRouteFiles(pagesDir, adapter)))
|
|
@@ -131,7 +129,23 @@ async function detectAppRouterImpl(projectDir, config, adapter) {
|
|
|
131
129
|
}
|
|
132
130
|
const ROUTE_EXTENSIONS = new Set([".mdx", ".md", ".tsx", ".jsx", ".ts", ".js"]);
|
|
133
131
|
const ROUTE_PATTERNS = ["page", "layout", "error", "loading", "not-found", "index"];
|
|
134
|
-
async function
|
|
132
|
+
async function resolveTraversalKey(dir, adapter, requireCanonicalPath) {
|
|
133
|
+
if (!adapter.fs.realPath) {
|
|
134
|
+
return requireCanonicalPath ? null : normalize(dir);
|
|
135
|
+
}
|
|
136
|
+
try {
|
|
137
|
+
return normalize(await adapter.fs.realPath(dir));
|
|
138
|
+
}
|
|
139
|
+
catch (_) {
|
|
140
|
+
/* expected: virtual adapters may not resolve physical paths */
|
|
141
|
+
return requireCanonicalPath ? null : normalize(dir);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
async function hasRouteFiles(dir, adapter, visited = new Set(), requireCanonicalPath = false) {
|
|
145
|
+
const traversalKey = await resolveTraversalKey(dir, adapter, requireCanonicalPath);
|
|
146
|
+
if (traversalKey === null || visited.has(traversalKey))
|
|
147
|
+
return false;
|
|
148
|
+
visited.add(traversalKey);
|
|
135
149
|
const entries = await readDirWithFallback(dir, adapter);
|
|
136
150
|
for (const entry of entries) {
|
|
137
151
|
if (entry.isFile) {
|
|
@@ -143,7 +157,12 @@ async function hasRouteFiles(dir, adapter) {
|
|
|
143
157
|
}
|
|
144
158
|
continue;
|
|
145
159
|
}
|
|
146
|
-
if (entry.isDirectory &&
|
|
160
|
+
if (entry.isDirectory &&
|
|
161
|
+
(await hasRouteFiles(join(dir, entry.name), adapter, visited))) {
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
if (entry.isSymlink &&
|
|
165
|
+
(await hasRouteFiles(join(dir, entry.name), adapter, visited, true))) {
|
|
147
166
|
return true;
|
|
148
167
|
}
|
|
149
168
|
}
|
|
@@ -164,6 +183,18 @@ async function withAdapterFallback(adapterFn, fallbackFn, defaultValue) {
|
|
|
164
183
|
}
|
|
165
184
|
}
|
|
166
185
|
}
|
|
186
|
+
async function directoryExists(path, projectDir, adapter) {
|
|
187
|
+
if (normalize(path) === normalize(projectDir))
|
|
188
|
+
return true;
|
|
189
|
+
const parentEntries = await readDirWithFallback(dirname(path), adapter);
|
|
190
|
+
const directoryName = basename(path);
|
|
191
|
+
const listed = parentEntries.some((entry) => entry.name === directoryName && (entry.isDirectory || entry.isSymlink));
|
|
192
|
+
if (listed || adapter.id !== "cloudflare")
|
|
193
|
+
return listed;
|
|
194
|
+
// Cloudflare KV represents directories only as key prefixes, so its parent
|
|
195
|
+
// listing can omit a directory that stat can still resolve.
|
|
196
|
+
return Boolean((await statWithFallback(path, adapter))?.isDirectory);
|
|
197
|
+
}
|
|
167
198
|
async function statWithFallback(path, adapter) {
|
|
168
199
|
const fs = createFileSystem();
|
|
169
200
|
return await withAdapterFallback(async () => (await adapter.fs.stat(path)), async () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-stream.handler.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/request/agent-stream.handler.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AAGpF,OAAO,EAEL,KAAK,+BAA+B,EACrC,MAAM,wCAAwC,CAAC;AAchD,OAAO,EACL,4BAA4B,EAE7B,MAAM,2CAA2C,CAAC;AA0BnD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAmB,aAAa,EAAE,MAAM,aAAa,CAAC;AAkBnG,MAAM,WAAW,sBACf,SAAQ,yBAAyB,EAAE,+BAA+B;IAClE,4BAA4B,CAAC,EAAE,OAAO,4BAA4B,CAAC;IACnE,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,+BAA+B,CAAC,YAAY,CAAC,CAAC;CACpF;
|
|
1
|
+
{"version":3,"file":"agent-stream.handler.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/request/agent-stream.handler.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AAGpF,OAAO,EAEL,KAAK,+BAA+B,EACrC,MAAM,wCAAwC,CAAC;AAchD,OAAO,EACL,4BAA4B,EAE7B,MAAM,2CAA2C,CAAC;AA0BnD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAmB,aAAa,EAAE,MAAM,aAAa,CAAC;AAkBnG,MAAM,WAAW,sBACf,SAAQ,yBAAyB,EAAE,+BAA+B;IAClE,4BAA4B,CAAC,EAAE,OAAO,4BAA4B,CAAC;IACnE,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,+BAA+B,CAAC,YAAY,CAAC,CAAC;CACpF;AAwgBD,qBAAa,kBAAmB,SAAQ,WAAW;IASrC,OAAO,CAAC,QAAQ,CAAC,IAAI;IARjC,QAAQ,EAAE,eAAe,CAMvB;gBAE2B,IAAI,GAAE,sBAAoC;IAIvE,OAAO,CAAC,sBAAsB;IAsBxB,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;CA6NxE"}
|
|
@@ -232,6 +232,7 @@ async function resolveAgentSourceConfig(ctx, sourceContext) {
|
|
|
232
232
|
if (!cacheKey) {
|
|
233
233
|
throw new Error("Explicit agent source requires a project identity");
|
|
234
234
|
}
|
|
235
|
+
await ctx.adapter.fs.ensureSourceSnapshotFresh?.("agent-source-config");
|
|
235
236
|
return await getConfig(ctx.projectDir, ctx.adapter, {
|
|
236
237
|
cacheKey,
|
|
237
238
|
sourceContext: buildAgentSourceRunOptions(sourceContext),
|
|
@@ -9,5 +9,6 @@ export declare class ApiHandlerWrapper extends BaseHandler {
|
|
|
9
9
|
initialize(): Promise<void>;
|
|
10
10
|
handle(req: Request, ctx: HandlerContext): Promise<HandlerResult>;
|
|
11
11
|
private handleWithContext;
|
|
12
|
+
private isPageRequest;
|
|
12
13
|
}
|
|
13
14
|
//# sourceMappingURL=api-handler-wrapper.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-handler-wrapper.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/handlers/request/api/api-handler-wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EAEf,aAAa,EACd,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"api-handler-wrapper.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/handlers/request/api/api-handler-wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EAEf,aAAa,EACd,MAAM,gBAAgB,CAAC;AA2BxB,qBAAa,iBAAkB,SAAQ,WAAW;IAChD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAiE;IAChF,OAAO,CAAC,WAAW,CAA8B;IAEjD,QAAQ,EAAE,eAAe,CAGvB;gBAGA,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,OAAO,uCAAuC,EAAE,cAAc;IAOnE,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAW3B,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;YAmDzD,iBAAiB;YAkFjB,aAAa;CAuB5B"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { BaseHandler } from "../../response/base.js";
|
|
2
|
-
import { getApiHandler, withApiHandler } from "./pages-api-handler.js";
|
|
2
|
+
import { ensurePreviewSourceSnapshotFresh, getApiHandler, withApiHandler, } from "./pages-api-handler.js";
|
|
3
3
|
import { PRIORITY_MEDIUM_API } from "../../../../utils/constants/index.js";
|
|
4
4
|
import { withSpan } from "../../../../observability/tracing/otlp-setup.js";
|
|
5
5
|
import { ensureProjectDiscovery } from "./project-discovery.js";
|
|
6
|
+
import { PageResolver } from "../../../../rendering/page-resolution/page-resolver.js";
|
|
6
7
|
export class ApiHandlerWrapper extends BaseHandler {
|
|
7
8
|
projectDir;
|
|
8
9
|
adapter;
|
|
@@ -54,13 +55,27 @@ export class ApiHandlerWrapper extends BaseHandler {
|
|
|
54
55
|
environmentName: ctx.environmentName,
|
|
55
56
|
});
|
|
56
57
|
}
|
|
57
|
-
handleWithContext(req, ctx, pathname) {
|
|
58
|
+
async handleWithContext(req, ctx, pathname) {
|
|
58
59
|
return withSpan("api.handleWithContext", async () => {
|
|
59
60
|
try {
|
|
61
|
+
// WebSocket pokes update mutable previews immediately. This bounded,
|
|
62
|
+
// coalesced check is the fallback for missed pokes and establishes
|
|
63
|
+
// one source snapshot for route and primitive discovery.
|
|
64
|
+
await ensurePreviewSourceSnapshotFresh(ctx);
|
|
65
|
+
const canResolveAsPage = pathname !== "/api" &&
|
|
66
|
+
!pathname.startsWith("/api/") &&
|
|
67
|
+
(req.method === "GET" || req.method === "HEAD");
|
|
68
|
+
let isPageRequest = false;
|
|
69
|
+
if (canResolveAsPage) {
|
|
70
|
+
isPageRequest = await this.isPageRequest(pathname, ctx);
|
|
71
|
+
}
|
|
72
|
+
if (isPageRequest) {
|
|
73
|
+
return this.continue();
|
|
74
|
+
}
|
|
60
75
|
// Lazy per-project primitive discovery (agents, tools) on first access.
|
|
61
76
|
// Must run within runWithContext so VFS and registry scope are correct.
|
|
62
77
|
await ensureProjectDiscovery(ctx);
|
|
63
|
-
const apiRes = await withApiHandler(ctx, (api) => api.handle(req, ctx));
|
|
78
|
+
const apiRes = await withApiHandler(ctx, (api) => api.handle(req, ctx), { sourceSnapshotReady: true });
|
|
64
79
|
if (!apiRes) {
|
|
65
80
|
this.logDebug("[API-Wrapper] API handler returned null, continuing to next handler", { pathname }, ctx);
|
|
66
81
|
return this.continue();
|
|
@@ -88,4 +103,23 @@ export class ApiHandlerWrapper extends BaseHandler {
|
|
|
88
103
|
"api.projectSlug": ctx.projectSlug ?? "unknown",
|
|
89
104
|
});
|
|
90
105
|
}
|
|
106
|
+
async isPageRequest(pathname, ctx) {
|
|
107
|
+
const slug = pathname === "/" ? "" : pathname.replace(/^\/+|\/+$/g, "");
|
|
108
|
+
const pageResolver = new PageResolver({
|
|
109
|
+
projectDir: ctx.projectDir,
|
|
110
|
+
projectId: ctx.projectId,
|
|
111
|
+
config: ctx.config ?? {},
|
|
112
|
+
adapter: ctx.adapter,
|
|
113
|
+
});
|
|
114
|
+
try {
|
|
115
|
+
return await pageResolver.pageExists(slug);
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
this.logDebug("[API-Wrapper] Page ownership is indeterminate; preserving API discovery", {
|
|
119
|
+
pathname,
|
|
120
|
+
error: this.getErrorMessage(error),
|
|
121
|
+
}, ctx);
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
91
125
|
}
|
|
@@ -31,13 +31,18 @@ export declare class LRUHandlerCache<T> implements HandlerCache<T> {
|
|
|
31
31
|
values(): IterableIterator<T>;
|
|
32
32
|
}
|
|
33
33
|
export declare function __injectCacheForTests(cache: HandlerCache<Promise<APIRouteHandler>> | null): void;
|
|
34
|
+
export declare function ensurePreviewSourceSnapshotFresh(ctx: HandlerContext): Promise<void>;
|
|
35
|
+
export declare function refreshPreviewSourceSnapshot(ctx: HandlerContext): Promise<void>;
|
|
36
|
+
interface ApiHandlerOptions {
|
|
37
|
+
sourceSnapshotReady?: boolean;
|
|
38
|
+
}
|
|
34
39
|
export declare function getApiHandler(ctx: HandlerContext): Promise<APIRouteHandler>;
|
|
35
40
|
/**
|
|
36
41
|
* Use an API handler while holding a lease that defers cache-eviction cleanup.
|
|
37
42
|
* The lease begins before the handler promise is awaited, closing the gap
|
|
38
43
|
* between a cache lookup and APIRouteHandler.handle() registering the request.
|
|
39
44
|
*/
|
|
40
|
-
export declare function withApiHandler<T>(ctx: HandlerContext, use: (handler: APIRouteHandler) => T | Promise<T
|
|
45
|
+
export declare function withApiHandler<T>(ctx: HandlerContext, use: (handler: APIRouteHandler) => T | Promise<T>, options?: ApiHandlerOptions): Promise<T>;
|
|
41
46
|
export declare function resetApiHandler(projectDir?: string): Promise<void>;
|
|
42
47
|
/**
|
|
43
48
|
* Reset cached API handlers for a specific project slug.
|
|
@@ -47,4 +52,5 @@ export declare function resetApiHandler(projectDir?: string): Promise<void>;
|
|
|
47
52
|
* all entries and destroy those scoped to the project slug.
|
|
48
53
|
*/
|
|
49
54
|
export declare function resetApiHandlerForProject(projectSlug: string): Promise<void>;
|
|
55
|
+
export {};
|
|
50
56
|
//# sourceMappingURL=pages-api-handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pages-api-handler.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/handlers/request/api/pages-api-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAO/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAIrD,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC;IAChC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;IACjC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAC7B,KAAK,IAAI,IAAI,CAAC;IACd,OAAO,IAAI,gBAAgB,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IACzC,MAAM,IAAI,gBAAgB,CAAC,CAAC,CAAC,CAAC;CAC/B;AAID,qBAAa,eAAe,CAAC,CAAC,CAAE,YAAW,YAAY,CAAC,CAAC,CAAC;IACxD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAkB;IACtC,OAAO,CAAC,uBAAuB,CAAS;gBAGtC,OAAO,GAAE;QACP,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;KACzB;IAUR,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAG/B,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI;IAGhC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAU5B,KAAK,IAAI,IAAI;IAQb,OAAO,IAAI,gBAAgB,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAGvC,MAAM,IAAI,gBAAgB,CAAC,CAAC,CAAC;CAG/B;AAqBD,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,GAAG,IAAI,GACnD,IAAI,CAEN;
|
|
1
|
+
{"version":3,"file":"pages-api-handler.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/handlers/request/api/pages-api-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAO/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAIrD,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC;IAChC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;IACjC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAC7B,KAAK,IAAI,IAAI,CAAC;IACd,OAAO,IAAI,gBAAgB,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IACzC,MAAM,IAAI,gBAAgB,CAAC,CAAC,CAAC,CAAC;CAC/B;AAID,qBAAa,eAAe,CAAC,CAAC,CAAE,YAAW,YAAY,CAAC,CAAC,CAAC;IACxD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAkB;IACtC,OAAO,CAAC,uBAAuB,CAAS;gBAGtC,OAAO,GAAE;QACP,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;KACzB;IAUR,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAG/B,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI;IAGhC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAU5B,KAAK,IAAI,IAAI;IAQb,OAAO,IAAI,gBAAgB,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAGvC,MAAM,IAAI,gBAAgB,CAAC,CAAC,CAAC;CAG/B;AAqBD,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,GAAG,IAAI,GACnD,IAAI,CAEN;AA8BD,wBAAsB,gCAAgC,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAUzF;AAED,wBAAsB,4BAA4B,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAGrF;AAED,UAAU,iBAAiB;IACzB,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAyFD,wBAAsB,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC,CAEjF;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,CAAC,EACpC,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EACjD,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,CAAC,CAAC,CAUZ;AAED,wBAAsB,eAAe,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAaxE;AAED;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAC7C,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAcf"}
|
|
@@ -91,17 +91,33 @@ function shouldCacheApiHandler(ctx) {
|
|
|
91
91
|
// Cannot confirm a production context → do not cache.
|
|
92
92
|
return getApiHandlerCacheContext(ctx)?.mode === "production";
|
|
93
93
|
}
|
|
94
|
-
|
|
94
|
+
function hasMutablePreviewSource(ctx) {
|
|
95
95
|
if (!ctx.projectSlug)
|
|
96
|
-
return;
|
|
96
|
+
return false;
|
|
97
97
|
const cacheContext = getApiHandlerCacheContext(ctx);
|
|
98
98
|
// Skip when production, or when the context is indeterminate.
|
|
99
|
-
|
|
99
|
+
return !!cacheContext && cacheContext.mode !== "production";
|
|
100
|
+
}
|
|
101
|
+
export async function ensurePreviewSourceSnapshotFresh(ctx) {
|
|
102
|
+
if (!hasMutablePreviewSource(ctx))
|
|
103
|
+
return;
|
|
104
|
+
if (ctx.adapter.fs.ensureSourceSnapshotFresh) {
|
|
105
|
+
await ctx.adapter.fs.ensureSourceSnapshotFresh("preview-request-routing");
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
// Backward compatibility for custom remote adapters that only implement the
|
|
109
|
+
// original unconditional refresh contract.
|
|
110
|
+
await refreshPreviewSourceSnapshot(ctx);
|
|
111
|
+
}
|
|
112
|
+
export async function refreshPreviewSourceSnapshot(ctx) {
|
|
113
|
+
if (!hasMutablePreviewSource(ctx))
|
|
100
114
|
return;
|
|
101
115
|
await ctx.adapter.fs.refreshSourceSnapshot?.("preview-api-route-discovery");
|
|
102
116
|
}
|
|
103
|
-
async function createApiHandler(ctx) {
|
|
104
|
-
|
|
117
|
+
async function createApiHandler(ctx, options = {}) {
|
|
118
|
+
if (!options.sourceSnapshotReady) {
|
|
119
|
+
await ensurePreviewSourceSnapshotFresh(ctx);
|
|
120
|
+
}
|
|
105
121
|
const handler = new APIRouteHandler(ctx.projectDir, ctx.adapter);
|
|
106
122
|
await handler.initialize();
|
|
107
123
|
return handler;
|
|
@@ -156,15 +172,15 @@ function retainHandler(promise) {
|
|
|
156
172
|
}
|
|
157
173
|
};
|
|
158
174
|
}
|
|
159
|
-
function getApiHandlerPromise(ctx) {
|
|
175
|
+
function getApiHandlerPromise(ctx, options = {}) {
|
|
160
176
|
if (!shouldCacheApiHandler(ctx)) {
|
|
161
|
-
return { promise: createApiHandler(ctx), cached: false };
|
|
177
|
+
return { promise: createApiHandler(ctx, options), cached: false };
|
|
162
178
|
}
|
|
163
179
|
const cache = getCache();
|
|
164
180
|
const key = getCacheKey(ctx);
|
|
165
181
|
let promise = cache.get(key);
|
|
166
182
|
if (!promise) {
|
|
167
|
-
promise = createApiHandler(ctx);
|
|
183
|
+
promise = createApiHandler(ctx, options);
|
|
168
184
|
cache.set(key, promise);
|
|
169
185
|
}
|
|
170
186
|
return { promise, cached: true };
|
|
@@ -177,8 +193,8 @@ export async function getApiHandler(ctx) {
|
|
|
177
193
|
* The lease begins before the handler promise is awaited, closing the gap
|
|
178
194
|
* between a cache lookup and APIRouteHandler.handle() registering the request.
|
|
179
195
|
*/
|
|
180
|
-
export async function withApiHandler(ctx, use) {
|
|
181
|
-
const { promise, cached } = getApiHandlerPromise(ctx);
|
|
196
|
+
export async function withApiHandler(ctx, use, options = {}) {
|
|
197
|
+
const { promise, cached } = getApiHandlerPromise(ctx, options);
|
|
182
198
|
const release = retainHandler(promise);
|
|
183
199
|
try {
|
|
184
200
|
return await use(await promise);
|
|
@@ -7,4 +7,10 @@ import type { HandlerContext } from "../../types.js";
|
|
|
7
7
|
* correct project scope.
|
|
8
8
|
*/
|
|
9
9
|
export declare function ensureProjectDiscovery(ctx: HandlerContext): Promise<DiscoveryResult>;
|
|
10
|
+
/**
|
|
11
|
+
* Drop completed and in-flight discovery records for every source scope owned
|
|
12
|
+
* by a project. The next scoped request rebuilds registries transactionally
|
|
13
|
+
* from its current source snapshot.
|
|
14
|
+
*/
|
|
15
|
+
export declare function clearProjectDiscoveryCacheForProject(projectId: string): void;
|
|
10
16
|
//# sourceMappingURL=project-discovery.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-discovery.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/handlers/request/api/project-discovery.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAOtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"project-discovery.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/handlers/request/api/project-discovery.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAOtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AA4HrD;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC,CAyG1F;AAED;;;;GAIG;AACH,wBAAgB,oCAAoC,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAM5E"}
|
|
@@ -68,15 +68,17 @@ function discoveryKey(ctx) {
|
|
|
68
68
|
if (registryScope) {
|
|
69
69
|
return registryScope.scopeId;
|
|
70
70
|
}
|
|
71
|
-
const
|
|
71
|
+
const projectIdentity = ctx.projectId ?? ctx.projectSlug ?? ctx.projectDir;
|
|
72
72
|
const environment = ctx.enriched?.environment ?? ctx.resolvedEnvironment ??
|
|
73
73
|
(ctx.releaseId ? "production" : "preview");
|
|
74
74
|
if (environment === "production") {
|
|
75
|
-
return ctx.releaseId
|
|
75
|
+
return ctx.releaseId
|
|
76
|
+
? `${projectIdentity}:release:${ctx.releaseId}`
|
|
77
|
+
: `${projectIdentity}:production:unreleased`;
|
|
76
78
|
}
|
|
77
79
|
const branch = ctx.requestContext?.branch ?? ctx.enriched?.branch ?? ctx.parsedDomain?.branch ??
|
|
78
80
|
"main";
|
|
79
|
-
return `${
|
|
81
|
+
return `${projectIdentity}:preview:${branch}`;
|
|
80
82
|
}
|
|
81
83
|
function shouldCacheCompletedDiscovery(ctx) {
|
|
82
84
|
const registryScope = tryGetRegistryScopeContext();
|
|
@@ -94,17 +96,24 @@ function shouldCacheCompletedDiscovery(ctx) {
|
|
|
94
96
|
* correct project scope.
|
|
95
97
|
*/
|
|
96
98
|
export async function ensureProjectDiscovery(ctx) {
|
|
99
|
+
await ctx.adapter.fs.ensureSourceSnapshotFresh?.("primitive-discovery");
|
|
97
100
|
const key = discoveryKey(ctx);
|
|
98
|
-
const
|
|
101
|
+
const sourceSnapshotVersion = await ctx.adapter.fs.getSourceSnapshotVersion?.();
|
|
102
|
+
const cacheCompletedDiscovery = shouldCacheCompletedDiscovery(ctx) ||
|
|
103
|
+
sourceSnapshotVersion !== undefined;
|
|
99
104
|
const existing = discoveredProjects.get(key);
|
|
100
|
-
if (existing
|
|
105
|
+
if (existing &&
|
|
106
|
+
(sourceSnapshotVersion === undefined ||
|
|
107
|
+
existing.sourceSnapshotVersion === sourceSnapshotVersion)) {
|
|
101
108
|
return existing.promise;
|
|
109
|
+
}
|
|
102
110
|
const discovery = {
|
|
111
|
+
sourceSnapshotVersion,
|
|
103
112
|
promise: (async () => {
|
|
104
|
-
const { clearTranspileCache, discoverAll } = await import("../../../../discovery/index.js");
|
|
105
|
-
const { agentRegistry } = await import("../../../../agent/composition/composition.js");
|
|
106
|
-
const { toolRegistry } = await import("../../../../tool/registry.js");
|
|
107
113
|
return await runWithRegistryTransaction(async () => {
|
|
114
|
+
const { clearTranspileCache, discoverAll } = await import("../../../../discovery/index.js");
|
|
115
|
+
const { agentRegistry } = await import("../../../../agent/composition/composition.js");
|
|
116
|
+
const { toolRegistry } = await import("../../../../tool/registry.js");
|
|
108
117
|
// Clear stale entries in a transaction-local copy. Concurrent runs keep
|
|
109
118
|
// using the prior live registry until discovery succeeds and the staged
|
|
110
119
|
// replacement is committed atomically.
|
|
@@ -146,11 +155,22 @@ export async function ensureProjectDiscovery(ctx) {
|
|
|
146
155
|
};
|
|
147
156
|
discoveredProjects.set(key, discovery);
|
|
148
157
|
try {
|
|
149
|
-
|
|
158
|
+
const result = await discovery.promise;
|
|
159
|
+
if (result.errors.length > 0) {
|
|
160
|
+
const current = discoveredProjects.get(key);
|
|
161
|
+
if (current === discovery) {
|
|
162
|
+
discoveredProjects.delete(key);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return result;
|
|
150
166
|
}
|
|
151
167
|
catch (error) {
|
|
152
|
-
//
|
|
153
|
-
|
|
168
|
+
// A superseded generation may already own this key. Delete only our own
|
|
169
|
+
// record so the newer discovery remains reusable after it completes.
|
|
170
|
+
const current = discoveredProjects.get(key);
|
|
171
|
+
if (current === discovery) {
|
|
172
|
+
discoveredProjects.delete(key);
|
|
173
|
+
}
|
|
154
174
|
logger.warn("Primitive discovery failed (will retry)", {
|
|
155
175
|
projectSlug: ctx.projectSlug,
|
|
156
176
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -170,3 +190,15 @@ export async function ensureProjectDiscovery(ctx) {
|
|
|
170
190
|
}
|
|
171
191
|
}
|
|
172
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* Drop completed and in-flight discovery records for every source scope owned
|
|
195
|
+
* by a project. The next scoped request rebuilds registries transactionally
|
|
196
|
+
* from its current source snapshot.
|
|
197
|
+
*/
|
|
198
|
+
export function clearProjectDiscoveryCacheForProject(projectId) {
|
|
199
|
+
for (const key of discoveredProjects.keys()) {
|
|
200
|
+
if (key === projectId || key.startsWith(`${projectId}:`)) {
|
|
201
|
+
discoveredProjects.delete(key);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter-factory.d.ts","sourceRoot":"","sources":["../../../../src/src/server/runtime-handler/adapter-factory.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAGtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAG7D,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAQ9D,UAAU,uBAAuB;IAC/B,6CAA6C;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,0CAA0C;IAC1C,OAAO,EAAE,cAAc,CAAC;IACxB,kCAAkC;IAClC,MAAM,EAAE,eAAe,GAAG,SAAS,CAAC;IACpC,yDAAyD;IACzD,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,UAAU,wBAAwB;IAChC;;;OAGG;IACH,GAAG,EAAE,OAAO,CAAC;IACb,6BAA6B;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB;IACnB,OAAO,EAAE,cAAc,CAAC;IACxB,6BAA6B;IAC7B,MAAM,EAAE,eAAe,GAAG,SAAS,CAAC;IACpC,mBAAmB;IACnB,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,iBAAiB;IACjB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,kBAAkB;IAClB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,iBAAiB;IACjB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,uCAAuC;IACvC,QAAQ,EAAE,SAAS,GAAG,YAAY,GAAG,SAAS,CAAC;IAC/C,kBAAkB;IAClB,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAClC,yCAAyC;IACzC,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,yBAAyB;IACzB,YAAY,EAAE,YAAY,CAAC;IAC3B,qFAAqF;IACrF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,WAAW,EAAE,OAAO,CAAC;IACrB,sEAAsE;IACtE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,qEAAqE;IACrE,KAAK,CAAC,EAAE,qBAAqB,CAAC;CAC/B;AASD;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,wBAAwB,GAC7B,OAAO,CAAC,uBAAuB,CAAC,
|
|
1
|
+
{"version":3,"file":"adapter-factory.d.ts","sourceRoot":"","sources":["../../../../src/src/server/runtime-handler/adapter-factory.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAGtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAG7D,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAQ9D,UAAU,uBAAuB;IAC/B,6CAA6C;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,0CAA0C;IAC1C,OAAO,EAAE,cAAc,CAAC;IACxB,kCAAkC;IAClC,MAAM,EAAE,eAAe,GAAG,SAAS,CAAC;IACpC,yDAAyD;IACzD,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,UAAU,wBAAwB;IAChC;;;OAGG;IACH,GAAG,EAAE,OAAO,CAAC;IACb,6BAA6B;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB;IACnB,OAAO,EAAE,cAAc,CAAC;IACxB,6BAA6B;IAC7B,MAAM,EAAE,eAAe,GAAG,SAAS,CAAC;IACpC,mBAAmB;IACnB,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,iBAAiB;IACjB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,kBAAkB;IAClB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,iBAAiB;IACjB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,uCAAuC;IACvC,QAAQ,EAAE,SAAS,GAAG,YAAY,GAAG,SAAS,CAAC;IAC/C,kBAAkB;IAClB,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAClC,yCAAyC;IACzC,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,yBAAyB;IACzB,YAAY,EAAE,YAAY,CAAC;IAC3B,qFAAqF;IACrF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,WAAW,EAAE,OAAO,CAAC;IACrB,sEAAsE;IACtE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,qEAAqE;IACrE,KAAK,CAAC,EAAE,qBAAqB,CAAC;CAC/B;AASD;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,wBAAwB,GAC7B,OAAO,CAAC,uBAAuB,CAAC,CAiJlC"}
|