diff --git a/.changeset/add-intercepts-capability.md b/.changeset/add-intercepts-capability.md new file mode 100644 index 00000000000..7d3cba12279 --- /dev/null +++ b/.changeset/add-intercepts-capability.md @@ -0,0 +1,6 @@ +--- +'@shopify/app': minor +'@shopify/ui-extensions-server-kit': minor +--- + +Add support for the `intercepts` UI extension target capability. diff --git a/packages/app/src/cli/models/extensions/schemas.test.ts b/packages/app/src/cli/models/extensions/schemas.test.ts index e4244c98a03..d149d24b791 100644 --- a/packages/app/src/cli/models/extensions/schemas.test.ts +++ b/packages/app/src/cli/models/extensions/schemas.test.ts @@ -1,4 +1,4 @@ -import {BaseSchema, MAX_UID_LENGTH} from './schemas.js' +import {BaseSchema, MAX_UID_LENGTH, NewExtensionPointsSchema} from './schemas.js' import {describe, expect, test} from 'vitest' const validUIDTestCases = [ @@ -55,3 +55,29 @@ describe('UIDSchema', () => { }) }) }) + +describe('NewExtensionPointsSchema', () => { + test.each([ + [ + 'valid intercepts', + [ + {event: 'cartvalidations', blocking: true}, + {event: 'paymentvalidations', blocking: true, applies_to: ['cash']}, + ], + true, + ], + ['an invalid event', [{event: 1, blocking: true}], false], + ['an invalid blocking value', [{event: 'cartvalidations', blocking: 'true'}], false], + ['an invalid applies_to value', [{event: 'paymentvalidations', blocking: true, applies_to: [1]}], false], + ])('validates %s', (_description, intercepts, isValid) => { + const result = NewExtensionPointsSchema.safeParse([ + { + target: 'pos.app.ready.data', + module: './src/app.ts', + capabilities: {intercepts}, + }, + ]) + + expect(result.success).toBe(isValid) + }) +}) diff --git a/packages/app/src/cli/models/extensions/schemas.ts b/packages/app/src/cli/models/extensions/schemas.ts index 55d0b3d2526..11d6f2fdc7e 100644 --- a/packages/app/src/cli/models/extensions/schemas.ts +++ b/packages/app/src/cli/models/extensions/schemas.ts @@ -38,8 +38,15 @@ export const ExtensionsArraySchema = zod.object({ extensions: zod.array(zod.any()).optional(), }) +const TargetInterceptSchema = zod.object({ + event: zod.string(), + blocking: zod.boolean().default(false), + applies_to: zod.array(zod.string()).optional(), +}) + const TargetCapabilitiesSchema = zod.object({ allow_direct_linking: zod.boolean().optional(), + intercepts: zod.array(TargetInterceptSchema).optional(), }) const ShouldRenderSchema = zod.object({ diff --git a/packages/app/src/cli/models/extensions/specifications/ui_extension.test.ts b/packages/app/src/cli/models/extensions/specifications/ui_extension.test.ts index 089bc427389..14aa354b05c 100644 --- a/packages/app/src/cli/models/extensions/specifications/ui_extension.test.ts +++ b/packages/app/src/cli/models/extensions/specifications/ui_extension.test.ts @@ -241,15 +241,19 @@ describe('ui_extension', async () => { ]) }) - test('targeting object accepts allow_direct_linking for target capabilities', async () => { + test('targeting object accepts intercepts target capabilities', async () => { const allSpecs = await loadLocalExtensionsSpecifications() const specification = allSpecs.find((spec) => spec.identifier === 'ui_extension')! + const intercepts = [ + {event: 'cartvalidations'}, + {event: 'paymentvalidations', blocking: true, applies_to: ['cash']}, + ] const configuration = { targeting: [ { target: 'EXTENSION::POINT::A', module: './src/ExtensionPointA.js', - capabilities: {allow_direct_linking: true}, + capabilities: {allow_direct_linking: true, intercepts}, }, ], api_version: '2023-01' as const, @@ -292,7 +296,13 @@ describe('ui_extension', async () => { metafields: [], urls: {}, default_placement_reference: undefined, - capabilities: {allow_direct_linking: true}, + capabilities: { + allow_direct_linking: true, + intercepts: [ + {event: 'cartvalidations', blocking: false}, + {event: 'paymentvalidations', blocking: true, applies_to: ['cash']}, + ], + }, preloads: {}, build_manifest: { assets: { diff --git a/packages/ui-extensions-server-kit/src/types.ts b/packages/ui-extensions-server-kit/src/types.ts index 44ce009f07b..5a3e469d34f 100644 --- a/packages/ui-extensions-server-kit/src/types.ts +++ b/packages/ui-extensions-server-kit/src/types.ts @@ -83,6 +83,17 @@ interface Metafield { key: string } +export interface ExtensionPointIntercept { + event: string + blocking: boolean + applies_to?: string[] +} + +export interface ExtensionPointCapabilities { + allow_direct_linking?: boolean + intercepts?: ExtensionPointIntercept[] +} + export interface ExtensionPoint { target: string surface: Surface @@ -93,6 +104,7 @@ export interface ExtensionPoint { name: string description?: string assets?: Record + capabilities?: ExtensionPointCapabilities } type ExtensionPoints = string[] | ExtensionPoint[] | null