Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions packages/app/src/cli/commands/app/config/pull.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,17 @@ This command reuses the existing linked app and organization and skips all inter
userProvidedConfigName: flags.config,
})

const {configuration} = await pull({
const {configuration, configPath} = await pull({
directory: flags.path,
configName: flags.config,
configPath: app.configPath,
configuration: app.configuration,
remoteApp,
})

renderSuccess({
headline: `Pulled latest configuration for "${configuration.name}"`,
body: `Updated ${basename(configuration.path)} with the remote data.`,
body: `Updated ${basename(configPath)} with the remote data.`,
})

return {app}
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/cli/commands/app/env/pull.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export default class EnvPull extends AppLinkedCommand {
forceRelink: flags.reset,
userProvidedConfigName: flags.config,
})
const envFile = joinPath(app.directory, flags['env-file'] ?? getDotEnvFileName(app.configuration.path))
const envFile = joinPath(app.directory, flags['env-file'] ?? getDotEnvFileName(app.configPath))
outputResult(await pullEnv({app, remoteApp, organization, envFile}))
return {app}
}
Expand Down
8 changes: 3 additions & 5 deletions packages/app/src/cli/models/app/app.test-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import {
App,
AppConfiguration,
AppConfigurationSchema,
AppConfigurationWithoutPath,
AppInterface,
AppLinkedInterface,
CurrentAppConfiguration,
Expand Down Expand Up @@ -84,7 +83,6 @@ import {vi} from 'vitest'
import {joinPath} from '@shopify/cli-kit/node/path'

export const DEFAULT_CONFIG = {
path: '/tmp/project/shopify.app.toml',
application_url: 'https://myapp.com',
client_id: 'api-key',
name: 'my app',
Expand All @@ -100,7 +98,7 @@ export const DEFAULT_CONFIG = {
export function testApp(app: Partial<AppInterface> = {}, schemaType: 'current' | 'legacy' = 'legacy'): AppInterface {
const getConfig = () => {
if (schemaType === 'legacy') {
return {scopes: '', extension_directories: [], path: ''}
return {scopes: '', extension_directories: []}
} else {
return DEFAULT_CONFIG as CurrentAppConfiguration
}
Expand All @@ -109,6 +107,7 @@ export function testApp(app: Partial<AppInterface> = {}, schemaType: 'current' |
const newApp = new App({
name: app.name ?? 'App',
directory: app.directory ?? '/tmp/project',
configPath: app.configPath ?? '/tmp/project/shopify.app.toml',
packageManager: app.packageManager ?? 'yarn',
configuration: app.configuration ?? getConfig(),
nodeDependencies: app.nodeDependencies ?? {},
Expand Down Expand Up @@ -155,7 +154,6 @@ export function testAppWithLegacyConfig({
config = {},
}: TestAppWithConfigOptions): AppInterface<LegacyAppConfiguration> {
const configuration: AppConfiguration = {
path: '',
scopes: '',
name: 'name',
extension_directories: [],
Expand Down Expand Up @@ -207,7 +205,7 @@ export function testOrganizationApp(app: Partial<OrganizationApp> = {}): Organiz
return {...defaultApp, ...app}
}

export const placeholderAppConfiguration: AppConfigurationWithoutPath = {scopes: ''}
export const placeholderAppConfiguration: AppConfiguration = {scopes: ''}

export async function testUIExtension(
uiExtension: Omit<Partial<ExtensionInstance>, 'configuration'> & {
Expand Down
7 changes: 3 additions & 4 deletions packages/app/src/cli/models/app/app.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
AppConfiguration,
AppSchema,
CurrentAppConfiguration,
LegacyAppConfiguration,
Expand Down Expand Up @@ -34,7 +35,6 @@ import {joinPath} from '@shopify/cli-kit/node/path'
import {AbortError} from '@shopify/cli-kit/node/error'

const CORRECT_CURRENT_APP_SCHEMA: CurrentAppConfiguration = {
path: '',
name: 'app 1',
client_id: '12345',
extension_directories: ['extensions/*'],
Expand Down Expand Up @@ -64,7 +64,6 @@ const CORRECT_CURRENT_APP_SCHEMA: CurrentAppConfiguration = {
}

const CORRECT_LEGACY_APP_SCHEMA: LegacyAppConfiguration = {
path: '',
extension_directories: [],
web_directories: [],
scopes: 'write_products',
Expand Down Expand Up @@ -213,7 +212,7 @@ describe('getUIExtensionRendererVersion', () => {

describe('getAppScopes', () => {
test('returns the scopes key when schema is legacy', () => {
const config = {path: '', scopes: 'read_themes,read_products'}
const config = {scopes: 'read_themes,read_products'} as AppConfiguration
expect(getAppScopes(config)).toEqual('read_themes,read_products')
})

Expand All @@ -225,7 +224,7 @@ describe('getAppScopes', () => {

describe('getAppScopesArray', () => {
test('returns the scopes key when schema is legacy', () => {
const config = {path: '', scopes: 'read_themes, read_order ,write_products'}
const config = {scopes: 'read_themes, read_order ,write_products'} as AppConfiguration
expect(getAppScopesArray(config)).toEqual(['read_themes', 'read_order', 'write_products'])
})

Expand Down
26 changes: 13 additions & 13 deletions packages/app/src/cli/models/app/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,14 +142,12 @@ export const AppConfigurationSchema = zod.union([LegacyAppSchema, AppSchema])
*
* Try to avoid using this: generally you should be working with a more specific type.
*/
export type AppConfiguration = zod.infer<typeof AppConfigurationSchema> & {path: string}

export type AppConfigurationWithoutPath = zod.infer<typeof AppConfigurationSchema>
export type AppConfiguration = zod.infer<typeof AppConfigurationSchema>

/**
* App configuration for a normal, linked, app. Doesn't include properties that are module derived.
*/
export type BasicAppConfigurationWithoutModules = zod.infer<typeof AppSchema> & {path: string}
export type BasicAppConfigurationWithoutModules = zod.infer<typeof AppSchema>

/**
* The build section for a normal, linked app. The options here tweak the CLI's behavior when working with the app.
Expand All @@ -164,15 +162,15 @@ export type CurrentAppConfiguration = BasicAppConfigurationWithoutModules & AppC
/**
* App configuration for a freshly minted app template. Very old apps *may* have a client_id provided.
*/
export type LegacyAppConfiguration = zod.infer<typeof LegacyAppSchema> & {path: string}
export type LegacyAppConfiguration = zod.infer<typeof LegacyAppSchema>

/** Validation schema that produces a provided app configuration type */
export type SchemaForConfig<TConfig extends {path: string}> = ZodObjectOf<Omit<TConfig, 'path'>>
export type SchemaForConfig<TConfig> = ZodObjectOf<TConfig>

export function getAppVersionedSchema(
specs: ExtensionSpecification[],
allowDynamicallySpecifiedConfigs = true,
): ZodObjectOf<Omit<CurrentAppConfiguration, 'path'>> {
): ZodObjectOf<CurrentAppConfiguration> {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const schema = specs.reduce<any>((schema, spec) => spec.contributeToAppConfigurationSchema(schema), AppSchema)

Expand All @@ -188,17 +186,15 @@ export function getAppVersionedSchema(
* @param item - the item to validate
*/
export function isLegacyAppSchema(item: AppConfiguration): item is LegacyAppConfiguration {
const {path, ...rest} = item
return isType(LegacyAppSchema, rest)
return isType(LegacyAppSchema, item)
}

/**
* Check whether a shopify.app.toml schema is valid against the current schema definition.
* @param item - the item to validate
*/
export function isCurrentAppSchema(item: AppConfiguration): item is CurrentAppConfiguration {
const {path, ...rest} = item
return isType(AppSchema.nonstrict(), rest)
return isType(AppSchema.nonstrict(), item)
}

/**
Expand Down Expand Up @@ -237,7 +233,7 @@ export function appHiddenConfigPath(appDirectory: string) {
* Get the field names from the configuration that aren't found in the basic built-in app configuration schema.
*/
export function filterNonVersionedAppFields(configuration: object): string[] {
const builtInFieldNames = Object.keys(AppSchema.shape).concat('path', 'organization_id')
const builtInFieldNames = Object.keys(AppSchema.shape).concat('organization_id')
return Object.keys(configuration).filter((fieldName) => {
return !builtInFieldNames.includes(fieldName)
})
Expand Down Expand Up @@ -287,6 +283,7 @@ export interface AppConfigurationInterface<
TModuleSpec extends ExtensionSpecification = ExtensionSpecification,
> {
directory: string
configPath: string
configuration: TConfig
configSchema: SchemaForConfig<TConfig>
specifications: TModuleSpec[]
Expand Down Expand Up @@ -377,6 +374,7 @@ export class App<
name: string
idEnvironmentVariableName: 'SHOPIFY_API_KEY' = 'SHOPIFY_API_KEY' as const
directory: string
configPath: string
packageManager: PackageManager
configuration: TConfig
nodeDependencies: {[key: string]: string}
Expand All @@ -385,7 +383,7 @@ export class App<
dotenv?: DotEnvFile
errors?: AppErrors
specifications: TModuleSpec[]
configSchema: ZodObjectOf<Omit<TConfig, 'path'>>
configSchema: SchemaForConfig<TConfig>
remoteFlags: Flag[]
realExtensions: ExtensionInstance[]
devApplicationURLs?: ApplicationURLs
Expand All @@ -394,6 +392,7 @@ export class App<
constructor({
name,
directory,
configPath,
packageManager,
configuration,
nodeDependencies,
Expand All @@ -410,6 +409,7 @@ export class App<
}: AppConstructor<TConfig, TModuleSpec>) {
this.name = name
this.directory = directory
this.configPath = configPath
this.packageManager = packageManager
this.configuration = configuration
this.nodeDependencies = nodeDependencies
Expand Down
5 changes: 2 additions & 3 deletions packages/app/src/cli/models/app/identifiers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,10 @@ describe('updateAppIdentifiers', () => {
const app = testAppWithConfig({
app: {
directory: tmpDir,
configPath: joinPath(tmpDir, 'shopify.app.staging.toml'),
allExtensions: [uiExtension],
},
config: {
path: joinPath(tmpDir, 'shopify.app.staging.toml'),
},
config: {},
})

// When
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/cli/models/app/identifiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export async function updateAppIdentifiers(

if (!dotenvFile) {
dotenvFile = {
path: joinPath(app.directory, getDotEnvFileName(app.configuration.path)),
path: joinPath(app.directory, getDotEnvFileName(app.configPath)),
variables: {},
}
}
Expand Down
27 changes: 9 additions & 18 deletions packages/app/src/cli/models/app/loader.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
loadHiddenConfig,
} from './loader.js'
import {parseHumanReadableError} from './error-parsing.js'
import {App, AppLinkedInterface, LegacyAppSchema, WebConfigurationSchema} from './app.js'
import {App, AppConfiguration, AppLinkedInterface, LegacyAppSchema, WebConfigurationSchema} from './app.js'
import {DEFAULT_CONFIG, buildVersionedAppSchema, getWebhookConfig} from './app.test-data.js'
import {configurationFileNames, blocks} from '../../constants.js'
import metadata from '../../metadata.js'
Expand Down Expand Up @@ -2920,8 +2920,7 @@ describe('parseConfigurationObject', () => {
const abortOrReport = vi.fn()

const {schema} = await buildVersionedAppSchema()
const {path, ...toParse} = configurationObject
await parseConfigurationObject(schema, 'tmp', toParse, abortOrReport)
await parseConfigurationObject(schema, 'tmp', configurationObject, abortOrReport)

expect(abortOrReport).toHaveBeenCalledWith(expectedFormatted, {}, 'tmp')
})
Expand Down Expand Up @@ -3501,7 +3500,7 @@ describe('WebhooksSchema', () => {
)} in tmp:\n\n${parseHumanReadableError(err)}`
const abortOrReport = vi.fn()

const {path, ...toParse} = getWebhookConfig(webhookConfigOverrides)
const toParse = getWebhookConfig(webhookConfigOverrides)
const parsedConfiguration = await parseConfigurationObject(WebhooksSchema, 'tmp', toParse, abortOrReport)
return {abortOrReport, expectedFormatted, parsedConfiguration}
}
Expand All @@ -3518,7 +3517,6 @@ describe('getAppConfigurationState', () => {
appDirectory: expect.any(String),
configurationPath: expect.stringMatching(/shopify.app.toml$/),
startingOptions: {
path: expect.stringMatching(/shopify.app.toml$/),
scopes: 'write_abc,write_xyz',
},
},
Expand All @@ -3541,7 +3539,6 @@ describe('getAppConfigurationState', () => {
{
state: 'connected-app',
basicConfiguration: {
path: expect.stringMatching(/shopify.app.toml$/),
client_id: 'abcdef',
something_extra: 'keep',
},
Expand Down Expand Up @@ -3759,9 +3756,8 @@ describe('loadHiddenConfig', () => {
await inTemporaryDirectory(async (tmpDir) => {
// Given
const configuration = {
path: joinPath(tmpDir, 'shopify.app.toml'),
scopes: 'write_products',
}
} as AppConfiguration

// When
const got = await loadHiddenConfig(tmpDir, configuration)
Expand All @@ -3775,9 +3771,8 @@ describe('loadHiddenConfig', () => {
await inTemporaryDirectory(async (tmpDir) => {
// Given
const configuration = {
path: joinPath(tmpDir, 'shopify.app.toml'),
client_id: '12345',
}
} as AppConfiguration
await writeFile(joinPath(tmpDir, '.gitignore'), '')

// When
Expand All @@ -3797,9 +3792,8 @@ describe('loadHiddenConfig', () => {
await inTemporaryDirectory(async (tmpDir) => {
// Given
const configuration = {
path: joinPath(tmpDir, 'shopify.app.toml'),
client_id: '12345',
}
} as AppConfiguration
const hiddenConfigPath = joinPath(tmpDir, '.shopify', 'project.json')
await mkdir(dirname(hiddenConfigPath))
await writeFile(
Expand All @@ -3822,9 +3816,8 @@ describe('loadHiddenConfig', () => {
await inTemporaryDirectory(async (tmpDir) => {
// Given
const configuration = {
path: joinPath(tmpDir, 'shopify.app.toml'),
client_id: 'not-found',
}
} as AppConfiguration
const hiddenConfigPath = joinPath(tmpDir, '.shopify', 'project.json')
await mkdir(dirname(hiddenConfigPath))
await writeFile(
Expand All @@ -3846,9 +3839,8 @@ describe('loadHiddenConfig', () => {
await inTemporaryDirectory(async (tmpDir) => {
// Given
const configuration = {
path: joinPath(tmpDir, 'shopify.app.toml'),
client_id: 'not-found',
}
} as AppConfiguration
const hiddenConfigPath = joinPath(tmpDir, '.shopify', 'project.json')
await mkdir(dirname(hiddenConfigPath))
await writeFile(
Expand All @@ -3870,9 +3862,8 @@ describe('loadHiddenConfig', () => {
await inTemporaryDirectory(async (tmpDir) => {
// Given
const configuration = {
path: joinPath(tmpDir, 'shopify.app.toml'),
client_id: '12345',
}
} as AppConfiguration
const hiddenConfigPath = joinPath(tmpDir, '.shopify', 'project.json')
await mkdir(dirname(hiddenConfigPath))
await writeFile(hiddenConfigPath, 'invalid json')
Expand Down
Loading
Loading