diff --git a/packages/app/src/cli/models/extensions/extension-instance.ts b/packages/app/src/cli/models/extensions/extension-instance.ts index bae90a842b..59a01eafc4 100644 --- a/packages/app/src/cli/models/extensions/extension-instance.ts +++ b/packages/app/src/cli/models/extensions/extension-instance.ts @@ -206,14 +206,20 @@ export class ExtensionInstance { const {moduleId} = await uploadWasmBlob(this.localIdentifier, this.outputPath, developerPlatformClient) - return this.specification.deployConfig?.(this.configuration, this.directory, apiKey, moduleId) + return this.specification.deployConfig?.(this.configuration, this.directory, apiKey, this.features, moduleId) } async commonDeployConfig( apiKey: string, appConfiguration: AppConfigurationWithoutPath, ): Promise<{[key: string]: unknown} | undefined> { - const deployConfig = await this.specification.deployConfig?.(this.configuration, this.directory, apiKey, undefined) + const deployConfig = await this.specification.deployConfig?.( + this.configuration, + this.directory, + apiKey, + this.features, + undefined, + ) const transformedConfig = this.specification.transformLocalToRemote?.(this.configuration, appConfiguration) as | {[key: string]: unknown} | undefined diff --git a/packages/app/src/cli/models/extensions/load-specifications.ts b/packages/app/src/cli/models/extensions/load-specifications.ts index 8d662eb66e..435d5810e6 100644 --- a/packages/app/src/cli/models/extensions/load-specifications.ts +++ b/packages/app/src/cli/models/extensions/load-specifications.ts @@ -27,6 +27,7 @@ import uiExtensionSpec from './specifications/ui_extension.js' import webPixelSpec from './specifications/web_pixel_extension.js' import editorExtensionCollectionSpecification from './specifications/editor_extension_collection.js' import customDataSpec, {CustomDataSpecIdentifier} from './specifications/custom_data.js' +import adminLinkSpec from './specifications/admin_link_extension.js' const SORTED_CONFIGURATION_SPEC_IDENTIFIERS = [ BrandingSpecIdentifier, @@ -78,6 +79,7 @@ function loadSpecifications() { uiExtensionSpec, webPixelSpec, editorExtensionCollectionSpecification, + adminLinkSpec, ] as ExtensionSpecification[] return [...configModuleSpecs, ...moduleSpecs] diff --git a/packages/app/src/cli/models/extensions/specification.ts b/packages/app/src/cli/models/extensions/specification.ts index 50eac5142a..d86c78e1a0 100644 --- a/packages/app/src/cli/models/extensions/specification.ts +++ b/packages/app/src/cli/models/extensions/specification.ts @@ -8,6 +8,7 @@ import {Result} from '@shopify/cli-kit/node/result' import {capitalize} from '@shopify/cli-kit/common/string' import {ParseConfigurationResult, zod} from '@shopify/cli-kit/node/schema' import {getPathValue, setPathValue} from '@shopify/cli-kit/common/object' +import {loadLocalesConfig} from '../../utilities/extensions/locales-configuration.js' export type ExtensionFeature = | 'ui_preview' @@ -17,6 +18,7 @@ export type ExtensionFeature = | 'cart_url' | 'esbuild' | 'single_js_entry_path' + | 'localization' export interface TransformationConfig { [key: string]: string @@ -50,6 +52,7 @@ export interface ExtensionSpecification Promise<{[key: string]: unknown} | undefined> validate?: (config: TConfiguration, configPath: string, directory: string) => Promise> @@ -271,10 +274,17 @@ export function createContractBasedModuleSpecification, appModuleFeatures: () => appModuleFeatures ?? [], - deployConfig: async (config, _) => { + deployConfig: async (config, directory) => { // These are loaded automatically for all modules, but are considered "first class" and not part of extension contracts // If a module needs them, they can access them from the manifest. - const {type, handle, uid, ...configWithoutFirstClassFields} = config + let {type, handle, uid, ...configWithoutFirstClassFields} = config + //Check for 'localization' feature and load the locales configuration + if (appModuleFeatures?.includes('localization')) { + configWithoutFirstClassFields = { + ...configWithoutFirstClassFields, + localization: await loadLocalesConfig(directory, config.type), + } + } return configWithoutFirstClassFields }, }) diff --git a/packages/app/src/cli/models/extensions/specifications/admin_link_extension.ts b/packages/app/src/cli/models/extensions/specifications/admin_link_extension.ts new file mode 100644 index 0000000000..dd3c25328f --- /dev/null +++ b/packages/app/src/cli/models/extensions/specifications/admin_link_extension.ts @@ -0,0 +1,7 @@ +import {createContractBasedModuleSpecification} from '../specification.js' + +export const AdminLinkSpecIdentifier = 'admin_link' + +const AdminLinkSpec = createContractBasedModuleSpecification(AdminLinkSpecIdentifier, ['localization']) + +export default AdminLinkSpec diff --git a/packages/app/src/cli/models/extensions/specifications/function.ts b/packages/app/src/cli/models/extensions/specifications/function.ts index 9da115b137..a3f124a2f0 100644 --- a/packages/app/src/cli/models/extensions/specifications/function.ts +++ b/packages/app/src/cli/models/extensions/specifications/function.ts @@ -77,7 +77,7 @@ const functionSpec = createExtensionSpecification({ ], schema: FunctionExtensionSchema, appModuleFeatures: (_) => ['function'], - deployConfig: async (config, directory, apiKey, moduleId) => { + deployConfig: async (config, directory, apiKey, _, moduleId) => { let inputQuery: string | undefined const inputQueryPath = joinPath(directory, 'input.graphql') if (await fileExists(inputQueryPath)) {