( source: EditableSettingSource, settings: SettingsJson, )
| 499 | * the key is present with an explicit `undefined` value. |
| 500 | */ |
| 501 | export function updateSettingsForSource( |
| 502 | source: EditableSettingSource, |
| 503 | settings: SettingsJson, |
| 504 | ): { error: Error | null } { |
| 505 | if ( |
| 506 | (source as unknown) === 'policySettings' || |
| 507 | (source as unknown) === 'flagSettings' |
| 508 | ) { |
| 509 | return { error: null } |
| 510 | } |
| 511 | |
| 512 | // Create the folder if needed |
| 513 | const readPath = getSettingsFilePathForSource(source) |
| 514 | const filePath = getSettingsWriteFilePathForSource(source) |
| 515 | if (!filePath) { |
| 516 | return { error: null } |
| 517 | } |
| 518 | |
| 519 | try { |
| 520 | getFsImplementation().mkdirSync(dirname(filePath)) |
| 521 | |
| 522 | // Try to get existing settings with validation. Bypass the per-source |
| 523 | // cache — mergeWith below mutates its target (including nested refs), |
| 524 | // and mutating the cached object would leak unpersisted state if the |
| 525 | // write fails before resetSettingsCache(). |
| 526 | let existingSettings = getSettingsForSourceUncached(source) |
| 527 | |
| 528 | // If validation failed, check if file exists with a JSON syntax error |
| 529 | if (!existingSettings) { |
| 530 | let content: string | null = null |
| 531 | const rawReadPath = readPath ?? filePath |
| 532 | try { |
| 533 | content = readFileSync(rawReadPath) |
| 534 | } catch (e) { |
| 535 | if (!isENOENT(e)) { |
| 536 | throw e |
| 537 | } |
| 538 | // File doesn't exist — fall through to merge with empty settings |
| 539 | } |
| 540 | if (content !== null) { |
| 541 | const rawData = safeParseJSON(content) |
| 542 | if (rawData === null) { |
| 543 | // JSON syntax error - return validation error instead of overwriting |
| 544 | // safeParseJSON will already log the error, so we'll just return the error here |
| 545 | return { |
| 546 | error: new Error( |
| 547 | `Invalid JSON syntax in settings file at ${rawReadPath}`, |
| 548 | ), |
| 549 | } |
| 550 | } |
| 551 | if (rawData && typeof rawData === 'object') { |
| 552 | existingSettings = rawData as SettingsJson |
| 553 | logForDebugging( |
| 554 | `Using raw settings from ${rawReadPath} due to validation failure`, |
| 555 | ) |
| 556 | } |
| 557 | } |
| 558 | } |
no test coverage detected