MCPcopy Index your code
hub / github.com/sourcebot-dev/sourcebot / loadJsonFile

Function loadJsonFile

packages/shared/src/utils.ts:18–75  ·  view source on GitHub ↗
(
    filePath: string,
    schema: any
)

Source from the content-addressed store, hash-verified

16
17// TODO: Merge this with config loading logic which uses AJV
18export const loadJsonFile = async <T>(
19 filePath: string,
20 schema: any
21): Promise<T> => {
22 const fileContent = await (async () => {
23 if (isRemotePath(filePath)) {
24 const response = await fetch(filePath);
25 if (!response.ok) {
26 throw new Error(`Failed to fetch file ${filePath}: ${response.statusText}`);
27 }
28 return response.text();
29 } else {
30 // Retry logic for handling race conditions with mounted volumes
31 const maxAttempts = 5;
32 const retryDelayMs = 2000;
33 let lastError: Error | null = null;
34
35 for (let attempt = 1; attempt <= maxAttempts; attempt++) {
36 try {
37 return await readFile(filePath, {
38 encoding: 'utf-8',
39 });
40 } catch (error) {
41 lastError = error as Error;
42
43 // Only retry on ENOENT errors (file not found)
44 if ((error as NodeJS.ErrnoException)?.code !== 'ENOENT') {
45 throw error; // Throw immediately for non-ENOENT errors
46 }
47
48 // Log warning before retry (except on the last attempt)
49 if (attempt < maxAttempts) {
50 console.warn(`File not found, retrying in 2s... (Attempt ${attempt}/${maxAttempts})`);
51 await new Promise(resolve => setTimeout(resolve, retryDelayMs));
52 }
53 }
54 }
55
56 // If we've exhausted all retries, throw the last ENOENT error
57 if (lastError) {
58 throw lastError;
59 }
60
61 throw new Error('Failed to load file after all retry attempts');
62 }
63 })();
64
65 const parsedData = JSON.parse(stripJsonComments(fileContent));
66
67 try {
68 return schema.parse(parsedData);
69 } catch (error) {
70 if (error instanceof z.ZodError) {
71 throw new Error(`File '${filePath}' is invalid: ${error.errors.map(e => `${e.path.join('.')}: ${e.message}`).join(', ')}`);
72 }
73 throw error;
74 }
75}

Callers 1

ChatLandingPageFunction · 0.90

Calls 1

isRemotePathFunction · 0.85

Tested by

no test coverage detected