Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/cli/__tests__/global-config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,15 @@ describe('global-config', () => {
});
});

it('does not overwrite malformed config', async () => {
await writeFile(tmp.configFile, '{ invalid json');

const ok = await updateGlobalConfig({ telemetry: { enabled: true } }, tmp.configDir, tmp.configFile);

expect(ok).toBe(false);
expect(await readFile(tmp.configFile, 'utf-8')).toBe('{ invalid json');
});

it('returns false on write failures', async () => {
const ok = await updateGlobalConfig(
{ telemetry: { enabled: true } },
Expand Down
14 changes: 13 additions & 1 deletion src/lib/schemas/io/global-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export async function updateGlobalConfig(
configFile = GLOBAL_CONFIG_FILE
): Promise<boolean> {
try {
const existing = await readGlobalConfig(configFile);
const existing = await readGlobalConfigForUpdate(configFile);
const merged: GlobalConfig = mergeConfig(existing, partial);

await mkdir(configDir, { recursive: true });
Expand All @@ -63,6 +63,18 @@ export async function updateGlobalConfig(
}
}

async function readGlobalConfigForUpdate(configFile: string): Promise<GlobalConfig> {
try {
const data = await readFile(configFile, 'utf-8');
return GlobalConfigSchema.parse(JSON.parse(data));
} catch (error) {
if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
return {};
}
throw error;
}
}

function mergeConfig(target: GlobalConfig, source: GlobalConfig): GlobalConfig {
return {
...target,
Expand Down
Loading