From 4e16a7cdebf610bba545d205d0153ea60eb76145 Mon Sep 17 00:00:00 2001
From: James Meng <james.meng@shopify.com>
Date: Wed, 11 Dec 2024 11:23:35 -0800
Subject: [PATCH] --wip-- [skip ci]

---
 packages/cli/README.md                        | 22 +++++++--------
 packages/cli/oclif.manifest.json              |  6 -----
 .../src/cli/commands/theme/generate/block.ts  |  9 +++----
 .../cli/commands/theme/generate/section.ts    |  9 +++----
 .../cli/commands/theme/generate/template.ts   | 16 +++--------
 packages/theme/src/cli/utilities/generator.ts | 27 +++++++++++++++++++
 6 files changed, 50 insertions(+), 39 deletions(-)
 create mode 100644 packages/theme/src/cli/utilities/generator.ts

diff --git a/packages/cli/README.md b/packages/cli/README.md
index caf474f5389..7b071557cf4 100644
--- a/packages/cli/README.md
+++ b/packages/cli/README.md
@@ -1904,12 +1904,12 @@ Creates and adds a new block file to your local theme directory
 
 ```
 USAGE
-  $ shopify theme generate block -n <value> -t text|image|video|product|collection [--no-color] [--path <value>]
+  $ shopify theme generate block [-n <value>] [--no-color] [--path <value>] [-t text|image|video|product|collection]
     [--verbose]
 
 FLAGS
-  -n, --name=<value>   (required) Name of the block
-  -t, --type=<option>  (required) Type of block to generate
+  -n, --name=<value>   Name of the block
+  -t, --type=<option>  Type of block to generate
                        <options: text|image|video|product|collection>
       --no-color       Disable color output.
       --path=<value>   The path to your theme directory.
@@ -1932,12 +1932,12 @@ Creates and adds a new section file to your local theme directory
 
 ```
 USAGE
-  $ shopify theme generate section -n <value> -t featured-collection|image-with-text|rich-text|custom [--no-color] [--path
-    <value>] [--verbose]
+  $ shopify theme generate section [-n <value>] [--no-color] [--path <value>] [-t
+    featured-collection|image-with-text|rich-text|custom] [--verbose]
 
 FLAGS
-  -n, --name=<value>   (required) Name of the section
-  -t, --type=<option>  (required) Type of section to generate
+  -n, --name=<value>   Name of the section
+  -t, --type=<option>  Type of section to generate
                        <options: featured-collection|image-with-text|rich-text|custom>
       --no-color       Disable color output.
       --path=<value>   The path to your theme directory.
@@ -1961,12 +1961,12 @@ Creates and adds a new template file to your local theme directory
 
 ```
 USAGE
-  $ shopify theme generate template -n <value> -t product|collection|page|blog|article|custom [--no-color] [--path <value>]
-    [--verbose]
+  $ shopify theme generate template [-n <value>] [--no-color] [--path <value>] [-t
+    product|collection|page|blog|article|custom] [--verbose]
 
 FLAGS
-  -n, --name=<value>   (required) Name of the template
-  -t, --type=<option>  (required) Type of template to generate
+  -n, --name=<value>   Name of the template
+  -t, --type=<option>  Type of template to generate
                        <options: product|collection|page|blog|article|custom>
       --no-color       Disable color output.
       --path=<value>   The path to your theme directory.
diff --git a/packages/cli/oclif.manifest.json b/packages/cli/oclif.manifest.json
index 0a407bf9526..a04a883b3ed 100644
--- a/packages/cli/oclif.manifest.json
+++ b/packages/cli/oclif.manifest.json
@@ -5333,7 +5333,6 @@
           "hasDynamicHelp": false,
           "multiple": false,
           "name": "name",
-          "required": true,
           "type": "option"
         },
         "no-color": {
@@ -5367,7 +5366,6 @@
             "product",
             "collection"
           ],
-          "required": true,
           "type": "option"
         },
         "verbose": {
@@ -5405,7 +5403,6 @@
           "hasDynamicHelp": false,
           "multiple": false,
           "name": "name",
-          "required": true,
           "type": "option"
         },
         "no-color": {
@@ -5438,7 +5435,6 @@
             "rich-text",
             "custom"
           ],
-          "required": true,
           "type": "option"
         },
         "verbose": {
@@ -5476,7 +5472,6 @@
           "hasDynamicHelp": false,
           "multiple": false,
           "name": "name",
-          "required": true,
           "type": "option"
         },
         "no-color": {
@@ -5511,7 +5506,6 @@
             "article",
             "custom"
           ],
-          "required": true,
           "type": "option"
         },
         "verbose": {
diff --git a/packages/theme/src/cli/commands/theme/generate/block.ts b/packages/theme/src/cli/commands/theme/generate/block.ts
index 7da12a15db3..3c66d8afef9 100644
--- a/packages/theme/src/cli/commands/theme/generate/block.ts
+++ b/packages/theme/src/cli/commands/theme/generate/block.ts
@@ -4,6 +4,8 @@ import {Flags} from '@oclif/core'
 import {globalFlags} from '@shopify/cli-kit/node/cli'
 import {renderSelectPrompt, renderSuccess, renderTextPrompt} from '@shopify/cli-kit/node/ui'
 
+const BLOCK_TYPES = ['text', 'image', 'video', 'product', 'collection']
+
 export default class GenerateBlock extends ThemeCommand {
   static summary = 'Creates and adds a new block file to your local theme directory'
 
@@ -26,7 +28,7 @@ export default class GenerateBlock extends ThemeCommand {
     type: Flags.string({
       char: 't',
       description: 'Type of block to generate',
-      options: ['text', 'image', 'video', 'product', 'collection'],
+      options: [...BLOCK_TYPES],
       env: 'SHOPIFY_FLAG_THEME_GENERATE_BLOCK_TYPE',
     }),
   }
@@ -40,10 +42,7 @@ export default class GenerateBlock extends ThemeCommand {
         message: 'Name of the block',
       }))
 
-    const blockTypes = ['text', 'image', 'video', 'product', 'collection']
-    const choices = blockTypes.map((type) => {
-      return {label: type, value: type}
-    })
+    const choices = BLOCK_TYPES.map((type) => ({label: type, value: type}))
     const type =
       flags.type ??
       (await renderSelectPrompt({
diff --git a/packages/theme/src/cli/commands/theme/generate/section.ts b/packages/theme/src/cli/commands/theme/generate/section.ts
index 64c7a432bf1..2d3b43eb14b 100644
--- a/packages/theme/src/cli/commands/theme/generate/section.ts
+++ b/packages/theme/src/cli/commands/theme/generate/section.ts
@@ -4,6 +4,8 @@ import {Flags} from '@oclif/core'
 import {globalFlags} from '@shopify/cli-kit/node/cli'
 import {renderSelectPrompt, renderSuccess, renderTextPrompt} from '@shopify/cli-kit/node/ui'
 
+const SECTION_TYPES = ['featured-collection', 'image-with-text', 'rich-text', 'custom']
+
 export default class GenerateSection extends ThemeCommand {
   static summary = 'Creates and adds a new section file to your local theme directory'
 
@@ -26,7 +28,7 @@ export default class GenerateSection extends ThemeCommand {
     type: Flags.string({
       char: 't',
       description: 'Type of section to generate',
-      options: ['featured-collection', 'image-with-text', 'rich-text', 'custom'],
+      options: [...SECTION_TYPES],
       env: 'SHOPIFY_FLAG_THEME_GENERATE_SECTION_TYPE',
     }),
   }
@@ -40,10 +42,7 @@ export default class GenerateSection extends ThemeCommand {
         message: 'Name of the section',
       }))
 
-    const sectionTypes = ['featured-collection', 'image-with-text', 'rich-text', 'custom']
-    const choices = sectionTypes.map((type) => {
-      return {label: type, value: type}
-    })
+    const choices = SECTION_TYPES.map((type) => ({label: type, value: type}))
     const type =
       flags.type ??
       (await renderSelectPrompt({
diff --git a/packages/theme/src/cli/commands/theme/generate/template.ts b/packages/theme/src/cli/commands/theme/generate/template.ts
index 87d03f6bad1..85837bda898 100644
--- a/packages/theme/src/cli/commands/theme/generate/template.ts
+++ b/packages/theme/src/cli/commands/theme/generate/template.ts
@@ -1,8 +1,9 @@
+import {TEMPLATE_TYPES, promptForType} from '../../../utilities/generator.js'
 import {themeFlags} from '../../../flags.js'
 import ThemeCommand from '../../../utilities/theme-command.js'
 import {Flags} from '@oclif/core'
 import {globalFlags} from '@shopify/cli-kit/node/cli'
-import {renderSelectPrompt, renderSuccess, renderTextPrompt} from '@shopify/cli-kit/node/ui'
+import {renderSuccess, renderTextPrompt} from '@shopify/cli-kit/node/ui'
 
 export default class GenerateTemplate extends ThemeCommand {
   static summary = 'Creates and adds a new template file to your local theme directory'
@@ -26,7 +27,7 @@ export default class GenerateTemplate extends ThemeCommand {
     type: Flags.string({
       char: 't',
       description: 'Type of template to generate',
-      options: ['product', 'collection', 'page', 'blog', 'article', 'custom'],
+      options: [...TEMPLATE_TYPES],
       env: 'SHOPIFY_FLAG_THEME_GENERATE_TEMPLATE_TYPE',
     }),
   }
@@ -40,16 +41,7 @@ export default class GenerateTemplate extends ThemeCommand {
         message: 'Name of the template',
       }))
 
-    const templateTypes = ['product', 'collection', 'page', 'blog', 'article', 'custom']
-    const choices = templateTypes.map((type) => {
-      return {label: type, value: type}
-    })
-    const type =
-      flags.type ??
-      (await renderSelectPrompt({
-        message: 'Type of template',
-        choices,
-      }))
+    const type = flags.type ?? (await promptForType('Type of template', TEMPLATE_TYPES))
 
     renderSuccess({
       body: [`Placeholder: Generating template with name: ${name}, type: ${type}`],
diff --git a/packages/theme/src/cli/utilities/generator.ts b/packages/theme/src/cli/utilities/generator.ts
new file mode 100644
index 00000000000..9bfaa16ffd3
--- /dev/null
+++ b/packages/theme/src/cli/utilities/generator.ts
@@ -0,0 +1,27 @@
+import {renderSelectPrompt} from '@shopify/cli-kit/node/ui'
+
+export const BLOCK_TYPES = ['text', 'image', 'video', 'product', 'collection'] as const
+export const SECTION_TYPES = ['featured-collection', 'image-with-text', 'rich-text', 'custom'] as const
+export const TEMPLATE_TYPES = ['product', 'collection', 'page', 'blog', 'article', 'custom'] as const
+
+export type BlockType = (typeof BLOCK_TYPES)[number]
+export type SectionType = (typeof SECTION_TYPES)[number]
+export type TemplateType = (typeof TEMPLATE_TYPES)[number]
+
+export interface Choice {
+  label: string
+  value: string
+}
+
+export function generateChoices<T extends string>(types: ReadonlyArray<T>): Choice[] {
+  return types.map((type) => ({label: type, value: type}))
+}
+
+export async function promptForType<T extends string>(message: string, types: ReadonlyArray<T>): Promise<T> {
+  const choices = generateChoices(types)
+  const result = await renderSelectPrompt({
+    message,
+    choices,
+  })
+  return result as T
+}