Skip to content

Commit

Permalink
Merge pull request #4846 from Shopify/condition-with-manifest
Browse files Browse the repository at this point in the history
Enable multiple asset handling
  • Loading branch information
belalsj authored Nov 28, 2024
2 parents 9f4fbc6 + 26ceb5c commit ef45023
Show file tree
Hide file tree
Showing 15 changed files with 608 additions and 59 deletions.
26 changes: 24 additions & 2 deletions packages/app/src/cli/models/app/app.test-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,30 @@ export async function testUIExtension(
},
},
extension_points: [
{target: 'target1', module: 'module1'},
{target: 'target2', module: 'module2'},
{
target: 'target1',
module: 'module1',
build_manifest: {
assets: {
main: {
module: 'module1',
filepath: uiExtension?.handle ? `/${uiExtension.handle}.js` : '/test-ui-extension.js',
},
},
},
},
{
target: 'target2',
module: 'module2',
build_manifest: {
assets: {
main: {
module: 'module2',
filepath: uiExtension?.handle ? `/${uiExtension.handle}.js` : '/test-ui-extension.js',
},
},
},
},
],
}
const configurationPath = uiExtension?.configurationPath ?? `${directory}/shopify.ui.extension.toml`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ export class ExtensionInstance<TConfiguration extends BaseConfigType = BaseConfi
return this.specification.getBundleExtensionStdinContent(this.configuration)
}
const relativeImportPath = this.entrySourceFilePath.replace(this.directory, '')
return `import '.${relativeImportPath}';`
return {main: `import '.${relativeImportPath}';`}
}

shouldFetchCartUrl(): boolean {
Expand Down
5 changes: 5 additions & 0 deletions packages/app/src/cli/models/extensions/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,14 @@ const TargetCapabilitiesSchema = zod.object({
allow_direct_linking: zod.boolean().optional(),
})

const ShouldRenderSchema = zod.object({
module: zod.string(),
})

const NewExtensionPointSchema = zod.object({
target: zod.string(),
module: zod.string(),
should_render: ShouldRenderSchema.optional(),
metafields: zod.array(MetafieldSchema).optional(),
default_placement: zod.string().optional(),
capabilities: TargetCapabilitiesSchema.optional(),
Expand Down
12 changes: 11 additions & 1 deletion packages/app/src/cli/models/extensions/specification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ export interface CustomTransformationConfig {
type ExtensionExperience = 'extension' | 'configuration'
type UidStrategy = 'single' | 'dynamic' | 'uuid'

export enum AssetIdentifier {
ShouldRender = 'should_render',
Main = 'main',
}

export interface Asset {
identifier: AssetIdentifier
outputFileName: string
content: string
}
/**
* Extension specification with all the needed properties and methods to load an extension.
*/
Expand All @@ -50,7 +60,7 @@ export interface ExtensionSpecification<TConfiguration extends BaseConfigType =
experience: ExtensionExperience
dependency?: string
graphQLType?: string
getBundleExtensionStdinContent?: (config: TConfiguration) => string
getBundleExtensionStdinContent?: (config: TConfiguration) => {main: string; assets?: Asset[]}
deployConfig?: (
config: TConfiguration,
directory: string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,27 @@ import {describe, expect, test, vi} from 'vitest'
describe('ui_extension', async () => {
interface GetUIExtensionProps {
directory: string
extensionPoints?: {target: string; module: string; label?: string; default_placement_reference?: string}[]
extensionPoints?: {
target: string
module: string
label?: string
default_placement_reference?: string
should_render?: {
module: string
}
build_manifest?: {
assets: {
main: {
filepath: string
module: string
}
should_render?: {
filepath: string
module: string
}
}
}
}[]
}

async function getTestUIExtension({directory, extensionPoints}: GetUIExtensionProps) {
Expand Down Expand Up @@ -82,9 +102,13 @@ describe('ui_extension', async () => {
{
target: 'EXTENSION::POINT::A',
module: './src/ExtensionPointA.js',
should_render: {
module: './src/ShouldRender.js',
},
},
],
api_version: '2023-01' as const,
handle: 'test-ui-extension',
name: 'UI Extension',
description: 'This is an ordinary test extension',
type: 'ui_extension',
Expand Down Expand Up @@ -121,6 +145,18 @@ describe('ui_extension', async () => {
default_placement_reference: undefined,
capabilities: undefined,
preloads: {},
build_manifest: {
assets: {
main: {
filepath: 'test-ui-extension.js',
module: './src/ExtensionPointA.js',
},
should_render: {
filepath: 'test-ui-extension-conditions.js',
module: './src/ShouldRender.js',
},
},
},
},
])
})
Expand All @@ -140,6 +176,7 @@ describe('ui_extension', async () => {
name: 'UI Extension',
description: 'This is an ordinary test extension',
type: 'ui_extension',
handle: 'test-ui-extension',
capabilities: {
block_progress: false,
network_access: false,
Expand Down Expand Up @@ -172,6 +209,14 @@ describe('ui_extension', async () => {
default_placement_reference: 'PLACEMENT_REFERENCE1',
capabilities: undefined,
preloads: {},
build_manifest: {
assets: {
main: {
filepath: 'test-ui-extension.js',
module: './src/ExtensionPointA.js',
},
},
},
},
])
})
Expand All @@ -191,6 +236,7 @@ describe('ui_extension', async () => {
name: 'UI Extension',
description: 'This is an ordinary test extension',
type: 'ui_extension',
handle: 'test-ui-extension',
capabilities: {
block_progress: false,
network_access: false,
Expand Down Expand Up @@ -223,6 +269,14 @@ describe('ui_extension', async () => {
default_placement_reference: undefined,
capabilities: {allow_direct_linking: true},
preloads: {},
build_manifest: {
assets: {
main: {
filepath: 'test-ui-extension.js',
module: './src/ExtensionPointA.js',
},
},
},
},
])
})
Expand All @@ -242,6 +296,70 @@ describe('ui_extension', async () => {
name: 'UI Extension',
description: 'This is an ordinary test extension',
type: 'ui_extension',
handle: 'test-ui-extension',
capabilities: {
block_progress: false,
network_access: false,
api_access: false,
collect_buyer_consent: {
customer_privacy: true,
sms_marketing: false,
},
iframe: {
sources: [],
},
},
settings: {},
}

// When
const parsed = specification.parseConfigurationObject(configuration)
if (parsed.state !== 'ok') {
throw new Error("Couldn't parse configuration")
}

const got = parsed.data

// Then
expect(got.extension_points).toStrictEqual([
{
target: 'EXTENSION::POINT::A',
module: './src/ExtensionPointA.js',
metafields: [],
default_placement_reference: undefined,
capabilities: undefined,
preloads: {chat: '/chat'},
build_manifest: {
assets: {
main: {
filepath: 'test-ui-extension.js',
module: './src/ExtensionPointA.js',
},
},
},
},
])
})

test('build_manifest includes should_render asset when should_render.module is present', async () => {
const allSpecs = await loadLocalExtensionsSpecifications()
const specification = allSpecs.find((spec) => spec.identifier === 'ui_extension')!
const configuration = {
targeting: [
{
target: 'EXTENSION::POINT::A',
module: './src/ExtensionPointA.js',
should_render: {
module: './src/ShouldRender.js',
},
preloads: {chat: '/chat', not_supported: '/hello'},
},
],
api_version: '2023-01' as const,
name: 'UI Extension',
description: 'This is an ordinary test extension',
type: 'ui_extension',
handle: 'test-ui-extension',
capabilities: {
block_progress: false,
network_access: false,
Expand Down Expand Up @@ -274,6 +392,18 @@ describe('ui_extension', async () => {
default_placement_reference: undefined,
capabilities: undefined,
preloads: {chat: '/chat'},
build_manifest: {
assets: {
main: {
filepath: 'test-ui-extension.js',
module: './src/ExtensionPointA.js',
},
should_render: {
filepath: 'test-ui-extension-conditions.js',
module: './src/ShouldRender.js',
},
},
},
},
])
})
Expand Down Expand Up @@ -392,6 +522,14 @@ Please check the configuration in ${uiExtension.configurationPath}`),
{
target: 'EXTENSION::POINT::A',
module: './src/ExtensionPointA.js',
build_manifest: {
assets: {
main: {
filepath: 'test-ui-extension.js',
module: './src/ExtensionPointA.js',
},
},
},
},
],
})
Expand All @@ -406,7 +544,18 @@ Please check the configuration in ${uiExtension.configurationPath}`),
expect(loadLocales.loadLocalesConfig).toBeCalledWith(tmpDir, uiExtension.configuration.type)
expect(deployConfig).toStrictEqual({
localization,
extension_points: uiExtension.configuration.extension_points,
extension_points: uiExtension.configuration.extension_points?.map((extPoint) => ({
...extPoint,
build_manifest: {
...extPoint.build_manifest,
assets: {
main: {
filepath: 'dist/test-ui-extension.js',
module: extPoint.module,
},
},
},
})),

// Ensure nested capabilities are updated
capabilities: {
Expand Down Expand Up @@ -437,16 +586,32 @@ Please check the configuration in ${uiExtension.configurationPath}`),
{
target: 'EXTENSION::POINT::A',
module: './src/ExtensionPointA.js',
build_manifest: {
assets: {
main: {
module: './src/ExtensionPointA.js',
filepath: '/test-ui-extension.js',
},
},
},
},
{
target: 'EXTENSION::POINT::B',
module: './src/ExtensionPointB.js',
build_manifest: {
assets: {
main: {
module: './src/ExtensionPointB.js',
filepath: '/test-ui-extension.js',
},
},
},
},
],
})

// When
const stdInContent = uiExtension.getBundleExtensionStdinContent()
const stdInContent = uiExtension.getBundleExtensionStdinContent().main

// Then
expect(stdInContent).toContain(`import './src/ExtensionPointA.js';`)
Expand Down
Loading

0 comments on commit ef45023

Please sign in to comment.