Skip to content

Commit 8cc0fa0

Browse files
committed
Fix how app name is set from the AppLoader
1 parent 6bfe37d commit 8cc0fa0

File tree

5 files changed

+93
-23
lines changed

5 files changed

+93
-23
lines changed

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export const LegacyAppSchema = zod
4848
.object({
4949
client_id: zod.number().optional(),
5050
name: zod.string().optional(),
51+
handle: zod.string().optional(),
5152
scopes: zod
5253
.string()
5354
.transform((scopes) => normalizeDelimitedString(scopes) ?? '')
@@ -80,14 +81,15 @@ function fixSingleWildcards(value: string[] | undefined) {
8081
*/
8182
export const AppSchema = zod.object({
8283
client_id: zod.string(),
84+
extension_directories: ExtensionDirectoriesSchema,
85+
handle: zod.string().optional(),
8386
build: zod
8487
.object({
8588
automatically_update_urls_on_dev: zod.boolean().optional(),
8689
dev_store_url: zod.string().optional(),
8790
include_config_on_deploy: zod.boolean().optional(),
8891
})
8992
.optional(),
90-
extension_directories: ExtensionDirectoriesSchema,
9193
web_directories: zod.array(zod.string()).optional(),
9294
})
9395

@@ -168,7 +170,7 @@ export function isLegacyAppSchema(item: AppConfiguration): item is LegacyAppConf
168170
*/
169171
export function isCurrentAppSchema(item: AppConfiguration): item is CurrentAppConfiguration {
170172
const {path, ...rest} = item
171-
return isType(AppSchema.nonstrict(), rest)
173+
return isType(AppSchema.passthrough(), rest)
172174
}
173175

174176
/**

packages/app/src/cli/models/app/loader.test.ts

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ describe('load', () => {
6464
}
6565

6666
const appConfiguration = `
67+
name = "my_app"
6768
scopes = "read_products"
6869
`
6970
const linkedAppConfiguration = `
@@ -264,7 +265,54 @@ wrong = "property"
264265
const app = await loadApp({directory: tmpDir, specifications: [], userProvidedConfigName: undefined})
265266

266267
// Then
267-
expect(app.name).toBe('my_app')
268+
expect(app.name).toBe('for-testing')
269+
})
270+
271+
test('uses handle from configuration as app name when present', async () => {
272+
// Given
273+
const appConfiguration = `
274+
name = "display-name"
275+
handle = "app-handle"
276+
client_id = "1234567890"
277+
application_url = "https://example.com/lala"
278+
embedded = true
279+
280+
[webhooks]
281+
api_version = "2023-07"
282+
283+
[auth]
284+
redirect_urls = [ "https://example.com/api/auth" ]
285+
`
286+
await writeConfig(appConfiguration)
287+
288+
// When
289+
const app = await loadTestingApp()
290+
291+
// Then
292+
expect(app.name).toBe('app-handle')
293+
})
294+
295+
test('uses name from configuration when handle is not present', async () => {
296+
// Given
297+
const appConfiguration = `
298+
name = "config-name"
299+
client_id = "1234567890"
300+
application_url = "https://example.com/lala"
301+
embedded = true
302+
303+
[webhooks]
304+
api_version = "2023-07"
305+
306+
[auth]
307+
redirect_urls = [ "https://example.com/api/auth" ]
308+
`
309+
await writeConfig(appConfiguration)
310+
311+
// When
312+
const app = await loadTestingApp()
313+
314+
// Then
315+
expect(app.name).toBe('config-name')
268316
})
269317

270318
test('defaults to npm as the package manager when the configuration is valid', async () => {
@@ -618,6 +666,7 @@ wrong = "property"
618666
test('loads the app with custom located web blocks', async () => {
619667
// Given
620668
const {webDirectory} = await writeConfig(`
669+
name = "my_app"
621670
scopes = ""
622671
web_directories = ["must_be_here"]
623672
`)
@@ -633,6 +682,7 @@ wrong = "property"
633682
test('loads the app with custom located web blocks, only checks given directory', async () => {
634683
// Given
635684
const {webDirectory} = await writeConfig(`
685+
name = "my_app"
636686
scopes = ""
637687
web_directories = ["must_be_here"]
638688
`)
@@ -700,6 +750,7 @@ wrong = "property"
700750
test('loads the app when it has a extension with a valid configuration using a supported extension type and in a non-conventional directory configured in the app configuration file', async () => {
701751
// Given
702752
await writeConfig(`
753+
name = "my_app"
703754
scopes = ""
704755
extension_directories = ["custom_extension"]
705756
`)

packages/app/src/cli/models/app/loader.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ import {readAndParseDotEnv, DotEnvFile} from '@shopify/cli-kit/node/dot-env'
4242
import {
4343
getDependencies,
4444
getPackageManager,
45-
getPackageName,
4645
usesWorkspaces as appUsesWorkspaces,
4746
} from '@shopify/cli-kit/node/node-package-manager'
4847
import {resolveFramework} from '@shopify/cli-kit/node/framework'
@@ -343,7 +342,9 @@ class AppLoader<TConfig extends AppConfiguration, TModuleSpec extends ExtensionS
343342
const packageJSONPath = joinPath(directory, 'package.json')
344343

345344
// These don't need to be processed again if the app is being reloaded
346-
const name = this.previousApp?.name ?? (await loadAppName(directory))
345+
// name is required by BrandingSchema, so it must be present in the configuration
346+
const configName = 'name' in configuration ? configuration.name : undefined
347+
const name = this.previousApp?.name ?? configuration.handle ?? configName ?? ''
347348
const nodeDependencies = this.previousApp?.nodeDependencies ?? (await getDependencies(packageJSONPath))
348349
const packageManager = this.previousApp?.packageManager ?? (await getPackageManager(directory))
349350
const usesWorkspaces = this.previousApp?.usesWorkspaces ?? (await appUsesWorkspaces(directory))
@@ -1108,11 +1109,6 @@ export async function loadHiddenConfig(
11081109
}
11091110
}
11101111

1111-
export async function loadAppName(appDirectory: string): Promise<string> {
1112-
const packageJSONPath = joinPath(appDirectory, 'package.json')
1113-
return (await getPackageName(packageJSONPath)) ?? basename(appDirectory)
1114-
}
1115-
11161112
async function getProjectType(webs: Web[]): Promise<'node' | 'php' | 'ruby' | 'frontend' | undefined> {
11171113
const backendWebs = webs.filter((web) => isWebType(web, WebType.Backend))
11181114
const frontendWebs = webs.filter((web) => isWebType(web, WebType.Frontend))

packages/app/src/cli/services/app-context.test.ts

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ describe('linkedAppContext', () => {
4949
test('returns linked app context when app is already linked', async () => {
5050
await inTemporaryDirectory(async (tmp) => {
5151
// Given
52-
const content = `client_id="test-api-key"`
52+
const content = `
53+
name = "test-app"
54+
client_id="test-api-key"`
5355
await writeAppConfig(tmp, content)
5456

5557
// When
@@ -65,6 +67,7 @@ describe('linkedAppContext', () => {
6567
app: expect.objectContaining({
6668
configuration: {
6769
client_id: 'test-api-key',
70+
name: 'test-app',
6871
path: normalizePath(joinPath(tmp, 'shopify.app.toml')),
6972
},
7073
}),
@@ -98,7 +101,10 @@ describe('linkedAppContext', () => {
98101
configurationPath: `${tmp}/shopify.app.stg.toml`,
99102
configSource: 'cached',
100103
configurationFileName: 'shopify.app.stg.toml',
101-
basicConfiguration: {client_id: 'test-api-key', path: normalizePath(joinPath(tmp, 'shopify.app.stg.toml'))},
104+
basicConfiguration: {
105+
client_id: 'test-api-key',
106+
path: normalizePath(joinPath(tmp, 'shopify.app.stg.toml')),
107+
},
102108
},
103109
configuration: {
104110
client_id: 'test-api-key',
@@ -133,7 +139,9 @@ describe('linkedAppContext', () => {
133139
await inTemporaryDirectory(async (tmp) => {
134140
// Given
135141
vi.mocked(appFromIdentifiers).mockResolvedValue({...mockRemoteApp, apiKey: 'test-api-key-new'})
136-
const content = `client_id="test-api-key-new"`
142+
const content = `
143+
name = "test-app"
144+
client_id="test-api-key-new"`
137145
await writeAppConfig(tmp, content)
138146
localStorage.setCachedAppInfo({
139147
appId: 'test-api-key-old',
@@ -166,7 +174,9 @@ describe('linkedAppContext', () => {
166174
test('uses provided clientId when available and updates the app configuration', async () => {
167175
await inTemporaryDirectory(async (tmp) => {
168176
// Given
169-
const content = `client_id="test-api-key"`
177+
const content = `
178+
name = "test-app"
179+
client_id="test-api-key"`
170180
await writeAppConfig(tmp, content)
171181
const newClientId = 'new-api-key'
172182

@@ -191,7 +201,9 @@ describe('linkedAppContext', () => {
191201
test('resets app when there is a valid toml but reset option is true', async () => {
192202
await inTemporaryDirectory(async (tmp) => {
193203
// Given
194-
const content = `client_id="test-api-key"`
204+
const content = `
205+
name = "test-app"
206+
client_id="test-api-key"`
195207
await writeAppConfig(tmp, content)
196208

197209
vi.mocked(link).mockResolvedValue({
@@ -202,7 +214,10 @@ describe('linkedAppContext', () => {
202214
configurationPath: `${tmp}/shopify.app.toml`,
203215
configSource: 'cached',
204216
configurationFileName: 'shopify.app.toml',
205-
basicConfiguration: {client_id: 'test-api-key', path: normalizePath(joinPath(tmp, 'shopify.app.toml'))},
217+
basicConfiguration: {
218+
client_id: 'test-api-key',
219+
path: normalizePath(joinPath(tmp, 'shopify.app.toml')),
220+
},
206221
},
207222
configuration: {
208223
client_id: 'test-api-key',
@@ -229,7 +244,9 @@ describe('linkedAppContext', () => {
229244
test('logs metadata', async () => {
230245
await inTemporaryDirectory(async (tmp) => {
231246
// Given
232-
const content = `client_id="test-api-key"`
247+
const content = `
248+
name = "test-app"
249+
client_id="test-api-key"`
233250
await writeAppConfig(tmp, content)
234251

235252
// When
@@ -255,7 +272,9 @@ describe('linkedAppContext', () => {
255272
test('uses unsafeReportMode when provided', async () => {
256273
await inTemporaryDirectory(async (tmp) => {
257274
// Given
258-
const content = `client_id="test-api-key"`
275+
const content = `
276+
name = "test-app"
277+
client_id="test-api-key"`
259278
await writeAppConfig(tmp, content)
260279
const loadSpy = vi.spyOn(loader, 'loadAppUsingConfigurationState')
261280

@@ -278,7 +297,9 @@ describe('linkedAppContext', () => {
278297
test('does not use unsafeReportMode when not provided', async () => {
279298
await inTemporaryDirectory(async (tmp) => {
280299
// Given
281-
const content = `client_id="test-api-key"`
300+
const content = `
301+
name = "test-app"
302+
client_id="test-api-key"`
282303
await writeAppConfig(tmp, content)
283304
const loadSpy = vi.spyOn(loader, 'loadAppUsingConfigurationState')
284305

packages/app/src/cli/services/app/config/link.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1596,8 +1596,8 @@ embedded = false
15961596
15971597
client_id = "12345"
15981598
extension_directories = [ ]
1599-
name = "app1"
16001599
handle = "handle"
1600+
name = "app1"
16011601
application_url = "https://example.com"
16021602
embedded = true
16031603
@@ -1665,8 +1665,8 @@ embedded = false
16651665
const expectedContent = `# Learn more about configuring your app at https://shopify.dev/docs/apps/tools/cli/configuration
16661666
16671667
client_id = "12345"
1668-
name = "app1"
16691668
handle = "handle"
1669+
name = "app1"
16701670
application_url = "https://example.com"
16711671
embedded = true
16721672
@@ -1744,8 +1744,8 @@ embedded = false
17441744
const expectedContent = `# Learn more about configuring your app at https://shopify.dev/docs/apps/tools/cli/configuration
17451745
17461746
client_id = "12345"
1747-
name = "app1"
17481747
handle = "handle"
1748+
name = "app1"
17491749
application_url = "https://example.com"
17501750
embedded = true
17511751
@@ -1823,8 +1823,8 @@ embedded = false
18231823
const expectedContent = `# Learn more about configuring your app at https://shopify.dev/docs/apps/tools/cli/configuration
18241824
18251825
client_id = "12345"
1826-
name = "app1"
18271826
handle = "handle"
1827+
name = "app1"
18281828
application_url = "https://example.com"
18291829
embedded = true
18301830

0 commit comments

Comments
 (0)