Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
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
32 changes: 12 additions & 20 deletions packages/app/src/cli/models/app/identifiers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,9 @@ describe('updateAppIdentifiers', () => {
// When
const gotApp = await updateAppIdentifiers({
app,
identifiers: {
app: 'FOO',
extensions: {
my_extension: 'BAR',
},
appApiKey: 'FOO',
extensionUuids: {
my_extension: 'BAR',
},
command: 'deploy',
})
Expand Down Expand Up @@ -51,11 +49,9 @@ describe('updateAppIdentifiers', () => {
// When
const gotApp = await updateAppIdentifiers({
app,
identifiers: {
app: 'FOO',
extensions: {
my_extension: 'BAR',
},
appApiKey: 'FOO',
extensionUuids: {
my_extension: 'BAR',
},
command: 'deploy',
})
Expand Down Expand Up @@ -85,11 +81,9 @@ describe('updateAppIdentifiers', () => {
await updateAppIdentifiers(
{
app,
identifiers: {
app: 'FOO',
extensions: {
my_extension: 'BAR',
},
appApiKey: 'FOO',
extensionUuids: {
my_extension: 'BAR',
},
command: 'deploy',
},
Expand Down Expand Up @@ -152,11 +146,9 @@ type = "ui_extension"`,
await updateAppIdentifiers(
{
app,
identifiers: {
app: 'FOO',
extensions: {
my_extension: 'BAR',
},
appApiKey: 'FOO',
extensionUuids: {
my_extension: 'BAR',
},
command: 'deploy',
},
Expand Down
36 changes: 6 additions & 30 deletions packages/app/src/cli/models/app/identifiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,6 @@ import {joinPath} from '@shopify/cli-kit/node/path'
import {fileExists, readFile, writeFile} from '@shopify/cli-kit/node/fs'
import type {AppInterface} from './app.js'

export interface IdentifiersExtensions {
[localIdentifier: string]: string
}

interface Identifiers {
/** Application's API Key */
app: string

/**
* The extensions' unique identifiers.
*/
extensions: IdentifiersExtensions

/**
* The extensions' numeric identifiers (expressed as a string).
*/
extensionIds: IdentifiersExtensions

/**
* The extensions' unique identifiers which uuid is not managed.
*/
extensionsNonUuidManaged: IdentifiersExtensions
}

export interface ExtensionUuidsByLocalIdentifier {
[localIdentifier: string]: string
}
Expand All @@ -39,11 +15,11 @@ export interface DeployIdentifiers {
appModuleRegistrationIds: ExtensionUuidsByLocalIdentifier
}

type UuidOnlyIdentifiers = Omit<Identifiers, 'extensionIds' | 'extensionsNonUuidManaged'>
type UpdateAppIdentifiersCommand = 'dev' | 'deploy' | 'release' | 'import-extensions'
interface UpdateAppIdentifiersOptions {
app: AppInterface
identifiers: UuidOnlyIdentifiers
appApiKey: string
extensionUuids: ExtensionUuidsByLocalIdentifier
command: UpdateAppIdentifiersCommand
}

Expand All @@ -53,7 +29,7 @@ interface UpdateAppIdentifiersOptions {
* @returns An copy of the app with the environment updated to reflect the updated identifiers.
*/
export async function updateAppIdentifiers(
{app, identifiers, command}: UpdateAppIdentifiersOptions,
{app, appApiKey, extensionUuids, command}: UpdateAppIdentifiersOptions,
systemEnvironment = process.env,
): Promise<AppInterface> {
let dotenvFile = app.dotenv
Expand All @@ -64,12 +40,12 @@ export async function updateAppIdentifiers(
}
const updatedVariables: {[key: string]: string} = {...(app.dotenv?.variables ?? {})}
if (!systemEnvironment[app.idEnvironmentVariableName]) {
updatedVariables[app.idEnvironmentVariableName] = identifiers.app
updatedVariables[app.idEnvironmentVariableName] = appApiKey
}
Object.keys(identifiers.extensions).forEach((identifier) => {
Object.keys(extensionUuids).forEach((identifier) => {
const envVariable = `SHOPIFY_${constantize(identifier)}_ID`
if (!systemEnvironment[envVariable]) {
updatedVariables[envVariable] = identifiers.extensions[identifier]!
updatedVariables[envVariable] = extensionUuids[identifier]!
}
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {reduceWebhooks} from '../../models/extensions/specifications/transform/a
import {removeTrailingSlash} from '../../models/extensions/specifications/validation/common.js'
import {TomlFile} from '@shopify/cli-kit/node/toml/toml-file'
import {JsonMapType} from '@shopify/cli-kit/node/toml'
import {zod} from '@shopify/cli-kit/node/schema'
import {outputDebug} from '@shopify/cli-kit/node/output'

export async function writeAppConfigurationFile(configuration: CurrentAppConfiguration, configPath: string) {
Expand Down Expand Up @@ -46,53 +45,6 @@ export function stripEmptyObjects(obj: unknown): unknown {
return obj
}

/**
* Rewrite a configuration object to match the structure of a Zod schema.
*
* Used by breakdown-extensions.ts to normalize configs before diffing.
* Not used by writeAppConfigurationFile — that function uses stripEmptyObjects instead.
*/
export const rewriteConfiguration = <T extends zod.ZodTypeAny>(schema: T, config: unknown): unknown => {
if (schema === null || schema === undefined) return null
if (schema instanceof zod.ZodNullable || schema instanceof zod.ZodOptional)
return rewriteConfiguration(schema.unwrap(), config)
if (schema instanceof zod.ZodArray) {
return (config as unknown[]).map((item) => rewriteConfiguration(schema.element, item))
}
if (schema instanceof zod.ZodEffects) {
return rewriteConfiguration(schema._def.schema, config)
}
if (schema instanceof zod.ZodObject) {
const entries = Object.entries(schema.shape)
const confObj = config as {[key: string]: unknown}
let result: {[key: string]: unknown} = {}
entries.forEach(([key, subSchema]) => {
if (confObj !== undefined && confObj[key] !== undefined) {
let value = rewriteConfiguration(subSchema as T, confObj[key])
if (!(value instanceof Array) && value instanceof Object && Object.keys(value as object).length === 0) {
value = undefined
}
result = {...result, [key]: value}
}
})

// if dynamic config was enabled, its possible to have more keys in the file than the schema
const blockedKeys = ['scopes']

Object.entries(confObj)
.filter(([key]) => !blockedKeys.includes(key))
.sort(([keyA], [keyB]) => keyA.localeCompare(keyB))
.forEach(([key, value]) => {
if (!entries.map(([key]) => key).includes(key)) {
result = {...result, [key]: value}
}
})

return result
}
return config
}

function addDefaultCommentsToToml(fileString: string) {
const appTomlInitialComment = `# Learn more about configuring your app at https://shopify.dev/docs/apps/tools/cli/configuration\n`
const appTomlScopesComment = `\n# Learn more at https://shopify.dev/docs/apps/tools/cli/configuration#access_scopes`
Expand Down
Loading
Loading