From 5787c07812858f4be0909c53f4adf7d47bc470ec Mon Sep 17 00:00:00 2001 From: Jeffrey Deng Date: Mon, 23 Feb 2026 13:48:25 -0800 Subject: [PATCH 1/8] Add graphql to storefront scopes --- packages/cli-kit/src/private/node/session.ts | 2 +- packages/cli-kit/src/private/node/session/scopes.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cli-kit/src/private/node/session.ts b/packages/cli-kit/src/private/node/session.ts index 46d48594c45..6f87d00c66d 100644 --- a/packages/cli-kit/src/private/node/session.ts +++ b/packages/cli-kit/src/private/node/session.ts @@ -80,7 +80,7 @@ interface AppManagementAPIOauthOptions { /** * A scope supported by the Storefront Renderer API. */ -export type StorefrontRendererScope = 'devtools' +export type StorefrontRendererScope = 'devtools' | 'graphql' interface StorefrontRendererAPIOAuthOptions { /** List of scopes to request permissions for. */ scopes: StorefrontRendererScope[] diff --git a/packages/cli-kit/src/private/node/session/scopes.ts b/packages/cli-kit/src/private/node/session/scopes.ts index bced5231066..475ea4e578f 100644 --- a/packages/cli-kit/src/private/node/session/scopes.ts +++ b/packages/cli-kit/src/private/node/session/scopes.ts @@ -48,7 +48,7 @@ function defaultApiScopes(api: API): string[] { case 'admin': return ['graphql', 'themes', 'collaborator'] case 'storefront-renderer': - return ['devtools'] + return ['devtools', 'graphql'] case 'partners': return ['cli'] case 'business-platform': From 4855d87320424afe2913048fc693ecc4f039028f Mon Sep 17 00:00:00 2001 From: Jeffrey Deng Date: Mon, 23 Feb 2026 14:14:16 -0800 Subject: [PATCH 2/8] Add functionality to POST overrides for a theme preview --- .../utilities/theme-previews/preview.test.ts | 177 ++++++++++++++++++ .../cli/utilities/theme-previews/preview.ts | 106 +++++++++++ 2 files changed, 283 insertions(+) create mode 100644 packages/theme/src/cli/utilities/theme-previews/preview.test.ts create mode 100644 packages/theme/src/cli/utilities/theme-previews/preview.ts diff --git a/packages/theme/src/cli/utilities/theme-previews/preview.test.ts b/packages/theme/src/cli/utilities/theme-previews/preview.test.ts new file mode 100644 index 00000000000..8c006f09c3a --- /dev/null +++ b/packages/theme/src/cli/utilities/theme-previews/preview.test.ts @@ -0,0 +1,177 @@ +import {createThemePreview, updateThemePreview} from './preview.js' +import {DevServerSession} from '../theme-environment/types.js' +import {describe, expect, test, vi} from 'vitest' +import {shopifyFetch, Response} from '@shopify/cli-kit/node/http' + +vi.mock('@shopify/cli-kit/node/http') + +const session: DevServerSession = { + token: 'admin_token_abc123', + storeFqdn: 'store.myshopify.com', + storefrontToken: 'token_111222333', + storefrontPassword: 'password', + sessionCookies: {}, +} + +function jsonResponse(body: object, options: {status?: number; statusText?: string} = {}): Response { + const {status = 200, statusText = 'OK'} = options + return { + ok: status >= 200 && status < 300, + status, + statusText, + json: () => Promise.resolve(body), + } as unknown as Response +} + +describe('createThemePreview', () => { + test('POSTs to the preview endpoint and returns url and preview_identifier', async () => { + // Given + const expectedThemeId = '123' + const overrides = JSON.stringify({templates: {'index.liquid': '

Hello

'}}) + const responseBody = {url: 'https://abc.shopifypreview.com', preview_identifier: 'abc'} + vi.mocked(shopifyFetch).mockResolvedValue(jsonResponse(responseBody)) + + // When + const result = await createThemePreview({ + session, + storefrontToken: 'sf_token', + overridesContent: overrides, + themeId: expectedThemeId, + }) + + // Then + expect(result).toEqual(responseBody) + expect(shopifyFetch).toHaveBeenCalledWith( + `https://${session.storeFqdn}/theme_preview.json?preview_theme_id=${expectedThemeId}`, + expect.objectContaining({ + method: 'POST', + body: overrides, + headers: expect.objectContaining({ + Authorization: 'Bearer sf_token', + 'Content-Type': 'application/json', + }), + }), + ) + }) + + test('throws AbortError when the response is not ok', async () => { + // Given + const expectedThemeId = '123' + const overrides = JSON.stringify({templates: {}}) + vi.mocked(shopifyFetch).mockResolvedValue(jsonResponse({}, {status: 422, statusText: 'Unprocessable Entity'})) + + // When/Then + await expect( + createThemePreview({session, storefrontToken: 'sf_token', overridesContent: overrides, themeId: expectedThemeId}), + ).rejects.toThrow('Theme preview request failed with status 422: Unprocessable Entity') + }) + + test('throws AbortError when the response body contains an error', async () => { + // Given + const expectedThemeId = '123' + const overrides = JSON.stringify({templates: {}}) + vi.mocked(shopifyFetch).mockResolvedValue( + jsonResponse({url: null, preview_identifier: null, error: 'Invalid template'}), + ) + + // When/Then + await expect( + createThemePreview({session, storefrontToken: 'sf_token', overridesContent: overrides, themeId: expectedThemeId}), + ).rejects.toThrow('Theme preview failed: Invalid template') + }) +}) + +describe('updateThemePreview', () => { + test('POSTs to the preview endpoint with a session identifier and returns url and preview_identifier', async () => { + // Given + const expectedThemeId = '123' + const overrides = JSON.stringify({templates: {'index.liquid': '

Hello

'}}) + const responseBody = {url: 'https://abc.shopifypreview.com', preview_identifier: 'abc'} + const expectedSessionIdentifier = '1234-abc' + vi.mocked(shopifyFetch).mockResolvedValue(jsonResponse(responseBody)) + + // When + const result = await updateThemePreview({ + session, + storefrontToken: 'sf_token', + overridesContent: overrides, + themeId: expectedThemeId, + previewIdentifier: expectedSessionIdentifier, + }) + + // Then + expect(result).toEqual(responseBody) + expect(shopifyFetch).toHaveBeenCalledWith( + `https://${session.storeFqdn}/theme_preview.json?preview_theme_id=${expectedThemeId}&preview_identifier=${expectedSessionIdentifier}`, + expect.objectContaining({ + method: 'POST', + body: overrides, + headers: expect.objectContaining({ + Authorization: 'Bearer sf_token', + 'Content-Type': 'application/json', + }), + }), + ) + }) + + test('encodes the session identifier in the URL', async () => { + // Given + const expectedThemeId = '123' + const overrides = JSON.stringify({templates: {}}) + const responseBody = {url: 'https://abc.shopifypreview.com', preview_identifier: 'abc'} + vi.mocked(shopifyFetch).mockResolvedValue(jsonResponse(responseBody)) + + // When + await updateThemePreview({ + session, + storefrontToken: 'sf_token', + overridesContent: overrides, + themeId: expectedThemeId, + previewIdentifier: 'token with spaces&special=chars', + }) + + // Then + expect(shopifyFetch).toHaveBeenCalledWith( + `https://${session.storeFqdn}/theme_preview.json?preview_theme_id=${expectedThemeId}&preview_identifier=token%20with%20spaces%26special%3Dchars`, + expect.any(Object), + ) + }) + + test('throws AbortError when the response is not ok', async () => { + // Given + const expectedThemeId = '123' + const overrides = JSON.stringify({templates: {}}) + vi.mocked(shopifyFetch).mockResolvedValue(jsonResponse({}, {status: 422, statusText: 'Unprocessable Entity'})) + + // When/Then + await expect( + updateThemePreview({ + session, + storefrontToken: 'sf_token', + overridesContent: overrides, + themeId: expectedThemeId, + previewIdentifier: '1234-abc', + }), + ).rejects.toThrow('Theme preview request failed with status 422: Unprocessable Entity') + }) + + test('throws AbortError when the response body contains an error', async () => { + // Given + const expectedThemeId = '123' + const overrides = JSON.stringify({templates: {}}) + vi.mocked(shopifyFetch).mockResolvedValue( + jsonResponse({url: null, preview_identifier: null, error: 'Session expired'}), + ) + + // When/Then + await expect( + updateThemePreview({ + session, + storefrontToken: 'sf_token', + overridesContent: overrides, + themeId: expectedThemeId, + previewIdentifier: '1234-abc', + }), + ).rejects.toThrow('Theme preview failed: Session expired') + }) +}) diff --git a/packages/theme/src/cli/utilities/theme-previews/preview.ts b/packages/theme/src/cli/utilities/theme-previews/preview.ts new file mode 100644 index 00000000000..b26aca5f2a1 --- /dev/null +++ b/packages/theme/src/cli/utilities/theme-previews/preview.ts @@ -0,0 +1,106 @@ +import {buildBaseStorefrontUrl} from '../theme-environment/storefront-renderer.js' +import {defaultHeaders} from '../theme-environment/storefront-utils.js' +import {DevServerSession} from '../theme-environment/types.js' +import {AbortError} from '@shopify/cli-kit/node/error' +import {shopifyFetch, Response} from '@shopify/cli-kit/node/http' + +interface CreateThemePreviewOptions { + session: DevServerSession + storefrontToken: string + overridesContent: string + themeId: string +} + +interface UpdateThemePreviewOptions extends CreateThemePreviewOptions { + previewIdentifier: string +} + +interface ThemePreviewResult { + url: string + preview_identifier: string +} + +interface PreviewResponse { + url?: string + preview_identifier?: string + error?: string +} + +/** + * Creates a theme preview with overrides. + * + * @param options - The options for creating a theme preview. + * @returns The preview URL and identifier for the applied overrides. + */ +export async function createThemePreview({ + session, + storefrontToken, + overridesContent, + themeId, +}: CreateThemePreviewOptions): Promise { + const baseUrl = buildBaseStorefrontUrl(session) + const url = `${baseUrl}/theme_preview.json?preview_theme_id=${themeId}` + + const response = await shopifyFetch(url, { + method: 'POST', + body: overridesContent, + headers: { + ...defaultHeaders(), + Authorization: `Bearer ${storefrontToken}`, + 'Content-Type': 'application/json', + }, + }) + + if (!response.ok) { + throw new AbortError(`Theme preview request failed with status ${response.status}: ${response.statusText}`) + } + + return parsePreviewResponse(response) +} + +/** + * Overwrites a theme preview session with new overrides. + * + * @param options - The options for updating a theme preview. + * @returns The preview URL and identifier for the applied overrides. + */ +export async function updateThemePreview({ + session, + storefrontToken, + overridesContent, + themeId, + previewIdentifier, +}: UpdateThemePreviewOptions): Promise { + const baseUrl = buildBaseStorefrontUrl(session) + const url = `${baseUrl}/theme_preview.json?preview_theme_id=${themeId}&preview_identifier=${encodeURIComponent(previewIdentifier)}` + + const response = await shopifyFetch(url, { + method: 'POST', + body: overridesContent, + headers: { + ...defaultHeaders(), + Authorization: `Bearer ${storefrontToken}`, + 'Content-Type': 'application/json', + }, + }) + + if (!response.ok) { + throw new AbortError(`Theme preview request failed with status ${response.status}: ${response.statusText}`) + } + + return parsePreviewResponse(response) +} + +async function parsePreviewResponse(response: Response): Promise { + const body = (await response.json()) as PreviewResponse + + if (body.error) { + throw new AbortError(`Theme preview failed: ${body.error}`) + } + + if (!body.url || !body.preview_identifier) { + throw new AbortError('Theme preview returned an unexpected response') + } + + return {url: body.url, preview_identifier: body.preview_identifier} +} From 28823ee3b0a76f8aa641533b805865f92b5f6c80 Mon Sep 17 00:00:00 2001 From: Jeffrey Deng Date: Tue, 24 Feb 2026 10:09:24 -0800 Subject: [PATCH 3/8] Add preview-id flag and update path flag on theme dev to allow for theme previews uisng an override json --- packages/theme/src/cli/commands/theme/dev.ts | 49 +++++- .../src/cli/services/dev-override.test.ts | 154 ++++++++++++++++++ .../theme/src/cli/services/dev-override.ts | 71 ++++++++ 3 files changed, 271 insertions(+), 3 deletions(-) create mode 100644 packages/theme/src/cli/services/dev-override.test.ts create mode 100644 packages/theme/src/cli/services/dev-override.ts diff --git a/packages/theme/src/cli/commands/theme/dev.ts b/packages/theme/src/cli/commands/theme/dev.ts index 99eb6c25b7f..9e3b3dee9df 100644 --- a/packages/theme/src/cli/commands/theme/dev.ts +++ b/packages/theme/src/cli/commands/theme/dev.ts @@ -1,6 +1,7 @@ import {themeFlags} from '../../flags.js' import ThemeCommand, {RequiredFlags} from '../../utilities/theme-command.js' import {dev} from '../../services/dev.js' +import {devWithOverrideFile} from '../../services/dev-override.js' import {DevelopmentThemeManager} from '../../utilities/development-theme-manager.js' import {findOrSelectTheme} from '../../utilities/theme-selector.js' import {metafieldsPull} from '../../services/metafields-pull.js' @@ -10,6 +11,8 @@ import {globalFlags} from '@shopify/cli-kit/node/cli' import {Theme} from '@shopify/cli-kit/node/themes/types' import {recordEvent} from '@shopify/cli-kit/node/analytics' import {AdminSession} from '@shopify/cli-kit/node/session' +import {AbortError} from '@shopify/cli-kit/node/error' +import {isDirectorySync} from '@shopify/cli-kit/node/fs' import {InferredFlags} from '@oclif/core/interfaces' import type {ErrorOverlayMode, LiveReload} from '../../utilities/theme-environment/types.js' @@ -18,12 +21,14 @@ type DevFlags = InferredFlags export default class Dev extends ThemeCommand { static summary = - 'Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time.' + 'Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time. Alternatively, a JSON overrides file can be provided to quickly preview changes without uploading a theme.' static descriptionWithMarkdown = ` Uploads the current theme as the specified theme, or a [development theme](https://shopify.dev/docs/themes/tools/cli#development-themes), to a store so you can preview it. -This command returns the following information: + Alternatively, a JSON overrides file can be specified using --path to quickly preview changes without uploading a theme. + +This command returns the following information by default, unless --path is used to target a JSON overrides file: - A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the store's data. @@ -33,19 +38,26 @@ This command returns the following information: - A [preview link](https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers. +> Note: When using --path to target a JSON overrides file, the command will return the preview link instead of the development theme URL. + If you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the \`--theme-editor-sync\` flag. > Note: You can't preview checkout customizations using http://127.0.0.1:9292. Development themes are deleted when you run \`shopify auth logout\`. If you need a preview link that can be used after you log out, then you should [share](https://shopify.dev/docs/api/shopify-cli/theme/theme-share) your theme or [push](https://shopify.dev/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store. -You can run this command only in a directory that matches the [default Shopify theme folder structure](https://shopify.dev/docs/themes/tools/cli#directory-structure).` +You can run this command only in a directory that matches the [default Shopify theme folder structure](https://shopify.dev/docs/themes/tools/cli#directory-structure) unless --path is used to target a JSON overrides file.` static description = this.descriptionWithoutMarkdown() static flags = { ...globalFlags, ...themeFlags, + path: { + ...themeFlags.path, + description: + 'The path for the dev server. It can be a directory or a JSON overrides file. When a directory is provided, it is used as the theme directory. When a JSON file is provided, overrides are applied to the theme specified by --theme. Defaults to the current working directory.', + } as typeof themeFlags.path, host: Flags.string({ description: 'Set which network interface the web server listens on. The default value is 127.0.0.1.', env: 'SHOPIFY_FLAG_HOST', @@ -135,6 +147,11 @@ You can run this command only in a directory that matches the [default Shopify t env: 'SHOPIFY_FLAG_ALLOW_LIVE', default: false, }), + 'preview-id': Flags.string({ + description: + 'An existing preview identifier to update instead of creating a new preview. Used with --path when pointing to a JSON overrides file.', + env: 'SHOPIFY_FLAG_PREVIEW_ID', + }), } static multiEnvironmentsFlags: RequiredFlags = null @@ -144,6 +161,17 @@ You can run this command only in a directory that matches the [default Shopify t recordEvent('theme-command:dev:single-env:authenticated') + if (devFlags.source) { + const resolvedSource = resolvePath(devFlags.source) + + if (isDirectorySync(resolvedSource)) { + devFlags.path = resolvedSource + } else { + await createOverrideDevSession(resolvedSource, devFlags, adminSession) + return + } + } + let theme: Theme let flags @@ -196,3 +224,18 @@ You can run this command only in a directory that matches the [default Shopify t }) } } + +async function createOverrideDevSession(overrideJson: string, devFlags: DevFlags, adminSession: AdminSession) { + if (!devFlags.theme) { + throw new AbortError(`The --theme flag is required when using --path with a JSON file.`) + } + + const theme = await findOrSelectTheme(adminSession, {filter: {theme: devFlags.theme}}) + await devWithOverrideFile({ + adminSession, + overrideJson, + themeId: theme.id.toString(), + previewIdentifier: devFlags['preview-id'], + open: devFlags.open, + }) +} diff --git a/packages/theme/src/cli/services/dev-override.test.ts b/packages/theme/src/cli/services/dev-override.test.ts new file mode 100644 index 00000000000..5e09c87a918 --- /dev/null +++ b/packages/theme/src/cli/services/dev-override.test.ts @@ -0,0 +1,154 @@ +import {devWithOverrideFile} from './dev-override.js' +import {openURLSafely} from './dev.js' +import {fetchDevServerSession} from '../utilities/theme-environment/dev-server-session.js' +import {createThemePreview, updateThemePreview} from '../utilities/theme-previews/preview.js' +import {describe, expect, test, vi} from 'vitest' +import {renderSuccess} from '@shopify/cli-kit/node/ui' +import {fileExistsSync, readFile} from '@shopify/cli-kit/node/fs' + +vi.mock('../utilities/theme-environment/dev-server-session.js') +vi.mock('../utilities/theme-previews/preview.js') +vi.mock('./dev.js', () => ({openURLSafely: vi.fn()})) +vi.mock('@shopify/cli-kit/node/ui') +vi.mock('@shopify/cli-kit/node/fs') + +const adminSession = {token: 'token', storeFqdn: 'store.myshopify.com'} +const mockSession = { + token: 'token', + storeFqdn: 'store.myshopify.com', + storefrontToken: 'sf_token', + sessionCookies: {}, +} +const expectedPreviewUrl = 'https://abc123.shopifypreview.com' +const expectedPreviewId = 'abc123' + +describe('devWithOverrideFile', () => { + test('throws when override file does not exist', async () => { + // Given + vi.mocked(fileExistsSync).mockReturnValue(false) + + // When/Then + await expect( + devWithOverrideFile({adminSession, overrideJson: '/missing.json', themeId: '123', open: false}), + ).rejects.toThrow('Override file not found: /missing.json') + }) + + test('creates a preview when no previewIdentifier is provided', async () => { + // Given + vi.mocked(fileExistsSync).mockReturnValue(true) + vi.mocked(readFile).mockResolvedValue(Buffer.from(JSON.stringify({templates: {}}))) + vi.mocked(fetchDevServerSession).mockResolvedValue(mockSession) + vi.mocked(createThemePreview).mockResolvedValue({url: expectedPreviewUrl, preview_identifier: expectedPreviewId}) + const expectedThemeId = '789' + + // When + await devWithOverrideFile({adminSession, overrideJson: '/overrides.json', themeId: expectedThemeId, open: false}) + + // Then + expect(createThemePreview).toHaveBeenCalledWith( + expect.objectContaining({ + session: mockSession, + storefrontToken: 'sf_token', + themeId: expectedThemeId, + }), + ) + expect(updateThemePreview).not.toHaveBeenCalled() + expect(renderSuccess).toHaveBeenCalledWith( + expect.objectContaining({ + body: [ + { + list: { + title: 'Preview is ready', + items: [{link: {url: expectedPreviewUrl}}, `Preview ID: ${expectedPreviewId}`], + }, + }, + ], + }), + ) + }) + + test('updates a preview when previewIdentifier is provided', async () => { + // Given + vi.mocked(fileExistsSync).mockReturnValue(true) + vi.mocked(readFile).mockResolvedValue(Buffer.from(JSON.stringify({templates: {}}))) + vi.mocked(fetchDevServerSession).mockResolvedValue(mockSession) + vi.mocked(updateThemePreview).mockResolvedValue({url: expectedPreviewUrl, preview_identifier: expectedPreviewId}) + const expectedThemeId = '789'; + + // When + await devWithOverrideFile({ + adminSession, + overrideJson: '/overrides.json', + themeId: expectedThemeId, + previewIdentifier: expectedPreviewId, + open: false, + }) + + // Then + expect(updateThemePreview).toHaveBeenCalledWith( + expect.objectContaining({ + session: mockSession, + storefrontToken: 'sf_token', + themeId: expectedThemeId, + previewIdentifier: expectedPreviewId, + }), + ) + expect(createThemePreview).not.toHaveBeenCalled() + expect(renderSuccess).toHaveBeenCalledWith( + expect.objectContaining({ + body: [ + { + list: { + title: 'Preview updated', + items: [{link: {url: expectedPreviewUrl}}, `Preview ID: ${expectedPreviewId}`], + }, + }, + ], + }), + ) + }) + + test('throws when override file contains invalid JSON', async () => { + // Given + vi.mocked(fileExistsSync).mockReturnValue(true) + vi.mocked(readFile).mockResolvedValue(Buffer.from('not valid json')) + + // When/Then + const error = await devWithOverrideFile({ + adminSession, + overrideJson: '/bad.json', + themeId: '123', + open: false, + }).catch((err) => err) + expect(error.message).toBe('Failed to parse override file: /bad.json') + expect(error.tryMessage).toMatch(/not valid json/i) + }) + + test('opens the preview URL when open is true', async () => { + // Given + vi.mocked(fileExistsSync).mockReturnValue(true) + vi.mocked(readFile).mockResolvedValue(Buffer.from(JSON.stringify({templates: {}}))) + vi.mocked(fetchDevServerSession).mockResolvedValue(mockSession) + vi.mocked(createThemePreview).mockResolvedValue({url: expectedPreviewUrl, preview_identifier: expectedPreviewId}) + + // When + await devWithOverrideFile({adminSession, overrideJson: '/overrides.json', themeId: '789', open: true}) + + // Then + expect(openURLSafely).toHaveBeenCalledWith(expectedPreviewUrl, 'theme preview') + }) + + test('does not open the preview URL when open is false', async () => { + // Given + vi.mocked(fileExistsSync).mockReturnValue(true) + vi.mocked(readFile).mockResolvedValue(Buffer.from(JSON.stringify({templates: {}}))) + vi.mocked(fetchDevServerSession).mockResolvedValue(mockSession) + vi.mocked(createThemePreview).mockResolvedValue({url: expectedPreviewUrl, preview_identifier: expectedPreviewId}) + + // When + await devWithOverrideFile({adminSession, overrideJson: '/overrides.json', themeId: '789', open: false}) + + // Then + expect(openURLSafely).not.toHaveBeenCalled() + }) +}) diff --git a/packages/theme/src/cli/services/dev-override.ts b/packages/theme/src/cli/services/dev-override.ts new file mode 100644 index 00000000000..948eb9ff753 --- /dev/null +++ b/packages/theme/src/cli/services/dev-override.ts @@ -0,0 +1,71 @@ +import {openURLSafely} from './dev.js' +import {fetchDevServerSession} from '../utilities/theme-environment/dev-server-session.js' +import {createThemePreview, updateThemePreview} from '../utilities/theme-previews/preview.js' +import {renderSuccess} from '@shopify/cli-kit/node/ui' +import {AdminSession} from '@shopify/cli-kit/node/session' +import {AbortError} from '@shopify/cli-kit/node/error' +import {readFile, fileExistsSync} from '@shopify/cli-kit/node/fs' + +interface ThemeOverrides { + [key: string]: unknown +} + +interface DevWithOverrideFileOptions { + adminSession: AdminSession + overrideJson: string + themeId: string + previewIdentifier?: string + open: boolean +} + +/** + * Reads a JSON overrides file and creates or updates a Storefront preview. + * The resulting preview URL is displayed to the user. + */ +export async function devWithOverrideFile(options: DevWithOverrideFileOptions) { + if (!fileExistsSync(options.overrideJson)) { + throw new AbortError(`Override file not found: ${options.overrideJson}`) + } + + const fileContent = await readFile(options.overrideJson) + let overrides: ThemeOverrides + try { + overrides = JSON.parse(fileContent) as ThemeOverrides + } catch (error) { + const reason = error instanceof Error ? error.message : String(error) + throw new AbortError(`Failed to parse override file: ${options.overrideJson}`, reason) + } + + const session = await fetchDevServerSession(options.themeId, options.adminSession) + const overridesContent = JSON.stringify(overrides) + + const preview = options.previewIdentifier + ? await updateThemePreview({ + session, + storefrontToken: session.storefrontToken, + overridesContent, + themeId: options.themeId, + previewIdentifier: options.previewIdentifier, + }) + : await createThemePreview({ + session, + storefrontToken: session.storefrontToken, + overridesContent, + themeId: options.themeId, + }) + + renderSuccess({ + body: [ + { + list: { + title: options.previewIdentifier ? 'Preview updated' : 'Preview is ready', + items: [{link: {url: preview.url}}, `Preview ID: ${preview.preview_identifier}`], + }, + }, + ], + }) + + if (options.open) { + openURLSafely(preview.url, 'theme preview') + } +} From 2c3e408a7ef6c7e756157843f206fe60cc9330ff Mon Sep 17 00:00:00 2001 From: Jeffrey Deng Date: Tue, 24 Feb 2026 10:42:14 -0800 Subject: [PATCH 4/8] Update README and manifests for new flag changes in theme dev --- .../interfaces/theme-dev.interface.ts | 12 +++++++ docs-shopify.dev/commands/theme-dev.doc.ts | 10 ++++-- .../generated/generated_docs_data.json | 24 ++++++++++++-- packages/cli/README.md | 27 ++++++++++++---- packages/cli/oclif.manifest.json | 32 ++++++++++++++----- 5 files changed, 84 insertions(+), 21 deletions(-) diff --git a/docs-shopify.dev/commands/interfaces/theme-dev.interface.ts b/docs-shopify.dev/commands/interfaces/theme-dev.interface.ts index 311f0b9d57f..500b79feaf4 100644 --- a/docs-shopify.dev/commands/interfaces/theme-dev.interface.ts +++ b/docs-shopify.dev/commands/interfaces/theme-dev.interface.ts @@ -96,6 +96,18 @@ export interface themedev { */ '--port '?: string + /** + * An existing preview identifier to update instead of creating a new preview. Used with --source when pointing to a JSON overrides file. + * @environment SHOPIFY_FLAG_PREVIEW_ID + */ + '--preview-id '?: string + + /** + * The source for the dev server. Can be a directory or a JSON overrides file. When a directory is provided, it is used as the theme directory. When a JSON file is provided, overrides are applied to the theme specified by --theme. + * @environment SHOPIFY_FLAG_SOURCE + */ + '--source '?: string + /** * Store URL. It can be the store prefix (example) or the full myshopify.com URL (example.myshopify.com, https://example.myshopify.com). * @environment SHOPIFY_FLAG_STORE diff --git a/docs-shopify.dev/commands/theme-dev.doc.ts b/docs-shopify.dev/commands/theme-dev.doc.ts index 3f6a1c3029a..aaafa92be0f 100644 --- a/docs-shopify.dev/commands/theme-dev.doc.ts +++ b/docs-shopify.dev/commands/theme-dev.doc.ts @@ -6,7 +6,9 @@ const data: ReferenceEntityTemplateSchema = { description: ` Uploads the current theme as the specified theme, or a [development theme](/docs/themes/tools/cli#development-themes), to a store so you can preview it. -This command returns the following information: + Alternatively, a JSON overrides file can be specified using --source to quickly preview changes without uploading a theme. + +This command returns the following information by default, unless --source is used to target a JSON overrides file: - A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the store's data. @@ -16,14 +18,16 @@ This command returns the following information: - A [preview link](https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers. +> Note: When using --source to target a JSON overrides file, the command will return the preview link instead of the development theme URL. + If you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the \`--theme-editor-sync\` flag. > Note: You can't preview checkout customizations using http://127.0.0.1:9292. Development themes are deleted when you run \`shopify auth logout\`. If you need a preview link that can be used after you log out, then you should [share](/docs/api/shopify-cli/theme/theme-share) your theme or [push](/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store. -You can run this command only in a directory that matches the [default Shopify theme folder structure](/docs/themes/tools/cli#directory-structure).`, - overviewPreviewDescription: `Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time.`, +You can run this command only in a directory that matches the [default Shopify theme folder structure](/docs/themes/tools/cli#directory-structure) unless --source is used to target a JSON overrides file.`, + overviewPreviewDescription: `Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time. Alternatively, a JSON overrides file can be provided to quickly preview changes without uploading a theme.`, type: 'command', isVisualComponent: false, defaultExample: { diff --git a/docs-shopify.dev/generated/generated_docs_data.json b/docs-shopify.dev/generated/generated_docs_data.json index d25a20bd95c..ea732c15c42 100644 --- a/docs-shopify.dev/generated/generated_docs_data.json +++ b/docs-shopify.dev/generated/generated_docs_data.json @@ -5994,8 +5994,8 @@ }, { "name": "theme dev", - "description": "\n Uploads the current theme as the specified theme, or a [development theme](/docs/themes/tools/cli#development-themes), to a store so you can preview it.\n\nThis command returns the following information:\n\n- A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the store's data.\n\n You can specify a different network interface and port using `--host` and `--port`.\n\n- A link to the [editor](/docs/themes/tools/online-editor) for the theme in the Shopify admin.\n\n- A [preview link](https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers.\n\nIf you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the `--theme-editor-sync` flag.\n\n> Note: You can't preview checkout customizations using http://127.0.0.1:9292.\n\nDevelopment themes are deleted when you run `shopify auth logout`. If you need a preview link that can be used after you log out, then you should [share](/docs/api/shopify-cli/theme/theme-share) your theme or [push](/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store.\n\nYou can run this command only in a directory that matches the [default Shopify theme folder structure](/docs/themes/tools/cli#directory-structure).", - "overviewPreviewDescription": "Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time.", + "description": "\n Uploads the current theme as the specified theme, or a [development theme](/docs/themes/tools/cli#development-themes), to a store so you can preview it.\n\n Alternatively, a JSON overrides file can be specified using --source to quickly preview changes without uploading a theme.\n\nThis command returns the following information by default, unless --source is used to target a JSON overrides file:\n\n- A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the store's data.\n\n You can specify a different network interface and port using `--host` and `--port`.\n\n- A link to the [editor](/docs/themes/tools/online-editor) for the theme in the Shopify admin.\n\n- A [preview link](https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers.\n\n> Note: When using --source to target a JSON overrides file, the command will return the preview link instead of the development theme URL.\n\nIf you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the `--theme-editor-sync` flag.\n\n> Note: You can't preview checkout customizations using http://127.0.0.1:9292.\n\nDevelopment themes are deleted when you run `shopify auth logout`. If you need a preview link that can be used after you log out, then you should [share](/docs/api/shopify-cli/theme/theme-share) your theme or [push](/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store.\n\nYou can run this command only in a directory that matches the [default Shopify theme folder structure](/docs/themes/tools/cli#directory-structure) unless --source is used to target a JSON overrides file.", + "overviewPreviewDescription": "Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time. Alternatively, a JSON overrides file can be provided to quickly preview changes without uploading a theme.", "type": "command", "isVisualComponent": false, "defaultExample": { @@ -6111,6 +6111,24 @@ "isOptional": true, "environmentValue": "SHOPIFY_FLAG_PORT" }, + { + "filePath": "docs-shopify.dev/commands/interfaces/theme-dev.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--preview-id ", + "value": "string", + "description": "An existing preview identifier to update instead of creating a new preview. Used with --source when pointing to a JSON overrides file.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_PREVIEW_ID" + }, + { + "filePath": "docs-shopify.dev/commands/interfaces/theme-dev.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--source ", + "value": "string", + "description": "The source for the dev server. Can be a directory or a JSON overrides file. When a directory is provided, it is used as the theme directory. When a JSON file is provided, overrides are applied to the theme specified by --theme.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_SOURCE" + }, { "filePath": "docs-shopify.dev/commands/interfaces/theme-dev.interface.ts", "syntaxKind": "PropertySignature", @@ -6202,7 +6220,7 @@ "environmentValue": "SHOPIFY_FLAG_IGNORE" } ], - "value": "export interface themedev {\n /**\n * Allow development on a live theme.\n * @environment SHOPIFY_FLAG_ALLOW_LIVE\n */\n '-a, --allow-live'?: ''\n\n /**\n * The environment to apply to the current command.\n * @environment SHOPIFY_FLAG_ENVIRONMENT\n */\n '-e, --environment '?: string\n\n /**\n * Controls the visibility of the error overlay when an theme asset upload fails:\n- silent Prevents the error overlay from appearing.\n- default Displays the error overlay.\n \n * @environment SHOPIFY_FLAG_ERROR_OVERLAY\n */\n '--error-overlay '?: string\n\n /**\n * Set which network interface the web server listens on. The default value is 127.0.0.1.\n * @environment SHOPIFY_FLAG_HOST\n */\n '--host '?: string\n\n /**\n * Skip hot reloading any files that match the specified pattern.\n * @environment SHOPIFY_FLAG_IGNORE\n */\n '-x, --ignore '?: string\n\n /**\n * The listing preset to use for multi-preset themes. Applies preset files from listings/[preset-name] directory.\n * @environment SHOPIFY_FLAG_LISTING\n */\n '--listing '?: string\n\n /**\n * The live reload mode switches the server behavior when a file is modified:\n- hot-reload Hot reloads local changes to CSS and sections (default)\n- full-page Always refreshes the entire page\n- off Deactivate live reload\n * @environment SHOPIFY_FLAG_LIVE_RELOAD\n */\n '--live-reload '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * Prevents files from being deleted in the remote theme when a file has been deleted locally. This applies to files that are deleted while the command is running, and files that have been deleted locally before the command is run.\n * @environment SHOPIFY_FLAG_NODELETE\n */\n '-n, --nodelete'?: ''\n\n /**\n * The file path or URL. The file path is to a file that you want updated on idle. The URL path is where you want a webhook posted to report on file changes.\n * @environment SHOPIFY_FLAG_NOTIFY\n */\n '--notify '?: string\n\n /**\n * Hot reload only files that match the specified pattern.\n * @environment SHOPIFY_FLAG_ONLY\n */\n '-o, --only '?: string\n\n /**\n * Automatically launch the theme preview in your default web browser.\n * @environment SHOPIFY_FLAG_OPEN\n */\n '--open'?: ''\n\n /**\n * Password generated from the Theme Access app or an Admin API token.\n * @environment SHOPIFY_CLI_THEME_TOKEN\n */\n '--password '?: string\n\n /**\n * The path where you want to run the command. Defaults to the current working directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Local port to serve theme preview from.\n * @environment SHOPIFY_FLAG_PORT\n */\n '--port '?: string\n\n /**\n * Store URL. It can be the store prefix (example) or the full myshopify.com URL (example.myshopify.com, https://example.myshopify.com).\n * @environment SHOPIFY_FLAG_STORE\n */\n '-s, --store '?: string\n\n /**\n * The password for storefronts with password protection.\n * @environment SHOPIFY_FLAG_STORE_PASSWORD\n */\n '--store-password '?: string\n\n /**\n * Theme ID or name of the remote theme.\n * @environment SHOPIFY_FLAG_THEME_ID\n */\n '-t, --theme '?: string\n\n /**\n * Synchronize Theme Editor updates in the local theme files.\n * @environment SHOPIFY_FLAG_THEME_EDITOR_SYNC\n */\n '--theme-editor-sync'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" + "value": "export interface themedev {\n /**\n * Allow development on a live theme.\n * @environment SHOPIFY_FLAG_ALLOW_LIVE\n */\n '-a, --allow-live'?: ''\n\n /**\n * The environment to apply to the current command.\n * @environment SHOPIFY_FLAG_ENVIRONMENT\n */\n '-e, --environment '?: string\n\n /**\n * Controls the visibility of the error overlay when an theme asset upload fails:\n- silent Prevents the error overlay from appearing.\n- default Displays the error overlay.\n \n * @environment SHOPIFY_FLAG_ERROR_OVERLAY\n */\n '--error-overlay '?: string\n\n /**\n * Set which network interface the web server listens on. The default value is 127.0.0.1.\n * @environment SHOPIFY_FLAG_HOST\n */\n '--host '?: string\n\n /**\n * Skip hot reloading any files that match the specified pattern.\n * @environment SHOPIFY_FLAG_IGNORE\n */\n '-x, --ignore '?: string\n\n /**\n * The listing preset to use for multi-preset themes. Applies preset files from listings/[preset-name] directory.\n * @environment SHOPIFY_FLAG_LISTING\n */\n '--listing '?: string\n\n /**\n * The live reload mode switches the server behavior when a file is modified:\n- hot-reload Hot reloads local changes to CSS and sections (default)\n- full-page Always refreshes the entire page\n- off Deactivate live reload\n * @environment SHOPIFY_FLAG_LIVE_RELOAD\n */\n '--live-reload '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * Prevents files from being deleted in the remote theme when a file has been deleted locally. This applies to files that are deleted while the command is running, and files that have been deleted locally before the command is run.\n * @environment SHOPIFY_FLAG_NODELETE\n */\n '-n, --nodelete'?: ''\n\n /**\n * The file path or URL. The file path is to a file that you want updated on idle. The URL path is where you want a webhook posted to report on file changes.\n * @environment SHOPIFY_FLAG_NOTIFY\n */\n '--notify '?: string\n\n /**\n * Hot reload only files that match the specified pattern.\n * @environment SHOPIFY_FLAG_ONLY\n */\n '-o, --only '?: string\n\n /**\n * Automatically launch the theme preview in your default web browser.\n * @environment SHOPIFY_FLAG_OPEN\n */\n '--open'?: ''\n\n /**\n * Password generated from the Theme Access app or an Admin API token.\n * @environment SHOPIFY_CLI_THEME_TOKEN\n */\n '--password '?: string\n\n /**\n * The path where you want to run the command. Defaults to the current working directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Local port to serve theme preview from.\n * @environment SHOPIFY_FLAG_PORT\n */\n '--port '?: string\n\n /**\n * An existing preview identifier to update instead of creating a new preview. Used with --source when pointing to a JSON overrides file.\n * @environment SHOPIFY_FLAG_PREVIEW_ID\n */\n '--preview-id '?: string\n\n /**\n * The source for the dev server. Can be a directory or a JSON overrides file. When a directory is provided, it is used as the theme directory. When a JSON file is provided, overrides are applied to the theme specified by --theme.\n * @environment SHOPIFY_FLAG_SOURCE\n */\n '--source '?: string\n\n /**\n * Store URL. It can be the store prefix (example) or the full myshopify.com URL (example.myshopify.com, https://example.myshopify.com).\n * @environment SHOPIFY_FLAG_STORE\n */\n '-s, --store '?: string\n\n /**\n * The password for storefronts with password protection.\n * @environment SHOPIFY_FLAG_STORE_PASSWORD\n */\n '--store-password '?: string\n\n /**\n * Theme ID or name of the remote theme.\n * @environment SHOPIFY_FLAG_THEME_ID\n */\n '-t, --theme '?: string\n\n /**\n * Synchronize Theme Editor updates in the local theme files.\n * @environment SHOPIFY_FLAG_THEME_EDITOR_SYNC\n */\n '--theme-editor-sync'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" } } } diff --git a/packages/cli/README.md b/packages/cli/README.md index 63fa0299535..edf5b3846fc 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -2110,14 +2110,14 @@ DESCRIPTION ## `shopify theme dev` -Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time. +Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time. Alternatively, a JSON overrides file can be provided to quickly preview changes without uploading a theme. ``` USAGE $ shopify theme dev [-a] [-e ...] [--error-overlay silent|default] [--host ] [-x ...] [--listing ] [--live-reload hot-reload|full-page|off] [--no-color] [-n] [--notify ] [-o ...] - [--open] [--password ] [--path ] [--port ] [-s ] [--store-password ] [-t ] - [--theme-editor-sync] [--verbose] + [--open] [--password ] [--path ] [--port ] [--preview-id ] [-s ] + [--store-password ] [-t ] [--theme-editor-sync] [--verbose] FLAGS -a, --allow-live @@ -2181,11 +2181,17 @@ FLAGS [env: SHOPIFY_CLI_THEME_TOKEN] Password generated from the Theme Access app or an Admin API token. --path= - [env: SHOPIFY_FLAG_PATH] The path where you want to run the command. Defaults to the current working directory. + [env: SHOPIFY_FLAG_PATH] The path for the dev server. It can be a directory or a JSON overrides file. When a + directory is provided, it is used as the theme directory. When a JSON file is provided, overrides are applied to the + theme specified by --theme. Defaults to the current working directory. --port= [env: SHOPIFY_FLAG_PORT] Local port to serve theme preview from. + --preview-id= + [env: SHOPIFY_FLAG_PREVIEW_ID] An existing preview identifier to update instead of creating a new preview. Used with + --path when pointing to a JSON overrides file. + --store-password= [env: SHOPIFY_FLAG_STORE_PASSWORD] The password for storefronts with password protection. @@ -2197,13 +2203,17 @@ FLAGS DESCRIPTION Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to - your terminal. While running, changes will push to the store in real time. + your terminal. While running, changes will push to the store in real time. Alternatively, a JSON overrides file can be + provided to quickly preview changes without uploading a theme. Uploads the current theme as the specified theme, or a "development theme" (https://shopify.dev/docs/themes/tools/cli#development-themes), to a store so you can preview it. - This command returns the following information: + Alternatively, a JSON overrides file can be specified using --path to quickly preview changes without uploading a + theme. + + This command returns the following information by default, unless --path is used to target a JSON overrides file: - A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the @@ -2217,6 +2227,9 @@ DESCRIPTION (https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers. + > Note: When using --path to target a JSON overrides file, the command will return the preview link instead of the + development theme URL. + If you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the `--theme-editor-sync` flag. @@ -2227,7 +2240,7 @@ DESCRIPTION (https://shopify.dev/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store. You can run this command only in a directory that matches the "default Shopify theme folder structure" - (https://shopify.dev/docs/themes/tools/cli#directory-structure). + (https://shopify.dev/docs/themes/tools/cli#directory-structure) unless --path is used to target a JSON overrides file. ``` ## `shopify theme duplicate` diff --git a/packages/cli/oclif.manifest.json b/packages/cli/oclif.manifest.json index ba48270931b..fba0e93c664 100644 --- a/packages/cli/oclif.manifest.json +++ b/packages/cli/oclif.manifest.json @@ -5948,8 +5948,8 @@ "args": { }, "customPluginName": "@shopify/theme", - "description": "\n Uploads the current theme as the specified theme, or a \"development theme\" (https://shopify.dev/docs/themes/tools/cli#development-themes), to a store so you can preview it.\n\nThis command returns the following information:\n\n- A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the store's data.\n\n You can specify a different network interface and port using `--host` and `--port`.\n\n- A link to the \"editor\" (https://shopify.dev/docs/themes/tools/online-editor) for the theme in the Shopify admin.\n\n- A \"preview link\" (https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers.\n\nIf you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the `--theme-editor-sync` flag.\n\n> Note: You can't preview checkout customizations using http://127.0.0.1:9292.\n\nDevelopment themes are deleted when you run `shopify auth logout`. If you need a preview link that can be used after you log out, then you should \"share\" (https://shopify.dev/docs/api/shopify-cli/theme/theme-share) your theme or \"push\" (https://shopify.dev/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store.\n\nYou can run this command only in a directory that matches the \"default Shopify theme folder structure\" (https://shopify.dev/docs/themes/tools/cli#directory-structure).", - "descriptionWithMarkdown": "\n Uploads the current theme as the specified theme, or a [development theme](https://shopify.dev/docs/themes/tools/cli#development-themes), to a store so you can preview it.\n\nThis command returns the following information:\n\n- A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the store's data.\n\n You can specify a different network interface and port using `--host` and `--port`.\n\n- A link to the [editor](https://shopify.dev/docs/themes/tools/online-editor) for the theme in the Shopify admin.\n\n- A [preview link](https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers.\n\nIf you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the `--theme-editor-sync` flag.\n\n> Note: You can't preview checkout customizations using http://127.0.0.1:9292.\n\nDevelopment themes are deleted when you run `shopify auth logout`. If you need a preview link that can be used after you log out, then you should [share](https://shopify.dev/docs/api/shopify-cli/theme/theme-share) your theme or [push](https://shopify.dev/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store.\n\nYou can run this command only in a directory that matches the [default Shopify theme folder structure](https://shopify.dev/docs/themes/tools/cli#directory-structure).", + "description": "\n Uploads the current theme as the specified theme, or a \"development theme\" (https://shopify.dev/docs/themes/tools/cli#development-themes), to a store so you can preview it.\n\n Alternatively, a JSON overrides file can be specified using --path to quickly preview changes without uploading a theme.\n\nThis command returns the following information by default, unless --path is used to target a JSON overrides file:\n\n- A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the store's data.\n\n You can specify a different network interface and port using `--host` and `--port`.\n\n- A link to the \"editor\" (https://shopify.dev/docs/themes/tools/online-editor) for the theme in the Shopify admin.\n\n- A \"preview link\" (https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers.\n\n> Note: When using --path to target a JSON overrides file, the command will return the preview link instead of the development theme URL.\n\nIf you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the `--theme-editor-sync` flag.\n\n> Note: You can't preview checkout customizations using http://127.0.0.1:9292.\n\nDevelopment themes are deleted when you run `shopify auth logout`. If you need a preview link that can be used after you log out, then you should \"share\" (https://shopify.dev/docs/api/shopify-cli/theme/theme-share) your theme or \"push\" (https://shopify.dev/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store.\n\nYou can run this command only in a directory that matches the \"default Shopify theme folder structure\" (https://shopify.dev/docs/themes/tools/cli#directory-structure) unless --path is used to target a JSON overrides file.", + "descriptionWithMarkdown": "\n Uploads the current theme as the specified theme, or a [development theme](https://shopify.dev/docs/themes/tools/cli#development-themes), to a store so you can preview it.\n\n Alternatively, a JSON overrides file can be specified using --path to quickly preview changes without uploading a theme.\n\nThis command returns the following information by default, unless --path is used to target a JSON overrides file:\n\n- A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the store's data.\n\n You can specify a different network interface and port using `--host` and `--port`.\n\n- A link to the [editor](https://shopify.dev/docs/themes/tools/online-editor) for the theme in the Shopify admin.\n\n- A [preview link](https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers.\n\n> Note: When using --path to target a JSON overrides file, the command will return the preview link instead of the development theme URL.\n\nIf you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the `--theme-editor-sync` flag.\n\n> Note: You can't preview checkout customizations using http://127.0.0.1:9292.\n\nDevelopment themes are deleted when you run `shopify auth logout`. If you need a preview link that can be used after you log out, then you should [share](https://shopify.dev/docs/api/shopify-cli/theme/theme-share) your theme or [push](https://shopify.dev/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store.\n\nYou can run this command only in a directory that matches the [default Shopify theme folder structure](https://shopify.dev/docs/themes/tools/cli#directory-structure) unless --path is used to target a JSON overrides file.", "flags": { "allow-live": { "allowNo": false, @@ -6078,7 +6078,7 @@ "type": "option" }, "path": { - "description": "The path where you want to run the command. Defaults to the current working directory.", + "description": "The path for the dev server. It can be a directory or a JSON overrides file. When a directory is provided, it is used as the theme directory. When a JSON file is provided, overrides are applied to the theme specified by --theme. Defaults to the current working directory.", "env": "SHOPIFY_FLAG_PATH", "hasDynamicHelp": false, "multiple": false, @@ -6102,6 +6102,14 @@ "name": "port", "type": "option" }, + "preview-id": { + "description": "An existing preview identifier to update instead of creating a new preview. Used with --path when pointing to a JSON overrides file.", + "env": "SHOPIFY_FLAG_PREVIEW_ID", + "hasDynamicHelp": false, + "multiple": false, + "name": "preview-id", + "type": "option" + }, "store": { "char": "s", "description": "Store URL. It can be the store prefix (example) or the full myshopify.com URL (example.myshopify.com, https://example.myshopify.com).", @@ -6153,7 +6161,7 @@ "pluginName": "@shopify/cli", "pluginType": "core", "strict": true, - "summary": "Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time." + "summary": "Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time. Alternatively, a JSON overrides file can be provided to quickly preview changes without uploading a theme." }, "theme:duplicate": { "aliases": [ @@ -7465,8 +7473,8 @@ "args": { }, "customPluginName": "@shopify/theme", - "description": "\n Uploads the current theme as the specified theme, or a \"development theme\" (https://shopify.dev/docs/themes/tools/cli#development-themes), to a store so you can preview it.\n\nThis command returns the following information:\n\n- A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the store's data.\n\n You can specify a different network interface and port using `--host` and `--port`.\n\n- A link to the \"editor\" (https://shopify.dev/docs/themes/tools/online-editor) for the theme in the Shopify admin.\n\n- A \"preview link\" (https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers.\n\nIf you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the `--theme-editor-sync` flag.\n\n> Note: You can't preview checkout customizations using http://127.0.0.1:9292.\n\nDevelopment themes are deleted when you run `shopify auth logout`. If you need a preview link that can be used after you log out, then you should \"share\" (https://shopify.dev/docs/api/shopify-cli/theme/theme-share) your theme or \"push\" (https://shopify.dev/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store.\n\nYou can run this command only in a directory that matches the \"default Shopify theme folder structure\" (https://shopify.dev/docs/themes/tools/cli#directory-structure).", - "descriptionWithMarkdown": "\n Uploads the current theme as the specified theme, or a [development theme](https://shopify.dev/docs/themes/tools/cli#development-themes), to a store so you can preview it.\n\nThis command returns the following information:\n\n- A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the store's data.\n\n You can specify a different network interface and port using `--host` and `--port`.\n\n- A link to the [editor](https://shopify.dev/docs/themes/tools/online-editor) for the theme in the Shopify admin.\n\n- A [preview link](https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers.\n\nIf you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the `--theme-editor-sync` flag.\n\n> Note: You can't preview checkout customizations using http://127.0.0.1:9292.\n\nDevelopment themes are deleted when you run `shopify auth logout`. If you need a preview link that can be used after you log out, then you should [share](https://shopify.dev/docs/api/shopify-cli/theme/theme-share) your theme or [push](https://shopify.dev/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store.\n\nYou can run this command only in a directory that matches the [default Shopify theme folder structure](https://shopify.dev/docs/themes/tools/cli#directory-structure).", + "description": "\n Uploads the current theme as the specified theme, or a \"development theme\" (https://shopify.dev/docs/themes/tools/cli#development-themes), to a store so you can preview it.\n\n Alternatively, a JSON overrides file can be specified using --path to quickly preview changes without uploading a theme.\n\nThis command returns the following information by default, unless --path is used to target a JSON overrides file:\n\n- A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the store's data.\n\n You can specify a different network interface and port using `--host` and `--port`.\n\n- A link to the \"editor\" (https://shopify.dev/docs/themes/tools/online-editor) for the theme in the Shopify admin.\n\n- A \"preview link\" (https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers.\n\n> Note: When using --path to target a JSON overrides file, the command will return the preview link instead of the development theme URL.\n\nIf you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the `--theme-editor-sync` flag.\n\n> Note: You can't preview checkout customizations using http://127.0.0.1:9292.\n\nDevelopment themes are deleted when you run `shopify auth logout`. If you need a preview link that can be used after you log out, then you should \"share\" (https://shopify.dev/docs/api/shopify-cli/theme/theme-share) your theme or \"push\" (https://shopify.dev/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store.\n\nYou can run this command only in a directory that matches the \"default Shopify theme folder structure\" (https://shopify.dev/docs/themes/tools/cli#directory-structure) unless --path is used to target a JSON overrides file.", + "descriptionWithMarkdown": "\n Uploads the current theme as the specified theme, or a [development theme](https://shopify.dev/docs/themes/tools/cli#development-themes), to a store so you can preview it.\n\n Alternatively, a JSON overrides file can be specified using --path to quickly preview changes without uploading a theme.\n\nThis command returns the following information by default, unless --path is used to target a JSON overrides file:\n\n- A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the store's data.\n\n You can specify a different network interface and port using `--host` and `--port`.\n\n- A link to the [editor](https://shopify.dev/docs/themes/tools/online-editor) for the theme in the Shopify admin.\n\n- A [preview link](https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers.\n\n> Note: When using --path to target a JSON overrides file, the command will return the preview link instead of the development theme URL.\n\nIf you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the `--theme-editor-sync` flag.\n\n> Note: You can't preview checkout customizations using http://127.0.0.1:9292.\n\nDevelopment themes are deleted when you run `shopify auth logout`. If you need a preview link that can be used after you log out, then you should [share](https://shopify.dev/docs/api/shopify-cli/theme/theme-share) your theme or [push](https://shopify.dev/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store.\n\nYou can run this command only in a directory that matches the [default Shopify theme folder structure](https://shopify.dev/docs/themes/tools/cli#directory-structure) unless --path is used to target a JSON overrides file.", "flags": { "allow-live": { "allowNo": false, @@ -7595,7 +7603,7 @@ "type": "option" }, "path": { - "description": "The path where you want to run the command. Defaults to the current working directory.", + "description": "The path for the dev server. It can be a directory or a JSON overrides file. When a directory is provided, it is used as the theme directory. When a JSON file is provided, overrides are applied to the theme specified by --theme. Defaults to the current working directory.", "env": "SHOPIFY_FLAG_PATH", "hasDynamicHelp": false, "multiple": false, @@ -7619,6 +7627,14 @@ "name": "port", "type": "option" }, + "preview-id": { + "description": "An existing preview identifier to update instead of creating a new preview. Used with --path when pointing to a JSON overrides file.", + "env": "SHOPIFY_FLAG_PREVIEW_ID", + "hasDynamicHelp": false, + "multiple": false, + "name": "preview-id", + "type": "option" + }, "store": { "char": "s", "description": "Store URL. It can be the store prefix (example) or the full myshopify.com URL (example.myshopify.com, https://example.myshopify.com).", @@ -7670,7 +7686,7 @@ "pluginAlias": "@shopify/cli", "pluginName": "@shopify/cli", "pluginType": "core", - "summary": "Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time." + "summary": "Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time. Alternatively, a JSON overrides file can be provided to quickly preview changes without uploading a theme." }, "theme:share": { "aliases": [ From 628be7624b04845288601cdb0271fdd8061834df Mon Sep 17 00:00:00 2001 From: Jeffrey Deng Date: Wed, 25 Feb 2026 09:51:09 -0800 Subject: [PATCH 5/8] Add analytics and metrics to track performance for theme overrides --- packages/theme/src/cli/commands/theme/dev.ts | 13 ++++--------- .../src/cli/utilities/theme-previews/preview.ts | 11 +++++++++-- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/packages/theme/src/cli/commands/theme/dev.ts b/packages/theme/src/cli/commands/theme/dev.ts index 9e3b3dee9df..fa30f702329 100644 --- a/packages/theme/src/cli/commands/theme/dev.ts +++ b/packages/theme/src/cli/commands/theme/dev.ts @@ -161,15 +161,10 @@ You can run this command only in a directory that matches the [default Shopify t recordEvent('theme-command:dev:single-env:authenticated') - if (devFlags.source) { - const resolvedSource = resolvePath(devFlags.source) - - if (isDirectorySync(resolvedSource)) { - devFlags.path = resolvedSource - } else { - await createOverrideDevSession(resolvedSource, devFlags, adminSession) - return - } + if (!isDirectorySync(devFlags.path)) { + recordEvent('theme-command:dev:override-session') + await createOverrideDevSession(devFlags.path, devFlags, adminSession) + return } let theme: Theme diff --git a/packages/theme/src/cli/utilities/theme-previews/preview.ts b/packages/theme/src/cli/utilities/theme-previews/preview.ts index b26aca5f2a1..910fd47110e 100644 --- a/packages/theme/src/cli/utilities/theme-previews/preview.ts +++ b/packages/theme/src/cli/utilities/theme-previews/preview.ts @@ -1,6 +1,7 @@ import {buildBaseStorefrontUrl} from '../theme-environment/storefront-renderer.js' import {defaultHeaders} from '../theme-environment/storefront-utils.js' import {DevServerSession} from '../theme-environment/types.js' +import {recordTiming} from '@shopify/cli-kit/node/analytics' import {AbortError} from '@shopify/cli-kit/node/error' import {shopifyFetch, Response} from '@shopify/cli-kit/node/http' @@ -38,6 +39,7 @@ export async function createThemePreview({ overridesContent, themeId, }: CreateThemePreviewOptions): Promise { + recordTiming('theme-preview:create') const baseUrl = buildBaseStorefrontUrl(session) const url = `${baseUrl}/theme_preview.json?preview_theme_id=${themeId}` @@ -55,7 +57,9 @@ export async function createThemePreview({ throw new AbortError(`Theme preview request failed with status ${response.status}: ${response.statusText}`) } - return parsePreviewResponse(response) + const result = await parsePreviewResponse(response) + recordTiming('theme-preview:create') + return result } /** @@ -71,6 +75,7 @@ export async function updateThemePreview({ themeId, previewIdentifier, }: UpdateThemePreviewOptions): Promise { + recordTiming('theme-preview:update') const baseUrl = buildBaseStorefrontUrl(session) const url = `${baseUrl}/theme_preview.json?preview_theme_id=${themeId}&preview_identifier=${encodeURIComponent(previewIdentifier)}` @@ -88,7 +93,9 @@ export async function updateThemePreview({ throw new AbortError(`Theme preview request failed with status ${response.status}: ${response.statusText}`) } - return parsePreviewResponse(response) + const result = await parsePreviewResponse(response) + recordTiming('theme-preview:update') + return result } async function parsePreviewResponse(response: Response): Promise { From d4a0ef06f6e0ec3dc2b007331334919bf55a2b7a Mon Sep 17 00:00:00 2001 From: Jeffrey Deng Date: Wed, 25 Feb 2026 10:15:24 -0800 Subject: [PATCH 6/8] Add changeset for the updated --path and new --preview-id flags on theme dev --- .changeset/slick-humans-enjoy.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/slick-humans-enjoy.md diff --git a/.changeset/slick-humans-enjoy.md b/.changeset/slick-humans-enjoy.md new file mode 100644 index 00000000000..e0a35dada25 --- /dev/null +++ b/.changeset/slick-humans-enjoy.md @@ -0,0 +1,6 @@ +--- +'@shopify/theme': minor +'@shopify/cli': minor +--- + +Add support for theme previews using an override via `theme dev`. --path now supports an override JSON. A new --preview-id flag is also introduced to handle updates for preview. From 54aeb0ebbf66d18a97b0912f0f8daf32d7f02969 Mon Sep 17 00:00:00 2001 From: Jeffrey Deng Date: Thu, 26 Feb 2026 11:09:56 -0800 Subject: [PATCH 7/8] Updated dev docs --- .../commands/interfaces/theme-dev.interface.ts | 10 ++-------- docs-shopify.dev/commands/theme-dev.doc.ts | 8 ++++---- .../generated/generated_docs_data.json | 17 ++++------------- 3 files changed, 10 insertions(+), 25 deletions(-) diff --git a/docs-shopify.dev/commands/interfaces/theme-dev.interface.ts b/docs-shopify.dev/commands/interfaces/theme-dev.interface.ts index 500b79feaf4..1b1ae9a19c2 100644 --- a/docs-shopify.dev/commands/interfaces/theme-dev.interface.ts +++ b/docs-shopify.dev/commands/interfaces/theme-dev.interface.ts @@ -85,7 +85,7 @@ export interface themedev { '--password '?: string /** - * The path where you want to run the command. Defaults to the current working directory. + * The path for the dev server. It can be a directory or a JSON overrides file. When a directory is provided, it is used as the theme directory. When a JSON file is provided, overrides are applied to the theme specified by --theme. Defaults to the current working directory. * @environment SHOPIFY_FLAG_PATH */ '--path '?: string @@ -97,17 +97,11 @@ export interface themedev { '--port '?: string /** - * An existing preview identifier to update instead of creating a new preview. Used with --source when pointing to a JSON overrides file. + * An existing preview identifier to update instead of creating a new preview. Used with --path when pointing to a JSON overrides file. * @environment SHOPIFY_FLAG_PREVIEW_ID */ '--preview-id '?: string - /** - * The source for the dev server. Can be a directory or a JSON overrides file. When a directory is provided, it is used as the theme directory. When a JSON file is provided, overrides are applied to the theme specified by --theme. - * @environment SHOPIFY_FLAG_SOURCE - */ - '--source '?: string - /** * Store URL. It can be the store prefix (example) or the full myshopify.com URL (example.myshopify.com, https://example.myshopify.com). * @environment SHOPIFY_FLAG_STORE diff --git a/docs-shopify.dev/commands/theme-dev.doc.ts b/docs-shopify.dev/commands/theme-dev.doc.ts index aaafa92be0f..2372fd42d55 100644 --- a/docs-shopify.dev/commands/theme-dev.doc.ts +++ b/docs-shopify.dev/commands/theme-dev.doc.ts @@ -6,9 +6,9 @@ const data: ReferenceEntityTemplateSchema = { description: ` Uploads the current theme as the specified theme, or a [development theme](/docs/themes/tools/cli#development-themes), to a store so you can preview it. - Alternatively, a JSON overrides file can be specified using --source to quickly preview changes without uploading a theme. + Alternatively, a JSON overrides file can be specified using --path to quickly preview changes without uploading a theme. -This command returns the following information by default, unless --source is used to target a JSON overrides file: +This command returns the following information by default, unless --path is used to target a JSON overrides file: - A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the store's data. @@ -18,7 +18,7 @@ This command returns the following information by default, unless --source is us - A [preview link](https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers. -> Note: When using --source to target a JSON overrides file, the command will return the preview link instead of the development theme URL. +> Note: When using --path to target a JSON overrides file, the command will return the preview link instead of the development theme URL. If you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the \`--theme-editor-sync\` flag. @@ -26,7 +26,7 @@ If you already have a development theme for your current environment, then this Development themes are deleted when you run \`shopify auth logout\`. If you need a preview link that can be used after you log out, then you should [share](/docs/api/shopify-cli/theme/theme-share) your theme or [push](/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store. -You can run this command only in a directory that matches the [default Shopify theme folder structure](/docs/themes/tools/cli#directory-structure) unless --source is used to target a JSON overrides file.`, +You can run this command only in a directory that matches the [default Shopify theme folder structure](/docs/themes/tools/cli#directory-structure) unless --path is used to target a JSON overrides file.`, overviewPreviewDescription: `Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time. Alternatively, a JSON overrides file can be provided to quickly preview changes without uploading a theme.`, type: 'command', isVisualComponent: false, diff --git a/docs-shopify.dev/generated/generated_docs_data.json b/docs-shopify.dev/generated/generated_docs_data.json index ea732c15c42..0691a7d3cd4 100644 --- a/docs-shopify.dev/generated/generated_docs_data.json +++ b/docs-shopify.dev/generated/generated_docs_data.json @@ -5994,7 +5994,7 @@ }, { "name": "theme dev", - "description": "\n Uploads the current theme as the specified theme, or a [development theme](/docs/themes/tools/cli#development-themes), to a store so you can preview it.\n\n Alternatively, a JSON overrides file can be specified using --source to quickly preview changes without uploading a theme.\n\nThis command returns the following information by default, unless --source is used to target a JSON overrides file:\n\n- A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the store's data.\n\n You can specify a different network interface and port using `--host` and `--port`.\n\n- A link to the [editor](/docs/themes/tools/online-editor) for the theme in the Shopify admin.\n\n- A [preview link](https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers.\n\n> Note: When using --source to target a JSON overrides file, the command will return the preview link instead of the development theme URL.\n\nIf you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the `--theme-editor-sync` flag.\n\n> Note: You can't preview checkout customizations using http://127.0.0.1:9292.\n\nDevelopment themes are deleted when you run `shopify auth logout`. If you need a preview link that can be used after you log out, then you should [share](/docs/api/shopify-cli/theme/theme-share) your theme or [push](/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store.\n\nYou can run this command only in a directory that matches the [default Shopify theme folder structure](/docs/themes/tools/cli#directory-structure) unless --source is used to target a JSON overrides file.", + "description": "\n Uploads the current theme as the specified theme, or a [development theme](/docs/themes/tools/cli#development-themes), to a store so you can preview it.\n\n Alternatively, a JSON overrides file can be specified using --path to quickly preview changes without uploading a theme.\n\nThis command returns the following information by default, unless --path is used to target a JSON overrides file:\n\n- A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the store's data.\n\n You can specify a different network interface and port using `--host` and `--port`.\n\n- A link to the [editor](/docs/themes/tools/online-editor) for the theme in the Shopify admin.\n\n- A [preview link](https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers.\n\n> Note: When using --path to target a JSON overrides file, the command will return the preview link instead of the development theme URL.\n\nIf you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the `--theme-editor-sync` flag.\n\n> Note: You can't preview checkout customizations using http://127.0.0.1:9292.\n\nDevelopment themes are deleted when you run `shopify auth logout`. If you need a preview link that can be used after you log out, then you should [share](/docs/api/shopify-cli/theme/theme-share) your theme or [push](/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store.\n\nYou can run this command only in a directory that matches the [default Shopify theme folder structure](/docs/themes/tools/cli#directory-structure) unless --path is used to target a JSON overrides file.", "overviewPreviewDescription": "Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time. Alternatively, a JSON overrides file can be provided to quickly preview changes without uploading a theme.", "type": "command", "isVisualComponent": false, @@ -6098,7 +6098,7 @@ "syntaxKind": "PropertySignature", "name": "--path ", "value": "string", - "description": "The path where you want to run the command. Defaults to the current working directory.", + "description": "The path for the dev server. It can be a directory or a JSON overrides file. When a directory is provided, it is used as the theme directory. When a JSON file is provided, overrides are applied to the theme specified by --theme. Defaults to the current working directory.", "isOptional": true, "environmentValue": "SHOPIFY_FLAG_PATH" }, @@ -6116,19 +6116,10 @@ "syntaxKind": "PropertySignature", "name": "--preview-id ", "value": "string", - "description": "An existing preview identifier to update instead of creating a new preview. Used with --source when pointing to a JSON overrides file.", + "description": "An existing preview identifier to update instead of creating a new preview. Used with --path when pointing to a JSON overrides file.", "isOptional": true, "environmentValue": "SHOPIFY_FLAG_PREVIEW_ID" }, - { - "filePath": "docs-shopify.dev/commands/interfaces/theme-dev.interface.ts", - "syntaxKind": "PropertySignature", - "name": "--source ", - "value": "string", - "description": "The source for the dev server. Can be a directory or a JSON overrides file. When a directory is provided, it is used as the theme directory. When a JSON file is provided, overrides are applied to the theme specified by --theme.", - "isOptional": true, - "environmentValue": "SHOPIFY_FLAG_SOURCE" - }, { "filePath": "docs-shopify.dev/commands/interfaces/theme-dev.interface.ts", "syntaxKind": "PropertySignature", @@ -6220,7 +6211,7 @@ "environmentValue": "SHOPIFY_FLAG_IGNORE" } ], - "value": "export interface themedev {\n /**\n * Allow development on a live theme.\n * @environment SHOPIFY_FLAG_ALLOW_LIVE\n */\n '-a, --allow-live'?: ''\n\n /**\n * The environment to apply to the current command.\n * @environment SHOPIFY_FLAG_ENVIRONMENT\n */\n '-e, --environment '?: string\n\n /**\n * Controls the visibility of the error overlay when an theme asset upload fails:\n- silent Prevents the error overlay from appearing.\n- default Displays the error overlay.\n \n * @environment SHOPIFY_FLAG_ERROR_OVERLAY\n */\n '--error-overlay '?: string\n\n /**\n * Set which network interface the web server listens on. The default value is 127.0.0.1.\n * @environment SHOPIFY_FLAG_HOST\n */\n '--host '?: string\n\n /**\n * Skip hot reloading any files that match the specified pattern.\n * @environment SHOPIFY_FLAG_IGNORE\n */\n '-x, --ignore '?: string\n\n /**\n * The listing preset to use for multi-preset themes. Applies preset files from listings/[preset-name] directory.\n * @environment SHOPIFY_FLAG_LISTING\n */\n '--listing '?: string\n\n /**\n * The live reload mode switches the server behavior when a file is modified:\n- hot-reload Hot reloads local changes to CSS and sections (default)\n- full-page Always refreshes the entire page\n- off Deactivate live reload\n * @environment SHOPIFY_FLAG_LIVE_RELOAD\n */\n '--live-reload '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * Prevents files from being deleted in the remote theme when a file has been deleted locally. This applies to files that are deleted while the command is running, and files that have been deleted locally before the command is run.\n * @environment SHOPIFY_FLAG_NODELETE\n */\n '-n, --nodelete'?: ''\n\n /**\n * The file path or URL. The file path is to a file that you want updated on idle. The URL path is where you want a webhook posted to report on file changes.\n * @environment SHOPIFY_FLAG_NOTIFY\n */\n '--notify '?: string\n\n /**\n * Hot reload only files that match the specified pattern.\n * @environment SHOPIFY_FLAG_ONLY\n */\n '-o, --only '?: string\n\n /**\n * Automatically launch the theme preview in your default web browser.\n * @environment SHOPIFY_FLAG_OPEN\n */\n '--open'?: ''\n\n /**\n * Password generated from the Theme Access app or an Admin API token.\n * @environment SHOPIFY_CLI_THEME_TOKEN\n */\n '--password '?: string\n\n /**\n * The path where you want to run the command. Defaults to the current working directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Local port to serve theme preview from.\n * @environment SHOPIFY_FLAG_PORT\n */\n '--port '?: string\n\n /**\n * An existing preview identifier to update instead of creating a new preview. Used with --source when pointing to a JSON overrides file.\n * @environment SHOPIFY_FLAG_PREVIEW_ID\n */\n '--preview-id '?: string\n\n /**\n * The source for the dev server. Can be a directory or a JSON overrides file. When a directory is provided, it is used as the theme directory. When a JSON file is provided, overrides are applied to the theme specified by --theme.\n * @environment SHOPIFY_FLAG_SOURCE\n */\n '--source '?: string\n\n /**\n * Store URL. It can be the store prefix (example) or the full myshopify.com URL (example.myshopify.com, https://example.myshopify.com).\n * @environment SHOPIFY_FLAG_STORE\n */\n '-s, --store '?: string\n\n /**\n * The password for storefronts with password protection.\n * @environment SHOPIFY_FLAG_STORE_PASSWORD\n */\n '--store-password '?: string\n\n /**\n * Theme ID or name of the remote theme.\n * @environment SHOPIFY_FLAG_THEME_ID\n */\n '-t, --theme '?: string\n\n /**\n * Synchronize Theme Editor updates in the local theme files.\n * @environment SHOPIFY_FLAG_THEME_EDITOR_SYNC\n */\n '--theme-editor-sync'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" + "value": "export interface themedev {\n /**\n * Allow development on a live theme.\n * @environment SHOPIFY_FLAG_ALLOW_LIVE\n */\n '-a, --allow-live'?: ''\n\n /**\n * The environment to apply to the current command.\n * @environment SHOPIFY_FLAG_ENVIRONMENT\n */\n '-e, --environment '?: string\n\n /**\n * Controls the visibility of the error overlay when an theme asset upload fails:\n- silent Prevents the error overlay from appearing.\n- default Displays the error overlay.\n \n * @environment SHOPIFY_FLAG_ERROR_OVERLAY\n */\n '--error-overlay '?: string\n\n /**\n * Set which network interface the web server listens on. The default value is 127.0.0.1.\n * @environment SHOPIFY_FLAG_HOST\n */\n '--host '?: string\n\n /**\n * Skip hot reloading any files that match the specified pattern.\n * @environment SHOPIFY_FLAG_IGNORE\n */\n '-x, --ignore '?: string\n\n /**\n * The listing preset to use for multi-preset themes. Applies preset files from listings/[preset-name] directory.\n * @environment SHOPIFY_FLAG_LISTING\n */\n '--listing '?: string\n\n /**\n * The live reload mode switches the server behavior when a file is modified:\n- hot-reload Hot reloads local changes to CSS and sections (default)\n- full-page Always refreshes the entire page\n- off Deactivate live reload\n * @environment SHOPIFY_FLAG_LIVE_RELOAD\n */\n '--live-reload '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * Prevents files from being deleted in the remote theme when a file has been deleted locally. This applies to files that are deleted while the command is running, and files that have been deleted locally before the command is run.\n * @environment SHOPIFY_FLAG_NODELETE\n */\n '-n, --nodelete'?: ''\n\n /**\n * The file path or URL. The file path is to a file that you want updated on idle. The URL path is where you want a webhook posted to report on file changes.\n * @environment SHOPIFY_FLAG_NOTIFY\n */\n '--notify '?: string\n\n /**\n * Hot reload only files that match the specified pattern.\n * @environment SHOPIFY_FLAG_ONLY\n */\n '-o, --only '?: string\n\n /**\n * Automatically launch the theme preview in your default web browser.\n * @environment SHOPIFY_FLAG_OPEN\n */\n '--open'?: ''\n\n /**\n * Password generated from the Theme Access app or an Admin API token.\n * @environment SHOPIFY_CLI_THEME_TOKEN\n */\n '--password '?: string\n\n /**\n * The path for the dev server. It can be a directory or a JSON overrides file. When a directory is provided, it is used as the theme directory. When a JSON file is provided, overrides are applied to the theme specified by --theme. Defaults to the current working directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Local port to serve theme preview from.\n * @environment SHOPIFY_FLAG_PORT\n */\n '--port '?: string\n\n /**\n * An existing preview identifier to update instead of creating a new preview. Used with --path when pointing to a JSON overrides file.\n * @environment SHOPIFY_FLAG_PREVIEW_ID\n */\n '--preview-id '?: string\n\n /**\n * Store URL. It can be the store prefix (example) or the full myshopify.com URL (example.myshopify.com, https://example.myshopify.com).\n * @environment SHOPIFY_FLAG_STORE\n */\n '-s, --store '?: string\n\n /**\n * The password for storefronts with password protection.\n * @environment SHOPIFY_FLAG_STORE_PASSWORD\n */\n '--store-password '?: string\n\n /**\n * Theme ID or name of the remote theme.\n * @environment SHOPIFY_FLAG_THEME_ID\n */\n '-t, --theme '?: string\n\n /**\n * Synchronize Theme Editor updates in the local theme files.\n * @environment SHOPIFY_FLAG_THEME_EDITOR_SYNC\n */\n '--theme-editor-sync'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" } } } From e7a6bcb581258356e3748c4f939f578a1b16a315 Mon Sep 17 00:00:00 2001 From: Jeffrey Deng Date: Fri, 27 Feb 2026 14:42:14 -0800 Subject: [PATCH 8/8] Change override flag from --path to --override --- .../interfaces/theme-dev.interface.ts | 10 +- docs-shopify.dev/commands/theme-dev.doc.ts | 10 +- .../generated/generated_docs_data.json | 19 +- packages/cli/README.md | 29 +-- packages/cli/oclif.manifest.json | 36 +++- .../theme/src/cli/commands/theme/dev.test.ts | 175 ++++++++++++++++++ packages/theme/src/cli/commands/theme/dev.ts | 30 ++- 7 files changed, 258 insertions(+), 51 deletions(-) create mode 100644 packages/theme/src/cli/commands/theme/dev.test.ts diff --git a/docs-shopify.dev/commands/interfaces/theme-dev.interface.ts b/docs-shopify.dev/commands/interfaces/theme-dev.interface.ts index 1b1ae9a19c2..172124f95ea 100644 --- a/docs-shopify.dev/commands/interfaces/theme-dev.interface.ts +++ b/docs-shopify.dev/commands/interfaces/theme-dev.interface.ts @@ -78,6 +78,12 @@ export interface themedev { */ '--open'?: '' + /** + * Path to a JSON overrides file. When provided, overrides are applied to the theme specified by --theme instead of uploading a local theme. + * @environment SHOPIFY_FLAG_OVERRIDES + */ + '--overrides '?: string + /** * Password generated from the Theme Access app or an Admin API token. * @environment SHOPIFY_CLI_THEME_TOKEN @@ -85,7 +91,7 @@ export interface themedev { '--password '?: string /** - * The path for the dev server. It can be a directory or a JSON overrides file. When a directory is provided, it is used as the theme directory. When a JSON file is provided, overrides are applied to the theme specified by --theme. Defaults to the current working directory. + * The path where you want to run the command. Defaults to the current working directory. * @environment SHOPIFY_FLAG_PATH */ '--path '?: string @@ -97,7 +103,7 @@ export interface themedev { '--port '?: string /** - * An existing preview identifier to update instead of creating a new preview. Used with --path when pointing to a JSON overrides file. + * An existing preview identifier to update instead of creating a new preview. Used with --overrides. * @environment SHOPIFY_FLAG_PREVIEW_ID */ '--preview-id '?: string diff --git a/docs-shopify.dev/commands/theme-dev.doc.ts b/docs-shopify.dev/commands/theme-dev.doc.ts index 2372fd42d55..3ea04b483d1 100644 --- a/docs-shopify.dev/commands/theme-dev.doc.ts +++ b/docs-shopify.dev/commands/theme-dev.doc.ts @@ -6,9 +6,9 @@ const data: ReferenceEntityTemplateSchema = { description: ` Uploads the current theme as the specified theme, or a [development theme](/docs/themes/tools/cli#development-themes), to a store so you can preview it. - Alternatively, a JSON overrides file can be specified using --path to quickly preview changes without uploading a theme. + Alternatively, a JSON overrides file can be specified using --overrides to quickly preview changes without uploading a theme. -This command returns the following information by default, unless --path is used to target a JSON overrides file: +This command returns the following information by default, unless --overrides is used to target a JSON overrides file: - A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the store's data. @@ -18,7 +18,7 @@ This command returns the following information by default, unless --path is used - A [preview link](https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers. -> Note: When using --path to target a JSON overrides file, the command will return the preview link instead of the development theme URL. +> Note: When using --overrides to target a JSON overrides file, the command will return the preview link instead of the development theme URL. If you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the \`--theme-editor-sync\` flag. @@ -26,8 +26,8 @@ If you already have a development theme for your current environment, then this Development themes are deleted when you run \`shopify auth logout\`. If you need a preview link that can be used after you log out, then you should [share](/docs/api/shopify-cli/theme/theme-share) your theme or [push](/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store. -You can run this command only in a directory that matches the [default Shopify theme folder structure](/docs/themes/tools/cli#directory-structure) unless --path is used to target a JSON overrides file.`, - overviewPreviewDescription: `Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time. Alternatively, a JSON overrides file can be provided to quickly preview changes without uploading a theme.`, +You can run this command only in a directory that matches the [default Shopify theme folder structure](/docs/themes/tools/cli#directory-structure) unless --overrides is used to target a JSON overrides file.`, + overviewPreviewDescription: `Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time. Alternatively, a JSON overrides file can be provided via --overrides to quickly preview changes without uploading a theme.`, type: 'command', isVisualComponent: false, defaultExample: { diff --git a/docs-shopify.dev/generated/generated_docs_data.json b/docs-shopify.dev/generated/generated_docs_data.json index 0691a7d3cd4..79f0e3a4bad 100644 --- a/docs-shopify.dev/generated/generated_docs_data.json +++ b/docs-shopify.dev/generated/generated_docs_data.json @@ -5994,8 +5994,8 @@ }, { "name": "theme dev", - "description": "\n Uploads the current theme as the specified theme, or a [development theme](/docs/themes/tools/cli#development-themes), to a store so you can preview it.\n\n Alternatively, a JSON overrides file can be specified using --path to quickly preview changes without uploading a theme.\n\nThis command returns the following information by default, unless --path is used to target a JSON overrides file:\n\n- A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the store's data.\n\n You can specify a different network interface and port using `--host` and `--port`.\n\n- A link to the [editor](/docs/themes/tools/online-editor) for the theme in the Shopify admin.\n\n- A [preview link](https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers.\n\n> Note: When using --path to target a JSON overrides file, the command will return the preview link instead of the development theme URL.\n\nIf you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the `--theme-editor-sync` flag.\n\n> Note: You can't preview checkout customizations using http://127.0.0.1:9292.\n\nDevelopment themes are deleted when you run `shopify auth logout`. If you need a preview link that can be used after you log out, then you should [share](/docs/api/shopify-cli/theme/theme-share) your theme or [push](/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store.\n\nYou can run this command only in a directory that matches the [default Shopify theme folder structure](/docs/themes/tools/cli#directory-structure) unless --path is used to target a JSON overrides file.", - "overviewPreviewDescription": "Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time. Alternatively, a JSON overrides file can be provided to quickly preview changes without uploading a theme.", + "description": "\n Uploads the current theme as the specified theme, or a [development theme](/docs/themes/tools/cli#development-themes), to a store so you can preview it.\n\n Alternatively, a JSON overrides file can be specified using --overrides to quickly preview changes without uploading a theme.\n\nThis command returns the following information by default, unless --overrides is used to target a JSON overrides file:\n\n- A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the store's data.\n\n You can specify a different network interface and port using `--host` and `--port`.\n\n- A link to the [editor](/docs/themes/tools/online-editor) for the theme in the Shopify admin.\n\n- A [preview link](https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers.\n\n> Note: When using --overrides to target a JSON overrides file, the command will return the preview link instead of the development theme URL.\n\nIf you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the `--theme-editor-sync` flag.\n\n> Note: You can't preview checkout customizations using http://127.0.0.1:9292.\n\nDevelopment themes are deleted when you run `shopify auth logout`. If you need a preview link that can be used after you log out, then you should [share](/docs/api/shopify-cli/theme/theme-share) your theme or [push](/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store.\n\nYou can run this command only in a directory that matches the [default Shopify theme folder structure](/docs/themes/tools/cli#directory-structure) unless --overrides is used to target a JSON overrides file.", + "overviewPreviewDescription": "Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time. Alternatively, a JSON overrides file can be provided via --overrides to quickly preview changes without uploading a theme.", "type": "command", "isVisualComponent": false, "defaultExample": { @@ -6084,6 +6084,15 @@ "isOptional": true, "environmentValue": "SHOPIFY_FLAG_OPEN" }, + { + "filePath": "docs-shopify.dev/commands/interfaces/theme-dev.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--overrides ", + "value": "string", + "description": "Path to a JSON overrides file. When provided, overrides are applied to the theme specified by --theme instead of uploading a local theme.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_OVERRIDES" + }, { "filePath": "docs-shopify.dev/commands/interfaces/theme-dev.interface.ts", "syntaxKind": "PropertySignature", @@ -6098,7 +6107,7 @@ "syntaxKind": "PropertySignature", "name": "--path ", "value": "string", - "description": "The path for the dev server. It can be a directory or a JSON overrides file. When a directory is provided, it is used as the theme directory. When a JSON file is provided, overrides are applied to the theme specified by --theme. Defaults to the current working directory.", + "description": "The path where you want to run the command. Defaults to the current working directory.", "isOptional": true, "environmentValue": "SHOPIFY_FLAG_PATH" }, @@ -6116,7 +6125,7 @@ "syntaxKind": "PropertySignature", "name": "--preview-id ", "value": "string", - "description": "An existing preview identifier to update instead of creating a new preview. Used with --path when pointing to a JSON overrides file.", + "description": "An existing preview identifier to update instead of creating a new preview. Used with --overrides.", "isOptional": true, "environmentValue": "SHOPIFY_FLAG_PREVIEW_ID" }, @@ -6211,7 +6220,7 @@ "environmentValue": "SHOPIFY_FLAG_IGNORE" } ], - "value": "export interface themedev {\n /**\n * Allow development on a live theme.\n * @environment SHOPIFY_FLAG_ALLOW_LIVE\n */\n '-a, --allow-live'?: ''\n\n /**\n * The environment to apply to the current command.\n * @environment SHOPIFY_FLAG_ENVIRONMENT\n */\n '-e, --environment '?: string\n\n /**\n * Controls the visibility of the error overlay when an theme asset upload fails:\n- silent Prevents the error overlay from appearing.\n- default Displays the error overlay.\n \n * @environment SHOPIFY_FLAG_ERROR_OVERLAY\n */\n '--error-overlay '?: string\n\n /**\n * Set which network interface the web server listens on. The default value is 127.0.0.1.\n * @environment SHOPIFY_FLAG_HOST\n */\n '--host '?: string\n\n /**\n * Skip hot reloading any files that match the specified pattern.\n * @environment SHOPIFY_FLAG_IGNORE\n */\n '-x, --ignore '?: string\n\n /**\n * The listing preset to use for multi-preset themes. Applies preset files from listings/[preset-name] directory.\n * @environment SHOPIFY_FLAG_LISTING\n */\n '--listing '?: string\n\n /**\n * The live reload mode switches the server behavior when a file is modified:\n- hot-reload Hot reloads local changes to CSS and sections (default)\n- full-page Always refreshes the entire page\n- off Deactivate live reload\n * @environment SHOPIFY_FLAG_LIVE_RELOAD\n */\n '--live-reload '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * Prevents files from being deleted in the remote theme when a file has been deleted locally. This applies to files that are deleted while the command is running, and files that have been deleted locally before the command is run.\n * @environment SHOPIFY_FLAG_NODELETE\n */\n '-n, --nodelete'?: ''\n\n /**\n * The file path or URL. The file path is to a file that you want updated on idle. The URL path is where you want a webhook posted to report on file changes.\n * @environment SHOPIFY_FLAG_NOTIFY\n */\n '--notify '?: string\n\n /**\n * Hot reload only files that match the specified pattern.\n * @environment SHOPIFY_FLAG_ONLY\n */\n '-o, --only '?: string\n\n /**\n * Automatically launch the theme preview in your default web browser.\n * @environment SHOPIFY_FLAG_OPEN\n */\n '--open'?: ''\n\n /**\n * Password generated from the Theme Access app or an Admin API token.\n * @environment SHOPIFY_CLI_THEME_TOKEN\n */\n '--password '?: string\n\n /**\n * The path for the dev server. It can be a directory or a JSON overrides file. When a directory is provided, it is used as the theme directory. When a JSON file is provided, overrides are applied to the theme specified by --theme. Defaults to the current working directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Local port to serve theme preview from.\n * @environment SHOPIFY_FLAG_PORT\n */\n '--port '?: string\n\n /**\n * An existing preview identifier to update instead of creating a new preview. Used with --path when pointing to a JSON overrides file.\n * @environment SHOPIFY_FLAG_PREVIEW_ID\n */\n '--preview-id '?: string\n\n /**\n * Store URL. It can be the store prefix (example) or the full myshopify.com URL (example.myshopify.com, https://example.myshopify.com).\n * @environment SHOPIFY_FLAG_STORE\n */\n '-s, --store '?: string\n\n /**\n * The password for storefronts with password protection.\n * @environment SHOPIFY_FLAG_STORE_PASSWORD\n */\n '--store-password '?: string\n\n /**\n * Theme ID or name of the remote theme.\n * @environment SHOPIFY_FLAG_THEME_ID\n */\n '-t, --theme '?: string\n\n /**\n * Synchronize Theme Editor updates in the local theme files.\n * @environment SHOPIFY_FLAG_THEME_EDITOR_SYNC\n */\n '--theme-editor-sync'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" + "value": "export interface themedev {\n /**\n * Allow development on a live theme.\n * @environment SHOPIFY_FLAG_ALLOW_LIVE\n */\n '-a, --allow-live'?: ''\n\n /**\n * The environment to apply to the current command.\n * @environment SHOPIFY_FLAG_ENVIRONMENT\n */\n '-e, --environment '?: string\n\n /**\n * Controls the visibility of the error overlay when an theme asset upload fails:\n- silent Prevents the error overlay from appearing.\n- default Displays the error overlay.\n \n * @environment SHOPIFY_FLAG_ERROR_OVERLAY\n */\n '--error-overlay '?: string\n\n /**\n * Set which network interface the web server listens on. The default value is 127.0.0.1.\n * @environment SHOPIFY_FLAG_HOST\n */\n '--host '?: string\n\n /**\n * Skip hot reloading any files that match the specified pattern.\n * @environment SHOPIFY_FLAG_IGNORE\n */\n '-x, --ignore '?: string\n\n /**\n * The listing preset to use for multi-preset themes. Applies preset files from listings/[preset-name] directory.\n * @environment SHOPIFY_FLAG_LISTING\n */\n '--listing '?: string\n\n /**\n * The live reload mode switches the server behavior when a file is modified:\n- hot-reload Hot reloads local changes to CSS and sections (default)\n- full-page Always refreshes the entire page\n- off Deactivate live reload\n * @environment SHOPIFY_FLAG_LIVE_RELOAD\n */\n '--live-reload '?: string\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * Prevents files from being deleted in the remote theme when a file has been deleted locally. This applies to files that are deleted while the command is running, and files that have been deleted locally before the command is run.\n * @environment SHOPIFY_FLAG_NODELETE\n */\n '-n, --nodelete'?: ''\n\n /**\n * The file path or URL. The file path is to a file that you want updated on idle. The URL path is where you want a webhook posted to report on file changes.\n * @environment SHOPIFY_FLAG_NOTIFY\n */\n '--notify '?: string\n\n /**\n * Hot reload only files that match the specified pattern.\n * @environment SHOPIFY_FLAG_ONLY\n */\n '-o, --only '?: string\n\n /**\n * Automatically launch the theme preview in your default web browser.\n * @environment SHOPIFY_FLAG_OPEN\n */\n '--open'?: ''\n\n /**\n * Path to a JSON overrides file. When provided, overrides are applied to the theme specified by --theme instead of uploading a local theme.\n * @environment SHOPIFY_FLAG_OVERRIDES\n */\n '--overrides '?: string\n\n /**\n * Password generated from the Theme Access app or an Admin API token.\n * @environment SHOPIFY_CLI_THEME_TOKEN\n */\n '--password '?: string\n\n /**\n * The path where you want to run the command. Defaults to the current working directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Local port to serve theme preview from.\n * @environment SHOPIFY_FLAG_PORT\n */\n '--port '?: string\n\n /**\n * An existing preview identifier to update instead of creating a new preview. Used with --overrides.\n * @environment SHOPIFY_FLAG_PREVIEW_ID\n */\n '--preview-id '?: string\n\n /**\n * Store URL. It can be the store prefix (example) or the full myshopify.com URL (example.myshopify.com, https://example.myshopify.com).\n * @environment SHOPIFY_FLAG_STORE\n */\n '-s, --store '?: string\n\n /**\n * The password for storefronts with password protection.\n * @environment SHOPIFY_FLAG_STORE_PASSWORD\n */\n '--store-password '?: string\n\n /**\n * Theme ID or name of the remote theme.\n * @environment SHOPIFY_FLAG_THEME_ID\n */\n '-t, --theme '?: string\n\n /**\n * Synchronize Theme Editor updates in the local theme files.\n * @environment SHOPIFY_FLAG_THEME_EDITOR_SYNC\n */\n '--theme-editor-sync'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" } } } diff --git a/packages/cli/README.md b/packages/cli/README.md index edf5b3846fc..9a29f620562 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -2110,14 +2110,14 @@ DESCRIPTION ## `shopify theme dev` -Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time. Alternatively, a JSON overrides file can be provided to quickly preview changes without uploading a theme. +Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time. Alternatively, a JSON overrides file can be provided via --overrides to quickly preview changes without uploading a theme. ``` USAGE $ shopify theme dev [-a] [-e ...] [--error-overlay silent|default] [--host ] [-x ...] [--listing ] [--live-reload hot-reload|full-page|off] [--no-color] [-n] [--notify ] [-o ...] - [--open] [--password ] [--path ] [--port ] [--preview-id ] [-s ] - [--store-password ] [-t ] [--theme-editor-sync] [--verbose] + [--open] [--overrides ] [--password ] [--path ] [--port ] [--preview-id ] [-s + ] [--store-password ] [-t ] [--theme-editor-sync] [--verbose] FLAGS -a, --allow-live @@ -2177,20 +2177,22 @@ FLAGS --open [env: SHOPIFY_FLAG_OPEN] Automatically launch the theme preview in your default web browser. + --overrides= + [env: SHOPIFY_FLAG_OVERRIDES] Path to a JSON overrides file. When provided, overrides are applied to the theme + specified by --theme instead of uploading a local theme. + --password= [env: SHOPIFY_CLI_THEME_TOKEN] Password generated from the Theme Access app or an Admin API token. --path= - [env: SHOPIFY_FLAG_PATH] The path for the dev server. It can be a directory or a JSON overrides file. When a - directory is provided, it is used as the theme directory. When a JSON file is provided, overrides are applied to the - theme specified by --theme. Defaults to the current working directory. + [env: SHOPIFY_FLAG_PATH] The path where you want to run the command. Defaults to the current working directory. --port= [env: SHOPIFY_FLAG_PORT] Local port to serve theme preview from. --preview-id= [env: SHOPIFY_FLAG_PREVIEW_ID] An existing preview identifier to update instead of creating a new preview. Used with - --path when pointing to a JSON overrides file. + --overrides. --store-password= [env: SHOPIFY_FLAG_STORE_PASSWORD] The password for storefronts with password protection. @@ -2204,16 +2206,16 @@ FLAGS DESCRIPTION Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time. Alternatively, a JSON overrides file can be - provided to quickly preview changes without uploading a theme. + provided via --overrides to quickly preview changes without uploading a theme. Uploads the current theme as the specified theme, or a "development theme" (https://shopify.dev/docs/themes/tools/cli#development-themes), to a store so you can preview it. - Alternatively, a JSON overrides file can be specified using --path to quickly preview changes without uploading a + Alternatively, a JSON overrides file can be specified using --overrides to quickly preview changes without uploading a theme. - This command returns the following information by default, unless --path is used to target a JSON overrides file: + This command returns the following information by default, unless --overrides is used to target a JSON overrides file: - A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the @@ -2227,8 +2229,8 @@ DESCRIPTION (https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers. - > Note: When using --path to target a JSON overrides file, the command will return the preview link instead of the - development theme URL. + > Note: When using --overrides to target a JSON overrides file, the command will return the preview link instead of + the development theme URL. If you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the `--theme-editor-sync` flag. @@ -2240,7 +2242,8 @@ DESCRIPTION (https://shopify.dev/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store. You can run this command only in a directory that matches the "default Shopify theme folder structure" - (https://shopify.dev/docs/themes/tools/cli#directory-structure) unless --path is used to target a JSON overrides file. + (https://shopify.dev/docs/themes/tools/cli#directory-structure) unless --overrides is used to target a JSON overrides + file. ``` ## `shopify theme duplicate` diff --git a/packages/cli/oclif.manifest.json b/packages/cli/oclif.manifest.json index fba0e93c664..316e5386f5b 100644 --- a/packages/cli/oclif.manifest.json +++ b/packages/cli/oclif.manifest.json @@ -5948,8 +5948,8 @@ "args": { }, "customPluginName": "@shopify/theme", - "description": "\n Uploads the current theme as the specified theme, or a \"development theme\" (https://shopify.dev/docs/themes/tools/cli#development-themes), to a store so you can preview it.\n\n Alternatively, a JSON overrides file can be specified using --path to quickly preview changes without uploading a theme.\n\nThis command returns the following information by default, unless --path is used to target a JSON overrides file:\n\n- A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the store's data.\n\n You can specify a different network interface and port using `--host` and `--port`.\n\n- A link to the \"editor\" (https://shopify.dev/docs/themes/tools/online-editor) for the theme in the Shopify admin.\n\n- A \"preview link\" (https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers.\n\n> Note: When using --path to target a JSON overrides file, the command will return the preview link instead of the development theme URL.\n\nIf you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the `--theme-editor-sync` flag.\n\n> Note: You can't preview checkout customizations using http://127.0.0.1:9292.\n\nDevelopment themes are deleted when you run `shopify auth logout`. If you need a preview link that can be used after you log out, then you should \"share\" (https://shopify.dev/docs/api/shopify-cli/theme/theme-share) your theme or \"push\" (https://shopify.dev/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store.\n\nYou can run this command only in a directory that matches the \"default Shopify theme folder structure\" (https://shopify.dev/docs/themes/tools/cli#directory-structure) unless --path is used to target a JSON overrides file.", - "descriptionWithMarkdown": "\n Uploads the current theme as the specified theme, or a [development theme](https://shopify.dev/docs/themes/tools/cli#development-themes), to a store so you can preview it.\n\n Alternatively, a JSON overrides file can be specified using --path to quickly preview changes without uploading a theme.\n\nThis command returns the following information by default, unless --path is used to target a JSON overrides file:\n\n- A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the store's data.\n\n You can specify a different network interface and port using `--host` and `--port`.\n\n- A link to the [editor](https://shopify.dev/docs/themes/tools/online-editor) for the theme in the Shopify admin.\n\n- A [preview link](https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers.\n\n> Note: When using --path to target a JSON overrides file, the command will return the preview link instead of the development theme URL.\n\nIf you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the `--theme-editor-sync` flag.\n\n> Note: You can't preview checkout customizations using http://127.0.0.1:9292.\n\nDevelopment themes are deleted when you run `shopify auth logout`. If you need a preview link that can be used after you log out, then you should [share](https://shopify.dev/docs/api/shopify-cli/theme/theme-share) your theme or [push](https://shopify.dev/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store.\n\nYou can run this command only in a directory that matches the [default Shopify theme folder structure](https://shopify.dev/docs/themes/tools/cli#directory-structure) unless --path is used to target a JSON overrides file.", + "description": "\n Uploads the current theme as the specified theme, or a \"development theme\" (https://shopify.dev/docs/themes/tools/cli#development-themes), to a store so you can preview it.\n\n Alternatively, a JSON overrides file can be specified using --overrides to quickly preview changes without uploading a theme.\n\nThis command returns the following information by default, unless --overrides is used to target a JSON overrides file:\n\n- A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the store's data.\n\n You can specify a different network interface and port using `--host` and `--port`.\n\n- A link to the \"editor\" (https://shopify.dev/docs/themes/tools/online-editor) for the theme in the Shopify admin.\n\n- A \"preview link\" (https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers.\n\n> Note: When using --overrides to target a JSON overrides file, the command will return the preview link instead of the development theme URL.\n\nIf you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the `--theme-editor-sync` flag.\n\n> Note: You can't preview checkout customizations using http://127.0.0.1:9292.\n\nDevelopment themes are deleted when you run `shopify auth logout`. If you need a preview link that can be used after you log out, then you should \"share\" (https://shopify.dev/docs/api/shopify-cli/theme/theme-share) your theme or \"push\" (https://shopify.dev/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store.\n\nYou can run this command only in a directory that matches the \"default Shopify theme folder structure\" (https://shopify.dev/docs/themes/tools/cli#directory-structure) unless --overrides is used to target a JSON overrides file.", + "descriptionWithMarkdown": "\n Uploads the current theme as the specified theme, or a [development theme](https://shopify.dev/docs/themes/tools/cli#development-themes), to a store so you can preview it.\n\n Alternatively, a JSON overrides file can be specified using --overrides to quickly preview changes without uploading a theme.\n\nThis command returns the following information by default, unless --overrides is used to target a JSON overrides file:\n\n- A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the store's data.\n\n You can specify a different network interface and port using `--host` and `--port`.\n\n- A link to the [editor](https://shopify.dev/docs/themes/tools/online-editor) for the theme in the Shopify admin.\n\n- A [preview link](https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers.\n\n> Note: When using --overrides to target a JSON overrides file, the command will return the preview link instead of the development theme URL.\n\nIf you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the `--theme-editor-sync` flag.\n\n> Note: You can't preview checkout customizations using http://127.0.0.1:9292.\n\nDevelopment themes are deleted when you run `shopify auth logout`. If you need a preview link that can be used after you log out, then you should [share](https://shopify.dev/docs/api/shopify-cli/theme/theme-share) your theme or [push](https://shopify.dev/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store.\n\nYou can run this command only in a directory that matches the [default Shopify theme folder structure](https://shopify.dev/docs/themes/tools/cli#directory-structure) unless --overrides is used to target a JSON overrides file.", "flags": { "allow-live": { "allowNo": false, @@ -6069,6 +6069,14 @@ "name": "open", "type": "boolean" }, + "overrides": { + "description": "Path to a JSON overrides file. When provided, overrides are applied to the theme specified by --theme instead of uploading a local theme.", + "env": "SHOPIFY_FLAG_OVERRIDES", + "hasDynamicHelp": false, + "multiple": false, + "name": "overrides", + "type": "option" + }, "password": { "description": "Password generated from the Theme Access app or an Admin API token.", "env": "SHOPIFY_CLI_THEME_TOKEN", @@ -6078,7 +6086,7 @@ "type": "option" }, "path": { - "description": "The path for the dev server. It can be a directory or a JSON overrides file. When a directory is provided, it is used as the theme directory. When a JSON file is provided, overrides are applied to the theme specified by --theme. Defaults to the current working directory.", + "description": "The path where you want to run the command. Defaults to the current working directory.", "env": "SHOPIFY_FLAG_PATH", "hasDynamicHelp": false, "multiple": false, @@ -6103,7 +6111,7 @@ "type": "option" }, "preview-id": { - "description": "An existing preview identifier to update instead of creating a new preview. Used with --path when pointing to a JSON overrides file.", + "description": "An existing preview identifier to update instead of creating a new preview. Used with --overrides.", "env": "SHOPIFY_FLAG_PREVIEW_ID", "hasDynamicHelp": false, "multiple": false, @@ -6161,7 +6169,7 @@ "pluginName": "@shopify/cli", "pluginType": "core", "strict": true, - "summary": "Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time. Alternatively, a JSON overrides file can be provided to quickly preview changes without uploading a theme." + "summary": "Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time. Alternatively, a JSON overrides file can be provided via --overrides to quickly preview changes without uploading a theme." }, "theme:duplicate": { "aliases": [ @@ -7473,8 +7481,8 @@ "args": { }, "customPluginName": "@shopify/theme", - "description": "\n Uploads the current theme as the specified theme, or a \"development theme\" (https://shopify.dev/docs/themes/tools/cli#development-themes), to a store so you can preview it.\n\n Alternatively, a JSON overrides file can be specified using --path to quickly preview changes without uploading a theme.\n\nThis command returns the following information by default, unless --path is used to target a JSON overrides file:\n\n- A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the store's data.\n\n You can specify a different network interface and port using `--host` and `--port`.\n\n- A link to the \"editor\" (https://shopify.dev/docs/themes/tools/online-editor) for the theme in the Shopify admin.\n\n- A \"preview link\" (https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers.\n\n> Note: When using --path to target a JSON overrides file, the command will return the preview link instead of the development theme URL.\n\nIf you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the `--theme-editor-sync` flag.\n\n> Note: You can't preview checkout customizations using http://127.0.0.1:9292.\n\nDevelopment themes are deleted when you run `shopify auth logout`. If you need a preview link that can be used after you log out, then you should \"share\" (https://shopify.dev/docs/api/shopify-cli/theme/theme-share) your theme or \"push\" (https://shopify.dev/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store.\n\nYou can run this command only in a directory that matches the \"default Shopify theme folder structure\" (https://shopify.dev/docs/themes/tools/cli#directory-structure) unless --path is used to target a JSON overrides file.", - "descriptionWithMarkdown": "\n Uploads the current theme as the specified theme, or a [development theme](https://shopify.dev/docs/themes/tools/cli#development-themes), to a store so you can preview it.\n\n Alternatively, a JSON overrides file can be specified using --path to quickly preview changes without uploading a theme.\n\nThis command returns the following information by default, unless --path is used to target a JSON overrides file:\n\n- A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the store's data.\n\n You can specify a different network interface and port using `--host` and `--port`.\n\n- A link to the [editor](https://shopify.dev/docs/themes/tools/online-editor) for the theme in the Shopify admin.\n\n- A [preview link](https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers.\n\n> Note: When using --path to target a JSON overrides file, the command will return the preview link instead of the development theme URL.\n\nIf you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the `--theme-editor-sync` flag.\n\n> Note: You can't preview checkout customizations using http://127.0.0.1:9292.\n\nDevelopment themes are deleted when you run `shopify auth logout`. If you need a preview link that can be used after you log out, then you should [share](https://shopify.dev/docs/api/shopify-cli/theme/theme-share) your theme or [push](https://shopify.dev/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store.\n\nYou can run this command only in a directory that matches the [default Shopify theme folder structure](https://shopify.dev/docs/themes/tools/cli#directory-structure) unless --path is used to target a JSON overrides file.", + "description": "\n Uploads the current theme as the specified theme, or a \"development theme\" (https://shopify.dev/docs/themes/tools/cli#development-themes), to a store so you can preview it.\n\n Alternatively, a JSON overrides file can be specified using --overrides to quickly preview changes without uploading a theme.\n\nThis command returns the following information by default, unless --overrides is used to target a JSON overrides file:\n\n- A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the store's data.\n\n You can specify a different network interface and port using `--host` and `--port`.\n\n- A link to the \"editor\" (https://shopify.dev/docs/themes/tools/online-editor) for the theme in the Shopify admin.\n\n- A \"preview link\" (https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers.\n\n> Note: When using --overrides to target a JSON overrides file, the command will return the preview link instead of the development theme URL.\n\nIf you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the `--theme-editor-sync` flag.\n\n> Note: You can't preview checkout customizations using http://127.0.0.1:9292.\n\nDevelopment themes are deleted when you run `shopify auth logout`. If you need a preview link that can be used after you log out, then you should \"share\" (https://shopify.dev/docs/api/shopify-cli/theme/theme-share) your theme or \"push\" (https://shopify.dev/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store.\n\nYou can run this command only in a directory that matches the \"default Shopify theme folder structure\" (https://shopify.dev/docs/themes/tools/cli#directory-structure) unless --overrides is used to target a JSON overrides file.", + "descriptionWithMarkdown": "\n Uploads the current theme as the specified theme, or a [development theme](https://shopify.dev/docs/themes/tools/cli#development-themes), to a store so you can preview it.\n\n Alternatively, a JSON overrides file can be specified using --overrides to quickly preview changes without uploading a theme.\n\nThis command returns the following information by default, unless --overrides is used to target a JSON overrides file:\n\n- A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the store's data.\n\n You can specify a different network interface and port using `--host` and `--port`.\n\n- A link to the [editor](https://shopify.dev/docs/themes/tools/online-editor) for the theme in the Shopify admin.\n\n- A [preview link](https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers.\n\n> Note: When using --overrides to target a JSON overrides file, the command will return the preview link instead of the development theme URL.\n\nIf you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the `--theme-editor-sync` flag.\n\n> Note: You can't preview checkout customizations using http://127.0.0.1:9292.\n\nDevelopment themes are deleted when you run `shopify auth logout`. If you need a preview link that can be used after you log out, then you should [share](https://shopify.dev/docs/api/shopify-cli/theme/theme-share) your theme or [push](https://shopify.dev/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store.\n\nYou can run this command only in a directory that matches the [default Shopify theme folder structure](https://shopify.dev/docs/themes/tools/cli#directory-structure) unless --overrides is used to target a JSON overrides file.", "flags": { "allow-live": { "allowNo": false, @@ -7594,6 +7602,14 @@ "name": "open", "type": "boolean" }, + "overrides": { + "description": "Path to a JSON overrides file. When provided, overrides are applied to the theme specified by --theme instead of uploading a local theme.", + "env": "SHOPIFY_FLAG_OVERRIDES", + "hasDynamicHelp": false, + "multiple": false, + "name": "overrides", + "type": "option" + }, "password": { "description": "Password generated from the Theme Access app or an Admin API token.", "env": "SHOPIFY_CLI_THEME_TOKEN", @@ -7603,7 +7619,7 @@ "type": "option" }, "path": { - "description": "The path for the dev server. It can be a directory or a JSON overrides file. When a directory is provided, it is used as the theme directory. When a JSON file is provided, overrides are applied to the theme specified by --theme. Defaults to the current working directory.", + "description": "The path where you want to run the command. Defaults to the current working directory.", "env": "SHOPIFY_FLAG_PATH", "hasDynamicHelp": false, "multiple": false, @@ -7628,7 +7644,7 @@ "type": "option" }, "preview-id": { - "description": "An existing preview identifier to update instead of creating a new preview. Used with --path when pointing to a JSON overrides file.", + "description": "An existing preview identifier to update instead of creating a new preview. Used with --overrides.", "env": "SHOPIFY_FLAG_PREVIEW_ID", "hasDynamicHelp": false, "multiple": false, @@ -7686,7 +7702,7 @@ "pluginAlias": "@shopify/cli", "pluginName": "@shopify/cli", "pluginType": "core", - "summary": "Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time. Alternatively, a JSON overrides file can be provided to quickly preview changes without uploading a theme." + "summary": "Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time. Alternatively, a JSON overrides file can be provided via --overrides to quickly preview changes without uploading a theme." }, "theme:share": { "aliases": [ diff --git a/packages/theme/src/cli/commands/theme/dev.test.ts b/packages/theme/src/cli/commands/theme/dev.test.ts new file mode 100644 index 00000000000..409de61010d --- /dev/null +++ b/packages/theme/src/cli/commands/theme/dev.test.ts @@ -0,0 +1,175 @@ +import Dev from './dev.js' +import {dev} from '../../services/dev.js' +import {devWithOverrideFile} from '../../services/dev-override.js' +import {DevelopmentThemeManager} from '../../utilities/development-theme-manager.js' +import {findOrSelectTheme} from '../../utilities/theme-selector.js' +import {ensureLiveThemeConfirmed} from '../../utilities/theme-ui.js' +import {metafieldsPull} from '../../services/metafields-pull.js' +import {ensureThemeStore} from '../../utilities/theme-store.js' +import {fileExistsSync} from '@shopify/cli-kit/node/fs' +import {DEVELOPMENT_THEME_ROLE} from '@shopify/cli-kit/node/themes/utils' +import {buildTheme} from '@shopify/cli-kit/node/themes/factories' +import {ensureAuthenticatedThemes} from '@shopify/cli-kit/node/session' +import {Config} from '@oclif/core' +import {describe, vi, expect, test, beforeEach} from 'vitest' + +vi.mock('@shopify/cli-kit/node/session') +vi.mock('@shopify/cli-kit/node/fs') +vi.mock('@shopify/cli-kit/node/analytics', () => ({ + recordEvent: vi.fn(), + compileData: vi.fn().mockReturnValue({timings: {}, errors: {}, retries: {}, events: {}}), +})) +vi.mock('@shopify/cli-kit/node/metadata', () => ({ + addPublicMetadata: vi.fn(), + addSensitiveMetadata: vi.fn(), +})) +vi.mock('@shopify/cli-kit/node/environments') +vi.mock('../../services/dev.js') +vi.mock('../../services/dev-override.js') +vi.mock('../../utilities/development-theme-manager.js') +vi.mock('../../utilities/theme-selector.js') +vi.mock('../../utilities/theme-ui.js') +vi.mock('../../services/metafields-pull.js') +vi.mock('../../utilities/theme-store.js') + +const CommandConfig = new Config({root: __dirname}) + +const adminSession = {token: 'test-token', storeFqdn: 'test-store.myshopify.com'} +const devTheme = buildTheme({id: 1, name: 'Dev Theme', role: DEVELOPMENT_THEME_ROLE})! +const namedTheme = buildTheme({id: 2, name: 'My Theme', role: 'unpublished'})! + +async function run(argv: string[]) { + await CommandConfig.load() + const command = new Dev(['--store=test-store.myshopify.com', '--path=/theme', ...argv], CommandConfig) + await command.run() +} + +describe('Dev', () => { + beforeEach(() => { + vi.mocked(ensureThemeStore).mockReturnValue('test-store.myshopify.com') + vi.mocked(ensureAuthenticatedThemes).mockResolvedValue(adminSession) + vi.mocked(fileExistsSync).mockReturnValue(true) + vi.mocked(ensureLiveThemeConfirmed).mockResolvedValue(true) + vi.mocked(metafieldsPull).mockResolvedValue(undefined) + vi.mocked(dev).mockResolvedValue(undefined) + vi.mocked(DevelopmentThemeManager).mockImplementation( + () => + ({ + findOrCreate: vi.fn().mockResolvedValue({...devTheme, createdAtRuntime: false}), + } as any), + ) + }) + + describe('--overrides flag', () => { + test('calls devWithOverrideFile when --overrides and --theme are provided', async () => { + // Given + vi.mocked(findOrSelectTheme).mockResolvedValue(namedTheme) + vi.mocked(devWithOverrideFile).mockResolvedValue(undefined) + + // When + await run(['--overrides=/path/to/overrides.json', '--theme=My Theme']) + + // Then + expect(devWithOverrideFile).toHaveBeenCalledWith( + expect.objectContaining({ + adminSession, + overrideJson: '/path/to/overrides.json', + themeId: namedTheme.id.toString(), + open: false, + }), + ) + expect(dev).not.toHaveBeenCalled() + }) + + test('passes --preview-id to devWithOverrideFile when provided', async () => { + // Given + vi.mocked(findOrSelectTheme).mockResolvedValue(namedTheme) + vi.mocked(devWithOverrideFile).mockResolvedValue(undefined) + + // When + await run(['--overrides=/path/to/overrides.json', '--theme=My Theme', '--preview-id=abc123']) + + // Then + expect(devWithOverrideFile).toHaveBeenCalledWith( + expect.objectContaining({ + previewIdentifier: 'abc123', + }), + ) + }) + + test('throws AbortError when --overrides is used without --theme', async () => { + // When/Then + await expect(run(['--overrides=/path/to/overrides.json'])).rejects.toThrow( + 'The --theme flag is required when using --overrides.', + ) + expect(devWithOverrideFile).not.toHaveBeenCalled() + }) + + test('does not run normal dev flow when --overrides is provided', async () => { + // Given + vi.mocked(findOrSelectTheme).mockResolvedValue(namedTheme) + vi.mocked(devWithOverrideFile).mockResolvedValue(undefined) + + // When + await run(['--overrides=/path/to/overrides.json', '--theme=My Theme']) + + // Then + expect(dev).not.toHaveBeenCalled() + }) + }) + + describe('normal dev flow', () => { + test('creates a development theme when no --theme flag is provided', async () => { + // When + await run([]) + + // Then + expect(DevelopmentThemeManager).toHaveBeenCalledWith(adminSession) + expect(dev).toHaveBeenCalledWith( + expect.objectContaining({ + directory: '/theme', + theme: devTheme, + }), + ) + }) + + test('finds the specified theme when --theme flag is provided', async () => { + // Given + vi.mocked(findOrSelectTheme).mockResolvedValue(namedTheme) + + // When + await run(['--theme=My Theme']) + + // Then + expect(findOrSelectTheme).toHaveBeenCalledWith(adminSession, {filter: {theme: 'My Theme'}}) + expect(dev).toHaveBeenCalledWith( + expect.objectContaining({ + theme: namedTheme, + }), + ) + }) + + test('runs metafieldsPull after dev', async () => { + // When + await run([]) + + // Then + expect(metafieldsPull).toHaveBeenCalledWith( + expect.objectContaining({ + path: '/theme', + }), + ) + }) + + test('returns early when live theme is not confirmed', async () => { + // Given + vi.mocked(ensureLiveThemeConfirmed).mockResolvedValue(false) + + // When + await run([]) + + // Then + expect(dev).not.toHaveBeenCalled() + }) + }) +}) diff --git a/packages/theme/src/cli/commands/theme/dev.ts b/packages/theme/src/cli/commands/theme/dev.ts index fa30f702329..a16edce67b5 100644 --- a/packages/theme/src/cli/commands/theme/dev.ts +++ b/packages/theme/src/cli/commands/theme/dev.ts @@ -12,7 +12,6 @@ import {Theme} from '@shopify/cli-kit/node/themes/types' import {recordEvent} from '@shopify/cli-kit/node/analytics' import {AdminSession} from '@shopify/cli-kit/node/session' import {AbortError} from '@shopify/cli-kit/node/error' -import {isDirectorySync} from '@shopify/cli-kit/node/fs' import {InferredFlags} from '@oclif/core/interfaces' import type {ErrorOverlayMode, LiveReload} from '../../utilities/theme-environment/types.js' @@ -21,14 +20,14 @@ type DevFlags = InferredFlags export default class Dev extends ThemeCommand { static summary = - 'Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time. Alternatively, a JSON overrides file can be provided to quickly preview changes without uploading a theme.' + 'Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time. Alternatively, a JSON overrides file can be provided via --overrides to quickly preview changes without uploading a theme.' static descriptionWithMarkdown = ` Uploads the current theme as the specified theme, or a [development theme](https://shopify.dev/docs/themes/tools/cli#development-themes), to a store so you can preview it. - Alternatively, a JSON overrides file can be specified using --path to quickly preview changes without uploading a theme. + Alternatively, a JSON overrides file can be specified using --overrides to quickly preview changes without uploading a theme. -This command returns the following information by default, unless --path is used to target a JSON overrides file: +This command returns the following information by default, unless --overrides is used to target a JSON overrides file: - A link to your development theme at http://127.0.0.1:9292. This URL can hot reload local changes to CSS and sections, or refresh the entire page when a file changes, enabling you to preview changes in real time using the store's data. @@ -38,7 +37,7 @@ This command returns the following information by default, unless --path is used - A [preview link](https://help.shopify.com/manual/online-store/themes/adding-themes#share-a-theme-preview-with-others) that you can share with other developers. -> Note: When using --path to target a JSON overrides file, the command will return the preview link instead of the development theme URL. +> Note: When using --overrides to target a JSON overrides file, the command will return the preview link instead of the development theme URL. If you already have a development theme for your current environment, then this command replaces the development theme with your local theme. You can override this using the \`--theme-editor-sync\` flag. @@ -46,18 +45,13 @@ If you already have a development theme for your current environment, then this Development themes are deleted when you run \`shopify auth logout\`. If you need a preview link that can be used after you log out, then you should [share](https://shopify.dev/docs/api/shopify-cli/theme/theme-share) your theme or [push](https://shopify.dev/docs/api/shopify-cli/theme/theme-push) to an unpublished theme on your store. -You can run this command only in a directory that matches the [default Shopify theme folder structure](https://shopify.dev/docs/themes/tools/cli#directory-structure) unless --path is used to target a JSON overrides file.` +You can run this command only in a directory that matches the [default Shopify theme folder structure](https://shopify.dev/docs/themes/tools/cli#directory-structure) unless --overrides is used to target a JSON overrides file.` static description = this.descriptionWithoutMarkdown() static flags = { ...globalFlags, ...themeFlags, - path: { - ...themeFlags.path, - description: - 'The path for the dev server. It can be a directory or a JSON overrides file. When a directory is provided, it is used as the theme directory. When a JSON file is provided, overrides are applied to the theme specified by --theme. Defaults to the current working directory.', - } as typeof themeFlags.path, host: Flags.string({ description: 'Set which network interface the web server listens on. The default value is 127.0.0.1.', env: 'SHOPIFY_FLAG_HOST', @@ -147,9 +141,13 @@ You can run this command only in a directory that matches the [default Shopify t env: 'SHOPIFY_FLAG_ALLOW_LIVE', default: false, }), - 'preview-id': Flags.string({ + overrides: Flags.string({ description: - 'An existing preview identifier to update instead of creating a new preview. Used with --path when pointing to a JSON overrides file.', + 'Path to a JSON overrides file. When provided, overrides are applied to the theme specified by --theme instead of uploading a local theme.', + env: 'SHOPIFY_FLAG_OVERRIDES', + }), + 'preview-id': Flags.string({ + description: 'An existing preview identifier to update instead of creating a new preview. Used with --overrides.', env: 'SHOPIFY_FLAG_PREVIEW_ID', }), } @@ -161,9 +159,9 @@ You can run this command only in a directory that matches the [default Shopify t recordEvent('theme-command:dev:single-env:authenticated') - if (!isDirectorySync(devFlags.path)) { + if (devFlags.overrides) { recordEvent('theme-command:dev:override-session') - await createOverrideDevSession(devFlags.path, devFlags, adminSession) + await createOverrideDevSession(devFlags.overrides, devFlags, adminSession) return } @@ -222,7 +220,7 @@ You can run this command only in a directory that matches the [default Shopify t async function createOverrideDevSession(overrideJson: string, devFlags: DevFlags, adminSession: AdminSession) { if (!devFlags.theme) { - throw new AbortError(`The --theme flag is required when using --path with a JSON file.`) + throw new AbortError(`The --theme flag is required when using --overrides.`) } const theme = await findOrSelectTheme(adminSession, {filter: {theme: devFlags.theme}})