@shopify/cli-hydrogen 5.0.2 → 5.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (249) hide show
  1. package/dist/commands/hydrogen/build.js +21 -6
  2. package/dist/commands/hydrogen/check.js +2 -2
  3. package/dist/commands/hydrogen/codegen-unstable.js +14 -25
  4. package/dist/commands/hydrogen/dev.js +55 -43
  5. package/dist/commands/hydrogen/env/list.js +25 -24
  6. package/dist/commands/hydrogen/env/list.test.js +46 -43
  7. package/dist/commands/hydrogen/env/pull.js +53 -25
  8. package/dist/commands/hydrogen/env/pull.test.js +123 -42
  9. package/dist/commands/hydrogen/generate/route.js +31 -132
  10. package/dist/commands/hydrogen/generate/route.test.js +34 -126
  11. package/dist/commands/hydrogen/init.js +46 -127
  12. package/dist/commands/hydrogen/init.test.js +352 -100
  13. package/dist/commands/hydrogen/link.js +70 -69
  14. package/dist/commands/hydrogen/link.test.js +72 -107
  15. package/dist/commands/hydrogen/list.js +22 -12
  16. package/dist/commands/hydrogen/list.test.js +51 -48
  17. package/dist/commands/hydrogen/login.js +31 -0
  18. package/dist/commands/hydrogen/logout.js +21 -0
  19. package/dist/commands/hydrogen/preview.js +1 -1
  20. package/dist/commands/hydrogen/setup/css.js +79 -0
  21. package/dist/commands/hydrogen/setup/markets.js +53 -0
  22. package/dist/commands/hydrogen/setup.js +133 -0
  23. package/dist/commands/hydrogen/shortcut.js +2 -45
  24. package/dist/commands/hydrogen/shortcut.test.js +10 -37
  25. package/dist/generator-templates/assets/css-modules/package.json +6 -0
  26. package/dist/generator-templates/assets/postcss/package.json +10 -0
  27. package/dist/generator-templates/assets/postcss/postcss.config.js +8 -0
  28. package/dist/generator-templates/assets/tailwind/package.json +13 -0
  29. package/dist/generator-templates/assets/tailwind/postcss.config.js +10 -0
  30. package/dist/generator-templates/assets/tailwind/tailwind.config.js +8 -0
  31. package/dist/generator-templates/assets/tailwind/tailwind.css +3 -0
  32. package/dist/generator-templates/assets/vanilla-extract/package.json +9 -0
  33. package/dist/generator-templates/starter/.eslintignore +5 -0
  34. package/dist/generator-templates/starter/.eslintrc.js +18 -0
  35. package/dist/generator-templates/starter/.graphqlrc.yml +1 -0
  36. package/dist/generator-templates/starter/README.md +40 -0
  37. package/dist/generator-templates/starter/app/components/Aside.tsx +47 -0
  38. package/dist/generator-templates/starter/app/components/Cart.tsx +340 -0
  39. package/dist/generator-templates/starter/app/components/Footer.tsx +99 -0
  40. package/dist/generator-templates/starter/app/components/Header.tsx +178 -0
  41. package/dist/generator-templates/starter/app/components/Layout.tsx +95 -0
  42. package/dist/generator-templates/starter/app/components/Search.tsx +480 -0
  43. package/dist/generator-templates/starter/app/entry.client.tsx +12 -0
  44. package/dist/generator-templates/starter/app/entry.server.tsx +33 -0
  45. package/dist/generator-templates/starter/app/root.tsx +264 -0
  46. package/dist/generator-templates/starter/app/routes/$.tsx +7 -0
  47. package/dist/generator-templates/{routes → starter/app/routes}/[robots.txt].tsx +47 -69
  48. package/dist/generator-templates/starter/app/routes/[sitemap.xml].tsx +174 -0
  49. package/dist/generator-templates/starter/app/routes/_index.tsx +145 -0
  50. package/dist/generator-templates/starter/app/routes/account.$.tsx +9 -0
  51. package/dist/generator-templates/starter/app/routes/account.addresses.tsx +563 -0
  52. package/dist/generator-templates/starter/app/routes/account.orders.$id.tsx +309 -0
  53. package/dist/generator-templates/starter/app/routes/account.orders._index.tsx +196 -0
  54. package/dist/generator-templates/starter/app/routes/account.profile.tsx +289 -0
  55. package/dist/generator-templates/starter/app/routes/account.tsx +203 -0
  56. package/dist/generator-templates/starter/app/routes/account_.activate.$id.$activationToken.tsx +157 -0
  57. package/dist/generator-templates/starter/app/routes/account_.login.tsx +143 -0
  58. package/dist/generator-templates/starter/app/routes/account_.logout.tsx +33 -0
  59. package/dist/generator-templates/starter/app/routes/account_.recover.tsx +124 -0
  60. package/dist/generator-templates/starter/app/routes/account_.register.tsx +207 -0
  61. package/dist/generator-templates/starter/app/routes/account_.reset.$id.$resetToken.tsx +136 -0
  62. package/dist/generator-templates/starter/app/routes/api.predictive-search.tsx +342 -0
  63. package/dist/generator-templates/starter/app/routes/blogs.$blogHandle.$articleHandle.tsx +88 -0
  64. package/dist/generator-templates/starter/app/routes/blogs.$blogHandle._index.tsx +162 -0
  65. package/dist/generator-templates/starter/app/routes/blogs._index.tsx +94 -0
  66. package/dist/generator-templates/starter/app/routes/cart.tsx +104 -0
  67. package/dist/generator-templates/starter/app/routes/collections.$handle.tsx +184 -0
  68. package/dist/generator-templates/starter/app/routes/collections._index.tsx +120 -0
  69. package/dist/generator-templates/starter/app/routes/pages.$handle.tsx +57 -0
  70. package/dist/generator-templates/starter/app/routes/policies.$handle.tsx +94 -0
  71. package/dist/generator-templates/starter/app/routes/policies._index.tsx +63 -0
  72. package/dist/generator-templates/starter/app/routes/products.$handle.tsx +418 -0
  73. package/dist/generator-templates/starter/app/routes/search.tsx +168 -0
  74. package/dist/generator-templates/starter/app/styles/app.css +473 -0
  75. package/dist/generator-templates/starter/app/styles/reset.css +129 -0
  76. package/dist/generator-templates/starter/app/utils.ts +46 -0
  77. package/dist/generator-templates/starter/package.json +43 -0
  78. package/dist/generator-templates/starter/public/favicon.svg +28 -0
  79. package/dist/generator-templates/starter/remix.config.js +26 -0
  80. package/dist/generator-templates/starter/remix.env.d.ts +39 -0
  81. package/dist/generator-templates/starter/server.ts +253 -0
  82. package/dist/generator-templates/starter/storefrontapi.generated.d.ts +1906 -0
  83. package/dist/generator-templates/starter/tsconfig.json +22 -0
  84. package/dist/lib/auth.js +123 -0
  85. package/dist/lib/auth.test.js +157 -0
  86. package/dist/lib/build.js +51 -0
  87. package/dist/lib/check-version.js +3 -3
  88. package/dist/lib/check-version.test.js +24 -0
  89. package/dist/lib/codegen.js +26 -17
  90. package/dist/lib/environment-variables.js +68 -0
  91. package/dist/lib/environment-variables.test.js +147 -0
  92. package/dist/lib/file.js +41 -0
  93. package/dist/lib/file.test.js +69 -0
  94. package/dist/lib/flags.js +39 -2
  95. package/dist/lib/format-code.js +26 -0
  96. package/dist/lib/gid.js +12 -0
  97. package/dist/lib/{graphql.test.js → gid.test.js} +1 -1
  98. package/dist/lib/graphql/admin/client.js +27 -0
  99. package/dist/lib/graphql/admin/client.test.js +51 -0
  100. package/dist/lib/graphql/admin/create-storefront.js +13 -15
  101. package/dist/lib/graphql/admin/create-storefront.test.js +64 -0
  102. package/dist/lib/graphql/admin/fetch-job.js +6 -15
  103. package/dist/lib/graphql/admin/link-storefront.js +7 -11
  104. package/dist/lib/graphql/admin/link-storefront.test.js +38 -0
  105. package/dist/lib/graphql/admin/list-environments.js +2 -2
  106. package/dist/lib/graphql/admin/list-environments.test.js +44 -0
  107. package/dist/lib/graphql/admin/list-storefronts.js +7 -11
  108. package/dist/lib/graphql/admin/list-storefronts.test.js +44 -0
  109. package/dist/lib/graphql/admin/pull-variables.js +3 -3
  110. package/dist/lib/graphql/admin/pull-variables.test.js +37 -0
  111. package/dist/lib/graphql/business-platform/user-account.js +83 -0
  112. package/dist/lib/graphql/business-platform/user-account.test.js +80 -0
  113. package/dist/lib/log.js +216 -9
  114. package/dist/lib/log.test.js +92 -0
  115. package/dist/lib/mini-oxygen.js +19 -9
  116. package/dist/lib/missing-routes.js +0 -2
  117. package/dist/lib/onboarding/common.js +456 -0
  118. package/dist/lib/onboarding/index.js +2 -0
  119. package/dist/lib/onboarding/local.js +229 -0
  120. package/dist/lib/onboarding/remote.js +89 -0
  121. package/dist/lib/remix-config.js +135 -0
  122. package/dist/lib/remix-version-check.js +51 -0
  123. package/dist/lib/remix-version-check.test.js +38 -0
  124. package/dist/lib/remix-version-interop.js +6 -6
  125. package/dist/lib/remix-version-interop.test.js +12 -2
  126. package/dist/lib/render-errors.js +13 -11
  127. package/dist/lib/setups/css/assets.js +89 -0
  128. package/dist/lib/setups/css/css-modules.js +22 -0
  129. package/dist/lib/setups/css/index.js +44 -0
  130. package/dist/lib/setups/css/postcss.js +34 -0
  131. package/dist/lib/setups/css/replacers.js +137 -0
  132. package/dist/lib/setups/css/tailwind.js +54 -0
  133. package/dist/lib/setups/css/vanilla-extract.js +22 -0
  134. package/dist/lib/setups/i18n/domains.test.js +25 -0
  135. package/dist/lib/setups/i18n/index.js +46 -0
  136. package/dist/lib/setups/i18n/replacers.js +227 -0
  137. package/dist/lib/setups/i18n/subdomains.test.js +25 -0
  138. package/dist/lib/setups/i18n/subfolders.test.js +25 -0
  139. package/dist/lib/setups/i18n/templates/domains.js +14 -0
  140. package/dist/lib/setups/i18n/templates/domains.ts +25 -0
  141. package/dist/lib/setups/i18n/templates/subdomains.js +14 -0
  142. package/dist/lib/setups/i18n/templates/subdomains.ts +24 -0
  143. package/dist/lib/setups/i18n/templates/subfolders.js +14 -0
  144. package/dist/lib/setups/i18n/templates/subfolders.ts +28 -0
  145. package/dist/lib/setups/routes/generate.js +244 -0
  146. package/dist/lib/setups/routes/generate.test.js +313 -0
  147. package/dist/lib/shell.js +52 -5
  148. package/dist/lib/shell.test.js +42 -16
  149. package/dist/lib/shopify-config.js +23 -18
  150. package/dist/lib/shopify-config.test.js +63 -73
  151. package/dist/lib/template-downloader.js +9 -7
  152. package/dist/lib/transpile-ts.js +9 -29
  153. package/dist/virtual-routes/routes/index.jsx +40 -19
  154. package/oclif.manifest.json +710 -1
  155. package/package.json +20 -21
  156. package/dist/commands/hydrogen/build.d.ts +0 -23
  157. package/dist/commands/hydrogen/check.d.ts +0 -15
  158. package/dist/commands/hydrogen/codegen-unstable.d.ts +0 -15
  159. package/dist/commands/hydrogen/dev.d.ts +0 -21
  160. package/dist/commands/hydrogen/env/list.d.ts +0 -18
  161. package/dist/commands/hydrogen/env/pull.d.ts +0 -22
  162. package/dist/commands/hydrogen/g.d.ts +0 -10
  163. package/dist/commands/hydrogen/generate/route.d.ts +0 -32
  164. package/dist/commands/hydrogen/generate/route.test.d.ts +0 -1
  165. package/dist/commands/hydrogen/generate/routes.d.ts +0 -16
  166. package/dist/commands/hydrogen/init.d.ts +0 -24
  167. package/dist/commands/hydrogen/init.test.d.ts +0 -1
  168. package/dist/commands/hydrogen/link.d.ts +0 -23
  169. package/dist/commands/hydrogen/link.test.d.ts +0 -1
  170. package/dist/commands/hydrogen/list.d.ts +0 -21
  171. package/dist/commands/hydrogen/list.test.d.ts +0 -1
  172. package/dist/commands/hydrogen/preview.d.ts +0 -17
  173. package/dist/commands/hydrogen/shortcut.d.ts +0 -9
  174. package/dist/commands/hydrogen/shortcut.test.d.ts +0 -1
  175. package/dist/commands/hydrogen/unlink.d.ts +0 -16
  176. package/dist/commands/hydrogen/unlink.test.d.ts +0 -1
  177. package/dist/create-app.d.ts +0 -1
  178. package/dist/generator-templates/routes/[sitemap.xml].tsx +0 -235
  179. package/dist/generator-templates/routes/account/login.tsx +0 -103
  180. package/dist/generator-templates/routes/account/register.tsx +0 -103
  181. package/dist/generator-templates/routes/cart.tsx +0 -81
  182. package/dist/generator-templates/routes/collections/$collectionHandle.tsx +0 -104
  183. package/dist/generator-templates/routes/collections/index.tsx +0 -102
  184. package/dist/generator-templates/routes/graphiql.tsx +0 -10
  185. package/dist/generator-templates/routes/index.tsx +0 -40
  186. package/dist/generator-templates/routes/pages/$pageHandle.tsx +0 -112
  187. package/dist/generator-templates/routes/policies/$policyHandle.tsx +0 -140
  188. package/dist/generator-templates/routes/policies/index.tsx +0 -117
  189. package/dist/generator-templates/routes/products/$productHandle.tsx +0 -92
  190. package/dist/hooks/init.d.ts +0 -5
  191. package/dist/lib/admin-session.d.ts +0 -6
  192. package/dist/lib/admin-session.js +0 -16
  193. package/dist/lib/admin-session.test.d.ts +0 -1
  194. package/dist/lib/admin-session.test.js +0 -27
  195. package/dist/lib/admin-urls.d.ts +0 -8
  196. package/dist/lib/check-lockfile.d.ts +0 -3
  197. package/dist/lib/check-lockfile.test.d.ts +0 -1
  198. package/dist/lib/check-version.d.ts +0 -16
  199. package/dist/lib/check-version.test.d.ts +0 -1
  200. package/dist/lib/codegen.d.ts +0 -26
  201. package/dist/lib/combined-environment-variables.d.ts +0 -8
  202. package/dist/lib/combined-environment-variables.js +0 -57
  203. package/dist/lib/combined-environment-variables.test.d.ts +0 -1
  204. package/dist/lib/combined-environment-variables.test.js +0 -111
  205. package/dist/lib/config.d.ts +0 -20
  206. package/dist/lib/config.js +0 -141
  207. package/dist/lib/flags.d.ts +0 -27
  208. package/dist/lib/flags.test.d.ts +0 -1
  209. package/dist/lib/graphql/admin/create-storefront.d.ts +0 -17
  210. package/dist/lib/graphql/admin/fetch-job.d.ts +0 -23
  211. package/dist/lib/graphql/admin/link-storefront.d.ts +0 -14
  212. package/dist/lib/graphql/admin/list-environments.d.ts +0 -21
  213. package/dist/lib/graphql/admin/list-storefronts.d.ts +0 -25
  214. package/dist/lib/graphql/admin/pull-variables.d.ts +0 -21
  215. package/dist/lib/graphql.d.ts +0 -21
  216. package/dist/lib/graphql.js +0 -18
  217. package/dist/lib/graphql.test.d.ts +0 -1
  218. package/dist/lib/log.d.ts +0 -6
  219. package/dist/lib/mini-oxygen.d.ts +0 -22
  220. package/dist/lib/missing-routes.d.ts +0 -8
  221. package/dist/lib/missing-routes.test.d.ts +0 -1
  222. package/dist/lib/missing-storefronts.d.ts +0 -5
  223. package/dist/lib/missing-storefronts.js +0 -18
  224. package/dist/lib/process.d.ts +0 -6
  225. package/dist/lib/pull-environment-variables.d.ts +0 -20
  226. package/dist/lib/pull-environment-variables.js +0 -57
  227. package/dist/lib/pull-environment-variables.test.d.ts +0 -1
  228. package/dist/lib/pull-environment-variables.test.js +0 -174
  229. package/dist/lib/remix-version-interop.d.ts +0 -11
  230. package/dist/lib/remix-version-interop.test.d.ts +0 -1
  231. package/dist/lib/render-errors.d.ts +0 -16
  232. package/dist/lib/shell.d.ts +0 -11
  233. package/dist/lib/shell.test.d.ts +0 -1
  234. package/dist/lib/shop.d.ts +0 -7
  235. package/dist/lib/shop.js +0 -32
  236. package/dist/lib/shop.test.d.ts +0 -1
  237. package/dist/lib/shop.test.js +0 -78
  238. package/dist/lib/shopify-config.d.ts +0 -35
  239. package/dist/lib/shopify-config.test.d.ts +0 -1
  240. package/dist/lib/string.d.ts +0 -3
  241. package/dist/lib/string.test.d.ts +0 -1
  242. package/dist/lib/template-downloader.d.ts +0 -6
  243. package/dist/lib/transpile-ts.d.ts +0 -16
  244. package/dist/lib/user-errors.d.ts +0 -9
  245. package/dist/lib/user-errors.js +0 -11
  246. package/dist/lib/virtual-routes.d.ts +0 -7
  247. package/dist/lib/virtual-routes.test.d.ts +0 -1
  248. /package/dist/{commands/hydrogen/env/list.test.d.ts → lib/setups/css/common.js} +0 -0
  249. /package/dist/{commands/hydrogen/env/pull.test.d.ts → lib/setups/i18n/mock-i18n-types.js} +0 -0
@@ -1,134 +1,42 @@
1
- import { describe, beforeEach, vi, it, expect } from 'vitest';
2
- import { temporaryDirectoryTask } from 'tempy';
3
- import { runGenerate, GENERATOR_TEMPLATES_DIR } from './route.js';
4
- import { renderConfirmationPrompt } from '@shopify/cli-kit/node/ui';
5
- import { readFile, mkdir, writeFile } from '@shopify/cli-kit/node/fs';
6
- import { joinPath, dirname } from '@shopify/cli-kit/node/path';
7
- import { convertRouteToV2 } from '../../../lib/remix-version-interop.js';
1
+ import { describe, beforeEach, vi, afterEach, it, expect } from 'vitest';
2
+ import { mockAndCaptureOutput } from '@shopify/cli-kit/node/testing/output';
3
+ import { runGenerate } from './route.js';
4
+ import { generateRoutes } from '../../../lib/setups/routes/generate.js';
8
5
 
9
- describe("generate/route", () => {
6
+ describe("runGenerate", () => {
7
+ const outputMock = mockAndCaptureOutput();
10
8
  beforeEach(() => {
11
9
  vi.resetAllMocks();
12
- vi.mock("@shopify/cli-kit/node/output");
13
- vi.mock("@shopify/cli-kit/node/ui");
10
+ vi.mock("../../../lib/setups/routes/generate.js");
14
11
  });
15
- it("generates a route file", async () => {
16
- await temporaryDirectoryTask(async (tmpDir) => {
17
- const route = "pages/$pageHandle";
18
- const { appRoot, templatesRoot } = await createHydrogen(tmpDir, {
19
- files: [],
20
- templates: [[route, `const str = "hello world"`]]
21
- });
22
- await runGenerate(route, route, {
23
- directory: appRoot,
24
- templatesRoot
25
- });
26
- expect(
27
- await readFile(joinPath(appRoot, "app/routes", `${route}.jsx`))
28
- ).toContain(`const str = 'hello world'`);
29
- });
30
- });
31
- it("generates a route file for Remix v2", async () => {
32
- await temporaryDirectoryTask(async (tmpDir) => {
33
- const route = "custom/path/$handle/index";
34
- const { appRoot, templatesRoot } = await createHydrogen(tmpDir, {
35
- files: [],
36
- templates: [[route, `const str = "hello world"`]]
37
- });
38
- await runGenerate(route, convertRouteToV2(route), {
39
- directory: appRoot,
40
- templatesRoot
41
- });
42
- expect(
43
- await readFile(
44
- joinPath(appRoot, "app/routes", `custom.path.$handle._index.jsx`)
45
- )
46
- ).toContain(`const str = 'hello world'`);
47
- });
48
- });
49
- it("produces a typescript file when typescript argument is true", async () => {
50
- await temporaryDirectoryTask(async (tmpDir) => {
51
- const route = "pages/$pageHandle";
52
- const { appRoot, templatesRoot } = await createHydrogen(tmpDir, {
53
- files: [],
54
- templates: [[route, 'const str = "hello typescript"']]
55
- });
56
- await runGenerate(route, route, {
57
- directory: appRoot,
58
- templatesRoot,
59
- typescript: true
60
- });
61
- expect(
62
- await readFile(joinPath(appRoot, "app/routes", `${route}.tsx`))
63
- ).toContain(`const str = 'hello typescript'`);
64
- });
65
- });
66
- it("prompts the user if there the file already exists", async () => {
67
- await temporaryDirectoryTask(async (tmpDir) => {
68
- vi.mocked(renderConfirmationPrompt).mockImplementationOnce(
69
- async () => true
70
- );
71
- const route = "page/$pageHandle";
72
- const { appRoot, templatesRoot } = await createHydrogen(tmpDir, {
73
- files: [[`app/routes/${route}.jsx`, 'const str = "I exist"']],
74
- templates: [[route, 'const str = "hello world"']]
75
- });
76
- await runGenerate(route, route, {
77
- directory: appRoot,
78
- templatesRoot
79
- });
80
- expect(renderConfirmationPrompt).toHaveBeenCalledWith(
81
- expect.objectContaining({
82
- message: expect.stringContaining("already exists")
83
- })
84
- );
85
- });
12
+ afterEach(() => {
13
+ vi.resetAllMocks();
14
+ outputMock.clear();
86
15
  });
87
- it("does not prompt the user if the force property is true", async () => {
88
- await temporaryDirectoryTask(async (tmpDir) => {
89
- vi.mocked(renderConfirmationPrompt).mockImplementationOnce(
90
- async () => true
91
- );
92
- const route = "page/$pageHandle";
93
- const { appRoot, templatesRoot } = await createHydrogen(tmpDir, {
94
- files: [[`app/routes/${route}.jsx`, 'const str = "I exist"']],
95
- templates: [[route, 'const str = "hello world"']]
96
- });
97
- await runGenerate(route, route, {
98
- directory: appRoot,
99
- templatesRoot,
100
- force: true
101
- });
102
- expect(renderConfirmationPrompt).not.toHaveBeenCalled();
16
+ it("calls route generation and renders the result", async () => {
17
+ vi.mocked(generateRoutes).mockResolvedValue({
18
+ isTypescript: true,
19
+ transpilerOptions: {},
20
+ formatOptions: {},
21
+ v2Flags: {},
22
+ routeGroups: {},
23
+ routes: [
24
+ { sourceRoute: "", destinationRoute: "/cart", operation: "created" },
25
+ { sourceRoute: "", destinationRoute: "/about", operation: "skipped" },
26
+ {
27
+ sourceRoute: "",
28
+ destinationRoute: "/collections",
29
+ operation: "created"
30
+ }
31
+ ]
103
32
  });
33
+ const options = {
34
+ routeName: "all",
35
+ directory: "there",
36
+ typescript: true
37
+ };
38
+ await runGenerate(options);
39
+ expect(generateRoutes).toHaveBeenCalledWith(options);
40
+ expect(outputMock.info()).toMatch(/2 of 3 routes/i);
104
41
  });
105
42
  });
106
- async function createHydrogen(directory, {
107
- files,
108
- templates
109
- } = {
110
- files: [],
111
- templates: []
112
- }) {
113
- for (const item of files) {
114
- const [filePath, fileContent] = item;
115
- const fullFilePath = joinPath(directory, "app", filePath);
116
- await mkdir(dirname(fullFilePath));
117
- await writeFile(fullFilePath, fileContent);
118
- }
119
- for (const item of templates) {
120
- const [filePath, fileContent] = item;
121
- const fullFilePath = joinPath(
122
- directory,
123
- GENERATOR_TEMPLATES_DIR,
124
- "routes",
125
- `${filePath}.tsx`
126
- );
127
- await mkdir(dirname(fullFilePath));
128
- await writeFile(fullFilePath, fileContent);
129
- }
130
- return {
131
- appRoot: joinPath(directory, "app"),
132
- templatesRoot: directory
133
- };
134
- }
@@ -1,19 +1,17 @@
1
1
  import Command from '@shopify/cli-kit/node/base-command';
2
- import { readdir } from 'node:fs/promises';
3
2
  import { fileURLToPath } from 'node:url';
4
- import { packageManagerUsedForCreating, installNodeModules } from '@shopify/cli-kit/node/node-package-manager';
5
- import { renderFatalError, renderSelectPrompt, renderTextPrompt, renderConfirmationPrompt, renderInfo, renderTasks, renderSuccess } from '@shopify/cli-kit/node/ui';
3
+ import { packageManagerUsedForCreating } from '@shopify/cli-kit/node/node-package-manager';
6
4
  import { Flags } from '@oclif/core';
7
- import { basename, resolvePath, joinPath } from '@shopify/cli-kit/node/path';
8
- import { rmdir, copyFile, fileExists, isDirectory } from '@shopify/cli-kit/node/fs';
9
- import { outputContent, outputToken } from '@shopify/cli-kit/node/output';
5
+ import { AbortError } from '@shopify/cli-kit/node/error';
6
+ import { AbortController } from '@shopify/cli-kit/node/abort';
10
7
  import { commonFlags, flagsToCamelObject, parseProcessFlags } from '../../lib/flags.js';
11
- import { transpileProject } from '../../lib/transpile-ts.js';
12
- import { getLatestTemplates } from '../../lib/template-downloader.js';
13
8
  import { checkHydrogenVersion } from '../../lib/check-version.js';
9
+ import { SETUP_CSS_STRATEGIES } from './../../lib/setups/css/index.js';
10
+ import { I18N_CHOICES } from '../../lib/setups/i18n/index.js';
14
11
  import { supressNodeExperimentalWarnings } from '../../lib/process.js';
12
+ import { setupRemoteTemplate, setupLocalStarterTemplate } from '../../lib/onboarding/index.js';
13
+ import { LANGUAGES } from '../../lib/onboarding/common.js';
15
14
 
16
- const STARTER_TEMPLATES = ["hello-world", "demo-store"];
17
15
  const FLAG_MAP = { f: "force" };
18
16
  class Init extends Command {
19
17
  static description = "Creates a new Hydrogen storefront.";
@@ -25,148 +23,69 @@ class Init extends Command {
25
23
  }),
26
24
  language: Flags.string({
27
25
  description: "Sets the template language to use. One of `js` or `ts`.",
28
- choices: ["js", "ts"],
26
+ choices: Object.keys(LANGUAGES),
29
27
  env: "SHOPIFY_HYDROGEN_FLAG_LANGUAGE"
30
28
  }),
31
29
  template: Flags.string({
32
- description: "Sets the template to use. One of `demo-store` or `hello-world`.",
33
- choices: STARTER_TEMPLATES,
30
+ description: "Sets the template to use. Pass `demo-store` for a fully-featured store template or `hello-world` for a barebones project.",
34
31
  env: "SHOPIFY_HYDROGEN_FLAG_TEMPLATE"
35
32
  }),
36
- "install-deps": Flags.boolean({
37
- description: "Auto install dependencies using the active package manager",
38
- env: "SHOPIFY_HYDROGEN_FLAG_INSTALL_DEPS",
33
+ "install-deps": commonFlags.installDeps,
34
+ "mock-shop": Flags.boolean({
35
+ description: "Use mock.shop as the data source for the storefront.",
36
+ default: false,
37
+ env: "SHOPIFY_HYDROGEN_FLAG_MOCK_DATA"
38
+ }),
39
+ styling: commonFlags.styling,
40
+ markets: commonFlags.markets,
41
+ shortcut: commonFlags.shortcut,
42
+ routes: Flags.boolean({
43
+ description: "Generate routes for all pages.",
44
+ env: "SHOPIFY_HYDROGEN_FLAG_ROUTES",
45
+ hidden: true
46
+ }),
47
+ git: Flags.boolean({
48
+ description: "Init Git and create initial commits.",
49
+ env: "SHOPIFY_HYDROGEN_FLAG_GIT",
50
+ default: true,
39
51
  allowNo: true
40
52
  })
41
53
  };
42
54
  async run() {
43
55
  const { flags } = await this.parse(Init);
56
+ if (flags.markets && !I18N_CHOICES.includes(flags.markets)) {
57
+ throw new AbortError(
58
+ `Invalid URL structure strategy: ${flags.markets}. Must be one of ${I18N_CHOICES.join(", ")}`
59
+ );
60
+ }
61
+ if (flags.styling && !SETUP_CSS_STRATEGIES.includes(flags.styling)) {
62
+ throw new AbortError(
63
+ `Invalid styling strategy: ${flags.styling}. Must be one of ${SETUP_CSS_STRATEGIES.join(", ")}`
64
+ );
65
+ }
44
66
  await runInit(flagsToCamelObject(flags));
45
67
  }
46
68
  }
47
69
  async function runInit(options = parseProcessFlags(process.argv, FLAG_MAP)) {
48
70
  supressNodeExperimentalWarnings();
71
+ options.git ??= true;
49
72
  const showUpgrade = await checkHydrogenVersion(
50
73
  fileURLToPath(new URL("../../../package.json", import.meta.url)),
51
74
  "cli"
52
75
  );
53
76
  if (showUpgrade) {
54
- const packageManager2 = await packageManagerUsedForCreating();
77
+ const packageManager = await packageManagerUsedForCreating();
55
78
  showUpgrade(
56
- packageManager2 === "unknown" ? "" : `Please use the latest version with \`${packageManager2} create @shopify/hydrogen@latest\``
79
+ packageManager === "unknown" ? "" : `Please use the latest version with \`${packageManager} create @shopify/hydrogen@latest\``
57
80
  );
58
81
  }
59
- let templatesDownloaded = false;
60
- const templatesPromise = getLatestTemplates().then((result) => {
61
- templatesDownloaded = true;
62
- return result;
63
- }).catch((error) => {
64
- renderFatalError(error);
65
- process.exit(1);
66
- });
67
- const appTemplate = options.template ?? await renderSelectPrompt({
68
- message: "Choose a template",
69
- defaultValue: "hello-world",
70
- choices: STARTER_TEMPLATES.map((value) => ({
71
- label: value.replace(/-/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()),
72
- value
73
- }))
74
- });
75
- const language = options.language ?? await renderSelectPrompt({
76
- message: "Choose a language",
77
- choices: [
78
- { label: "JavaScript", value: "js" },
79
- { label: "TypeScript", value: "ts" }
80
- ],
81
- defaultValue: "js"
82
- });
83
- const location = options.path ?? await renderTextPrompt({
84
- message: "Where would you like to create your app?",
85
- defaultValue: "hydrogen-storefront"
86
- });
87
- const projectName = basename(location);
88
- const projectDir = resolvePath(process.cwd(), location);
89
- if (await projectExists(projectDir)) {
90
- if (!options.force) {
91
- const deleteFiles = await renderConfirmationPrompt({
92
- message: `${location} is not an empty directory. Do you want to delete the existing files and continue?`,
93
- defaultValue: false
94
- });
95
- if (!deleteFiles) {
96
- renderInfo({
97
- headline: `Destination path ${location} already exists and is not an empty directory. You may use \`--force\` or \`-f\` to override it.`
98
- });
99
- return;
100
- }
101
- }
102
- await rmdir(projectDir, { force: true });
103
- }
104
- if (!templatesDownloaded) {
105
- await renderTasks([
106
- {
107
- title: "Downloading templates",
108
- task: async () => {
109
- await templatesPromise;
110
- }
111
- }
112
- ]);
82
+ const controller = new AbortController();
83
+ try {
84
+ return options.template ? await setupRemoteTemplate(options, controller) : await setupLocalStarterTemplate(options, controller);
85
+ } catch (error) {
86
+ controller.abort();
87
+ throw error;
113
88
  }
114
- const { templatesDir } = await templatesPromise;
115
- await copyFile(joinPath(templatesDir, appTemplate), projectDir);
116
- if (language === "js") {
117
- try {
118
- await transpileProject(projectDir);
119
- } catch (error) {
120
- await rmdir(projectDir, { force: true });
121
- throw error;
122
- }
123
- }
124
- let depsInstalled = false;
125
- let packageManager = await packageManagerUsedForCreating();
126
- if (packageManager !== "unknown") {
127
- const installDeps = options.installDeps ?? await renderConfirmationPrompt({
128
- message: `Install dependencies with ${packageManager}?`
129
- });
130
- if (installDeps) {
131
- await installNodeModules({
132
- directory: projectDir,
133
- packageManager,
134
- args: [],
135
- stdout: process.stdout,
136
- stderr: process.stderr
137
- });
138
- depsInstalled = true;
139
- }
140
- } else {
141
- packageManager = "npm";
142
- }
143
- renderSuccess({
144
- headline: `${projectName} is ready to build.`,
145
- nextSteps: [
146
- outputContent`Run ${outputToken.genericShellCommand(`cd ${location}`)}`.value,
147
- depsInstalled ? void 0 : outputContent`Run ${outputToken.genericShellCommand(
148
- `${packageManager} install`
149
- )} to install the dependencies`.value,
150
- outputContent`Run ${outputToken.packagejsonScript(
151
- packageManager,
152
- "dev"
153
- )} to start your local development server and start building`.value
154
- ].filter((step) => Boolean(step)),
155
- reference: [
156
- "Getting started with Hydrogen: https://shopify.dev/docs/custom-storefronts/hydrogen/building/begin-development",
157
- "Hydrogen project structure: https://shopify.dev/docs/custom-storefronts/hydrogen/project-structure",
158
- "Setting up Hydrogen environment variables: https://shopify.dev/docs/custom-storefronts/hydrogen/environment-variables"
159
- ]
160
- });
161
- if (appTemplate === "demo-store") {
162
- renderInfo({
163
- headline: `Your project will display inventory from the Hydrogen Demo Store.`,
164
- body: `To connect this project to your Shopify store\u2019s inventory, update \`${projectName}/.env\` with your store ID and Storefront API key.`
165
- });
166
- }
167
- }
168
- async function projectExists(projectDir) {
169
- return await fileExists(projectDir) && await isDirectory(projectDir) && (await readdir(projectDir)).length > 0;
170
89
  }
171
90
 
172
91
  export { Init as default, runInit };