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
7 changes: 1 addition & 6 deletions packages/app/src/cli/models/app/app.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -651,12 +651,7 @@ describe('manifest', () => {
})

// When
const manifest = await app.manifest({
app: 'API_KEY',
extensions: {app_access: 'UUID_A'},
extensionIds: {},
extensionsNonUuidManaged: {},
})
const manifest = await app.manifest({app_access: 'UUID_A'})

// Then
expect(manifest).toEqual({
Expand Down
8 changes: 4 additions & 4 deletions packages/app/src/cli/models/app/app.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {AppErrors, isWebType} from './loader.js'
import {ensurePathStartsWithSlash} from './validation/common.js'
import {Identifiers} from './identifiers.js'
import {ExtensionUuidsByLocalIdentifier} from './identifiers.js'
import {ExtensionInstance} from '../extensions/extension-instance.js'
import {FunctionConfigType} from '../extensions/specifications/function.js'
import {ExtensionSpecification, RemoteAwareExtensionSpecification} from '../extensions/specification.js'
Expand Down Expand Up @@ -245,7 +245,7 @@ export interface AppInterface<
* If creating an app on the platform based on this app and its configuration, what default options should the app take?
*/
creationDefaultOptions(): CreateAppOptions
manifest: (identifiers: Identifiers | undefined) => Promise<AppManifest>
manifest: (appModuleUuids: ExtensionUuidsByLocalIdentifier | undefined) => Promise<AppManifest>
removeExtension: (extensionUid: string) => void
updateHiddenConfig: (values: Partial<AppHiddenConfig>) => Promise<void>
setDevApplicationURLs: (devApplicationURLs: ApplicationURLs) => void
Expand Down Expand Up @@ -331,7 +331,7 @@ export class App<
this.realExtensions.forEach((ext) => ext.patchWithAppDevURLs(devApplicationURLs))
}

async manifest(identifiers: Identifiers | undefined): Promise<AppManifest> {
async manifest(appModuleUuids: ExtensionUuidsByLocalIdentifier | undefined): Promise<AppManifest> {
const modules = await Promise.all(
this.realExtensions.map(async (module) => {
const config = await module.deployConfig({
Expand All @@ -342,7 +342,7 @@ export class App<
type: module.externalType,
handle: module.handle,
uid: module.uid,
uuid: identifiers?.extensions[module.localIdentifier],
uuid: appModuleUuids?.[module.localIdentifier],
assets: module.uid,
target: module.contextValue,
config: (config ?? {}) as JsonMapType,
Expand Down
38 changes: 14 additions & 24 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 Expand Up @@ -203,8 +195,7 @@ describe('getAppIdentifiers', () => {
})

// Then
expect(got.app).toEqual('FOO')
expect((got.extensions ?? {})['test-ui-extension']).toEqual('BAR')
expect(got['test-ui-extension']).toEqual('BAR')
})
})

Expand All @@ -229,8 +220,7 @@ describe('getAppIdentifiers', () => {
)

// Then
expect(got.app).toEqual('FOO')
expect((got.extensions ?? {})['test-ui-extension']).toEqual('BAR')
expect(got['test-ui-extension']).toEqual('BAR')
})
})
})
42 changes: 12 additions & 30 deletions packages/app/src/cli/models/app/identifiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,20 @@ 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 {
export interface ExtensionUuidsByLocalIdentifier {
[localIdentifier: string]: string
}

export 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 DeployIdentifiers {
appModuleUuids: ExtensionUuidsByLocalIdentifier
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 @@ -44,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 @@ -55,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 Expand Up @@ -91,7 +76,7 @@ interface GetAppIdentifiersOptions {
export function getAppIdentifiers(
{app}: GetAppIdentifiersOptions,
systemEnvironment = process.env,
): Partial<UuidOnlyIdentifiers> {
): ExtensionUuidsByLocalIdentifier {
const envVariables = {
...app.dotenv?.variables,
...(systemEnvironment as {[variable: string]: string}),
Expand All @@ -104,8 +89,5 @@ export function getAppIdentifiers(
}
app.allExtensions.forEach(processExtension)

return {
app: envVariables[app.idEnvironmentVariableName],
extensions: extensionsIdentifiers,
}
return extensionsIdentifiers
}
Original file line number Diff line number Diff line change
Expand Up @@ -233,16 +233,11 @@ describe('deployConfig', async () => {
})

describe('bundleConfig', async () => {
test('returns the uuid from extensions when the extension is uuid managed', async () => {
test('returns the uuid from appModuleUuids', async () => {
const extensionInstance = await testThemeExtensions()

const got = await extensionInstance.bundleConfig({
identifiers: {
extensions: {'theme-extension-name': 'theme-uuid'},
extensionIds: {},
app: 'My app',
extensionsNonUuidManaged: {},
},
appModuleUuids: {'theme-extension-name': 'theme-uuid'},
developerPlatformClient,
apiKey: 'apiKey',
appConfiguration: placeholderAppConfiguration,
Expand All @@ -260,12 +255,7 @@ describe('bundleConfig', async () => {
const extensionInstance = await testPaymentExtensions()

const got = await extensionInstance.bundleConfig({
identifiers: {
extensions: {'payment-extension-name': 'payment-uuid'},
extensionIds: {},
app: 'My app',
extensionsNonUuidManaged: {},
},
appModuleUuids: {'payment-extension-name': 'payment-uuid'},
developerPlatformClient,
apiKey: 'apiKey',
appConfiguration: placeholderAppConfiguration,
Expand All @@ -279,16 +269,11 @@ describe('bundleConfig', async () => {
)
})

test('returns the uuid from extensionsNonUuidManaged when the extension is not uuid managed', async () => {
test('returns the uuid for a non-uuid-managed extension', async () => {
const extensionInstance = await testAppConfigExtensions()

const got = await extensionInstance.bundleConfig({
identifiers: {
extensions: {},
extensionIds: {},
app: 'My app',
extensionsNonUuidManaged: {point_of_sale: 'uuid'},
},
appModuleUuids: {point_of_sale: 'uuid'},
developerPlatformClient,
apiKey: 'apiKey',
appConfiguration: placeholderAppConfiguration,
Expand Down Expand Up @@ -416,7 +401,7 @@ describe('buildUIDFromStrategy', async () => {
// Given
const extensionInstance = await testSingleWebhookSubscriptionExtension()
// Then
expect(extensionInstance.uid).toBe('orders/delete::undefined::https://my-app.com/webhooks')
expect(extensionInstance.uid).toBe('orders/delete::::https://my-app.com/webhooks')
})

test('returns a custom string when strategy is dynamic and it is a webhook subscription extension with filters', async () => {
Expand Down
29 changes: 12 additions & 17 deletions packages/app/src/cli/models/extensions/extension-instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {FunctionConfigType} from './specifications/function.js'
import {DevSessionWatchConfig, ExtensionFeature, ExtensionSpecification} from './specification.js'
import {SingleWebhookSubscriptionType} from './specifications/app_config_webhook_schemas/webhooks_schema.js'
import {ExtensionBuildOptions} from '../../services/build/extension.js'
import {Identifiers} from '../app/identifiers.js'
import {ExtensionUuidsByLocalIdentifier} from '../app/identifiers.js'
import {DeveloperPlatformClient} from '../../utilities/developer-platform-client.js'
import {AppConfiguration} from '../app/app.js'
import {ApplicationURLs} from '../../services/dev/urls.js'
Expand Down Expand Up @@ -245,10 +245,8 @@ export class ExtensionInstance<TConfiguration extends BaseConfigType = BaseConfi
return `https://${fqdn}/${options.orgId}/apps/${options.appId}/extensions/${parnersPath}/${options.extensionId}`
}

getOutputFolderId(outputId?: string) {
// Ideally we want to return `this.uid` always. To keep supporting Partners API we accept a value to override that.

return outputId ?? this.uid
getOutputFolderId() {
return this.uid
}

// UI Specific properties
Expand Down Expand Up @@ -347,17 +345,16 @@ export class ExtensionInstance<TConfiguration extends BaseConfigType = BaseConfi
}
}

async buildForBundle(options: ExtensionBuildOptions, bundleDirectory: string, outputId?: string) {
this.outputPath = this.getOutputPathForDirectory(bundleDirectory, outputId)
async buildForBundle(options: ExtensionBuildOptions, bundleDirectory: string) {
this.outputPath = this.getOutputPathForDirectory(bundleDirectory)
await this.build(options)

const bundleInputPath = joinPath(bundleDirectory, this.getOutputFolderId(outputId))
const bundleInputPath = joinPath(bundleDirectory, this.getOutputFolderId())
await this.keepBuiltSourcemapsLocally(bundleInputPath)
}

getOutputPathForDirectory(directory: string, outputId?: string) {
const id = this.getOutputFolderId(outputId)
return joinPath(directory, id, this.outputRelativePath)
getOutputPathForDirectory(directory: string) {
return joinPath(directory, this.getOutputFolderId(), this.outputRelativePath)
}

get singleTarget() {
Expand All @@ -373,7 +370,7 @@ export class ExtensionInstance<TConfiguration extends BaseConfigType = BaseConfi
}

async bundleConfig({
identifiers,
appModuleUuids,
developerPlatformClient,
apiKey,
appConfiguration,
Expand All @@ -387,9 +384,7 @@ export class ExtensionInstance<TConfiguration extends BaseConfigType = BaseConfi
handle: this.handle,
}

const uuid = this.isUUIDStrategyExtension
? identifiers.extensions[this.localIdentifier]!
: identifiers.extensionsNonUuidManaged[this.localIdentifier]!
const uuid = appModuleUuids[this.localIdentifier]!

return {
...result,
Expand Down Expand Up @@ -543,7 +538,7 @@ export class ExtensionInstance<TConfiguration extends BaseConfigType = BaseConfi
// Related issues: PR #559094 in old Core repo
if ('topic' in this.configuration && 'uri' in this.configuration) {
const subscription = this.configuration as unknown as SingleWebhookSubscriptionType
return `${subscription.topic}::${subscription.filter}::${subscription.uri}`.substring(0, MAX_UID_LENGTH)
return `${subscription.topic}::${subscription.filter ?? ''}::${subscription.uri}`.substring(0, MAX_UID_LENGTH)
} else {
return nonRandomUUID(JSON.stringify(this.configuration))
}
Expand All @@ -557,7 +552,7 @@ interface ExtensionDeployConfigOptions {
}

interface ExtensionBundleConfigOptions {
identifiers: Identifiers
appModuleUuids: ExtensionUuidsByLocalIdentifier
developerPlatformClient: DeveloperPlatformClient
apiKey: string
appConfiguration: AppConfiguration
Expand Down
Loading
Loading