veryfront 0.1.86 → 0.1.88

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.
Files changed (36) hide show
  1. package/esm/deno.js +1 -1
  2. package/esm/src/cache/distributed-cache-init.d.ts +9 -0
  3. package/esm/src/cache/distributed-cache-init.d.ts.map +1 -1
  4. package/esm/src/cache/distributed-cache-init.js +70 -52
  5. package/esm/src/cache/module-cache.d.ts +6 -2
  6. package/esm/src/cache/module-cache.d.ts.map +1 -1
  7. package/esm/src/cache/module-cache.js +73 -56
  8. package/esm/src/platform/adapters/fs/veryfront/content-metrics.d.ts +1 -1
  9. package/esm/src/platform/adapters/fs/veryfront/content-metrics.d.ts.map +1 -1
  10. package/esm/src/platform/adapters/fs/veryfront/content-metrics.js +7 -1
  11. package/esm/src/platform/adapters/fs/veryfront/file-list-index.d.ts +10 -0
  12. package/esm/src/platform/adapters/fs/veryfront/file-list-index.d.ts.map +1 -1
  13. package/esm/src/platform/adapters/fs/veryfront/file-list-index.js +83 -19
  14. package/esm/src/platform/adapters/fs/veryfront/read-operations-helpers.d.ts +5 -0
  15. package/esm/src/platform/adapters/fs/veryfront/read-operations-helpers.d.ts.map +1 -1
  16. package/esm/src/platform/adapters/fs/veryfront/read-operations-helpers.js +6 -0
  17. package/esm/src/platform/adapters/fs/veryfront/read-operations.d.ts.map +1 -1
  18. package/esm/src/platform/adapters/fs/veryfront/read-operations.js +53 -34
  19. package/esm/src/rendering/page-resolution/page-resolver.d.ts.map +1 -1
  20. package/esm/src/rendering/page-resolution/page-resolver.js +10 -4
  21. package/esm/src/transforms/esm/http-cache-wrapper.d.ts +3 -0
  22. package/esm/src/transforms/esm/http-cache-wrapper.d.ts.map +1 -1
  23. package/esm/src/transforms/esm/http-cache-wrapper.js +21 -7
  24. package/esm/src/utils/version.d.ts +1 -1
  25. package/esm/src/utils/version.js +1 -1
  26. package/package.json +1 -1
  27. package/src/deno.js +1 -1
  28. package/src/src/cache/distributed-cache-init.ts +95 -59
  29. package/src/src/cache/module-cache.ts +95 -57
  30. package/src/src/platform/adapters/fs/veryfront/content-metrics.ts +13 -2
  31. package/src/src/platform/adapters/fs/veryfront/file-list-index.ts +101 -18
  32. package/src/src/platform/adapters/fs/veryfront/read-operations-helpers.ts +10 -0
  33. package/src/src/platform/adapters/fs/veryfront/read-operations.ts +87 -30
  34. package/src/src/rendering/page-resolution/page-resolver.ts +17 -6
  35. package/src/src/transforms/esm/http-cache-wrapper.ts +28 -7
  36. package/src/src/utils/version.ts +1 -1
package/esm/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.1.86",
3
+ "version": "0.1.88",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "exclude": [
@@ -4,7 +4,16 @@ interface DistributedCacheStatus {
4
4
  ssrModuleCache: boolean;
5
5
  fileCache: boolean;
6
6
  projectCSSCache: boolean;
7
+ httpModuleCache: boolean;
7
8
  }
9
+ type DistributedCacheInitializers = {
10
+ transformCache: () => Promise<boolean>;
11
+ ssrModuleCache: () => Promise<boolean>;
12
+ fileCache: () => Promise<boolean>;
13
+ projectCSSCache: () => Promise<boolean>;
14
+ httpModuleCache: () => Promise<boolean>;
15
+ };
16
+ export declare function __runDistributedCacheInitializationForTests(backend: DistributedCacheStatus["backend"], initializers: DistributedCacheInitializers): Promise<DistributedCacheStatus>;
8
17
  export declare function initializeDistributedCaches(): Promise<DistributedCacheStatus>;
9
18
  export {};
10
19
  //# sourceMappingURL=distributed-cache-init.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"distributed-cache-init.d.ts","sourceRoot":"","sources":["../../../src/src/cache/distributed-cache-init.ts"],"names":[],"mappings":"AAYA,UAAU,sBAAsB;IAC9B,OAAO,EAAE,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;IAC7C,cAAc,EAAE,OAAO,CAAC;IACxB,cAAc,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAaD,wBAAgB,2BAA2B,IAAI,OAAO,CAAC,sBAAsB,CAAC,CA4E7E"}
1
+ {"version":3,"file":"distributed-cache-init.d.ts","sourceRoot":"","sources":["../../../src/src/cache/distributed-cache-init.ts"],"names":[],"mappings":"AAaA,UAAU,sBAAsB;IAC9B,OAAO,EAAE,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;IAC7C,cAAc,EAAE,OAAO,CAAC;IACxB,cAAc,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,eAAe,EAAE,OAAO,CAAC;IACzB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,KAAK,4BAA4B,GAAG;IAClC,cAAc,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,cAAc,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,SAAS,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAClC,eAAe,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACxC,eAAe,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;CACzC,CAAC;AAyFF,wBAAgB,2CAA2C,CACzD,OAAO,EAAE,sBAAsB,CAAC,SAAS,CAAC,EAC1C,YAAY,EAAE,4BAA4B,GACzC,OAAO,CAAC,sBAAsB,CAAC,CAEjC;AAED,wBAAgB,2BAA2B,IAAI,OAAO,CAAC,sBAAsB,CAAC,CAmB7E"}
@@ -1,6 +1,7 @@
1
1
  import { initializeFileCacheBackend } from "../platform/adapters/fs/cache/file-cache.js";
2
2
  import { initializeSSRDistributedCache } from "../modules/react-loader/ssr-module-loader/index.js";
3
3
  import { initializeTransformCache } from "../transforms/esm/transform-cache.js";
4
+ import { initializeHttpModuleDistributedCache } from "../transforms/esm/http-cache-wrapper.js";
4
5
  import { SpanNames } from "../observability/tracing/span-names.js";
5
6
  import { withSpan } from "../observability/tracing/otlp-setup.js";
6
7
  import { initializeProjectCSSCache } from "../html/styles-builder/tailwind-compiler.js";
@@ -8,6 +9,13 @@ import { logger as baseLogger } from "../utils/logger/logger.js";
8
9
  import { isRedisConfigured } from "../utils/redis-client.js";
9
10
  import { isApiCacheAvailable, isDiskCacheConfigured } from "./backend.js";
10
11
  const logger = baseLogger.component("distributed-cache");
12
+ const defaultInitializers = {
13
+ transformCache: initializeTransformCache,
14
+ ssrModuleCache: initializeSSRDistributedCache,
15
+ fileCache: initializeFileCacheBackend,
16
+ projectCSSCache: initializeProjectCSSCache,
17
+ httpModuleCache: initializeHttpModuleDistributedCache,
18
+ };
11
19
  function determineBackend() {
12
20
  if (isApiCacheAvailable())
13
21
  return "api";
@@ -20,6 +28,66 @@ function determineBackend() {
20
28
  function wasSuccessful(result) {
21
29
  return result.status === "fulfilled" && result.value;
22
30
  }
31
+ async function initializeDistributedCachesWithInitializers(backend, initializers) {
32
+ logger.info("Initializing caches...", { backend });
33
+ const cacheNames = [
34
+ "transformCache",
35
+ "ssrModuleCache",
36
+ "fileCache",
37
+ "projectCSSCache",
38
+ "httpModuleCache",
39
+ ];
40
+ const results = await Promise.allSettled([
41
+ initializers.transformCache(),
42
+ initializers.ssrModuleCache(),
43
+ initializers.fileCache(),
44
+ initializers.projectCSSCache(),
45
+ initializers.httpModuleCache(),
46
+ ]);
47
+ for (let i = 0; i < results.length; i++) {
48
+ const result = results[i];
49
+ if (result && result.status === "rejected") {
50
+ logger.error(`Cache initialization failed: ${cacheNames[i]}`, {
51
+ backend,
52
+ error: result.reason instanceof Error ? result.reason.message : String(result.reason),
53
+ });
54
+ }
55
+ }
56
+ const status = {
57
+ backend,
58
+ transformCache: wasSuccessful(results[0]),
59
+ ssrModuleCache: wasSuccessful(results[1]),
60
+ fileCache: wasSuccessful(results[2]),
61
+ projectCSSCache: wasSuccessful(results[3]),
62
+ httpModuleCache: wasSuccessful(results[4]),
63
+ };
64
+ const enabled = [
65
+ status.transformCache,
66
+ status.ssrModuleCache,
67
+ status.fileCache,
68
+ status.projectCSSCache,
69
+ status.httpModuleCache,
70
+ ].filter(Boolean).length;
71
+ if (enabled === 0) {
72
+ logger.warn("No caches enabled despite backend being available", {
73
+ backend,
74
+ });
75
+ return status;
76
+ }
77
+ logger.info("Initialization complete", {
78
+ backend,
79
+ enabled,
80
+ transform: status.transformCache,
81
+ ssrModule: status.ssrModuleCache,
82
+ file: status.fileCache,
83
+ projectCSS: status.projectCSSCache,
84
+ httpModule: status.httpModuleCache,
85
+ });
86
+ return status;
87
+ }
88
+ export function __runDistributedCacheInitializationForTests(backend, initializers) {
89
+ return initializeDistributedCachesWithInitializers(backend, initializers);
90
+ }
23
91
  export function initializeDistributedCaches() {
24
92
  const backend = determineBackend();
25
93
  if (backend === "memory") {
@@ -29,58 +97,8 @@ export function initializeDistributedCaches() {
29
97
  ssrModuleCache: false,
30
98
  fileCache: false,
31
99
  projectCSSCache: false,
100
+ httpModuleCache: false,
32
101
  });
33
102
  }
34
- return withSpan(SpanNames.CACHE_DISTRIBUTED_INIT, async () => {
35
- logger.info("Initializing caches...", { backend });
36
- const cacheNames = [
37
- "transformCache",
38
- "ssrModuleCache",
39
- "fileCache",
40
- "projectCSSCache",
41
- ];
42
- const results = await Promise.allSettled([
43
- initializeTransformCache(),
44
- initializeSSRDistributedCache(),
45
- initializeFileCacheBackend(),
46
- initializeProjectCSSCache(),
47
- ]);
48
- for (let i = 0; i < results.length; i++) {
49
- const result = results[i];
50
- if (result && result.status === "rejected") {
51
- logger.error(`Cache initialization failed: ${cacheNames[i]}`, {
52
- backend,
53
- error: result.reason instanceof Error ? result.reason.message : String(result.reason),
54
- });
55
- }
56
- }
57
- const status = {
58
- backend,
59
- transformCache: wasSuccessful(results[0]),
60
- ssrModuleCache: wasSuccessful(results[1]),
61
- fileCache: wasSuccessful(results[2]),
62
- projectCSSCache: wasSuccessful(results[3]),
63
- };
64
- const enabled = [
65
- status.transformCache,
66
- status.ssrModuleCache,
67
- status.fileCache,
68
- status.projectCSSCache,
69
- ].filter(Boolean).length;
70
- if (enabled === 0) {
71
- logger.warn("No caches enabled despite backend being available", {
72
- backend,
73
- });
74
- return status;
75
- }
76
- logger.info("Initialization complete", {
77
- backend,
78
- enabled,
79
- transform: status.transformCache,
80
- ssrModule: status.ssrModuleCache,
81
- file: status.fileCache,
82
- projectCSS: status.projectCSSCache,
83
- });
84
- return status;
85
- }, { "cache.backend": backend });
103
+ return withSpan(SpanNames.CACHE_DISTRIBUTED_INIT, () => initializeDistributedCachesWithInitializers(backend, defaultInitializers), { "cache.backend": backend });
86
104
  }
@@ -2,6 +2,10 @@
2
2
  * Pod-Level Module Cache Singleton
3
3
  **************************/
4
4
  import { LRUCache } from "../utils/lru-wrapper.js";
5
+ export interface ModuleCacheMap extends Map<string, string> {
6
+ getOrInsert(key: string, value: string): string;
7
+ getOrInsertComputed(key: string, callback: (key: string) => string): string;
8
+ }
5
9
  interface ModuleCacheStats {
6
10
  moduleCache: {
7
11
  size: number;
@@ -16,8 +20,8 @@ interface ModuleCacheStats {
16
20
  }
17
21
  export declare function getModuleCache(): LRUCache<string, string>;
18
22
  export declare function getEsmCache(): LRUCache<string, string>;
19
- export declare function createModuleCache(): Map<string, string>;
20
- export declare function createEsmCache(): Map<string, string>;
23
+ export declare function createModuleCache(): ModuleCacheMap;
24
+ export declare function createEsmCache(): ModuleCacheMap;
21
25
  export declare function getModuleCacheStats(): ModuleCacheStats;
22
26
  export declare function clearModuleCaches(): void;
23
27
  export declare function clearModuleCacheForProject(projectId: string): number;
@@ -1 +1 @@
1
- {"version":3,"file":"module-cache.d.ts","sourceRoot":"","sources":["../../../src/src/cache/module-cache.ts"],"names":[],"mappings":"AAAA;;4BAE4B;AAE5B,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAenD,UAAU,gBAAgB;IACxB,WAAW,EAAE;QACX,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAqDD,wBAAgB,cAAc,IAAI,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAEzD;AAED,wBAAgB,WAAW,IAAI,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAEtD;AAED,wBAAgB,iBAAiB,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAEvD;AAED,wBAAgB,cAAc,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAEpD;AA6DD,wBAAgB,mBAAmB,IAAI,gBAAgB,CAatD;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CAIxC;AAED,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAgBpE;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAM1C"}
1
+ {"version":3,"file":"module-cache.d.ts","sourceRoot":"","sources":["../../../src/src/cache/module-cache.ts"],"names":[],"mappings":"AAAA;;4BAE4B;AAE5B,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAenD,MAAM,WAAW,cAAe,SAAQ,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IACzD,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAChD,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,MAAM,CAAC;CAC7E;AAED,UAAU,gBAAgB;IACxB,WAAW,EAAE;QACX,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAqDD,wBAAgB,cAAc,IAAI,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAEzD;AAED,wBAAgB,WAAW,IAAI,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAEtD;AAED,wBAAgB,iBAAiB,IAAI,cAAc,CAElD;AAED,wBAAgB,cAAc,IAAI,cAAc,CAE/C;AA8FD,wBAAgB,mBAAmB,IAAI,gBAAgB,CAatD;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CAIxC;AAED,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAgBpE;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAM1C"}
@@ -57,64 +57,81 @@ export function createEsmCache() {
57
57
  return createMapInterface(getEsmCache());
58
58
  }
59
59
  function createMapInterface(cache) {
60
- const map = {
61
- get(key) {
62
- return cache.get(key);
63
- },
64
- set(key, value) {
65
- cache.set(key, value);
66
- return map;
67
- },
68
- has(key) {
69
- return cache.has(key);
70
- },
71
- delete(key) {
72
- return cache.delete(key);
73
- },
74
- clear() {
75
- cache.clear();
76
- },
77
- get size() {
78
- return cache.size;
79
- },
80
- keys() {
81
- return cache.keys();
82
- },
83
- values() {
84
- const keysIter = cache.keys();
85
- const cacheRef = cache;
86
- return (function* () {
87
- for (const key of keysIter) {
88
- const value = cacheRef.get(key);
89
- if (value !== undefined)
90
- yield value;
91
- }
92
- })();
93
- },
94
- entries() {
95
- const keysIter = cache.keys();
96
- const cacheRef = cache;
97
- return (function* () {
98
- for (const key of keysIter) {
99
- const value = cacheRef.get(key);
100
- if (value !== undefined)
101
- yield [key, value];
102
- }
103
- })();
104
- },
105
- forEach(callback) {
106
- for (const key of cache.keys()) {
107
- const value = cache.get(key);
60
+ return new LRUBackedMap(cache);
61
+ }
62
+ class LRUBackedMap {
63
+ cache;
64
+ [Symbol.toStringTag] = "Map";
65
+ constructor(cache) {
66
+ this.cache = cache;
67
+ }
68
+ get(key) {
69
+ return this.cache.get(key);
70
+ }
71
+ set(key, value) {
72
+ this.cache.set(key, value);
73
+ return this;
74
+ }
75
+ has(key) {
76
+ return this.cache.has(key);
77
+ }
78
+ delete(key) {
79
+ return this.cache.delete(key);
80
+ }
81
+ clear() {
82
+ this.cache.clear();
83
+ }
84
+ getOrInsert(key, value) {
85
+ const existing = this.cache.get(key);
86
+ if (existing !== undefined)
87
+ return existing;
88
+ this.cache.set(key, value);
89
+ return value;
90
+ }
91
+ getOrInsertComputed(key, callback) {
92
+ const existing = this.cache.get(key);
93
+ if (existing !== undefined)
94
+ return existing;
95
+ const value = callback(key);
96
+ this.cache.set(key, value);
97
+ return value;
98
+ }
99
+ get size() {
100
+ return this.cache.size;
101
+ }
102
+ keys() {
103
+ return this.cache.keys();
104
+ }
105
+ values() {
106
+ const keysIter = this.cache.keys();
107
+ const cacheRef = this.cache;
108
+ return (function* () {
109
+ for (const key of keysIter) {
110
+ const value = cacheRef.get(key);
108
111
  if (value !== undefined)
109
- callback(value, key, map);
112
+ yield value;
110
113
  }
111
- },
112
- [Symbol.iterator]() {
113
- return map.entries();
114
- },
115
- [Symbol.toStringTag]: "Map",
116
- };
117
- return map;
114
+ })();
115
+ }
116
+ entries() {
117
+ const keysIter = this.cache.keys();
118
+ const cacheRef = this.cache;
119
+ return (function* () {
120
+ for (const key of keysIter) {
121
+ const value = cacheRef.get(key);
122
+ if (value !== undefined)
123
+ yield [key, value];
124
+ }
125
+ })();
126
+ }
127
+ forEach(callback, thisArg) {
128
+ for (const [key, value] of this.entries()) {
129
+ callback.call(thisArg, value, key, this);
130
+ }
131
+ }
132
+ [Symbol.iterator]() {
133
+ return this.entries();
134
+ }
118
135
  }
119
136
  export function getModuleCacheStats() {
120
137
  return {
@@ -1,4 +1,4 @@
1
- export type MissReason = "cold_start" | "not_in_filelist" | "invalidation" | "no_filelist_cache";
1
+ export type MissReason = "cold_start" | "not_in_filelist" | "invalidation" | "no_filelist_cache" | "indexed_without_content";
2
2
  interface CumulativeMetrics {
3
3
  requestScopedHits: number;
4
4
  persistentCacheHits: number;
@@ -1 +1 @@
1
- {"version":3,"file":"content-metrics.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/content-metrics.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG,iBAAiB,GAAG,cAAc,GAAG,mBAAmB,CAAC;AAejG,UAAU,iBAAiB;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;CACzB;AAsCD,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAED,wBAAgB,iBAAiB,CAC/B,cAAc,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GACxE,IAAI,CAuCN;AAED,KAAK,kBAAkB,GACnB,oBAAoB,GACpB,sBAAsB,GACtB,eAAe,GACf,eAAe,GACf,wBAAwB,GACxB,YAAY,CAAC;AAEjB,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,kBAAkB,EACzB,OAAO,EAAE;IACP,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,GACA,IAAI,CAyCN;AAED,wBAAgB,yBAAyB,IAAI,iBAAiB,GAAG;IAC/D,sBAAsB,EAAE,MAAM,CAAC;CAChC,CAOA;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAO1C"}
1
+ {"version":3,"file":"content-metrics.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/content-metrics.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,UAAU,GAClB,YAAY,GACZ,iBAAiB,GACjB,cAAc,GACd,mBAAmB,GACnB,yBAAyB,CAAC;AAe9B,UAAU,iBAAiB;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;CACzB;AA4CD,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAED,wBAAgB,iBAAiB,CAC/B,cAAc,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GACxE,IAAI,CAuCN;AAED,KAAK,kBAAkB,GACnB,oBAAoB,GACpB,sBAAsB,GACtB,eAAe,GACf,eAAe,GACf,wBAAwB,GACxB,YAAY,CAAC;AAEjB,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,kBAAkB,EACzB,OAAO,EAAE;IACP,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,GACA,IAAI,CAyCN;AAED,wBAAgB,yBAAyB,IAAI,iBAAiB,GAAG;IAC/D,sBAAsB,EAAE,MAAM,CAAC;CAChC,CAOA;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAO1C"}
@@ -20,7 +20,13 @@ function createFreshRequestMetrics() {
20
20
  networkFetches: 0,
21
21
  networkMs: 0,
22
22
  fetchesByType: { page: 0, layout: 0, component: 0, api: 0, data: 0, config: 0, other: 0 },
23
- missReasons: { cold_start: 0, not_in_filelist: 0, invalidation: 0, no_filelist_cache: 0 },
23
+ missReasons: {
24
+ cold_start: 0,
25
+ not_in_filelist: 0,
26
+ invalidation: 0,
27
+ no_filelist_cache: 0,
28
+ indexed_without_content: 0,
29
+ },
24
30
  isPreviewMode: null,
25
31
  filesAccessed: new Set(),
26
32
  };
@@ -2,21 +2,31 @@ interface FileListCacheEntry {
2
2
  path: string;
3
3
  content?: string;
4
4
  }
5
+ export interface FileListMatchResult {
6
+ status: "unavailable" | "missing" | "present_without_content" | "hit";
7
+ fresh: boolean;
8
+ path?: string;
9
+ content?: string;
10
+ }
5
11
  export declare class FileListIndex {
6
12
  private readonly getFileListCache?;
7
13
  private index;
14
+ private pathSet;
8
15
  private indexKey;
9
16
  private indexBuiltAt;
17
+ private indexFresh;
10
18
  private readyPromise;
11
19
  constructor(getFileListCache?: (() => Promise<Array<FileListCacheEntry> | undefined>) | undefined);
12
20
  setReadyPromise(promise: Promise<void>): void;
13
21
  clear(): void;
14
22
  private ensureReady;
15
23
  lookup(normalizedPath: string): Promise<string | undefined>;
24
+ match(normalizedPath: string): Promise<FileListMatchResult>;
16
25
  findFirstWithContent(normalizedPaths: string[]): Promise<{
17
26
  path: string;
18
27
  content: string;
19
28
  } | undefined>;
29
+ findFirstMatch(normalizedPaths: string[]): Promise<FileListMatchResult>;
20
30
  private getOrBuild;
21
31
  }
22
32
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"file-list-index.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/file-list-index.ts"],"names":[],"mappings":"AAIA,UAAU,kBAAkB;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAeD,qBAAa,aAAa;IAOtB,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;IANpC,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,YAAY,CAA8B;gBAG/B,gBAAgB,CAAC,GAAE,MAAM,OAAO,CAAC,KAAK,CAAC,kBAAkB,CAAC,GAAG,SAAS,CAAC,aAAA;IAG1F,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAI7C,KAAK,IAAI,IAAI;YAUC,WAAW;IAWnB,MAAM,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IA4B3D,oBAAoB,CACxB,eAAe,EAAE,MAAM,EAAE,GACxB,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;YAc3C,UAAU;CA0EzB"}
1
+ {"version":3,"file":"file-list-index.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/file-list-index.ts"],"names":[],"mappings":"AAIA,UAAU,kBAAkB;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,aAAa,GAAG,SAAS,GAAG,yBAAyB,GAAG,KAAK,CAAC;IACtE,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAeD,qBAAa,aAAa;IAStB,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;IARpC,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,YAAY,CAA8B;gBAG/B,gBAAgB,CAAC,GAAE,MAAM,OAAO,CAAC,KAAK,CAAC,kBAAkB,CAAC,GAAG,SAAS,CAAC,aAAA;IAG1F,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAI7C,KAAK,IAAI,IAAI;YAYC,WAAW;IAWnB,MAAM,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAK3D,KAAK,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IA8C3D,oBAAoB,CACxB,eAAe,EAAE,MAAM,EAAE,GACxB,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IAMnD,cAAc,CAClB,eAAe,EAAE,MAAM,EAAE,GACxB,OAAO,CAAC,mBAAmB,CAAC;YA6BjB,UAAU;CAoGzB"}
@@ -13,8 +13,10 @@ const INDEX_STALENESS_LIMIT_MS = 5 * 60 * 1000; // 5 minutes
13
13
  export class FileListIndex {
14
14
  getFileListCache;
15
15
  index = null;
16
+ pathSet = null;
16
17
  indexKey = null;
17
18
  indexBuiltAt = 0;
19
+ indexFresh = false;
18
20
  readyPromise = null;
19
21
  constructor(getFileListCache) {
20
22
  this.getFileListCache = getFileListCache;
@@ -27,8 +29,10 @@ export class FileListIndex {
27
29
  return;
28
30
  const indexedWithContent = this.index.size;
29
31
  this.index = null;
32
+ this.pathSet = null;
30
33
  this.indexKey = null;
31
34
  this.indexBuiltAt = 0;
35
+ this.indexFresh = false;
32
36
  logger.debug("Cleared file list index", { indexedWithContent });
33
37
  }
34
38
  async ensureReady() {
@@ -43,19 +47,35 @@ export class FileListIndex {
43
47
  }
44
48
  }
45
49
  async lookup(normalizedPath) {
50
+ const match = await this.match(normalizedPath);
51
+ return match.status === "hit" ? match.content : undefined;
52
+ }
53
+ async match(normalizedPath) {
46
54
  await this.ensureReady();
47
- const index = await this.getOrBuild();
48
- if (!index) {
55
+ const snapshot = await this.getOrBuild();
56
+ if (!snapshot) {
49
57
  logger.debug("No file list cache available");
50
- return undefined;
58
+ return { status: "unavailable", fresh: false };
51
59
  }
52
- const content = index.get(normalizedPath);
53
- if (!content) {
60
+ if (!snapshot.paths.has(normalizedPath)) {
54
61
  logger.debug("Content not in file list index", {
55
62
  path: normalizedPath,
56
- indexSize: index.size,
63
+ indexSize: snapshot.content.size,
64
+ fresh: snapshot.fresh,
57
65
  });
58
- return undefined;
66
+ return { status: "missing", fresh: snapshot.fresh };
67
+ }
68
+ const content = snapshot.content.get(normalizedPath);
69
+ if (!content) {
70
+ logger.debug("File list index contains path without inline content", {
71
+ path: normalizedPath,
72
+ fresh: snapshot.fresh,
73
+ });
74
+ return {
75
+ status: "present_without_content",
76
+ fresh: snapshot.fresh,
77
+ path: normalizedPath,
78
+ };
59
79
  }
60
80
  logger.debug("FILE_LIST_CACHE_HIT - serving from file list cache", {
61
81
  path: normalizedPath,
@@ -63,19 +83,43 @@ export class FileListIndex {
63
83
  contentHash: hashPreview(content),
64
84
  contentPreview: previewText(content, 200).replace(/\n/g, "\\n"),
65
85
  });
66
- return content;
86
+ return {
87
+ status: "hit",
88
+ fresh: snapshot.fresh,
89
+ path: normalizedPath,
90
+ content,
91
+ };
67
92
  }
68
93
  async findFirstWithContent(normalizedPaths) {
69
- await this.ensureReady();
70
- const index = await this.getOrBuild();
71
- if (!index)
94
+ const match = await this.findFirstMatch(normalizedPaths);
95
+ if (match.status !== "hit" || !match.path || !match.content)
72
96
  return undefined;
97
+ return { path: match.path, content: match.content };
98
+ }
99
+ async findFirstMatch(normalizedPaths) {
100
+ await this.ensureReady();
101
+ const snapshot = await this.getOrBuild();
102
+ if (!snapshot)
103
+ return { status: "unavailable", fresh: false };
73
104
  for (const path of normalizedPaths) {
74
- const content = index.get(path);
75
- if (content)
76
- return { path, content };
105
+ if (!snapshot.paths.has(path))
106
+ continue;
107
+ const content = snapshot.content.get(path);
108
+ if (content) {
109
+ return {
110
+ status: "hit",
111
+ fresh: snapshot.fresh,
112
+ path,
113
+ content,
114
+ };
115
+ }
116
+ return {
117
+ status: "present_without_content",
118
+ fresh: snapshot.fresh,
119
+ path,
120
+ };
77
121
  }
78
- return undefined;
122
+ return { status: "missing", fresh: snapshot.fresh };
79
123
  }
80
124
  async getOrBuild() {
81
125
  if (!this.getFileListCache) {
@@ -95,7 +139,12 @@ export class FileListIndex {
95
139
  indexSize: this.index.size,
96
140
  indexAgeMs: age,
97
141
  });
98
- return this.index;
142
+ this.indexFresh = false;
143
+ return {
144
+ content: this.index,
145
+ paths: this.pathSet ?? new Set(),
146
+ fresh: false,
147
+ };
99
148
  }
100
149
  logger.debug("getOrBuildFileListIndex: in-memory index too stale, discarding", {
101
150
  indexSize: this.index.size,
@@ -103,7 +152,9 @@ export class FileListIndex {
103
152
  staleLimitMs: INDEX_STALENESS_LIMIT_MS,
104
153
  });
105
154
  this.index = null;
155
+ this.pathSet = null;
106
156
  this.indexKey = null;
157
+ this.indexFresh = false;
107
158
  }
108
159
  logger.debug("[ReadOperations] getOrBuildFileListIndex: getFileListCache returned null/undefined");
109
160
  return null;
@@ -117,18 +168,27 @@ export class FileListIndex {
117
168
  sampleContentPreview: cacheCheckSample?.content?.slice(0, 200)?.replace(/\n/g, "\\n"),
118
169
  });
119
170
  const indexKey = `${fileList.length}:${fileList[0]?.path ?? ""}:${fileList[fileList.length - 1]?.path ?? ""}`;
120
- if (this.index && this.indexKey === indexKey) {
171
+ if (this.index && this.pathSet && this.indexKey === indexKey) {
121
172
  this.indexBuiltAt = Date.now();
122
- return this.index;
173
+ this.indexFresh = true;
174
+ return {
175
+ content: this.index,
176
+ paths: this.pathSet,
177
+ fresh: true,
178
+ };
123
179
  }
124
180
  const index = new Map();
181
+ const pathSet = new Set();
125
182
  for (const file of fileList) {
183
+ pathSet.add(file.path);
126
184
  if (file.content)
127
185
  index.set(file.path, file.content);
128
186
  }
129
187
  this.index = index;
188
+ this.pathSet = pathSet;
130
189
  this.indexKey = indexKey;
131
190
  this.indexBuiltAt = Date.now();
191
+ this.indexFresh = true;
132
192
  const sampleFile = fileList.find((f) => /welcome/i.test(f.path));
133
193
  const sampleContent = sampleFile?.content;
134
194
  logger.debug("Built file list index", {
@@ -139,6 +199,10 @@ export class FileListIndex {
139
199
  sampleContentHash: sampleContent ? hashPreview(sampleContent) : undefined,
140
200
  sampleContentPreview: sampleContent?.slice(0, 200)?.replace(/\n/g, "\\n"),
141
201
  });
142
- return index;
202
+ return {
203
+ content: index,
204
+ paths: pathSet,
205
+ fresh: true,
206
+ };
143
207
  }
144
208
  }
@@ -1,6 +1,9 @@
1
1
  import { READ_OPERATION_EXTENSION_PRIORITY } from "./extension-priority.js";
2
2
  import type { ResolvedContentContext } from "./types.js";
3
3
  export { READ_OPERATION_EXTENSION_PRIORITY };
4
+ export type NotFoundLikeError = Error & {
5
+ code?: string;
6
+ };
4
7
  interface ReadContextProviderLike {
5
8
  isProductionMode: () => boolean;
6
9
  isPersistentCacheInvalidated?: (prefix: string) => boolean;
@@ -28,9 +31,11 @@ interface BuildReadFetchStateOptions {
28
31
  export declare function assertProjectSourcePath(normalizedPath: string): void;
29
32
  export declare function buildReadFetchState(options: BuildReadFetchStateOptions): ReadFetchState;
30
33
  export declare function getResolvedCacheKey(cacheKeyPrefix: string, normalizedResolvedPath: string): string;
34
+ export declare function buildExtensionCandidatePaths(basePath: string): string[];
31
35
  export declare function splitKnownFileExtension(apiPath: string): {
32
36
  originalExtension: string;
33
37
  basePath: string;
34
38
  } | null;
35
39
  export declare function isNotFoundLikeError(error: unknown): boolean;
40
+ export declare function createNotFoundLikeError(path: string): NotFoundLikeError;
36
41
  //# sourceMappingURL=read-operations-helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"read-operations-helpers.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/read-operations-helpers.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iCAAiC,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEzD,OAAO,EAAE,iCAAiC,EAAE,CAAC;AAE7C,UAAU,uBAAuB;IAC/B,gBAAgB,EAAE,MAAM,OAAO,CAAC;IAChC,4BAA4B,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAC3D,yBAAyB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;CAC5D;AAED,UAAU,cAAc;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC;IACtB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,aAAa,EAAE,OAAO,CAAC;IACvB,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACrC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,oBAAoB,EAAE,OAAO,GAAG,SAAS,CAAC;IAC1C,oBAAoB,EAAE,OAAO,CAAC;CAC/B;AAED,UAAU,0BAA0B;IAClC,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,sBAAsB,GAAG,IAAI,CAAC;IAC9C,eAAe,CAAC,EAAE,uBAAuB,CAAC;IAC1C,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CAC/C;AAED,wBAAgB,uBAAuB,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAOpE;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,0BAA0B,GAAG,cAAc,CA2BvF;AAED,wBAAgB,mBAAmB,CACjC,cAAc,EAAE,MAAM,EACtB,sBAAsB,EAAE,MAAM,GAC7B,MAAM,CAER;AAED,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,GACd;IAAE,iBAAiB,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CASxD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAG3D"}
1
+ {"version":3,"file":"read-operations-helpers.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/read-operations-helpers.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iCAAiC,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEzD,OAAO,EAAE,iCAAiC,EAAE,CAAC;AAE7C,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1D,UAAU,uBAAuB;IAC/B,gBAAgB,EAAE,MAAM,OAAO,CAAC;IAChC,4BAA4B,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAC3D,yBAAyB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;CAC5D;AAED,UAAU,cAAc;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC;IACtB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,aAAa,EAAE,OAAO,CAAC;IACvB,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACrC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,oBAAoB,EAAE,OAAO,GAAG,SAAS,CAAC;IAC1C,oBAAoB,EAAE,OAAO,CAAC;CAC/B;AAED,UAAU,0BAA0B;IAClC,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,sBAAsB,GAAG,IAAI,CAAC;IAC9C,eAAe,CAAC,EAAE,uBAAuB,CAAC;IAC1C,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CAC/C;AAED,wBAAgB,uBAAuB,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAOpE;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,0BAA0B,GAAG,cAAc,CA2BvF;AAED,wBAAgB,mBAAmB,CACjC,cAAc,EAAE,MAAM,EACtB,sBAAsB,EAAE,MAAM,GAC7B,MAAM,CAER;AAED,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAEvE;AAED,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,GACd;IAAE,iBAAiB,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CASxD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAG3D;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAEvE"}
@@ -40,6 +40,9 @@ export function buildReadFetchState(options) {
40
40
  export function getResolvedCacheKey(cacheKeyPrefix, normalizedResolvedPath) {
41
41
  return `${cacheKeyPrefix}:${normalizedResolvedPath}`;
42
42
  }
43
+ export function buildExtensionCandidatePaths(basePath) {
44
+ return READ_OPERATION_EXTENSION_PRIORITY.map((ext) => `${basePath}${ext}`);
45
+ }
43
46
  export function splitKnownFileExtension(apiPath) {
44
47
  const extMatch = apiPath.match(/\.(tsx|ts|jsx|js|mdx|md)$/);
45
48
  if (!extMatch)
@@ -54,3 +57,6 @@ export function isNotFoundLikeError(error) {
54
57
  const errorMessage = error instanceof Error ? error.message : String(error);
55
58
  return errorMessage.includes("404") || errorMessage.includes("Not Found");
56
59
  }
60
+ export function createNotFoundLikeError(path) {
61
+ return Object.assign(new Error(`404 Not Found: ${path}`), { code: "ENOENT" });
62
+ }