@epic-web/workshop-utils 6.45.7 → 6.47.0

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/README.md CHANGED
@@ -1,3 +1,62 @@
1
- # Workshop Utils
1
+ # @epic-web/workshop-utils
2
2
 
3
- Just a bunch of utils for a workshop....
3
+ Shared utilities for the Epic Workshop ecosystem.
4
+
5
+ This package is primarily consumed by the Epic Workshop App, the `epicshop` CLI,
6
+ and related tooling. It exposes many **subpath exports** (for example
7
+ `@epic-web/workshop-utils/config.server`).
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ npm install @epic-web/workshop-utils
13
+ ```
14
+
15
+ ## Important: server-only modules
16
+
17
+ Any module with `.server` in the import path is **server-only** and must not be
18
+ imported into browser/client bundles.
19
+
20
+ Examples of server-only entrypoints:
21
+
22
+ - `@epic-web/workshop-utils/config.server`
23
+ - `@epic-web/workshop-utils/db.server`
24
+ - `@epic-web/workshop-utils/git.server`
25
+
26
+ ## Common usage
27
+
28
+ ### Initialize env (CLI/tools)
29
+
30
+ Some tools import the env initializer for side effects:
31
+
32
+ ```js
33
+ import '@epic-web/workshop-utils/init-env'
34
+ ```
35
+
36
+ ### Small helpers
37
+
38
+ ```js
39
+ import { getErrorMessage } from '@epic-web/workshop-utils/utils'
40
+
41
+ try {
42
+ // ...
43
+ } catch (error) {
44
+ console.error(getErrorMessage(error))
45
+ }
46
+ ```
47
+
48
+ ## What’s exported?
49
+
50
+ This package uses explicit subpath exports. The canonical list is the `exports`
51
+ map in `package.json`.
52
+
53
+ Repository:
54
+ `https://github.com/epicweb-dev/epicshop/tree/main/packages/workshop-utils/package.json`
55
+
56
+ ## Documentation
57
+
58
+ - Repo docs: `https://github.com/epicweb-dev/epicshop/tree/main/docs`
59
+
60
+ ## License
61
+
62
+ GPL-3.0-only.
@@ -249,6 +249,8 @@ export declare const directoryEmptyCache: {
249
249
  };
250
250
  export declare const discordCache: C.Cache<unknown>;
251
251
  export declare const epicApiCache: C.Cache<unknown>;
252
+ export declare function makeGlobalFsCache<CacheEntryType>(name: string): C.Cache<CacheEntryType>;
253
+ export declare const githubCache: C.Cache<unknown>;
252
254
  export declare const WorkshopCacheSchema: z.ZodEffects<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodObject<{
253
255
  key: z.ZodString;
254
256
  entry: z.ZodObject<{
@@ -389,6 +391,34 @@ export declare function getAllWorkshopCaches(): Promise<{
389
391
  }>;
390
392
  }>;
391
393
  }[]>;
394
+ export declare function globalCacheDirectoryExists(): Promise<boolean>;
395
+ export declare function getGlobalCaches(): Promise<{
396
+ workshopId: string;
397
+ caches: Array<{
398
+ name: string;
399
+ entries: Array<{
400
+ key: string;
401
+ entry: {
402
+ metadata: {
403
+ createdTime: number;
404
+ ttl?: number | null | undefined;
405
+ swr?: number | undefined;
406
+ };
407
+ value?: unknown;
408
+ };
409
+ size?: number | undefined;
410
+ filepath?: string | undefined;
411
+ } & {
412
+ filename: string;
413
+ }>;
414
+ skippedFiles?: Array<{
415
+ filename: string;
416
+ error: string;
417
+ size: number;
418
+ skipped: true;
419
+ }>;
420
+ }>;
421
+ }[]>;
392
422
  export declare function getWorkshopFileCaches(): Promise<Record<string, any>>;
393
423
  export declare function readEntryByPath(cacheFilePath: string): Promise<any>;
394
424
  export declare function deleteCache(): Promise<null | undefined>;
@@ -1 +1 @@
1
- {"version":3,"file":"cache.server.d.ts","sourceRoot":"","sources":["../../src/cache.server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cache.server.d.ts","sourceRoot":"","sources":["../../src/cache.server.ts"],"names":[],"mappings":"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"}
@@ -180,6 +180,50 @@ export const notificationsCache = makeSingletonCache('NotificationsCache');
180
180
  export const directoryEmptyCache = makeSingletonCache('DirectoryEmptyCache');
181
181
  export const discordCache = makeSingletonFsCache('DiscordCache');
182
182
  export const epicApiCache = makeSingletonFsCache('EpicApiCache');
183
+ export function makeGlobalFsCache(name) {
184
+ return remember(`global-${name}`, () => {
185
+ const cacheInstanceDir = path.join(cacheDir, 'global', name);
186
+ const fsCache = {
187
+ name: `Filesystem cache (global-${name})`,
188
+ async get(key) {
189
+ const filePath = path.join(cacheInstanceDir, md5(key));
190
+ try {
191
+ const stats = await fsExtra.stat(filePath);
192
+ if (stats.size > MAX_CACHE_FILE_SIZE) {
193
+ const sizeInMB = (stats.size / (1024 * 1024)).toFixed(2);
194
+ log.warn(`Skipping large cache file ${filePath} (${sizeInMB}MB > 3MB limit). ` +
195
+ `Consider clearing "${name}" cache for key: ${key}`);
196
+ return null;
197
+ }
198
+ }
199
+ catch (error) {
200
+ if (error instanceof Error &&
201
+ 'code' in error &&
202
+ error.code === 'ENOENT') {
203
+ return null;
204
+ }
205
+ }
206
+ const data = await readJSONWithRetries(filePath);
207
+ if (data?.entry)
208
+ return data.entry;
209
+ return null;
210
+ },
211
+ async set(key, entry) {
212
+ const filePath = path.join(cacheInstanceDir, md5(key));
213
+ const tempPath = `${filePath}.tmp`;
214
+ await fsExtra.ensureDir(path.dirname(filePath));
215
+ await fsExtra.writeJSON(tempPath, { key, entry });
216
+ await fsExtra.move(tempPath, filePath, { overwrite: true });
217
+ },
218
+ async delete(key) {
219
+ const filePath = path.join(cacheInstanceDir, md5(key));
220
+ await fsExtra.remove(filePath);
221
+ },
222
+ };
223
+ return fsCache;
224
+ });
225
+ }
226
+ export const githubCache = makeGlobalFsCache('GitHubCache');
183
227
  async function readJsonFilesInDirectory(dir) {
184
228
  const files = await fsExtra.readdir(dir);
185
229
  const entries = await Promise.all(files
@@ -343,13 +387,35 @@ export const WorkshopCacheSchema = z
343
387
  });
344
388
  export async function getAllWorkshopCaches() {
345
389
  const files = await readJsonFilesInDirectory(cacheDir);
346
- const parseResult = WorkshopCacheSchema.safeParse(files);
390
+ // Exclude the global directory from workshop caches
391
+ const { global, ...workshopCaches } = files;
392
+ const parseResult = WorkshopCacheSchema.safeParse(workshopCaches);
347
393
  if (!parseResult.success) {
348
394
  log.error('Failed to parse workshop caches:', parseResult.error);
349
395
  return [];
350
396
  }
351
397
  return parseResult.data;
352
398
  }
399
+ export async function globalCacheDirectoryExists() {
400
+ const globalCacheDir = path.join(cacheDir, 'global');
401
+ return await fsExtra.exists(globalCacheDir);
402
+ }
403
+ export async function getGlobalCaches() {
404
+ const globalCacheDir = path.join(cacheDir, 'global');
405
+ if (!(await fsExtra.exists(globalCacheDir))) {
406
+ return [];
407
+ }
408
+ const files = await readJsonFilesInDirectory(globalCacheDir);
409
+ const parseResult = WorkshopCacheSchema.safeParse({ global: files });
410
+ if (!parseResult.success) {
411
+ log.error('Failed to parse global caches:', parseResult.error);
412
+ return [];
413
+ }
414
+ return parseResult.data.map((workshopCache) => ({
415
+ ...workshopCache,
416
+ workshopId: 'global',
417
+ }));
418
+ }
353
419
  export async function getWorkshopFileCaches() {
354
420
  const workshopCacheDir = path.join(cacheDir, getEnv().EPICSHOP_WORKSHOP_INSTANCE_ID);
355
421
  const caches = readJsonFilesInDirectory(workshopCacheDir);
@@ -1 +1 @@
1
- {"version":3,"file":"cache.server.js","sourceRoot":"","sources":["../../src/cache.server.ts"],"names":[],"mappings":"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","sourcesContent":["// eslint-disable-next-line import/order -- this must be first\nimport { getEnv } from './init-env.js'\n\nimport path from 'path'\nimport * as C from '@epic-web/cachified'\nimport { type CacheEntry, type CreateReporter } from '@epic-web/cachified'\nimport { remember } from '@epic-web/remember'\nimport fsExtra from 'fs-extra'\nimport { LRUCache } from 'lru-cache'\nimport md5 from 'md5-hex'\nimport z from 'zod'\nimport {\n\ttype ExampleApp,\n\ttype PlaygroundApp,\n\ttype ProblemApp,\n\ttype SolutionApp,\n} from './apps.server.js'\nimport { resolveCacheDir } from './data-storage.server.js'\nimport { logger } from './logger.js'\nimport { type Notification } from './notifications.server.js'\nimport { cachifiedTimingReporter, type Timings } from './timing.server.js'\nimport { checkConnection } from './utils.server.js'\n\nconst MAX_CACHE_FILE_SIZE = 3 * 1024 * 1024 // 3MB in bytes\nconst cacheDir = resolveCacheDir()\nconst log = logger('epic:cache')\n\n// Throttle repeated Sentry reports for corrupted cache files to reduce noise\nconst corruptedReportThrottle = remember(\n\t'epic:cache:corruption-throttle',\n\t() => new LRUCache<string, number>({ max: 2000, ttl: 60_000 }),\n)\n\n// Format cache time helper function (copied from @epic-web/cachified for consistency)\nfunction formatCacheTime(\n\tmetadata: any,\n\tformatDuration: (ms: number) => string,\n): string {\n\tconst ttl = metadata?.ttl\n\tif (ttl === undefined || ttl === Infinity) return 'forever'\n\treturn formatDuration(ttl)\n}\n\n// Default duration formatter (copied from @epic-web/cachified for consistency)\nfunction defaultFormatDuration(ms: number): string {\n\tif (ms < 1000) return `${Math.round(ms)}ms`\n\tif (ms < 60000) return `${Math.round(ms / 1000)}s`\n\tif (ms < 3600000) return `${Math.round(ms / 60000)}m`\n\treturn `${Math.round(ms / 3600000)}h`\n}\n\n/**\n * Creates a cachified reporter that integrates with the Epic Workshop logger system.\n * Uses the pattern `epic:cache:{name-of-cache}` for logger namespaces.\n * Only logs when the specific cache namespace is enabled via NODE_DEBUG.\n */\nexport function epicCacheReporter<Value>({\n\tformatDuration = defaultFormatDuration,\n\tperformance = globalThis.performance || Date,\n}: {\n\tformatDuration?: (ms: number) => string\n\tperformance?: Pick<typeof Date, 'now'>\n} = {}): CreateReporter<Value> {\n\treturn ({ key, fallbackToCache, forceFresh, metadata, cache }) => {\n\t\t// Determine cache name for logger namespace\n\t\tconst cacheName =\n\t\t\tcache.name || cache.toString().replace(/^\\[object (.*?)]$/, '$1')\n\n\t\t// Create logger with epic:cache:{name} pattern\n\t\t// Extract a reasonable cache name from longer descriptions\n\t\tlet loggerSuffix = 'unknown'\n\t\tif (cacheName.includes('(') && cacheName.includes(')')) {\n\t\t\t// Extract name from \"Filesystem cache (CacheName)\" format\n\t\t\tconst match = cacheName.match(/\\(([^)]+)\\)/)\n\t\t\tloggerSuffix = (match?.[1] ?? 'unknown').toLowerCase()\n\t\t} else if (cacheName === 'LRUCache') {\n\t\t\t// For LRU caches, we can't determine the name from the cache object alone\n\t\t\tloggerSuffix = 'lru'\n\t\t} else {\n\t\t\tloggerSuffix = cacheName.toLowerCase()\n\t\t}\n\n\t\tconst cacheLog = log.logger(loggerSuffix)\n\n\t\tlet freshValue: unknown\n\t\tlet getFreshValueStartTs: number\n\t\tlet refreshValueStartTS: number\n\n\t\treturn (event) => {\n\t\t\tswitch (event.name) {\n\t\t\t\tcase 'getCachedValueStart': {\n\t\t\t\t\tcacheLog(`Starting cache lookup for ${key}`)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'getCachedValueEmpty': {\n\t\t\t\t\tcacheLog(`Cache miss for ${key}`)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'getCachedValueSuccess': {\n\t\t\t\t\tcacheLog(`Cache hit for ${key}`)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'done': {\n\t\t\t\t\tcacheLog(`Cache operation done for ${key}`)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'getCachedValueRead': {\n\t\t\t\t\tcacheLog(`Read cached value for ${key}`)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'getFreshValueHookPending': {\n\t\t\t\t\tcacheLog(`Waiting for ongoing fetch for fresh value for ${key}`)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'getCachedValueOutdated': {\n\t\t\t\t\tcacheLog(`Cached value for ${key} is outdated`)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'checkCachedValueErrorObj': {\n\t\t\t\t\tlog.warn(\n\t\t\t\t\t\t`check failed for cached value of ${key}\\nReason: ${event.reason}.\\nDeleting the cache key and trying to get a fresh value.`,\n\t\t\t\t\t)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'checkFreshValueErrorObj': {\n\t\t\t\t\tlog.error(\n\t\t\t\t\t\t`check failed for fresh value of ${key}\\nReason: ${event.reason}.`,\n\t\t\t\t\t\tfreshValue,\n\t\t\t\t\t)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'getFreshValueCacheFallback': {\n\t\t\t\t\tcacheLog(\n\t\t\t\t\t\t`Falling back to cached value for ${key} due to error getting fresh value.`,\n\t\t\t\t\t)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'checkCachedValueError': {\n\t\t\t\t\tlog.warn(\n\t\t\t\t\t\t`check failed for cached value of ${key}\\nReason: ${event.reason}.\\nDeleting the cache key and trying to get a fresh value.`,\n\t\t\t\t\t)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'getCachedValueError': {\n\t\t\t\t\tlog.error(\n\t\t\t\t\t\t`error with cache at ${key}. Deleting the cache key and trying to get a fresh value.`,\n\t\t\t\t\t\tevent.error,\n\t\t\t\t\t)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'getFreshValueError': {\n\t\t\t\t\tlog.error(\n\t\t\t\t\t\t`getting a fresh value for ${key} failed`,\n\t\t\t\t\t\t{ fallbackToCache, forceFresh },\n\t\t\t\t\t\tevent.error,\n\t\t\t\t\t)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'getFreshValueStart': {\n\t\t\t\t\tgetFreshValueStartTs = performance.now()\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'writeFreshValueSuccess': {\n\t\t\t\t\tconst totalTime = performance.now() - getFreshValueStartTs\n\t\t\t\t\tif (event.written) {\n\t\t\t\t\t\tcacheLog(\n\t\t\t\t\t\t\t`Updated the cache value for ${key}.`,\n\t\t\t\t\t\t\t`Getting a fresh value for this took ${formatDuration(\n\t\t\t\t\t\t\t\ttotalTime,\n\t\t\t\t\t\t\t)}.`,\n\t\t\t\t\t\t\t`Caching for ${formatCacheTime(\n\t\t\t\t\t\t\t\tmetadata,\n\t\t\t\t\t\t\t\tformatDuration,\n\t\t\t\t\t\t\t)} in ${cacheName}.`,\n\t\t\t\t\t\t)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcacheLog(\n\t\t\t\t\t\t\t`Not updating the cache value for ${key}.`,\n\t\t\t\t\t\t\t`Getting a fresh value for this took ${formatDuration(\n\t\t\t\t\t\t\t\ttotalTime,\n\t\t\t\t\t\t\t)}.`,\n\t\t\t\t\t\t\t`Thereby exceeding caching time of ${formatCacheTime(\n\t\t\t\t\t\t\t\tmetadata,\n\t\t\t\t\t\t\t\tformatDuration,\n\t\t\t\t\t\t\t)}`,\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'writeFreshValueError': {\n\t\t\t\t\tlog.error(`error setting cache: ${key}`, event.error)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'getFreshValueSuccess': {\n\t\t\t\t\tfreshValue = event.value\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'checkFreshValueError': {\n\t\t\t\t\tlog.error(\n\t\t\t\t\t\t`check failed for fresh value of ${key}\\nReason: ${event.reason}.`,\n\t\t\t\t\t\tfreshValue,\n\t\t\t\t\t)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'refreshValueStart': {\n\t\t\t\t\trefreshValueStartTS = performance.now()\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'refreshValueSuccess': {\n\t\t\t\t\tcacheLog(\n\t\t\t\t\t\t`Background refresh for ${key} successful.`,\n\t\t\t\t\t\t`Getting a fresh value for this took ${formatDuration(\n\t\t\t\t\t\t\tperformance.now() - refreshValueStartTS,\n\t\t\t\t\t\t)}.`,\n\t\t\t\t\t\t`Caching for ${formatCacheTime(\n\t\t\t\t\t\t\tmetadata,\n\t\t\t\t\t\t\tformatDuration,\n\t\t\t\t\t\t)} in ${cacheName}.`,\n\t\t\t\t\t)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'refreshValueError': {\n\t\t\t\t\tlog.error(`Background refresh for ${key} failed.`, event.error)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tdefault: {\n\t\t\t\t\t// @ts-expect-error Defensive programming: log unknown events for debugging\n\t\t\t\t\tcacheLog(`Unknown cache event \"${event.name}\" for key ${key}`)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport const solutionAppCache =\n\tmakeSingletonFsCache<SolutionApp>('SolutionAppCache')\nexport const problemAppCache =\n\tmakeSingletonFsCache<ProblemApp>('ProblemAppCache')\nexport const exampleAppCache =\n\tmakeSingletonFsCache<ExampleApp>('ExampleAppCache')\nexport const playgroundAppCache =\n\tmakeSingletonFsCache<PlaygroundApp>('PlaygroundAppCache')\nexport const diffCodeCache = makeSingletonFsCache<string>('DiffCodeCache')\nexport const diffFilesCache = makeSingletonFsCache<string>('DiffFilesCache')\nexport const copyUnignoredFilesCache = makeSingletonCache<string>(\n\t'CopyUnignoredFilesCache',\n)\nexport const compiledMarkdownCache = makeSingletonFsCache<string>(\n\t'CompiledMarkdownCache',\n)\nexport const compiledCodeCache = makeSingletonCache<string>('CompiledCodeCache')\nexport const ogCache = makeSingletonCache<string>('OgCache')\nexport const compiledInstructionMarkdownCache = makeSingletonFsCache<{\n\tcode: string\n\ttitle: string | null\n\tepicVideoEmbeds: Array<string>\n}>('CompiledInstructionMarkdownCache')\nexport const dirModifiedTimeCache = makeSingletonCache<number>(\n\t'DirModifiedTimeCache',\n)\nexport const connectionCache = makeSingletonCache<boolean>('ConnectionCache')\nexport const checkForUpdatesCache = makeSingletonCache<{\n\tupdatesAvailable: boolean\n\tlocalCommit: string\n\tremoteCommit: string\n\tdiffLink: string | null\n}>('CheckForUpdatesCache')\nexport const notificationsCache =\n\tmakeSingletonCache<Array<Notification>>('NotificationsCache')\nexport const directoryEmptyCache = makeSingletonCache<boolean>(\n\t'DirectoryEmptyCache',\n)\n\nexport const discordCache = makeSingletonFsCache('DiscordCache')\nexport const epicApiCache = makeSingletonFsCache('EpicApiCache')\n\nasync function readJsonFilesInDirectory(\n\tdir: string,\n): Promise<Record<string, any>> {\n\tconst files = await fsExtra.readdir(dir)\n\tconst entries = await Promise.all(\n\t\tfiles\n\t\t\t.filter((file) => {\n\t\t\t\t// Filter out system files that should not be parsed as JSON\n\t\t\t\tconst lowercaseFile = file.toLowerCase()\n\t\t\t\treturn (\n\t\t\t\t\t!lowercaseFile.startsWith('.ds_store') &&\n\t\t\t\t\t!lowercaseFile.startsWith('.') &&\n\t\t\t\t\t!lowercaseFile.includes('thumbs.db')\n\t\t\t\t)\n\t\t\t})\n\t\t\t.map(async (file) => {\n\t\t\t\tconst filePath = path.join(dir, file)\n\t\t\t\tconst stats = await fsExtra.stat(filePath)\n\t\t\t\tif (stats.isDirectory()) {\n\t\t\t\t\tconst subEntries = await readJsonFilesInDirectory(filePath)\n\t\t\t\t\treturn [file, subEntries]\n\t\t\t\t} else {\n\t\t\t\t\t// Check file size before attempting to read JSON\n\t\t\t\t\tif (stats.size > MAX_CACHE_FILE_SIZE) {\n\t\t\t\t\t\tconst sizeInMB = (stats.size / (1024 * 1024)).toFixed(2)\n\t\t\t\t\t\tlog.warn(\n\t\t\t\t\t\t\t`Skipping large cache file ${filePath} (${sizeInMB}MB > 3MB limit). ` +\n\t\t\t\t\t\t\t\t`Consider clearing cache or excluding this file type from the admin interface.`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\tfile,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\terror: `File too large (${sizeInMB}MB > 3MB limit)`,\n\t\t\t\t\t\t\t\tsize: stats.size,\n\t\t\t\t\t\t\t\tskipped: true,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]\n\t\t\t\t\t}\n\n\t\t\t\t\tconst data = await readJSONWithRetries(filePath)\n\t\t\t\t\tif (data) {\n\t\t\t\t\t\treturn [file, { ...data, size: stats.size, filepath: filePath }]\n\t\t\t\t\t}\n\n\t\t\t\t\treturn [file, null]\n\t\t\t\t}\n\t\t\t}),\n\t)\n\treturn Object.fromEntries(entries)\n}\n\n// Helper to read JSON with a couple retries; deletes corrupted files and warns\nasync function readJSONWithRetries(filePath: string): Promise<any | null> {\n\tconst maxRetries = 3\n\tconst baseDelay = 10\n\tfor (let attempt = 0; attempt <= maxRetries; attempt++) {\n\t\ttry {\n\t\t\treturn await fsExtra.readJSON(filePath)\n\t\t} catch (error: unknown) {\n\t\t\tif (\n\t\t\t\terror instanceof Error &&\n\t\t\t\t'code' in error &&\n\t\t\t\t(error as NodeJS.ErrnoException).code === 'ENOENT'\n\t\t\t) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tconst isJsonParseError =\n\t\t\t\terror instanceof SyntaxError ||\n\t\t\t\t(error instanceof Error && error.message.includes('JSON'))\n\n\t\t\tif (isJsonParseError) {\n\t\t\t\tif (attempt < maxRetries) {\n\t\t\t\t\tconst delay = baseDelay * Math.pow(2, attempt)\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`JSON parsing error on attempt ${attempt + 1}/${maxRetries + 1} for ${filePath}, retrying in ${delay}ms...`,\n\t\t\t\t\t)\n\t\t\t\t\tawait new Promise((r) => setTimeout(r, delay))\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\t// Final attempt failed: optionally report and delete file\n\t\t\t\tif (getEnv().SENTRY_DSN && getEnv().EPICSHOP_IS_PUBLISHED) {\n\t\t\t\t\tconst throttleKey = `readJSON:${md5(filePath)}`\n\t\t\t\t\tif (!corruptedReportThrottle.has(throttleKey)) {\n\t\t\t\t\t\tcorruptedReportThrottle.set(throttleKey, Date.now())\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst Sentry = await import('@sentry/react-router')\n\t\t\t\t\t\t\tSentry.withScope((scope) => {\n\t\t\t\t\t\t\t\tscope.setLevel('warning')\n\t\t\t\t\t\t\t\tscope.setTag('error_type', 'corrupted_cache_file')\n\t\t\t\t\t\t\t\tscope.setExtra('filePath', filePath)\n\t\t\t\t\t\t\t\tscope.setExtra('errorMessage', (error as Error).message)\n\t\t\t\t\t\t\t\tscope.setExtra('retryAttempts', attempt)\n\t\t\t\t\t\t\t\tSentry.captureException(error)\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t} catch (sentryError) {\n\t\t\t\t\t\t\tconsole.error('Failed to log to Sentry:', sentryError)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Always delete corrupted files so subsequent reads can refetch\n\t\t\t\ttry {\n\t\t\t\t\tawait fsExtra.remove(filePath)\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`Deleted corrupted cache file after ${attempt + 1} attempts: ${filePath}`,\n\t\t\t\t\t)\n\t\t\t\t} catch (deleteError) {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t`Failed to delete corrupted cache file ${filePath}:`,\n\t\t\t\t\t\tdeleteError,\n\t\t\t\t\t)\n\t\t\t\t}\n\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\t// Other errors: do not retry\n\t\t\tthrow error\n\t\t}\n\t}\n\n\treturn null\n}\n\nconst CacheEntrySchema = z.object({\n\tkey: z.string(),\n\tentry: z.object({\n\t\tvalue: z.unknown(),\n\t\tmetadata: z.object({\n\t\t\tcreatedTime: z.number(),\n\t\t\t// Stored JSON may serialize Infinity as null; allow number | null | undefined\n\t\t\tttl: z.number().nullable().optional(),\n\t\t\t// Some entries may omit swr; allow optional\n\t\t\tswr: z.number().optional(),\n\t\t}),\n\t}),\n\tsize: z.number().optional(), // File size in bytes\n\tfilepath: z.string().optional(), // Full filesystem path to the cache file\n})\n\n// Schema for files that were skipped due to size limits\nconst SkippedFileSchema = z.object({\n\terror: z.string(),\n\tsize: z.number(),\n\tskipped: z.literal(true),\n})\n\n// Combined schema that can handle both cache entries and skipped files\nconst CacheFileSchema = z.union([CacheEntrySchema, SkippedFileSchema])\n\ntype CacheEntryType = z.infer<typeof CacheEntrySchema>\n\nexport const WorkshopCacheSchema = z\n\t.record(z.record(z.record(CacheFileSchema)))\n\t.transform((workshopCaches) => {\n\t\ttype CacheEntryWithFilename = CacheEntryType & { filename: string }\n\t\ttype SkippedFileWithFilename = {\n\t\t\tfilename: string\n\t\t\terror: string\n\t\t\tsize: number\n\t\t\tskipped: true\n\t\t}\n\t\ttype Cache = {\n\t\t\tname: string\n\t\t\tentries: Array<CacheEntryWithFilename>\n\t\t\tskippedFiles?: Array<SkippedFileWithFilename>\n\t\t}\n\n\t\tconst cachesArray: Array<{\n\t\t\tworkshopId: string\n\t\t\tcaches: Array<Cache>\n\t\t}> = []\n\n\t\tfor (const [workshopId, caches] of Object.entries(workshopCaches)) {\n\t\t\tconst cachesInDir: Array<Cache> = []\n\t\t\tfor (const [cacheName, entriesObj] of Object.entries(caches)) {\n\t\t\t\tconst entries: Array<CacheEntryWithFilename> = []\n\t\t\t\tconst skippedFiles: Array<SkippedFileWithFilename> = []\n\n\t\t\t\tfor (const [key, value] of Object.entries(entriesObj)) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tvalue &&\n\t\t\t\t\t\ttypeof value === 'object' &&\n\t\t\t\t\t\t'skipped' in value &&\n\t\t\t\t\t\tvalue.skipped\n\t\t\t\t\t) {\n\t\t\t\t\t\t// This is a skipped file\n\t\t\t\t\t\tskippedFiles.push({\n\t\t\t\t\t\t\tfilename: key,\n\t\t\t\t\t\t\terror: value.error as string,\n\t\t\t\t\t\t\tsize: value.size as number,\n\t\t\t\t\t\t\tskipped: true,\n\t\t\t\t\t\t})\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// This is a regular cache entry\n\t\t\t\t\t\tentries.push({ ...(value as CacheEntryType), filename: key })\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst cache: Cache = { name: cacheName, entries }\n\t\t\t\tif (skippedFiles.length > 0) {\n\t\t\t\t\tcache.skippedFiles = skippedFiles\n\t\t\t\t}\n\t\t\t\tcachesInDir.push(cache)\n\t\t\t}\n\t\t\tcachesArray.push({ workshopId, caches: cachesInDir })\n\t\t}\n\n\t\treturn cachesArray\n\t})\n\nexport async function getAllWorkshopCaches() {\n\tconst files = await readJsonFilesInDirectory(cacheDir)\n\tconst parseResult = WorkshopCacheSchema.safeParse(files)\n\tif (!parseResult.success) {\n\t\tlog.error('Failed to parse workshop caches:', parseResult.error)\n\t\treturn []\n\t}\n\treturn parseResult.data\n}\n\nexport async function getWorkshopFileCaches() {\n\tconst workshopCacheDir = path.join(\n\t\tcacheDir,\n\t\tgetEnv().EPICSHOP_WORKSHOP_INSTANCE_ID,\n\t)\n\tconst caches = readJsonFilesInDirectory(workshopCacheDir)\n\treturn caches\n}\n\nexport async function readEntryByPath(cacheFilePath: string) {\n\tconst filePath = path.join(cacheDir, cacheFilePath)\n\tconst data = await readJSONWithRetries(filePath)\n\treturn data?.entry ?? null\n}\n\nexport async function deleteCache() {\n\tif (getEnv().EPICSHOP_DEPLOYED) return null\n\n\ttry {\n\t\tif (await fsExtra.exists(cacheDir)) {\n\t\t\tawait fsExtra.remove(cacheDir)\n\t\t}\n\t} catch (error) {\n\t\tconsole.error(`Error deleting the cache in ${cacheDir}`, error)\n\t}\n}\n\nexport async function deleteCacheEntry(cacheFilePath: string) {\n\tif (getEnv().EPICSHOP_DEPLOYED) return null\n\n\ttry {\n\t\tconst filePath = path.join(cacheDir, cacheFilePath)\n\t\tawait fsExtra.remove(filePath)\n\t} catch (error) {\n\t\tconsole.error(`Error deleting cache entry ${cacheFilePath}:`, error)\n\t}\n}\n\nexport async function deleteWorkshopCache(\n\tworkshopId: string,\n\tcacheName?: string,\n) {\n\tif (getEnv().EPICSHOP_DEPLOYED) return null\n\n\ttry {\n\t\tif (cacheName) {\n\t\t\t// Delete specific cache within workshop\n\t\t\tconst cachePath = path.join(cacheDir, workshopId, cacheName)\n\t\t\tif (await fsExtra.exists(cachePath)) {\n\t\t\t\tawait fsExtra.remove(cachePath)\n\t\t\t}\n\t\t} else {\n\t\t\t// Delete entire workshop cache directory\n\t\t\tconst workshopCachePath = path.join(cacheDir, workshopId)\n\t\t\tif (await fsExtra.exists(workshopCachePath)) {\n\t\t\t\tawait fsExtra.remove(workshopCachePath)\n\t\t\t}\n\t\t}\n\t} catch (error) {\n\t\tconsole.error(\n\t\t\t`Error deleting workshop cache ${workshopId}/${cacheName || 'all'}:`,\n\t\t\terror,\n\t\t)\n\t}\n}\n\nexport async function updateCacheEntry(cacheFilePath: string, newEntry: any) {\n\tif (getEnv().EPICSHOP_DEPLOYED) return null\n\n\ttry {\n\t\tconst filePath = path.join(cacheDir, cacheFilePath)\n\t\tconst existingData = await readJSONWithRetries(filePath)\n\t\tif (!existingData) {\n\t\t\tthrow new Error(`Cache file does not exist: ${cacheFilePath}`)\n\t\t}\n\n\t\tconst updatedData = {\n\t\t\t...existingData,\n\t\t\tentry: {\n\t\t\t\t...existingData.entry,\n\t\t\t\tvalue: newEntry,\n\t\t\t\tmetadata: {\n\t\t\t\t\t...existingData.entry.metadata,\n\t\t\t\t\tcreatedTime: Date.now(), // Update timestamp\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\t\tawait fsExtra.writeJSON(filePath, updatedData)\n\t\treturn updatedData.entry\n\t} catch (error) {\n\t\tconsole.error(`Error updating cache entry ${cacheFilePath}:`, error)\n\t\tthrow error\n\t}\n}\n\nexport function makeSingletonCache<CacheEntryType>(name: string) {\n\treturn remember(name, () => {\n\t\tconst lruInstance = new LRUCache<string, CacheEntry<CacheEntryType>>({\n\t\t\tmax: 1000,\n\t\t})\n\n\t\tconst lru = {\n\t\t\tname,\n\t\t\tset: (key, value) => {\n\t\t\t\tconst ttl = C.totalTtl(value.metadata)\n\t\t\t\tlruInstance.set(key, value, {\n\t\t\t\t\tttl: ttl === Infinity ? undefined : ttl,\n\t\t\t\t\tstart: value.metadata.createdTime,\n\t\t\t\t})\n\t\t\t\treturn value\n\t\t\t},\n\t\t\tget: (key) => lruInstance.get(key),\n\t\t\tdelete: (key) => lruInstance.delete(key),\n\t\t} satisfies C.Cache<CacheEntryType>\n\n\t\treturn lru\n\t})\n}\n\nexport function makeSingletonFsCache<CacheEntryType>(name: string) {\n\treturn remember(name, () => {\n\t\tconst cacheInstanceDir = path.join(\n\t\t\tcacheDir,\n\t\t\tgetEnv().EPICSHOP_WORKSHOP_INSTANCE_ID,\n\t\t\tname,\n\t\t)\n\n\t\tconst fsCache: C.Cache<CacheEntryType> = {\n\t\t\tname: `Filesystem cache (${name})`,\n\t\t\tasync get(key) {\n\t\t\t\tconst filePath = path.join(cacheInstanceDir, md5(key))\n\n\t\t\t\t// Check file size before attempting to read\n\t\t\t\ttry {\n\t\t\t\t\tconst stats = await fsExtra.stat(filePath)\n\t\t\t\t\tif (stats.size > MAX_CACHE_FILE_SIZE) {\n\t\t\t\t\t\tconst sizeInMB = (stats.size / (1024 * 1024)).toFixed(2)\n\t\t\t\t\t\tlog.warn(\n\t\t\t\t\t\t\t`Skipping large cache file ${filePath} (${sizeInMB}MB > 3MB limit). ` +\n\t\t\t\t\t\t\t\t`Consider clearing \"${name}\" cache for key: ${key}`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\treturn null\n\t\t\t\t\t}\n\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\tif (\n\t\t\t\t\t\terror instanceof Error &&\n\t\t\t\t\t\t'code' in error &&\n\t\t\t\t\t\terror.code === 'ENOENT'\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn null\n\t\t\t\t\t}\n\t\t\t\t\t// For other stat errors, continue with the read attempt\n\t\t\t\t}\n\n\t\t\t\t// Use the shared helper which retries and deletes corrupted files\n\t\t\t\tconst data = await readJSONWithRetries(filePath)\n\t\t\t\tif (data?.entry) return data.entry\n\t\t\t\treturn null\n\n\t\t\t\t// This should never be reached, but just in case\n\t\t\t\treturn null\n\t\t\t},\n\t\t\tasync set(key, entry) {\n\t\t\t\tconst filePath = path.join(cacheInstanceDir, md5(key))\n\t\t\t\tconst tempPath = `${filePath}.tmp`\n\t\t\t\tawait fsExtra.ensureDir(path.dirname(filePath))\n\t\t\t\t// Write to temp file first, then atomically move to final location\n\t\t\t\t// This prevents race conditions where readers see partially written JSON files\n\t\t\t\tawait fsExtra.writeJSON(tempPath, { key, entry })\n\t\t\t\tawait fsExtra.move(tempPath, filePath, { overwrite: true })\n\t\t\t},\n\t\t\tasync delete(key) {\n\t\t\t\tconst filePath = path.join(cacheInstanceDir, md5(key))\n\t\t\t\tawait fsExtra.remove(filePath)\n\t\t\t},\n\t\t}\n\n\t\treturn fsCache\n\t})\n}\n\n/**\n * This wraps @epic-web/cachified to add a few handy features:\n *\n * 1. Automatic timing for timing headers\n * 2. Automatic force refresh based on the request and enhancement of forceFresh\n * to support comma-separated keys to force\n * 3. Offline fallback support. If a fallback is given and we are detected to be\n * offline, then the cached value is used regardless of whether it's expired and\n * if one is not present then the given fallback will be used.\n */\nexport async function cachified<Value>({\n\trequest,\n\ttimings,\n\tkey,\n\ttimingKey = key.length > 18 ? `${key.slice(0, 7)}...${key.slice(-8)}` : key,\n\tofflineFallbackValue,\n\t...options\n}: Omit<C.CachifiedOptions<Value>, 'forceFresh'> & {\n\trequest?: Request\n\ttimings?: Timings\n\tforceFresh?: boolean | string\n\ttimingKey?: string\n\tofflineFallbackValue?: Value\n}): Promise<Value> {\n\tif (offlineFallbackValue !== undefined) {\n\t\tconst isOnline = await checkConnection({ request, timings })\n\t\tif (!isOnline) {\n\t\t\tlog.warn(\n\t\t\t\t`Offline: using cached value for ${key} or offline fallback if no cache is present`,\n\t\t\t)\n\t\t\tconst cacheEntry = await options.cache.get(key)\n\t\t\treturn cacheEntry?.value ?? offlineFallbackValue\n\t\t}\n\t}\n\tconst forceFresh = await shouldForceFresh({\n\t\tforceFresh: options.forceFresh,\n\t\trequest,\n\t\tkey,\n\t})\n\treturn C.cachified(\n\t\t{\n\t\t\t...options,\n\t\t\tkey,\n\t\t\tforceFresh,\n\t\t},\n\t\tC.mergeReporters(\n\t\t\tcachifiedTimingReporter(timings, timingKey),\n\t\t\tepicCacheReporter(),\n\t\t),\n\t)\n}\n\nexport async function shouldForceFresh({\n\tforceFresh,\n\trequest,\n\tkey,\n}: {\n\tforceFresh?: boolean | string\n\trequest?: Request\n\tkey?: string\n}) {\n\tif (typeof forceFresh === 'boolean') return forceFresh\n\tif (typeof forceFresh === 'string' && key) {\n\t\treturn forceFresh.split(',').includes(key)\n\t}\n\n\tif (!request) return false\n\tconst fresh = new URL(request.url).searchParams.get('fresh')\n\tif (typeof fresh !== 'string') return false\n\tif (fresh === '') return true\n\tif (!key) return false\n\n\treturn fresh.split(',').includes(key)\n}\n"]}
1
+ {"version":3,"file":"cache.server.js","sourceRoot":"","sources":["../../src/cache.server.ts"],"names":[],"mappings":"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","sourcesContent":["// eslint-disable-next-line import/order -- this must be first\nimport { getEnv } from './init-env.js'\n\nimport path from 'path'\nimport * as C from '@epic-web/cachified'\nimport { type CacheEntry, type CreateReporter } from '@epic-web/cachified'\nimport { remember } from '@epic-web/remember'\nimport fsExtra from 'fs-extra'\nimport { LRUCache } from 'lru-cache'\nimport md5 from 'md5-hex'\nimport z from 'zod'\nimport {\n\ttype ExampleApp,\n\ttype PlaygroundApp,\n\ttype ProblemApp,\n\ttype SolutionApp,\n} from './apps.server.js'\nimport { resolveCacheDir } from './data-storage.server.js'\nimport { logger } from './logger.js'\nimport { type Notification } from './notifications.server.js'\nimport { cachifiedTimingReporter, type Timings } from './timing.server.js'\nimport { checkConnection } from './utils.server.js'\n\nconst MAX_CACHE_FILE_SIZE = 3 * 1024 * 1024 // 3MB in bytes\nconst cacheDir = resolveCacheDir()\nconst log = logger('epic:cache')\n\n// Throttle repeated Sentry reports for corrupted cache files to reduce noise\nconst corruptedReportThrottle = remember(\n\t'epic:cache:corruption-throttle',\n\t() => new LRUCache<string, number>({ max: 2000, ttl: 60_000 }),\n)\n\n// Format cache time helper function (copied from @epic-web/cachified for consistency)\nfunction formatCacheTime(\n\tmetadata: any,\n\tformatDuration: (ms: number) => string,\n): string {\n\tconst ttl = metadata?.ttl\n\tif (ttl === undefined || ttl === Infinity) return 'forever'\n\treturn formatDuration(ttl)\n}\n\n// Default duration formatter (copied from @epic-web/cachified for consistency)\nfunction defaultFormatDuration(ms: number): string {\n\tif (ms < 1000) return `${Math.round(ms)}ms`\n\tif (ms < 60000) return `${Math.round(ms / 1000)}s`\n\tif (ms < 3600000) return `${Math.round(ms / 60000)}m`\n\treturn `${Math.round(ms / 3600000)}h`\n}\n\n/**\n * Creates a cachified reporter that integrates with the Epic Workshop logger system.\n * Uses the pattern `epic:cache:{name-of-cache}` for logger namespaces.\n * Only logs when the specific cache namespace is enabled via NODE_DEBUG.\n */\nexport function epicCacheReporter<Value>({\n\tformatDuration = defaultFormatDuration,\n\tperformance = globalThis.performance || Date,\n}: {\n\tformatDuration?: (ms: number) => string\n\tperformance?: Pick<typeof Date, 'now'>\n} = {}): CreateReporter<Value> {\n\treturn ({ key, fallbackToCache, forceFresh, metadata, cache }) => {\n\t\t// Determine cache name for logger namespace\n\t\tconst cacheName =\n\t\t\tcache.name || cache.toString().replace(/^\\[object (.*?)]$/, '$1')\n\n\t\t// Create logger with epic:cache:{name} pattern\n\t\t// Extract a reasonable cache name from longer descriptions\n\t\tlet loggerSuffix = 'unknown'\n\t\tif (cacheName.includes('(') && cacheName.includes(')')) {\n\t\t\t// Extract name from \"Filesystem cache (CacheName)\" format\n\t\t\tconst match = cacheName.match(/\\(([^)]+)\\)/)\n\t\t\tloggerSuffix = (match?.[1] ?? 'unknown').toLowerCase()\n\t\t} else if (cacheName === 'LRUCache') {\n\t\t\t// For LRU caches, we can't determine the name from the cache object alone\n\t\t\tloggerSuffix = 'lru'\n\t\t} else {\n\t\t\tloggerSuffix = cacheName.toLowerCase()\n\t\t}\n\n\t\tconst cacheLog = log.logger(loggerSuffix)\n\n\t\tlet freshValue: unknown\n\t\tlet getFreshValueStartTs: number\n\t\tlet refreshValueStartTS: number\n\n\t\treturn (event) => {\n\t\t\tswitch (event.name) {\n\t\t\t\tcase 'getCachedValueStart': {\n\t\t\t\t\tcacheLog(`Starting cache lookup for ${key}`)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'getCachedValueEmpty': {\n\t\t\t\t\tcacheLog(`Cache miss for ${key}`)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'getCachedValueSuccess': {\n\t\t\t\t\tcacheLog(`Cache hit for ${key}`)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'done': {\n\t\t\t\t\tcacheLog(`Cache operation done for ${key}`)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'getCachedValueRead': {\n\t\t\t\t\tcacheLog(`Read cached value for ${key}`)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'getFreshValueHookPending': {\n\t\t\t\t\tcacheLog(`Waiting for ongoing fetch for fresh value for ${key}`)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'getCachedValueOutdated': {\n\t\t\t\t\tcacheLog(`Cached value for ${key} is outdated`)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'checkCachedValueErrorObj': {\n\t\t\t\t\tlog.warn(\n\t\t\t\t\t\t`check failed for cached value of ${key}\\nReason: ${event.reason}.\\nDeleting the cache key and trying to get a fresh value.`,\n\t\t\t\t\t)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'checkFreshValueErrorObj': {\n\t\t\t\t\tlog.error(\n\t\t\t\t\t\t`check failed for fresh value of ${key}\\nReason: ${event.reason}.`,\n\t\t\t\t\t\tfreshValue,\n\t\t\t\t\t)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'getFreshValueCacheFallback': {\n\t\t\t\t\tcacheLog(\n\t\t\t\t\t\t`Falling back to cached value for ${key} due to error getting fresh value.`,\n\t\t\t\t\t)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'checkCachedValueError': {\n\t\t\t\t\tlog.warn(\n\t\t\t\t\t\t`check failed for cached value of ${key}\\nReason: ${event.reason}.\\nDeleting the cache key and trying to get a fresh value.`,\n\t\t\t\t\t)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'getCachedValueError': {\n\t\t\t\t\tlog.error(\n\t\t\t\t\t\t`error with cache at ${key}. Deleting the cache key and trying to get a fresh value.`,\n\t\t\t\t\t\tevent.error,\n\t\t\t\t\t)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'getFreshValueError': {\n\t\t\t\t\tlog.error(\n\t\t\t\t\t\t`getting a fresh value for ${key} failed`,\n\t\t\t\t\t\t{ fallbackToCache, forceFresh },\n\t\t\t\t\t\tevent.error,\n\t\t\t\t\t)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'getFreshValueStart': {\n\t\t\t\t\tgetFreshValueStartTs = performance.now()\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'writeFreshValueSuccess': {\n\t\t\t\t\tconst totalTime = performance.now() - getFreshValueStartTs\n\t\t\t\t\tif (event.written) {\n\t\t\t\t\t\tcacheLog(\n\t\t\t\t\t\t\t`Updated the cache value for ${key}.`,\n\t\t\t\t\t\t\t`Getting a fresh value for this took ${formatDuration(\n\t\t\t\t\t\t\t\ttotalTime,\n\t\t\t\t\t\t\t)}.`,\n\t\t\t\t\t\t\t`Caching for ${formatCacheTime(\n\t\t\t\t\t\t\t\tmetadata,\n\t\t\t\t\t\t\t\tformatDuration,\n\t\t\t\t\t\t\t)} in ${cacheName}.`,\n\t\t\t\t\t\t)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcacheLog(\n\t\t\t\t\t\t\t`Not updating the cache value for ${key}.`,\n\t\t\t\t\t\t\t`Getting a fresh value for this took ${formatDuration(\n\t\t\t\t\t\t\t\ttotalTime,\n\t\t\t\t\t\t\t)}.`,\n\t\t\t\t\t\t\t`Thereby exceeding caching time of ${formatCacheTime(\n\t\t\t\t\t\t\t\tmetadata,\n\t\t\t\t\t\t\t\tformatDuration,\n\t\t\t\t\t\t\t)}`,\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'writeFreshValueError': {\n\t\t\t\t\tlog.error(`error setting cache: ${key}`, event.error)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'getFreshValueSuccess': {\n\t\t\t\t\tfreshValue = event.value\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'checkFreshValueError': {\n\t\t\t\t\tlog.error(\n\t\t\t\t\t\t`check failed for fresh value of ${key}\\nReason: ${event.reason}.`,\n\t\t\t\t\t\tfreshValue,\n\t\t\t\t\t)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'refreshValueStart': {\n\t\t\t\t\trefreshValueStartTS = performance.now()\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'refreshValueSuccess': {\n\t\t\t\t\tcacheLog(\n\t\t\t\t\t\t`Background refresh for ${key} successful.`,\n\t\t\t\t\t\t`Getting a fresh value for this took ${formatDuration(\n\t\t\t\t\t\t\tperformance.now() - refreshValueStartTS,\n\t\t\t\t\t\t)}.`,\n\t\t\t\t\t\t`Caching for ${formatCacheTime(\n\t\t\t\t\t\t\tmetadata,\n\t\t\t\t\t\t\tformatDuration,\n\t\t\t\t\t\t)} in ${cacheName}.`,\n\t\t\t\t\t)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'refreshValueError': {\n\t\t\t\t\tlog.error(`Background refresh for ${key} failed.`, event.error)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tdefault: {\n\t\t\t\t\t// @ts-expect-error Defensive programming: log unknown events for debugging\n\t\t\t\t\tcacheLog(`Unknown cache event \"${event.name}\" for key ${key}`)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport const solutionAppCache =\n\tmakeSingletonFsCache<SolutionApp>('SolutionAppCache')\nexport const problemAppCache =\n\tmakeSingletonFsCache<ProblemApp>('ProblemAppCache')\nexport const exampleAppCache =\n\tmakeSingletonFsCache<ExampleApp>('ExampleAppCache')\nexport const playgroundAppCache =\n\tmakeSingletonFsCache<PlaygroundApp>('PlaygroundAppCache')\nexport const diffCodeCache = makeSingletonFsCache<string>('DiffCodeCache')\nexport const diffFilesCache = makeSingletonFsCache<string>('DiffFilesCache')\nexport const copyUnignoredFilesCache = makeSingletonCache<string>(\n\t'CopyUnignoredFilesCache',\n)\nexport const compiledMarkdownCache = makeSingletonFsCache<string>(\n\t'CompiledMarkdownCache',\n)\nexport const compiledCodeCache = makeSingletonCache<string>('CompiledCodeCache')\nexport const ogCache = makeSingletonCache<string>('OgCache')\nexport const compiledInstructionMarkdownCache = makeSingletonFsCache<{\n\tcode: string\n\ttitle: string | null\n\tepicVideoEmbeds: Array<string>\n}>('CompiledInstructionMarkdownCache')\nexport const dirModifiedTimeCache = makeSingletonCache<number>(\n\t'DirModifiedTimeCache',\n)\nexport const connectionCache = makeSingletonCache<boolean>('ConnectionCache')\nexport const checkForUpdatesCache = makeSingletonCache<{\n\tupdatesAvailable: boolean\n\tlocalCommit: string\n\tremoteCommit: string\n\tdiffLink: string | null\n}>('CheckForUpdatesCache')\nexport const notificationsCache =\n\tmakeSingletonCache<Array<Notification>>('NotificationsCache')\nexport const directoryEmptyCache = makeSingletonCache<boolean>(\n\t'DirectoryEmptyCache',\n)\n\nexport const discordCache = makeSingletonFsCache('DiscordCache')\nexport const epicApiCache = makeSingletonFsCache('EpicApiCache')\n\nexport function makeGlobalFsCache<CacheEntryType>(name: string) {\n\treturn remember(`global-${name}`, () => {\n\t\tconst cacheInstanceDir = path.join(cacheDir, 'global', name)\n\n\t\tconst fsCache: C.Cache<CacheEntryType> = {\n\t\t\tname: `Filesystem cache (global-${name})`,\n\t\t\tasync get(key) {\n\t\t\t\tconst filePath = path.join(cacheInstanceDir, md5(key))\n\n\t\t\t\ttry {\n\t\t\t\t\tconst stats = await fsExtra.stat(filePath)\n\t\t\t\t\tif (stats.size > MAX_CACHE_FILE_SIZE) {\n\t\t\t\t\t\tconst sizeInMB = (stats.size / (1024 * 1024)).toFixed(2)\n\t\t\t\t\t\tlog.warn(\n\t\t\t\t\t\t\t`Skipping large cache file ${filePath} (${sizeInMB}MB > 3MB limit). ` +\n\t\t\t\t\t\t\t\t`Consider clearing \"${name}\" cache for key: ${key}`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\treturn null\n\t\t\t\t\t}\n\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\tif (\n\t\t\t\t\t\terror instanceof Error &&\n\t\t\t\t\t\t'code' in error &&\n\t\t\t\t\t\terror.code === 'ENOENT'\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn null\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst data = await readJSONWithRetries(filePath)\n\t\t\t\tif (data?.entry) return data.entry\n\t\t\t\treturn null\n\t\t\t},\n\t\t\tasync set(key, entry) {\n\t\t\t\tconst filePath = path.join(cacheInstanceDir, md5(key))\n\t\t\t\tconst tempPath = `${filePath}.tmp`\n\t\t\t\tawait fsExtra.ensureDir(path.dirname(filePath))\n\t\t\t\tawait fsExtra.writeJSON(tempPath, { key, entry })\n\t\t\t\tawait fsExtra.move(tempPath, filePath, { overwrite: true })\n\t\t\t},\n\t\t\tasync delete(key) {\n\t\t\t\tconst filePath = path.join(cacheInstanceDir, md5(key))\n\t\t\t\tawait fsExtra.remove(filePath)\n\t\t\t},\n\t\t}\n\n\t\treturn fsCache\n\t})\n}\n\nexport const githubCache = makeGlobalFsCache('GitHubCache')\n\nasync function readJsonFilesInDirectory(\n\tdir: string,\n): Promise<Record<string, any>> {\n\tconst files = await fsExtra.readdir(dir)\n\tconst entries = await Promise.all(\n\t\tfiles\n\t\t\t.filter((file) => {\n\t\t\t\t// Filter out system files that should not be parsed as JSON\n\t\t\t\tconst lowercaseFile = file.toLowerCase()\n\t\t\t\treturn (\n\t\t\t\t\t!lowercaseFile.startsWith('.ds_store') &&\n\t\t\t\t\t!lowercaseFile.startsWith('.') &&\n\t\t\t\t\t!lowercaseFile.includes('thumbs.db')\n\t\t\t\t)\n\t\t\t})\n\t\t\t.map(async (file) => {\n\t\t\t\tconst filePath = path.join(dir, file)\n\t\t\t\tconst stats = await fsExtra.stat(filePath)\n\t\t\t\tif (stats.isDirectory()) {\n\t\t\t\t\tconst subEntries = await readJsonFilesInDirectory(filePath)\n\t\t\t\t\treturn [file, subEntries]\n\t\t\t\t} else {\n\t\t\t\t\t// Check file size before attempting to read JSON\n\t\t\t\t\tif (stats.size > MAX_CACHE_FILE_SIZE) {\n\t\t\t\t\t\tconst sizeInMB = (stats.size / (1024 * 1024)).toFixed(2)\n\t\t\t\t\t\tlog.warn(\n\t\t\t\t\t\t\t`Skipping large cache file ${filePath} (${sizeInMB}MB > 3MB limit). ` +\n\t\t\t\t\t\t\t\t`Consider clearing cache or excluding this file type from the admin interface.`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\tfile,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\terror: `File too large (${sizeInMB}MB > 3MB limit)`,\n\t\t\t\t\t\t\t\tsize: stats.size,\n\t\t\t\t\t\t\t\tskipped: true,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]\n\t\t\t\t\t}\n\n\t\t\t\t\tconst data = await readJSONWithRetries(filePath)\n\t\t\t\t\tif (data) {\n\t\t\t\t\t\treturn [file, { ...data, size: stats.size, filepath: filePath }]\n\t\t\t\t\t}\n\n\t\t\t\t\treturn [file, null]\n\t\t\t\t}\n\t\t\t}),\n\t)\n\treturn Object.fromEntries(entries)\n}\n\n// Helper to read JSON with a couple retries; deletes corrupted files and warns\nasync function readJSONWithRetries(filePath: string): Promise<any | null> {\n\tconst maxRetries = 3\n\tconst baseDelay = 10\n\tfor (let attempt = 0; attempt <= maxRetries; attempt++) {\n\t\ttry {\n\t\t\treturn await fsExtra.readJSON(filePath)\n\t\t} catch (error: unknown) {\n\t\t\tif (\n\t\t\t\terror instanceof Error &&\n\t\t\t\t'code' in error &&\n\t\t\t\t(error as NodeJS.ErrnoException).code === 'ENOENT'\n\t\t\t) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tconst isJsonParseError =\n\t\t\t\terror instanceof SyntaxError ||\n\t\t\t\t(error instanceof Error && error.message.includes('JSON'))\n\n\t\t\tif (isJsonParseError) {\n\t\t\t\tif (attempt < maxRetries) {\n\t\t\t\t\tconst delay = baseDelay * Math.pow(2, attempt)\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`JSON parsing error on attempt ${attempt + 1}/${maxRetries + 1} for ${filePath}, retrying in ${delay}ms...`,\n\t\t\t\t\t)\n\t\t\t\t\tawait new Promise((r) => setTimeout(r, delay))\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\t// Final attempt failed: optionally report and delete file\n\t\t\t\tif (getEnv().SENTRY_DSN && getEnv().EPICSHOP_IS_PUBLISHED) {\n\t\t\t\t\tconst throttleKey = `readJSON:${md5(filePath)}`\n\t\t\t\t\tif (!corruptedReportThrottle.has(throttleKey)) {\n\t\t\t\t\t\tcorruptedReportThrottle.set(throttleKey, Date.now())\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst Sentry = await import('@sentry/react-router')\n\t\t\t\t\t\t\tSentry.withScope((scope) => {\n\t\t\t\t\t\t\t\tscope.setLevel('warning')\n\t\t\t\t\t\t\t\tscope.setTag('error_type', 'corrupted_cache_file')\n\t\t\t\t\t\t\t\tscope.setExtra('filePath', filePath)\n\t\t\t\t\t\t\t\tscope.setExtra('errorMessage', (error as Error).message)\n\t\t\t\t\t\t\t\tscope.setExtra('retryAttempts', attempt)\n\t\t\t\t\t\t\t\tSentry.captureException(error)\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t} catch (sentryError) {\n\t\t\t\t\t\t\tconsole.error('Failed to log to Sentry:', sentryError)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Always delete corrupted files so subsequent reads can refetch\n\t\t\t\ttry {\n\t\t\t\t\tawait fsExtra.remove(filePath)\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`Deleted corrupted cache file after ${attempt + 1} attempts: ${filePath}`,\n\t\t\t\t\t)\n\t\t\t\t} catch (deleteError) {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t`Failed to delete corrupted cache file ${filePath}:`,\n\t\t\t\t\t\tdeleteError,\n\t\t\t\t\t)\n\t\t\t\t}\n\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\t// Other errors: do not retry\n\t\t\tthrow error\n\t\t}\n\t}\n\n\treturn null\n}\n\nconst CacheEntrySchema = z.object({\n\tkey: z.string(),\n\tentry: z.object({\n\t\tvalue: z.unknown(),\n\t\tmetadata: z.object({\n\t\t\tcreatedTime: z.number(),\n\t\t\t// Stored JSON may serialize Infinity as null; allow number | null | undefined\n\t\t\tttl: z.number().nullable().optional(),\n\t\t\t// Some entries may omit swr; allow optional\n\t\t\tswr: z.number().optional(),\n\t\t}),\n\t}),\n\tsize: z.number().optional(), // File size in bytes\n\tfilepath: z.string().optional(), // Full filesystem path to the cache file\n})\n\n// Schema for files that were skipped due to size limits\nconst SkippedFileSchema = z.object({\n\terror: z.string(),\n\tsize: z.number(),\n\tskipped: z.literal(true),\n})\n\n// Combined schema that can handle both cache entries and skipped files\nconst CacheFileSchema = z.union([CacheEntrySchema, SkippedFileSchema])\n\ntype CacheEntryType = z.infer<typeof CacheEntrySchema>\n\nexport const WorkshopCacheSchema = z\n\t.record(z.record(z.record(CacheFileSchema)))\n\t.transform((workshopCaches) => {\n\t\ttype CacheEntryWithFilename = CacheEntryType & { filename: string }\n\t\ttype SkippedFileWithFilename = {\n\t\t\tfilename: string\n\t\t\terror: string\n\t\t\tsize: number\n\t\t\tskipped: true\n\t\t}\n\t\ttype Cache = {\n\t\t\tname: string\n\t\t\tentries: Array<CacheEntryWithFilename>\n\t\t\tskippedFiles?: Array<SkippedFileWithFilename>\n\t\t}\n\n\t\tconst cachesArray: Array<{\n\t\t\tworkshopId: string\n\t\t\tcaches: Array<Cache>\n\t\t}> = []\n\n\t\tfor (const [workshopId, caches] of Object.entries(workshopCaches)) {\n\t\t\tconst cachesInDir: Array<Cache> = []\n\t\t\tfor (const [cacheName, entriesObj] of Object.entries(caches)) {\n\t\t\t\tconst entries: Array<CacheEntryWithFilename> = []\n\t\t\t\tconst skippedFiles: Array<SkippedFileWithFilename> = []\n\n\t\t\t\tfor (const [key, value] of Object.entries(entriesObj)) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tvalue &&\n\t\t\t\t\t\ttypeof value === 'object' &&\n\t\t\t\t\t\t'skipped' in value &&\n\t\t\t\t\t\tvalue.skipped\n\t\t\t\t\t) {\n\t\t\t\t\t\t// This is a skipped file\n\t\t\t\t\t\tskippedFiles.push({\n\t\t\t\t\t\t\tfilename: key,\n\t\t\t\t\t\t\terror: value.error as string,\n\t\t\t\t\t\t\tsize: value.size as number,\n\t\t\t\t\t\t\tskipped: true,\n\t\t\t\t\t\t})\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// This is a regular cache entry\n\t\t\t\t\t\tentries.push({ ...(value as CacheEntryType), filename: key })\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst cache: Cache = { name: cacheName, entries }\n\t\t\t\tif (skippedFiles.length > 0) {\n\t\t\t\t\tcache.skippedFiles = skippedFiles\n\t\t\t\t}\n\t\t\t\tcachesInDir.push(cache)\n\t\t\t}\n\t\t\tcachesArray.push({ workshopId, caches: cachesInDir })\n\t\t}\n\n\t\treturn cachesArray\n\t})\n\nexport async function getAllWorkshopCaches() {\n\tconst files = await readJsonFilesInDirectory(cacheDir)\n\t// Exclude the global directory from workshop caches\n\tconst { global, ...workshopCaches } = files\n\tconst parseResult = WorkshopCacheSchema.safeParse(workshopCaches)\n\tif (!parseResult.success) {\n\t\tlog.error('Failed to parse workshop caches:', parseResult.error)\n\t\treturn []\n\t}\n\treturn parseResult.data\n}\n\nexport async function globalCacheDirectoryExists(): Promise<boolean> {\n\tconst globalCacheDir = path.join(cacheDir, 'global')\n\treturn await fsExtra.exists(globalCacheDir)\n}\n\nexport async function getGlobalCaches() {\n\tconst globalCacheDir = path.join(cacheDir, 'global')\n\tif (!(await fsExtra.exists(globalCacheDir))) {\n\t\treturn []\n\t}\n\n\tconst files = await readJsonFilesInDirectory(globalCacheDir)\n\tconst parseResult = WorkshopCacheSchema.safeParse({ global: files })\n\tif (!parseResult.success) {\n\t\tlog.error('Failed to parse global caches:', parseResult.error)\n\t\treturn []\n\t}\n\treturn parseResult.data.map((workshopCache) => ({\n\t\t...workshopCache,\n\t\tworkshopId: 'global',\n\t}))\n}\n\nexport async function getWorkshopFileCaches() {\n\tconst workshopCacheDir = path.join(\n\t\tcacheDir,\n\t\tgetEnv().EPICSHOP_WORKSHOP_INSTANCE_ID,\n\t)\n\tconst caches = readJsonFilesInDirectory(workshopCacheDir)\n\treturn caches\n}\n\nexport async function readEntryByPath(cacheFilePath: string) {\n\tconst filePath = path.join(cacheDir, cacheFilePath)\n\tconst data = await readJSONWithRetries(filePath)\n\treturn data?.entry ?? null\n}\n\nexport async function deleteCache() {\n\tif (getEnv().EPICSHOP_DEPLOYED) return null\n\n\ttry {\n\t\tif (await fsExtra.exists(cacheDir)) {\n\t\t\tawait fsExtra.remove(cacheDir)\n\t\t}\n\t} catch (error) {\n\t\tconsole.error(`Error deleting the cache in ${cacheDir}`, error)\n\t}\n}\n\nexport async function deleteCacheEntry(cacheFilePath: string) {\n\tif (getEnv().EPICSHOP_DEPLOYED) return null\n\n\ttry {\n\t\tconst filePath = path.join(cacheDir, cacheFilePath)\n\t\tawait fsExtra.remove(filePath)\n\t} catch (error) {\n\t\tconsole.error(`Error deleting cache entry ${cacheFilePath}:`, error)\n\t}\n}\n\nexport async function deleteWorkshopCache(\n\tworkshopId: string,\n\tcacheName?: string,\n) {\n\tif (getEnv().EPICSHOP_DEPLOYED) return null\n\n\ttry {\n\t\tif (cacheName) {\n\t\t\t// Delete specific cache within workshop\n\t\t\tconst cachePath = path.join(cacheDir, workshopId, cacheName)\n\t\t\tif (await fsExtra.exists(cachePath)) {\n\t\t\t\tawait fsExtra.remove(cachePath)\n\t\t\t}\n\t\t} else {\n\t\t\t// Delete entire workshop cache directory\n\t\t\tconst workshopCachePath = path.join(cacheDir, workshopId)\n\t\t\tif (await fsExtra.exists(workshopCachePath)) {\n\t\t\t\tawait fsExtra.remove(workshopCachePath)\n\t\t\t}\n\t\t}\n\t} catch (error) {\n\t\tconsole.error(\n\t\t\t`Error deleting workshop cache ${workshopId}/${cacheName || 'all'}:`,\n\t\t\terror,\n\t\t)\n\t}\n}\n\nexport async function updateCacheEntry(cacheFilePath: string, newEntry: any) {\n\tif (getEnv().EPICSHOP_DEPLOYED) return null\n\n\ttry {\n\t\tconst filePath = path.join(cacheDir, cacheFilePath)\n\t\tconst existingData = await readJSONWithRetries(filePath)\n\t\tif (!existingData) {\n\t\t\tthrow new Error(`Cache file does not exist: ${cacheFilePath}`)\n\t\t}\n\n\t\tconst updatedData = {\n\t\t\t...existingData,\n\t\t\tentry: {\n\t\t\t\t...existingData.entry,\n\t\t\t\tvalue: newEntry,\n\t\t\t\tmetadata: {\n\t\t\t\t\t...existingData.entry.metadata,\n\t\t\t\t\tcreatedTime: Date.now(), // Update timestamp\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\t\tawait fsExtra.writeJSON(filePath, updatedData)\n\t\treturn updatedData.entry\n\t} catch (error) {\n\t\tconsole.error(`Error updating cache entry ${cacheFilePath}:`, error)\n\t\tthrow error\n\t}\n}\n\nexport function makeSingletonCache<CacheEntryType>(name: string) {\n\treturn remember(name, () => {\n\t\tconst lruInstance = new LRUCache<string, CacheEntry<CacheEntryType>>({\n\t\t\tmax: 1000,\n\t\t})\n\n\t\tconst lru = {\n\t\t\tname,\n\t\t\tset: (key, value) => {\n\t\t\t\tconst ttl = C.totalTtl(value.metadata)\n\t\t\t\tlruInstance.set(key, value, {\n\t\t\t\t\tttl: ttl === Infinity ? undefined : ttl,\n\t\t\t\t\tstart: value.metadata.createdTime,\n\t\t\t\t})\n\t\t\t\treturn value\n\t\t\t},\n\t\t\tget: (key) => lruInstance.get(key),\n\t\t\tdelete: (key) => lruInstance.delete(key),\n\t\t} satisfies C.Cache<CacheEntryType>\n\n\t\treturn lru\n\t})\n}\n\nexport function makeSingletonFsCache<CacheEntryType>(name: string) {\n\treturn remember(name, () => {\n\t\tconst cacheInstanceDir = path.join(\n\t\t\tcacheDir,\n\t\t\tgetEnv().EPICSHOP_WORKSHOP_INSTANCE_ID,\n\t\t\tname,\n\t\t)\n\n\t\tconst fsCache: C.Cache<CacheEntryType> = {\n\t\t\tname: `Filesystem cache (${name})`,\n\t\t\tasync get(key) {\n\t\t\t\tconst filePath = path.join(cacheInstanceDir, md5(key))\n\n\t\t\t\t// Check file size before attempting to read\n\t\t\t\ttry {\n\t\t\t\t\tconst stats = await fsExtra.stat(filePath)\n\t\t\t\t\tif (stats.size > MAX_CACHE_FILE_SIZE) {\n\t\t\t\t\t\tconst sizeInMB = (stats.size / (1024 * 1024)).toFixed(2)\n\t\t\t\t\t\tlog.warn(\n\t\t\t\t\t\t\t`Skipping large cache file ${filePath} (${sizeInMB}MB > 3MB limit). ` +\n\t\t\t\t\t\t\t\t`Consider clearing \"${name}\" cache for key: ${key}`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\treturn null\n\t\t\t\t\t}\n\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\tif (\n\t\t\t\t\t\terror instanceof Error &&\n\t\t\t\t\t\t'code' in error &&\n\t\t\t\t\t\terror.code === 'ENOENT'\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn null\n\t\t\t\t\t}\n\t\t\t\t\t// For other stat errors, continue with the read attempt\n\t\t\t\t}\n\n\t\t\t\t// Use the shared helper which retries and deletes corrupted files\n\t\t\t\tconst data = await readJSONWithRetries(filePath)\n\t\t\t\tif (data?.entry) return data.entry\n\t\t\t\treturn null\n\n\t\t\t\t// This should never be reached, but just in case\n\t\t\t\treturn null\n\t\t\t},\n\t\t\tasync set(key, entry) {\n\t\t\t\tconst filePath = path.join(cacheInstanceDir, md5(key))\n\t\t\t\tconst tempPath = `${filePath}.tmp`\n\t\t\t\tawait fsExtra.ensureDir(path.dirname(filePath))\n\t\t\t\t// Write to temp file first, then atomically move to final location\n\t\t\t\t// This prevents race conditions where readers see partially written JSON files\n\t\t\t\tawait fsExtra.writeJSON(tempPath, { key, entry })\n\t\t\t\tawait fsExtra.move(tempPath, filePath, { overwrite: true })\n\t\t\t},\n\t\t\tasync delete(key) {\n\t\t\t\tconst filePath = path.join(cacheInstanceDir, md5(key))\n\t\t\t\tawait fsExtra.remove(filePath)\n\t\t\t},\n\t\t}\n\n\t\treturn fsCache\n\t})\n}\n\n/**\n * This wraps @epic-web/cachified to add a few handy features:\n *\n * 1. Automatic timing for timing headers\n * 2. Automatic force refresh based on the request and enhancement of forceFresh\n * to support comma-separated keys to force\n * 3. Offline fallback support. If a fallback is given and we are detected to be\n * offline, then the cached value is used regardless of whether it's expired and\n * if one is not present then the given fallback will be used.\n */\nexport async function cachified<Value>({\n\trequest,\n\ttimings,\n\tkey,\n\ttimingKey = key.length > 18 ? `${key.slice(0, 7)}...${key.slice(-8)}` : key,\n\tofflineFallbackValue,\n\t...options\n}: Omit<C.CachifiedOptions<Value>, 'forceFresh'> & {\n\trequest?: Request\n\ttimings?: Timings\n\tforceFresh?: boolean | string\n\ttimingKey?: string\n\tofflineFallbackValue?: Value\n}): Promise<Value> {\n\tif (offlineFallbackValue !== undefined) {\n\t\tconst isOnline = await checkConnection({ request, timings })\n\t\tif (!isOnline) {\n\t\t\tlog.warn(\n\t\t\t\t`Offline: using cached value for ${key} or offline fallback if no cache is present`,\n\t\t\t)\n\t\t\tconst cacheEntry = await options.cache.get(key)\n\t\t\treturn cacheEntry?.value ?? offlineFallbackValue\n\t\t}\n\t}\n\tconst forceFresh = await shouldForceFresh({\n\t\tforceFresh: options.forceFresh,\n\t\trequest,\n\t\tkey,\n\t})\n\treturn C.cachified(\n\t\t{\n\t\t\t...options,\n\t\t\tkey,\n\t\t\tforceFresh,\n\t\t},\n\t\tC.mergeReporters(\n\t\t\tcachifiedTimingReporter(timings, timingKey),\n\t\t\tepicCacheReporter(),\n\t\t),\n\t)\n}\n\nexport async function shouldForceFresh({\n\tforceFresh,\n\trequest,\n\tkey,\n}: {\n\tforceFresh?: boolean | string\n\trequest?: Request\n\tkey?: string\n}) {\n\tif (typeof forceFresh === 'boolean') return forceFresh\n\tif (typeof forceFresh === 'string' && key) {\n\t\treturn forceFresh.split(',').includes(key)\n\t}\n\n\tif (!request) return false\n\tconst fresh = new URL(request.url).searchParams.get('fresh')\n\tif (typeof fresh !== 'string') return false\n\tif (fresh === '') return true\n\tif (!key) return false\n\n\treturn fresh.split(',').includes(key)\n}\n"]}