diff --git a/packages/theme/src/cli/commands/theme/generate/block.ts b/packages/theme/src/cli/commands/theme/generate/block.ts index 5c42fbf70d7..1cc238dd08b 100644 --- a/packages/theme/src/cli/commands/theme/generate/block.ts +++ b/packages/theme/src/cli/commands/theme/generate/block.ts @@ -1,11 +1,11 @@ import {themeFlags} from '../../../flags.js' import ThemeCommand from '../../../utilities/theme-command.js' import {hasRequiredThemeDirectories} from '../../../utilities/theme-fs.js' +import {generateBlock} from '../../../services/generate/blocks.js' +import {BLOCK_TYPES, promptForType} from '../../../utilities/generator.js' import {Flags} from '@oclif/core' import {globalFlags} from '@shopify/cli-kit/node/cli' -import {renderSelectPrompt, renderSuccess, renderTextPrompt, renderWarning} from '@shopify/cli-kit/node/ui' - -const BLOCK_TYPES = ['text', 'image', 'video', 'product', 'collection'] +import {renderTextPrompt, renderWarning} from '@shopify/cli-kit/node/ui' export default class GenerateBlock extends ThemeCommand { static summary = 'Creates and adds a new block file to your local theme directory' @@ -58,16 +58,12 @@ export default class GenerateBlock extends ThemeCommand { message: 'Name of the block', })) - const choices = BLOCK_TYPES.map((type) => ({label: type, value: type})) - const type = - flags.type ?? - (await renderSelectPrompt({ - message: 'Type of block', - choices, - })) + const type = flags.type ?? (await promptForType('Type of block', BLOCK_TYPES)) - renderSuccess({ - body: [`Placeholder: Generating block with name: ${name}, type: ${type}`], + await generateBlock({ + name, + type, + path: flags.path ?? '.', }) } } diff --git a/packages/theme/src/cli/services/generate/blocks.test.ts b/packages/theme/src/cli/services/generate/blocks.test.ts new file mode 100644 index 00000000000..88cc4fee42b --- /dev/null +++ b/packages/theme/src/cli/services/generate/blocks.test.ts @@ -0,0 +1,43 @@ +import {generateBlock} from './blocks.js' +import {describe, expect, test, vi} from 'vitest' +import {fileExists, writeFile} from '@shopify/cli-kit/node/fs' +import {joinPath} from '@shopify/cli-kit/node/path' +import {outputInfo} from '@shopify/cli-kit/node/output' + +vi.mock('@shopify/cli-kit/node/fs') +vi.mock('@shopify/cli-kit/node/path') +vi.mock('@shopify/cli-kit/node/output') + +describe('generateBlock', () => { + const mockOptions = { + name: 'test-block', + type: 'basic', + path: 'theme', + } as const + + test('creates a new block file with correct content', async () => { + vi.mocked(fileExists).mockResolvedValue(false) + vi.mocked(joinPath).mockReturnValue('theme/blocks/test-block.liquid') + + await generateBlock(mockOptions) + + const expectedContent = `{% schema %} +{ + "name": "test-block", + "settings": [] +} +{% endschema %}` + + expect(writeFile).toHaveBeenCalledWith('theme/blocks/test-block.liquid', expectedContent) + expect(outputInfo).toHaveBeenCalledWith('Created block: theme/blocks/test-block.liquid') + }) + + test('throws error if block already exists', async () => { + vi.mocked(fileExists).mockResolvedValue(true) + vi.mocked(joinPath).mockReturnValue('theme/blocks/test-block.liquid') + + await expect(generateBlock(mockOptions)).rejects.toThrow( + 'Block test-block already exists at theme/blocks/test-block.liquid', + ) + }) +}) diff --git a/packages/theme/src/cli/services/generate/blocks.ts b/packages/theme/src/cli/services/generate/blocks.ts new file mode 100644 index 00000000000..9e7e5395255 --- /dev/null +++ b/packages/theme/src/cli/services/generate/blocks.ts @@ -0,0 +1,34 @@ +import {BlockType} from '../../utilities/generator.js' +import {fileExists, writeFile} from '@shopify/cli-kit/node/fs' +import {joinPath} from '@shopify/cli-kit/node/path' +import {outputInfo} from '@shopify/cli-kit/node/output' + +export interface BlockGeneratorOptions { + name: string + type: BlockType + path: string +} + +export async function generateBlock(options: BlockGeneratorOptions) { + const blockPath = joinPath(options.path, 'blocks', `${options.name}.liquid`) + + // Check if block already exists + if (await fileExists(blockPath)) { + throw new Error(`Block ${options.name} already exists at ${blockPath}`) + } + + // Write the file + await writeFile(blockPath, generateBlockContent(options)) + outputInfo(`Created block: ${blockPath}`) +} + +function generateBlockContent(options: BlockGeneratorOptions): string { + const baseSchema = { + name: options.name, + settings: [], + } + + return `{% schema %} +${JSON.stringify(baseSchema, null, 2)} +{% endschema %}` +} diff --git a/packages/theme/src/cli/utilities/generator.ts b/packages/theme/src/cli/utilities/generator.ts index 11b47a324d2..1492caddb0e 100644 --- a/packages/theme/src/cli/utilities/generator.ts +++ b/packages/theme/src/cli/utilities/generator.ts @@ -1,6 +1,6 @@ import {renderSelectPrompt} from '@shopify/cli-kit/node/ui' -export const BLOCK_TYPES = ['text', 'image', 'video', 'product', 'collection'] +export const BLOCK_TYPES = ['basic'] export const SECTION_TYPES = ['featured-collection', 'image-with-text', 'rich-text', 'custom'] export const TEMPLATE_TYPES = ['product', 'collection', 'page', 'blog', 'article', 'custom']