Skip to content

Commit 53479bd

Browse files
committed
Support admin_link extensions in the Dev Server
1 parent 4459720 commit 53479bd

5 files changed

Lines changed: 64 additions & 13 deletions

File tree

packages/app/src/cli/models/extensions/specification.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ export function createContractBasedModuleSpecification<TConfiguration extends Ba
295295
| 'clientSteps'
296296
| 'experience'
297297
| 'transformRemoteToLocal'
298+
| 'getOutputRelativePath'
298299
>,
299300
) {
300301
return createExtensionSpecification({
@@ -305,6 +306,7 @@ export function createContractBasedModuleSpecification<TConfiguration extends Ba
305306
buildConfig: spec.buildConfig ?? {mode: 'none'},
306307
clientSteps: spec.clientSteps,
307308
uidStrategy: spec.uidStrategy,
309+
getOutputRelativePath: spec.getOutputRelativePath,
308310
transformRemoteToLocal: spec.transformRemoteToLocal,
309311
deployConfig: async (config, directory) => {
310312
let parsedConfig = configWithoutFirstClassFields(config)

packages/app/src/cli/models/extensions/specifications/admin_link.test.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,18 @@ describe('admin_link', async () => {
3232
})
3333
})
3434

35-
test('has localization in appModuleFeatures', async () => {
35+
test('has localization and ui_preview in appModuleFeatures', async () => {
3636
await inTemporaryDirectory(async (tmpDir) => {
3737
const extension = await getTestAdminLink(tmpDir)
3838
expect(extension.specification.appModuleFeatures()).toContain('localization')
39+
expect(extension.specification.appModuleFeatures()).toContain('ui_preview')
40+
})
41+
})
42+
43+
test('is previewable', async () => {
44+
await inTemporaryDirectory(async (tmpDir) => {
45+
const extension = await getTestAdminLink(tmpDir)
46+
expect(extension.isPreviewable).toBe(true)
3947
})
4048
})
4149

@@ -49,11 +57,11 @@ describe('admin_link', async () => {
4957
const steps = clientSteps[0]!.steps
5058
expect(steps).toHaveLength(1)
5159
expect(steps[0]).toMatchObject({
52-
id: 'copy-admin-link-assets',
53-
name: 'Copy Admin Link Assets',
60+
id: 'include-admin-link-assets',
61+
name: 'Include Admin Link Assets',
5462
type: 'include_assets',
5563
config: {
56-
generateManifest: true,
64+
generatesAssetsManifest: true,
5765
inclusions: [
5866
{type: 'configKey', key: 'targeting[].tools'},
5967
{type: 'configKey', key: 'targeting[].instructions'},

packages/app/src/cli/models/extensions/specifications/admin_link.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,29 +19,31 @@ const adminLinkSpec = createContractBasedModuleSpecification({
1919
inclusions: [
2020
{
2121
type: 'configKey',
22-
anchor: 'extensions[].targeting[]',
22+
anchor: 'targeting[]',
2323
groupBy: 'target',
24-
key: 'extensions[].targeting[].tools',
24+
key: 'targeting[].tools',
2525
},
2626
{
2727
type: 'configKey',
28-
anchor: 'extensions[].targeting[]',
28+
anchor: 'targeting[]',
2929
groupBy: 'target',
30-
key: 'extensions[].targeting[].instructions',
30+
key: 'targeting[].instructions',
3131
},
3232
{
3333
type: 'configKey',
34-
anchor: 'extensions[].targeting[]',
34+
anchor: 'targeting[]',
3535
groupBy: 'target',
36-
key: 'extensions[].targeting[].intents[].schema',
36+
key: 'targeting[].intents[].schema',
3737
},
3838
],
3939
},
4040
},
4141
],
4242
},
4343
],
44-
appModuleFeatures: () => ['localization'],
44+
// This needs to be a file path so the extension directory can be resolved to the correct path
45+
getOutputRelativePath: () => 'shopify.extension.toml',
46+
appModuleFeatures: () => ['localization', 'ui_preview'],
4547
})
4648

4749
export default adminLinkSpec

packages/app/src/cli/services/dev/extension/payload.test.ts

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import {UIExtensionPayload} from './payload/models.js'
21
import {getUIExtensionPayload} from './payload.js'
32
import {ExtensionsPayloadStoreOptions} from './payload/store.js'
43
import {testUIExtension} from '../../../models/app/app.test-data.js'
@@ -244,6 +243,45 @@ describe('getUIExtensionPayload', () => {
244243
})
245244
})
246245

246+
test('reads from targeting when extension_points is not set', async () => {
247+
await inTemporaryDirectory(async (tmpDir) => {
248+
const uiExtension = await testUIExtension({
249+
directory: tmpDir,
250+
configuration: {
251+
name: 'test-admin-link',
252+
type: 'admin_link',
253+
targeting: [{target: 'admin.app.link', url: '/editor', tools: './tools.json'}],
254+
} as any,
255+
devUUID: 'devUUID',
256+
})
257+
258+
await setupBuildOutput(
259+
uiExtension,
260+
tmpDir,
261+
{'admin.app.link': {tools: 'tools.json'}},
262+
{'tools.json': '{"tools": []}'},
263+
)
264+
265+
const got = await getUIExtensionPayload(uiExtension, tmpDir, {
266+
...createMockOptions(tmpDir, [uiExtension]),
267+
currentDevelopmentPayload: {hidden: true, status: 'success'},
268+
})
269+
270+
expect(got.extensionPoints).toMatchObject([
271+
{
272+
target: 'admin.app.link',
273+
assets: {
274+
tools: {
275+
name: 'tools',
276+
url: 'http://tunnel-url.com/extensions/devUUID/assets/tools.json',
277+
lastUpdated: expect.any(Number),
278+
},
279+
},
280+
},
281+
])
282+
})
283+
})
284+
247285
test('returns the right payload for post-purchase extensions', async () => {
248286
await inTemporaryDirectory(async (tmpDir) => {
249287
const outputPath = joinPath(tmpDir, 'test-post-purchase-extension.js')

packages/app/src/cli/services/dev/extension/payload.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@ export async function getUIExtensionPayload(
104104
}
105105

106106
async function getExtensionPoints(extension: ExtensionInstance, url: string, buildDirectory: string) {
107-
let extensionPoints = extension.configuration.extension_points as DevNewExtensionPointSchema[]
107+
const config = extension.configuration as Record<string, unknown>
108+
let extensionPoints = (config.extension_points ?? config.targeting) as DevNewExtensionPointSchema[]
108109

109110
if (extension.type === 'checkout_post_purchase') {
110111
// Mock target for post-purchase in order to get the right extension point redirect url

0 commit comments

Comments
 (0)