Skip to content

Commit 4b19b63

Browse files
Merge branch 'main' into drop-cross-env
2 parents c3294fc + 936d7ac commit 4b19b63

File tree

15 files changed

+1254
-344
lines changed

15 files changed

+1254
-344
lines changed

.changeset/lemon-eggs-exist.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@shopify/app': patch
3+
---
4+
5+
Improve error message in function replay command when log directory doesnt exist

.changeset/witty-planes-crash.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@shopify/cli': patch
3+
---
4+
5+
Bump cli-hydrogen to 9.0.5

packages/app/src/cli/commands/app/init.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {validateFlavorValue, validateTemplateValue} from '../../services/init/va
77
import {MinimalOrganizationApp, Organization, OrganizationApp} from '../../models/organization.js'
88
import {appNamePrompt, createAsNewAppPrompt, selectAppPrompt} from '../../prompts/dev.js'
99
import {searchForAppsByNameFactory} from '../../services/dev/prompt-helpers.js'
10+
import {isValidName} from '../../models/app/validation/common.js'
1011
import {Flags} from '@oclif/core'
1112
import {globalFlags} from '@shopify/cli-kit/node/cli'
1213
import {resolvePath, cwd} from '@shopify/cli-kit/node/path'
@@ -72,7 +73,7 @@ export default class Init extends AppCommand {
7273
validateFlavorValue(flags.template, flags.flavor)
7374

7475
const inferredPackageManager = inferPackageManager(flags['package-manager'])
75-
const name = flags.name ?? (await generateRandomNameForSubdirectory({suffix: 'app', directory: flags.path}))
76+
const name = flags.name ?? (await getAppName(flags.path))
7677

7778
// Force user authentication before prompting.
7879
let developerPlatformClient = selectDeveloperPlatformClient()
@@ -126,6 +127,15 @@ export default class Init extends AppCommand {
126127
}
127128
}
128129

130+
async function getAppName(directory: string): Promise<string> {
131+
for (let i = 0; i < 3; i++) {
132+
// eslint-disable-next-line no-await-in-loop
133+
const name = await generateRandomNameForSubdirectory({suffix: 'app', directory})
134+
if (isValidName(name)) return name
135+
}
136+
return ''
137+
}
138+
129139
export type SelectAppOrNewAppNameResult =
130140
| {
131141
result: 'new'

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,9 @@ function isValidUrl(input: string, httpsOnly: boolean) {
2020
export function ensurePathStartsWithSlash(arg: unknown) {
2121
return typeof arg === 'string' && !arg.startsWith('/') ? `/${arg}` : arg
2222
}
23+
24+
export const APP_NAME_MAX_LENGTH = 30
25+
26+
export function isValidName(name: string): boolean {
27+
return name.length <= APP_NAME_MAX_LENGTH
28+
}

packages/app/src/cli/prompts/dev.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {Organization, MinimalOrganizationApp, OrganizationStore, MinimalAppIdent
33
import {getTomls} from '../utilities/app/config/getTomls.js'
44
import {setCachedCommandTomlMap} from '../services/local-storage.js'
55
import {Paginateable} from '../utilities/developer-platform-client.js'
6+
import {APP_NAME_MAX_LENGTH} from '../models/app/validation/common.js'
67
import {
78
RenderAutocompleteOptions,
89
renderAutocompletePrompt,
@@ -129,8 +130,8 @@ export async function appNamePrompt(currentName: string): Promise<string> {
129130
if (value.length === 0) {
130131
return "App name can't be empty"
131132
}
132-
if (value.length > 30) {
133-
return 'Enter a shorter name (30 character max.)'
133+
if (value.length > APP_NAME_MAX_LENGTH) {
134+
return `Enter a shorter name (${APP_NAME_MAX_LENGTH} character max.)`
134135
}
135136
if (value.includes('shopify')) {
136137
return 'Name can\'t contain "shopify." Enter another name.'

packages/app/src/cli/services/function/replay.test.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ import {readFile} from '@shopify/cli-kit/node/fs'
1010
import {describe, expect, beforeAll, test, vi} from 'vitest'
1111
import {AbortError} from '@shopify/cli-kit/node/error'
1212
import {outputInfo} from '@shopify/cli-kit/node/output'
13-
import {readdirSync} from 'fs'
13+
import {getLogsDir} from '@shopify/cli-kit/node/logs'
14+
15+
import {existsSync, readdirSync} from 'fs'
1416

1517
vi.mock('fs')
1618
vi.mock('@shopify/cli-kit/node/fs')
@@ -111,6 +113,24 @@ describe('replay', () => {
111113

112114
test('throws error if no logs available', async () => {
113115
// Given
116+
mockFileOperations([])
117+
118+
// When/Then
119+
await expect(async () => {
120+
await replay({
121+
app: testAppLinked(),
122+
extension,
123+
stdout: false,
124+
path: 'test-path',
125+
json: true,
126+
watch: false,
127+
})
128+
}).rejects.toThrow(new AbortError(`No logs found in ${getLogsDir()}`))
129+
})
130+
131+
test('throws error if log directory does not exist', async () => {
132+
// Given
133+
vi.mocked(existsSync).mockReturnValue(false)
114134

115135
// When/Then
116136
await expect(async () => {
@@ -122,7 +142,7 @@ describe('replay', () => {
122142
json: true,
123143
watch: false,
124144
})
125-
}).rejects.toThrow()
145+
}).rejects.toThrow(new AbortError(`No logs found in ${getLogsDir()}`))
126146
})
127147

128148
test('delegates to renderReplay when watch is true', async () => {
@@ -285,6 +305,7 @@ function expectFunctionRun(functionExtension: ExtensionInstance<FunctionConfigTy
285305
}
286306

287307
function mockFileOperations(data: {run: FunctionRunData; path: string}[]) {
308+
vi.mocked(existsSync).mockReturnValue(true)
288309
vi.mocked(readdirSync).mockReturnValue([...data].reverse().map(({path}) => path) as any)
289310
vi.mocked(readFile).mockImplementation((path) => {
290311
const run = data.find((file) => path.endsWith(file.path))

packages/app/src/cli/services/function/replay.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {getLogsDir} from '@shopify/cli-kit/node/logs'
1212
import {AbortError} from '@shopify/cli-kit/node/error'
1313
import {AbortController} from '@shopify/cli-kit/node/abort'
1414

15-
import {readdirSync} from 'fs'
15+
import {existsSync, readdirSync} from 'fs'
1616

1717
const LOG_SELECTOR_LIMIT = 100
1818

@@ -124,7 +124,7 @@ async function findFunctionRun(
124124
functionHandle: string,
125125
identifier: string,
126126
): Promise<string | undefined> {
127-
const fileName = readdirSync(functionRunsDir).find((filename) => {
127+
const fileName = getAllFunctionRunFileNames(functionRunsDir).find((filename) => {
128128
const fileMetadata = parseLogFilename(filename)
129129
return (
130130
fileMetadata?.namespace === 'extensions' &&
@@ -147,7 +147,7 @@ async function getRunFromSelector(functionRunsDir: string, functionHandle: strin
147147
}
148148

149149
async function getFunctionRunData(functionRunsDir: string, functionHandle: string): Promise<FunctionRunData[]> {
150-
const allFunctionRunFileNames = readdirSync(functionRunsDir)
150+
const allFunctionRunFileNames = getAllFunctionRunFileNames(functionRunsDir)
151151
.filter((filename) => {
152152
// Expected format: 20240522_150641_827Z_extensions_my-function_abcdef.json
153153
const fileMetadata = parseLogFilename(filename)
@@ -191,3 +191,7 @@ async function getFunctionRunData(functionRunsDir: string, functionHandle: strin
191191
function getIdentifierFromFilename(fileName: string): string {
192192
return fileName.split('_').pop()!.substring(0, 6)
193193
}
194+
195+
function getAllFunctionRunFileNames(functionRunsDir: string): string[] {
196+
return existsSync(functionRunsDir) ? readdirSync(functionRunsDir) : []
197+
}

packages/app/src/cli/utilities/developer-platform-client.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ import {DevSessionCreateMutation} from '../api/graphql/app-dev/generated/dev-ses
5656
import {DevSessionUpdateMutation} from '../api/graphql/app-dev/generated/dev-session-update.js'
5757
import {DevSessionDeleteMutation} from '../api/graphql/app-dev/generated/dev-session-delete.js'
5858
import {isAppManagementDisabled} from '@shopify/cli-kit/node/context/local'
59+
import {blockPartnersAccess} from '@shopify/cli-kit/node/environment'
60+
import {AbortError} from '@shopify/cli-kit/node/error'
5961

6062
export enum ClientName {
6163
AppManagement = 'app-management',
@@ -77,7 +79,17 @@ export interface AppVersionIdentifiers {
7779
}
7880

7981
export function allDeveloperPlatformClients(): DeveloperPlatformClient[] {
80-
return isAppManagementDisabled() ? [new PartnersClient()] : [new PartnersClient(), new AppManagementClient()]
82+
const clients: DeveloperPlatformClient[] = []
83+
if (!blockPartnersAccess()) {
84+
clients.push(new PartnersClient())
85+
}
86+
if (!isAppManagementDisabled()) {
87+
clients.push(new AppManagementClient())
88+
}
89+
if (clients.length === 0) {
90+
throw new AbortError('Both Partners and App Management APIs are deactivated.')
91+
}
92+
return clients
8193
}
8294

8395
/**

packages/cli-kit/src/private/node/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export const environmentVariables = {
4545
otelURL: 'SHOPIFY_CLI_OTEL_EXPORTER_OTLP_ENDPOINT',
4646
themeKitAccessDomain: 'SHOPIFY_CLI_THEME_KIT_ACCESS_DOMAIN',
4747
json: 'SHOPIFY_FLAG_JSON',
48+
neverUsePartnersApi: 'SHOPIFY_CLI_NEVER_USE_PARTNERS_API',
4849
}
4950

5051
export const defaultThemeKitAccessDomain = 'theme-kit-access.shopifyapps.com'

packages/cli-kit/src/public/common/string.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@ const SAFE_RANDOM_BUSINESS_NOUNS = [
110110
'franchise',
111111
'subsidiary',
112112
'logistics',
113-
'infrastructure',
114113
'sponsorship',
115114
'partnership',
116115
'tax',

0 commit comments

Comments
 (0)