Files
twenty/packages/twenty-cli/src/utils/jsonc-parser.ts
T
Félix Malfait 30a2164980 First Application POC (#14382)
Quick proof of concept for twenty-apps + twenty-cli, with local
development / hot reload

Let's discuss it!



https://github.com/user-attachments/assets/c6789936-cd5f-4110-a265-863a6ac1af2d
2025-09-10 15:12:38 +02:00

69 lines
1.8 KiB
TypeScript

import * as fs from 'fs-extra';
import { ParseError, parse as parseJsonc } from 'jsonc-parser';
export interface JsoncParseOptions {
allowTrailingComma?: boolean;
disallowComments?: boolean;
allowEmptyContent?: boolean;
}
export class JsoncParseError extends Error {
constructor(
message: string,
public readonly parseErrors: ParseError[],
public readonly filePath?: string,
) {
super(message);
this.name = 'JsoncParseError';
}
}
export const parseJsoncString = (
content: string,
options: JsoncParseOptions = {},
): any => {
const parseErrors: ParseError[] = [];
const result = parseJsonc(content, parseErrors, {
allowTrailingComma: options.allowTrailingComma ?? true,
disallowComments: options.disallowComments ?? false,
allowEmptyContent: options.allowEmptyContent ?? false,
});
if (parseErrors.length > 0) {
const errorMessages = parseErrors.map(
(error) => `Line ${error.offset}: ${error.error}`,
);
throw new JsoncParseError(
`JSONC parse errors:\n${errorMessages.join('\n')}`,
parseErrors,
);
}
return result;
};
export const parseJsoncFile = async (
filePath: string,
options: JsoncParseOptions = {},
): Promise<any> => {
try {
const content = await fs.readFile(filePath, 'utf8');
return parseJsoncString(content, options);
} catch (error) {
if (error instanceof JsoncParseError) {
throw new JsoncParseError(error.message, error.parseErrors, filePath);
}
throw new Error(`Failed to read file ${filePath}: ${error}`);
}
};
export const writeJsoncFile = async (
filePath: string,
data: any,
options: { spaces?: number } = {},
): Promise<void> => {
const content = JSON.stringify(data, null, options.spaces ?? 2);
await fs.writeFile(filePath, content, 'utf8');
};