diff --git a/packages/cli-kit/src/public/node/toml/toml-file.test.ts b/packages/cli-kit/src/public/node/toml/toml-file.test.ts index 9e507c60df0..1d6949a9a9f 100644 --- a/packages/cli-kit/src/public/node/toml/toml-file.test.ts +++ b/packages/cli-kit/src/public/node/toml/toml-file.test.ts @@ -83,6 +83,39 @@ describe('TomlFile', () => { }) }) + test('sets deeply nested values', async () => { + await inTemporaryDirectory(async (dir) => { + const path = joinPath(dir, 'test.toml') + await writeFile(path, '[access.admin]\ndirect_api_mode = "online"\n') + + const file = await TomlFile.read(path) + await file.patch({access: {admin: {direct_api_mode: 'offline'}}}) + + expect(file.content).toStrictEqual({access: {admin: {direct_api_mode: 'offline'}}}) + }) + }) + + test('sets multiple nested branches at once', async () => { + await inTemporaryDirectory(async (dir) => { + const path = joinPath(dir, 'test.toml') + await writeFile( + path, + ['[access.admin]', 'direct_api_mode = "online"', '', '[webhooks]', 'api_version = "2023-07"', ''].join('\n'), + ) + + const file = await TomlFile.read(path) + await file.patch({ + access: {admin: {direct_api_mode: 'offline'}}, + webhooks: {api_version: '2024-01'}, + }) + + expect(file.content).toStrictEqual({ + access: {admin: {direct_api_mode: 'offline'}}, + webhooks: {api_version: '2024-01'}, + }) + }) + }) + test('creates intermediate tables', async () => { await inTemporaryDirectory(async (dir) => { const path = joinPath(dir, 'test.toml') @@ -137,6 +170,20 @@ describe('TomlFile', () => { expect(content.auth.redirect_urls).toStrictEqual(['https://new.com', 'https://other.com']) }) }) + + test('removes a nested value when it is set to undefined', async () => { + await inTemporaryDirectory(async (dir) => { + const path = joinPath(dir, 'test.toml') + await writeFile(path, '[build]\ndev_store_url = "store.myshopify.com"\ninclude_config_on_deploy = true\n') + + const file = await TomlFile.read(path) + await file.patch({build: {include_config_on_deploy: undefined}}) + + const build = file.content.build as {[key: string]: unknown} + expect(build.dev_store_url).toBe('store.myshopify.com') + expect(build.include_config_on_deploy).toBeUndefined() + }) + }) }) describe('remove', () => { diff --git a/packages/cli-kit/src/public/node/toml/toml-file.ts b/packages/cli-kit/src/public/node/toml/toml-file.ts index a2ee81b3236..f5a2794f7ac 100644 --- a/packages/cli-kit/src/public/node/toml/toml-file.ts +++ b/packages/cli-kit/src/public/node/toml/toml-file.ts @@ -160,14 +160,11 @@ export class TomlFile { * @returns Flattened patch entries. */ function flattenToPatchEntries(obj: {[key: string]: unknown}, prefix: string[] = []): [string[], TomlPatchValue][] { - const entries: [string[], TomlPatchValue][] = [] - for (const [key, value] of Object.entries(obj)) { + return Object.entries(obj).flatMap(([key, value]) => { const path = [...prefix, key] if (value !== null && typeof value === 'object' && !Array.isArray(value)) { - entries.push(...flattenToPatchEntries(value as {[key: string]: unknown}, path)) - } else { - entries.push([path, value as TomlPatchValue]) + return flattenToPatchEntries(value as {[key: string]: unknown}, path) } - } - return entries + return [[path, value as TomlPatchValue]] + }) }