veryfront 0.1.746 → 0.1.749

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 (91) hide show
  1. package/esm/cli/templates/manifest.js +2 -2
  2. package/esm/deno.js +1 -1
  3. package/esm/src/build/production-build/static-generation.d.ts.map +1 -1
  4. package/esm/src/build/production-build/static-generation.js +2 -0
  5. package/esm/src/cache/backends/api.d.ts.map +1 -1
  6. package/esm/src/cache/backends/api.js +9 -5
  7. package/esm/src/cache/backends/disk.d.ts +1 -1
  8. package/esm/src/cache/backends/disk.d.ts.map +1 -1
  9. package/esm/src/cache/backends/disk.js +41 -13
  10. package/esm/src/cache/backends/glob.d.ts +6 -0
  11. package/esm/src/cache/backends/glob.d.ts.map +1 -0
  12. package/esm/src/cache/backends/glob.js +41 -0
  13. package/esm/src/cache/backends/memory.d.ts +1 -1
  14. package/esm/src/cache/backends/memory.d.ts.map +1 -1
  15. package/esm/src/cache/backends/memory.js +14 -12
  16. package/esm/src/cache/backends/redis.d.ts.map +1 -1
  17. package/esm/src/cache/backends/redis.js +33 -7
  18. package/esm/src/cache/dependency-graph.d.ts +1 -0
  19. package/esm/src/cache/dependency-graph.d.ts.map +1 -1
  20. package/esm/src/cache/dependency-graph.js +15 -1
  21. package/esm/src/cache/paths.d.ts.map +1 -1
  22. package/esm/src/cache/paths.js +5 -0
  23. package/esm/src/embedding/index.d.ts +4 -1
  24. package/esm/src/embedding/index.d.ts.map +1 -1
  25. package/esm/src/embedding/index.js +3 -1
  26. package/esm/src/embedding/rag-store.d.ts.map +1 -1
  27. package/esm/src/embedding/rag-store.js +157 -8
  28. package/esm/src/embedding/react/use-uploads.d.ts +1 -0
  29. package/esm/src/embedding/react/use-uploads.d.ts.map +1 -1
  30. package/esm/src/embedding/react/use-uploads.js +4 -1
  31. package/esm/src/embedding/upload-handler.d.ts +29 -8
  32. package/esm/src/embedding/upload-handler.d.ts.map +1 -1
  33. package/esm/src/embedding/upload-handler.js +66 -6
  34. package/esm/src/html/html-shell-generator.js +5 -5
  35. package/esm/src/html/nonce-injection.d.ts.map +1 -1
  36. package/esm/src/html/nonce-injection.js +11 -4
  37. package/esm/src/html/utils.d.ts +5 -0
  38. package/esm/src/html/utils.d.ts.map +1 -1
  39. package/esm/src/html/utils.js +19 -9
  40. package/esm/src/middleware/builtin/security/redis-rate-limit.d.ts +2 -0
  41. package/esm/src/middleware/builtin/security/redis-rate-limit.d.ts.map +1 -1
  42. package/esm/src/middleware/builtin/security/redis-rate-limit.js +46 -13
  43. package/esm/src/modules/react-loader/ssr-module-loader/import-rewriter.d.ts.map +1 -1
  44. package/esm/src/modules/react-loader/ssr-module-loader/import-rewriter.js +12 -5
  45. package/esm/src/modules/server/module-batch-handler.d.ts +1 -0
  46. package/esm/src/modules/server/module-batch-handler.d.ts.map +1 -1
  47. package/esm/src/modules/server/module-batch-handler.js +52 -26
  48. package/esm/src/modules/server/module-server.d.ts.map +1 -1
  49. package/esm/src/modules/server/module-server.js +87 -69
  50. package/esm/src/modules/server/module-source-resolution-cache.d.ts +16 -0
  51. package/esm/src/modules/server/module-source-resolution-cache.d.ts.map +1 -0
  52. package/esm/src/modules/server/module-source-resolution-cache.js +43 -0
  53. package/esm/src/oauth/providers/base.d.ts +0 -2
  54. package/esm/src/oauth/providers/base.d.ts.map +1 -1
  55. package/esm/src/oauth/providers/base.js +35 -10
  56. package/esm/src/oauth/token-store/memory.d.ts +7 -0
  57. package/esm/src/oauth/token-store/memory.d.ts.map +1 -1
  58. package/esm/src/oauth/token-store/memory.js +14 -1
  59. package/esm/src/observability/auto-instrument/http-instrumentation.d.ts.map +1 -1
  60. package/esm/src/observability/auto-instrument/http-instrumentation.js +10 -6
  61. package/esm/src/observability/file-log-subscriber.d.ts +1 -0
  62. package/esm/src/observability/file-log-subscriber.d.ts.map +1 -1
  63. package/esm/src/observability/file-log-subscriber.js +2 -1
  64. package/esm/src/observability/tracing/api-shim.d.ts +1 -0
  65. package/esm/src/observability/tracing/api-shim.d.ts.map +1 -1
  66. package/esm/src/observability/tracing/api-shim.js +7 -0
  67. package/esm/src/observability/tracing/otlp-setup.d.ts.map +1 -1
  68. package/esm/src/observability/tracing/otlp-setup.js +17 -7
  69. package/esm/src/proxy/handler.d.ts +5 -2
  70. package/esm/src/proxy/handler.d.ts.map +1 -1
  71. package/esm/src/proxy/handler.js +26 -25
  72. package/esm/src/proxy/main.js +8 -11
  73. package/esm/src/rendering/renderer.d.ts.map +1 -1
  74. package/esm/src/rendering/renderer.js +32 -12
  75. package/esm/src/server/context/cache-invalidation.d.ts.map +1 -1
  76. package/esm/src/server/context/cache-invalidation.js +2 -0
  77. package/esm/src/server/handlers/dev/scripts/error-overlay.d.ts.map +1 -1
  78. package/esm/src/server/handlers/dev/scripts/error-overlay.js +32 -18
  79. package/esm/src/server/handlers/monitoring/client-log.handler.d.ts +1 -0
  80. package/esm/src/server/handlers/monitoring/client-log.handler.d.ts.map +1 -1
  81. package/esm/src/server/handlers/monitoring/client-log.handler.js +39 -5
  82. package/esm/src/server/handlers/request/module/batch-module-handler.d.ts.map +1 -1
  83. package/esm/src/server/handlers/request/module/batch-module-handler.js +2 -1
  84. package/esm/src/utils/logger/redact.d.ts +10 -0
  85. package/esm/src/utils/logger/redact.d.ts.map +1 -1
  86. package/esm/src/utils/logger/redact.js +60 -1
  87. package/esm/src/utils/redis-client.d.ts +1 -0
  88. package/esm/src/utils/redis-client.d.ts.map +1 -1
  89. package/esm/src/utils/version-constant.d.ts +1 -1
  90. package/esm/src/utils/version-constant.js +1 -1
  91. package/package.json +1 -1
@@ -1,6 +1,15 @@
1
1
  import { createError, toError } from "../../../errors/veryfront-error.js";
2
2
  import { serverLogger } from "../../../utils/index.js";
3
3
  const logger = serverLogger.component("redis-ratelimit");
4
+ const INCREMENT_WITH_TTL_SCRIPT = `
5
+ local count = redis.call("INCR", KEYS[1])
6
+ local ttl = redis.call("PTTL", KEYS[1])
7
+ if ttl < 0 then
8
+ redis.call("PEXPIRE", KEYS[1], ARGV[1])
9
+ ttl = tonumber(ARGV[1])
10
+ end
11
+ return { count, ttl }
12
+ `;
4
13
  /** Implement redis rate limit store. */
5
14
  export class RedisRateLimitStore {
6
15
  client = null;
@@ -17,6 +26,19 @@ export class RedisRateLimitStore {
17
26
  this.clientPromise ??= this.connectClient();
18
27
  return this.clientPromise;
19
28
  }
29
+ clearCachedClient() {
30
+ this.client = null;
31
+ this.clientPromise = null;
32
+ }
33
+ attachClientLifecycleHandlers(client) {
34
+ client.on?.("error", (err) => {
35
+ logger.error("client error", err);
36
+ this.clearCachedClient();
37
+ });
38
+ client.on?.("end", () => {
39
+ this.clearCachedClient();
40
+ });
41
+ }
20
42
  async connectClient() {
21
43
  let createClient;
22
44
  try {
@@ -34,11 +56,10 @@ export class RedisRateLimitStore {
34
56
  }
35
57
  try {
36
58
  const client = createClient({ url: this.url });
37
- client.on?.("error", (err) => {
38
- logger.error("client error", err);
39
- });
59
+ this.attachClientLifecycleHandlers(client);
40
60
  await client.connect();
41
61
  this.client = client;
62
+ this.clientPromise = null;
42
63
  return client;
43
64
  }
44
65
  catch (error) {
@@ -52,15 +73,10 @@ export class RedisRateLimitStore {
52
73
  async increment(key, windowMs) {
53
74
  const client = await this.ensureClient();
54
75
  const redisKey = this.storageKey(key);
55
- const count = await client.incr(redisKey);
56
- if (count === 1) {
57
- await client.pExpire(redisKey, windowMs);
58
- }
59
- const pttl = await client.pTTL(redisKey);
60
- if (pttl === -1) {
61
- await client.pExpire(redisKey, windowMs);
62
- return { count, resetAt: Date.now() + windowMs };
63
- }
76
+ const [count, pttl] = parseIncrementResult(await client.eval(INCREMENT_WITH_TTL_SCRIPT, {
77
+ keys: [redisKey],
78
+ arguments: [String(windowMs)],
79
+ }));
64
80
  const ttl = pttl > 0 ? pttl : windowMs;
65
81
  return { count, resetAt: Date.now() + ttl };
66
82
  }
@@ -72,6 +88,23 @@ export class RedisRateLimitStore {
72
88
  if (!this.client)
73
89
  return;
74
90
  await this.client.disconnect();
75
- this.client = null;
91
+ this.clearCachedClient();
92
+ }
93
+ }
94
+ function parseIncrementResult(result) {
95
+ if (!Array.isArray(result) || result.length < 2) {
96
+ throw toError(createError({
97
+ type: "config",
98
+ message: "Redis rate limit eval returned an invalid result.",
99
+ }));
100
+ }
101
+ const count = Number(result[0]);
102
+ const ttl = Number(result[1]);
103
+ if (!Number.isFinite(count) || !Number.isFinite(ttl)) {
104
+ throw toError(createError({
105
+ type: "config",
106
+ message: "Redis rate limit eval returned non-numeric values.",
107
+ }));
76
108
  }
109
+ return [count, ttl];
77
110
  }
@@ -1 +1 @@
1
- {"version":3,"file":"import-rewriter.d.ts","sourceRoot":"","sources":["../../../../../src/src/modules/react-loader/ssr-module-loader/import-rewriter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAUH;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,MAAM,CAUR;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,EACnB,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EACrC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GACjB,MAAM,CAyBR"}
1
+ {"version":3,"file":"import-rewriter.d.ts","sourceRoot":"","sources":["../../../../../src/src/modules/react-loader/ssr-module-loader/import-rewriter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAUH;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,MAAM,CAUR;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,EACnB,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EACrC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GACjB,MAAM,CA8BR"}
@@ -34,16 +34,23 @@ export function rewriteLocalImports(transformed, localImportPaths, fromFilePath,
34
34
  const fromRelativeDir = fromFileDir.startsWith(normalizedProjectDir)
35
35
  ? fromFileDir.substring(normalizedProjectDir.length + 1)
36
36
  : fromFileDir;
37
- let result = transformed;
37
+ const replacementByPattern = new Map();
38
38
  for (const [specifierOrPath, tempPath] of localImportPaths) {
39
39
  const patterns = buildImportPatterns(specifierOrPath, fromRelativeDir, normalizedProjectDir);
40
40
  for (const pattern of patterns) {
41
- const escapedPattern = escapeRegExp(pattern);
42
- const regex = new RegExp(`${IMPORT_FROM_PREFIX}(${escapedPattern})${IMPORT_FROM_SUFFIX}`, "g");
43
- result = result.replace(regex, `from "file://${tempPath}"`);
41
+ if (!replacementByPattern.has(pattern)) {
42
+ replacementByPattern.set(pattern, tempPath);
43
+ }
44
44
  }
45
45
  }
46
- return result;
46
+ if (replacementByPattern.size === 0)
47
+ return transformed;
48
+ const importPattern = Array.from(replacementByPattern.keys()).map(escapeRegExp).join("|");
49
+ const regex = new RegExp(`${IMPORT_FROM_PREFIX}(${importPattern})${IMPORT_FROM_SUFFIX}`, "g");
50
+ return transformed.replace(regex, (match, specifier) => {
51
+ const tempPath = replacementByPattern.get(specifier);
52
+ return tempPath === undefined ? match : `from "file://${tempPath}"`;
53
+ });
47
54
  }
48
55
  /**
49
56
  * Build import patterns for a given specifier to match in transformed code.
@@ -22,6 +22,7 @@ export interface BatchHandlerOptions {
22
22
  projectSlug?: string;
23
23
  projectId?: string;
24
24
  branch?: string | null;
25
+ releaseId?: string | null;
25
26
  dev?: boolean;
26
27
  /**
27
28
  * Restrict module imports to specific directories (opt-in security).
@@ -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;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"}
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;AAiGtE,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,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,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,CA6K/F;AA0PD;;GAEG;AACH,wBAAgB,eAAe,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAc1D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAKrE"}
@@ -27,6 +27,7 @@ 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
29
  import { sha256Short } from "../../cache/hash.js";
30
+ import { buildSourceMissCacheKey, clearSourceMissCache, hasSourceMiss, rememberSourceMiss, } from "./module-source-resolution-cache.js";
30
31
  const logger = serverLogger.component("module-batch");
31
32
  /** Slow request threshold in milliseconds */
32
33
  const SLOW_REQUEST_THRESHOLD_MS = 500;
@@ -57,6 +58,30 @@ const FRAMEWORK_EXTENSIONS = [
57
58
  ".jsx",
58
59
  ".js", // Regular sources for dev mode
59
60
  ];
61
+ async function findFirstSecureFile(secureFs, paths) {
62
+ const results = await Promise.all(paths.map(async (path) => {
63
+ try {
64
+ const stat = await secureFs.stat(path);
65
+ return stat.isFile ? path : null;
66
+ }
67
+ catch {
68
+ return null;
69
+ }
70
+ }));
71
+ return results.find((path) => path !== null) ?? null;
72
+ }
73
+ async function findFirstPlatformFile(platformFs, paths) {
74
+ const results = await Promise.all(paths.map(async (path) => {
75
+ try {
76
+ const stat = await platformFs.stat(path);
77
+ return stat.isFile ? path : null;
78
+ }
79
+ catch {
80
+ return null;
81
+ }
82
+ }));
83
+ return results.find((path) => path !== null) ?? null;
84
+ }
60
85
  /**
61
86
  * Handle a batch module request
62
87
  */
@@ -87,7 +112,7 @@ export function handleModuleBatch(req, options) {
87
112
  headers: { "Content-Type": "text/plain" },
88
113
  });
89
114
  }
90
- const { projectDir, adapter, projectSlug, projectId, branch, dev = false, allowedImportDirs, reactVersion, } = options;
115
+ const { projectDir, adapter, projectSlug, projectId, branch, releaseId, dev = false, allowedImportDirs, reactVersion, } = options;
91
116
  const projectKey = projectId || projectSlug || "default";
92
117
  const userAgent = req.headers.get("user-agent") ?? "";
93
118
  const isSSR = url.searchParams.get("ssr") === "true" || userAgent.startsWith("Deno/");
@@ -124,6 +149,7 @@ export function handleModuleBatch(req, options) {
124
149
  projectSlug,
125
150
  branch,
126
151
  projectId,
152
+ releaseId,
127
153
  reactVersion,
128
154
  });
129
155
  const transformDurationMs = performance.now() - moduleStart;
@@ -196,21 +222,27 @@ export function handleModuleBatch(req, options) {
196
222
  */
197
223
  async function loadAndTransformModule(modulePath, projectDir, adapter, secureFs, options) {
198
224
  const basePath = modulePath.replace(/\.js$/, "");
199
- for (const ext of EXTENSIONS) {
200
- const fullPath = join(projectDir, basePath + ext);
201
- try {
202
- const stat = await secureFs.stat(fullPath);
203
- if (!stat.isFile)
204
- continue;
205
- const source = await secureFs.readFile(fullPath);
206
- return transformModule(source, fullPath, modulePath, projectDir, adapter, secureFs, options);
207
- }
208
- catch (_) {
209
- /* expected: file may not exist at this extension */
210
- }
225
+ const missCacheKey = buildSourceMissCacheKey({
226
+ resolver: "module-batch",
227
+ projectDir,
228
+ projectId: options.projectId,
229
+ projectSlug: options.projectSlug,
230
+ branch: options.branch,
231
+ releaseId: options.releaseId,
232
+ basePath,
233
+ reactVersion: options.reactVersion,
234
+ });
235
+ if (hasSourceMiss(missCacheKey))
236
+ return null;
237
+ const sourcePath = await findFirstSecureFile(secureFs, EXTENSIONS.map((ext) => join(projectDir, basePath + ext)));
238
+ if (sourcePath) {
239
+ const source = await secureFs.readFile(sourcePath);
240
+ return transformModule(source, sourcePath, modulePath, projectDir, adapter, secureFs, options);
211
241
  }
212
- if (!basePath.startsWith("lib/"))
242
+ if (!basePath.startsWith("lib/")) {
243
+ rememberSourceMiss(missCacheKey);
213
244
  return null;
245
+ }
214
246
  // Framework lookup directories in priority order
215
247
  const frameworkLookupDirs = [
216
248
  EMBEDDED_SRC_DIR, // Embedded sources for compiled binaries (.src files)
@@ -218,20 +250,13 @@ async function loadAndTransformModule(modulePath, projectDir, adapter, secureFs,
218
250
  ];
219
251
  const platformFs = createFileSystem();
220
252
  for (const lookupDir of frameworkLookupDirs) {
221
- for (const ext of FRAMEWORK_EXTENSIONS) {
222
- const frameworkPath = join(lookupDir, basePath + ext);
223
- try {
224
- const stat = await platformFs.stat(frameworkPath);
225
- if (!stat.isFile)
226
- continue;
227
- const source = await platformFs.readTextFile(frameworkPath);
228
- return transformModule(source, frameworkPath, modulePath, projectDir, adapter, secureFs, options);
229
- }
230
- catch (_) {
231
- /* expected: framework file may not exist at this extension */
232
- }
253
+ const frameworkPath = await findFirstPlatformFile(platformFs, FRAMEWORK_EXTENSIONS.map((ext) => join(lookupDir, basePath + ext)));
254
+ if (frameworkPath) {
255
+ const source = await platformFs.readTextFile(frameworkPath);
256
+ return transformModule(source, frameworkPath, modulePath, projectDir, adapter, secureFs, options);
233
257
  }
234
258
  }
259
+ rememberSourceMiss(missCacheKey);
235
260
  return null;
236
261
  }
237
262
  async function transformModule(source, sourceFile, modulePath, projectDir, adapter, secureFs, options) {
@@ -369,6 +394,7 @@ function transformExportsForBundle(code) {
369
394
  * Clear the transform cache (on deployment or memory pressure)
370
395
  */
371
396
  export function clearBatchCache(projectSlug) {
397
+ clearSourceMissCache("module-batch");
372
398
  if (!projectSlug) {
373
399
  transformCache.clear();
374
400
  logger.debug("Cleared all cache");
@@ -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;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"}
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;AAkCtE;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAsDrD,CAAC;AAiBF,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,CAkWzF;AAiVD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAGrD"}
@@ -17,6 +17,7 @@ import { FRAMEWORK_ROOT, resolveFrameworkSourcePath, } from "../../platform/comp
17
17
  import { getReactUrls, REACT_DEFAULT_VERSION } from "../../utils/constants/cdn.js";
18
18
  import { readLimitedCrossProjectSource } from "./cross-project-source-limit.js";
19
19
  import { sha256Short } from "../../cache/hash.js";
20
+ import { buildSourceMissCacheKey, hasSourceMiss, rememberSourceMiss, } from "./module-source-resolution-cache.js";
20
21
  const logger = serverLogger.component("module-server");
21
22
  /**
22
23
  * Embedded polyfills for compiled Deno binaries.
@@ -161,6 +162,10 @@ export function serveModule(req, options) {
161
162
  secureFs,
162
163
  projectDir,
163
164
  currentModulePath: `_snippets/${hash}.js`,
165
+ projectId: effectiveProjectId,
166
+ projectSlug: snippetProjectSlug,
167
+ branch: snippetBranch,
168
+ releaseId: options.releaseId,
164
169
  reactVersion,
165
170
  }),
166
171
  });
@@ -229,6 +234,8 @@ export function serveModule(req, options) {
229
234
  projectDir,
230
235
  currentModulePath: crossPath,
231
236
  crossProjectRef: projectRef,
237
+ projectId: effectiveProjectId,
238
+ releaseId: options.releaseId,
232
239
  reactVersion,
233
240
  }),
234
241
  });
@@ -262,7 +269,13 @@ export function serveModule(req, options) {
262
269
  branch ??= parsedHost.branch;
263
270
  }
264
271
  try {
265
- const findResult = await findSourceFile(secureFs, projectDir, filePathWithoutExt, reactVersion);
272
+ const findResult = await findSourceFile(secureFs, projectDir, filePathWithoutExt, {
273
+ projectId: effectiveProjectId,
274
+ projectSlug,
275
+ branch,
276
+ releaseId: options.releaseId,
277
+ reactVersion,
278
+ });
266
279
  if (!findResult) {
267
280
  logger.warn("Module not found", {
268
281
  modulePath,
@@ -326,6 +339,10 @@ export function serveModule(req, options) {
326
339
  secureFs,
327
340
  projectDir,
328
341
  currentModulePath: modulePath,
342
+ projectId: effectiveProjectId,
343
+ projectSlug,
344
+ branch,
345
+ releaseId: options.releaseId,
329
346
  reactVersion,
330
347
  }),
331
348
  });
@@ -375,7 +392,13 @@ function createSSRTargetCacheBusterResolver(options) {
375
392
  const source = await fetchCrossProjectSource(options.crossProjectRef, targetPath);
376
393
  return source === null ? undefined : await sha256Short(`${targetPath}\0${source}`);
377
394
  }
378
- const findResult = await findSourceFile(options.secureFs, options.projectDir, stripSSRModuleJsExtension(targetPath), options.reactVersion);
395
+ const findResult = await findSourceFile(options.secureFs, options.projectDir, stripSSRModuleJsExtension(targetPath), {
396
+ projectId: options.projectId,
397
+ projectSlug: options.projectSlug,
398
+ branch: options.branch,
399
+ releaseId: options.releaseId,
400
+ reactVersion: options.reactVersion,
401
+ });
379
402
  if (!findResult)
380
403
  return undefined;
381
404
  const source = await readSourceFileForVersion(options.secureFs, findResult);
@@ -415,20 +438,34 @@ function createBrowserReactPackageShim(basePathWithoutExt, reactVersion = REACT_
415
438
  async function findFrameworkPackageAssetFile(fs, basePathWithoutExt, extensions) {
416
439
  if (hasUnsafePackageAssetPath(basePathWithoutExt))
417
440
  return null;
418
- for (const ext of extensions) {
419
- const candidatePath = join(FRAMEWORK_ROOT, basePathWithoutExt + ext);
441
+ return await findFirstPlatformFile(fs, extensions.map((ext) => join(FRAMEWORK_ROOT, basePathWithoutExt + ext)));
442
+ }
443
+ async function findFirstPlatformFile(fs, paths) {
444
+ const results = await Promise.all(paths.map(async (path) => {
420
445
  try {
421
- const stat = await fs.stat(candidatePath);
422
- if (stat.isFile)
423
- return candidatePath;
446
+ const stat = await fs.stat(path);
447
+ return stat.isFile ? path : null;
424
448
  }
425
449
  catch {
426
- /* expected: package asset may not exist in source checkouts */
450
+ return null;
427
451
  }
428
- }
429
- return null;
452
+ }));
453
+ return results.find((path) => path !== null) ?? null;
430
454
  }
431
- async function findSourceFile(secureFs, projectDir, basePath, reactVersion) {
455
+ async function findFirstSecureFile(secureFs, paths) {
456
+ const results = await Promise.all(paths.map(async (path) => {
457
+ try {
458
+ const stat = await secureFs.stat(path);
459
+ return stat.isFile ? path : null;
460
+ }
461
+ catch {
462
+ return null;
463
+ }
464
+ }));
465
+ return results.find((path) => path !== null) ?? null;
466
+ }
467
+ async function findSourceFile(secureFs, projectDir, basePath, context) {
468
+ const { reactVersion } = context;
432
469
  // Extensions including .src for compiled binary embedded sources
433
470
  const extensions = [
434
471
  ".json",
@@ -457,6 +494,16 @@ async function findSourceFile(secureFs, projectDir, basePath, reactVersion) {
457
494
  const isFrameworkPath = basePathWithoutExt.startsWith("_veryfront/");
458
495
  const isFrameworkPackageAssetPath = basePathWithoutExt.startsWith("react/") ||
459
496
  basePathWithoutExt.startsWith("deps/");
497
+ const missCacheKey = buildSourceMissCacheKey({
498
+ resolver: "module-server",
499
+ projectDir,
500
+ projectId: context.projectId,
501
+ projectSlug: context.projectSlug,
502
+ branch: context.branch,
503
+ releaseId: context.releaseId,
504
+ basePath: basePathWithoutExt,
505
+ reactVersion,
506
+ });
460
507
  // Check embedded polyfills first (no filesystem access needed).
461
508
  // These cover both compiled-binary polyfills (node:async_hooks etc.)
462
509
  // and dnt build artifacts (_dnt.shims, _dnt.polyfills) that don't
@@ -475,6 +522,8 @@ async function findSourceFile(secureFs, projectDir, basePath, reactVersion) {
475
522
  embeddedContent,
476
523
  };
477
524
  }
525
+ if (hasSourceMiss(missCacheKey))
526
+ return null;
478
527
  if (isFrameworkPackageAssetPath) {
479
528
  const browserReactShim = createBrowserReactPackageShim(basePathWithoutExt, reactVersion);
480
529
  if (browserReactShim) {
@@ -525,78 +574,47 @@ async function findSourceFile(secureFs, projectDir, basePath, reactVersion) {
525
574
  }
526
575
  }
527
576
  // Project file lookups (using secureFs which may go through FSAdapter in proxy mode)
528
- for (const ext of extensions) {
529
- const fullPath = join(projectDir, basePathWithoutExt + ext);
530
- try {
531
- const stat = await secureFs.stat(fullPath);
532
- if (stat.isFile) {
533
- logger.debug("Found file", { basePath, resolvedPath: fullPath });
534
- return { path: fullPath, isFrameworkFile: false };
535
- }
536
- }
537
- catch (_) {
538
- /* expected: file may not exist at this extension */
539
- }
577
+ const projectFilePath = await findFirstSecureFile(secureFs, extensions.map((ext) => join(projectDir, basePathWithoutExt + ext)));
578
+ if (projectFilePath) {
579
+ logger.debug("Found file", { basePath, resolvedPath: projectFilePath });
580
+ return { path: projectFilePath, isFrameworkFile: false };
540
581
  }
541
582
  const prefixesToStrip = ["components/", "pages/", "lib/", "app/", "src/"];
542
583
  for (const prefix of prefixesToStrip) {
543
584
  if (!basePathWithoutExt.startsWith(prefix))
544
585
  continue;
545
586
  const strippedPath = basePathWithoutExt.slice(prefix.length);
546
- for (const ext of extensions) {
547
- const fullPath = join(projectDir, strippedPath + ext);
548
- try {
549
- const stat = await secureFs.stat(fullPath);
550
- if (stat.isFile) {
551
- logger.debug("Found file after stripping prefix", {
552
- originalPath: basePathWithoutExt,
553
- strippedPath,
554
- resolvedPath: fullPath,
555
- });
556
- return { path: fullPath, isFrameworkFile: false };
557
- }
558
- }
559
- catch (_) {
560
- /* expected: file may not exist after stripping prefix */
561
- }
587
+ const strippedFilePath = await findFirstSecureFile(secureFs, extensions.map((ext) => join(projectDir, strippedPath + ext)));
588
+ if (strippedFilePath) {
589
+ logger.debug("Found file after stripping prefix", {
590
+ originalPath: basePathWithoutExt,
591
+ strippedPath,
592
+ resolvedPath: strippedFilePath,
593
+ });
594
+ return { path: strippedFilePath, isFrameworkFile: false };
562
595
  }
563
596
  }
564
- for (const ext of extensions) {
565
- const fullPath = join(projectDir, basePathWithoutExt, `index${ext}`);
566
- try {
567
- const stat = await secureFs.stat(fullPath);
568
- if (stat.isFile) {
569
- logger.debug("Found index file", {
570
- basePath: basePathWithoutExt,
571
- resolvedPath: fullPath,
572
- });
573
- return { path: fullPath, isFrameworkFile: false };
574
- }
575
- }
576
- catch (_) {
577
- /* expected: index file may not exist at this extension */
578
- }
597
+ const indexFilePath = await findFirstSecureFile(secureFs, extensions.map((ext) => join(projectDir, basePathWithoutExt, `index${ext}`)));
598
+ if (indexFilePath) {
599
+ logger.debug("Found index file", {
600
+ basePath: basePathWithoutExt,
601
+ resolvedPath: indexFilePath,
602
+ });
603
+ return { path: indexFilePath, isFrameworkFile: false };
579
604
  }
580
605
  // Try looking in common project directories
581
606
  const commonDirs = ["components", "app", "pages", "lib", "src"];
582
607
  for (const dir of commonDirs) {
583
- for (const ext of extensions) {
584
- const fullPath = join(projectDir, dir, basePathWithoutExt + ext);
585
- try {
586
- const stat = await secureFs.stat(fullPath);
587
- if (stat.isFile) {
588
- logger.debug("Found file in common directory", {
589
- basePath,
590
- resolvedPath: fullPath,
591
- });
592
- return { path: fullPath, isFrameworkFile: false };
593
- }
594
- }
595
- catch (_) {
596
- /* expected: file may not exist in common directory */
597
- }
608
+ const commonDirFilePath = await findFirstSecureFile(secureFs, extensions.map((ext) => join(projectDir, dir, basePathWithoutExt + ext)));
609
+ if (commonDirFilePath) {
610
+ logger.debug("Found file in common directory", {
611
+ basePath,
612
+ resolvedPath: commonDirFilePath,
613
+ });
614
+ return { path: commonDirFilePath, isFrameworkFile: false };
598
615
  }
599
616
  }
617
+ rememberSourceMiss(missCacheKey);
600
618
  return null;
601
619
  }
602
620
  /**
@@ -0,0 +1,16 @@
1
+ type ModuleSourceResolver = "module-server" | "module-batch";
2
+ export declare function buildSourceMissCacheKey(options: {
3
+ resolver: ModuleSourceResolver;
4
+ projectDir: string;
5
+ projectId?: string;
6
+ projectSlug?: string | null;
7
+ branch?: string | null;
8
+ releaseId?: string | null;
9
+ basePath: string;
10
+ reactVersion?: string;
11
+ }): string;
12
+ export declare function hasSourceMiss(cacheKey: string): boolean;
13
+ export declare function rememberSourceMiss(cacheKey: string): void;
14
+ export declare function clearSourceMissCache(resolver?: ModuleSourceResolver): void;
15
+ export {};
16
+ //# sourceMappingURL=module-source-resolution-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-source-resolution-cache.d.ts","sourceRoot":"","sources":["../../../../src/src/modules/server/module-source-resolution-cache.ts"],"names":[],"mappings":"AAGA,KAAK,oBAAoB,GAAG,eAAe,GAAG,cAAc,CAAC;AAgB7D,wBAAgB,uBAAuB,CAAC,OAAO,EAAE;IAC/C,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,MAAM,CAWT;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAEzD;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAO1E"}
@@ -0,0 +1,43 @@
1
+ import { registerLRUCache } from "../../cache/index.js";
2
+ import { LRUCache } from "../../utils/lru-wrapper.js";
3
+ const SOURCE_MISS_CACHE_MAX_ENTRIES = 5_000;
4
+ const sourceMissCaches = {
5
+ "module-server": new LRUCache({
6
+ maxEntries: SOURCE_MISS_CACHE_MAX_ENTRIES,
7
+ }),
8
+ "module-batch": new LRUCache({
9
+ maxEntries: SOURCE_MISS_CACHE_MAX_ENTRIES,
10
+ }),
11
+ };
12
+ registerLRUCache("module-server-source-miss-cache", sourceMissCaches["module-server"]);
13
+ registerLRUCache("module-batch-source-miss-cache", sourceMissCaches["module-batch"]);
14
+ export function buildSourceMissCacheKey(options) {
15
+ return [
16
+ options.resolver,
17
+ options.projectDir,
18
+ options.projectId ?? "",
19
+ options.projectSlug ?? "",
20
+ options.branch ?? "",
21
+ options.releaseId ?? "",
22
+ options.reactVersion ?? "",
23
+ options.basePath,
24
+ ].join("\0");
25
+ }
26
+ export function hasSourceMiss(cacheKey) {
27
+ return sourceMissCaches[getResolverFromCacheKey(cacheKey)].has(cacheKey);
28
+ }
29
+ export function rememberSourceMiss(cacheKey) {
30
+ sourceMissCaches[getResolverFromCacheKey(cacheKey)].set(cacheKey, true);
31
+ }
32
+ export function clearSourceMissCache(resolver) {
33
+ if (resolver) {
34
+ sourceMissCaches[resolver].clear();
35
+ return;
36
+ }
37
+ for (const cache of Object.values(sourceMissCaches))
38
+ cache.clear();
39
+ }
40
+ function getResolverFromCacheKey(cacheKey) {
41
+ const resolver = cacheKey.split("\0", 1)[0];
42
+ return resolver === "module-batch" ? "module-batch" : "module-server";
43
+ }
@@ -36,11 +36,9 @@ export declare class OAuthProvider {
36
36
  export declare class OAuthService extends OAuthProvider {
37
37
  protected serviceConfig: OAuthServiceConfig;
38
38
  protected tokenStore?: TokenStore;
39
- private refreshPromises;
40
39
  constructor(config: OAuthServiceConfig, tokenStore?: TokenStore, envReader?: EnvReader);
41
40
  get serviceId(): string;
42
41
  get apiBaseUrl(): string;
43
- private refreshKey;
44
42
  createAuthorizationUrl(options?: AuthorizationUrlOptions): Promise<{
45
43
  url: string;
46
44
  state: OAuthState;
@@ -1 +1 @@
1
- {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../../src/src/oauth/providers/base.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,uBAAuB,EACvB,mBAAmB,EACnB,kBAAkB,EAClB,UAAU,EAEV,oBAAoB,EACpB,mBAAmB,EACnB,UAAU,EACX,MAAM,aAAa,CAAC;AAarB,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;AAuB5D,gCAAgC;AAChC,qBAAa,aAAa;IACxB,SAAS,CAAC,MAAM,EAAE,mBAAmB,CAAC;IACtC,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC;gBAEnB,MAAM,EAAE,mBAAmB,EAAE,SAAS,GAAE,SAAkB;IAKtE,WAAW,IAAI,MAAM,GAAG,IAAI;IAI5B,eAAe,IAAI,MAAM,GAAG,IAAI;IAIhC,YAAY,IAAI,OAAO;IAIjB,sBAAsB,CAC1B,OAAO,GAAE,uBAAuB,GAAG;QAAE,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;KAAO,GACnE,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,UAAU,CAAA;KAAE,CAAC;IA0C9C,OAAO,CAAC,iBAAiB;IAazB;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;YA0CZ,gBAAgB;IAe9B,OAAO,CAAC,4BAA4B;YAQtB,aAAa;IAyCrB,YAAY,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAgCzE,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAwBjE,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAiBnD;AAED,+BAA+B;AAC/B,qBAAa,YAAa,SAAQ,aAAa;IAC7C,SAAS,CAAC,aAAa,EAAE,kBAAkB,CAAC;IAC5C,SAAS,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;IAClC,OAAO,CAAC,eAAe,CAA6C;gBAExD,MAAM,EAAE,kBAAkB,EAAE,UAAU,CAAC,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,SAAS;IAMtF,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,OAAO,CAAC,UAAU;IAIT,sBAAsB,CAC7B,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,UAAU,CAAA;KAAE,CAAC;IAO9C;;;;;;OAMG;IACG,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;YAyB9C,0BAA0B;IAcxC;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;IAuBpB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,CAAC,CAAC;CA+BxF"}
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../../src/src/oauth/providers/base.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,uBAAuB,EACvB,mBAAmB,EACnB,kBAAkB,EAClB,UAAU,EAEV,oBAAoB,EACpB,mBAAmB,EACnB,UAAU,EACX,MAAM,aAAa,CAAC;AAarB,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;AAuB5D,gCAAgC;AAChC,qBAAa,aAAa;IACxB,SAAS,CAAC,MAAM,EAAE,mBAAmB,CAAC;IACtC,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC;gBAEnB,MAAM,EAAE,mBAAmB,EAAE,SAAS,GAAE,SAAkB;IAKtE,WAAW,IAAI,MAAM,GAAG,IAAI;IAI5B,eAAe,IAAI,MAAM,GAAG,IAAI;IAIhC,YAAY,IAAI,OAAO;IAIjB,sBAAsB,CAC1B,OAAO,GAAE,uBAAuB,GAAG;QAAE,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;KAAO,GACnE,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,UAAU,CAAA;KAAE,CAAC;IA0C9C,OAAO,CAAC,iBAAiB;IAazB;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;YA0CZ,gBAAgB;IAe9B,OAAO,CAAC,4BAA4B;YAQtB,aAAa;IAyCrB,YAAY,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAgCzE,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAwBjE,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAiBnD;AA2CD,+BAA+B;AAC/B,qBAAa,YAAa,SAAQ,aAAa;IAC7C,SAAS,CAAC,aAAa,EAAE,kBAAkB,CAAC;IAC5C,SAAS,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;gBAEtB,MAAM,EAAE,kBAAkB,EAAE,UAAU,CAAC,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,SAAS;IAMtF,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,IAAI,UAAU,IAAI,MAAM,CAEvB;IAEQ,sBAAsB,CAC7B,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,UAAU,CAAA;KAAE,CAAC;IAO9C;;;;;;OAMG;IACG,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;YA4B9C,0BAA0B;IAcxC;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;IAuBpB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,CAAC,CAAC;CA+BxF"}