@shopify/cli-hydrogen 5.0.2 → 5.1.0

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 (243) hide show
  1. package/dist/commands/hydrogen/build.js +16 -2
  2. package/dist/commands/hydrogen/codegen-unstable.js +13 -24
  3. package/dist/commands/hydrogen/dev.js +45 -39
  4. package/dist/commands/hydrogen/env/list.js +25 -24
  5. package/dist/commands/hydrogen/env/list.test.js +46 -43
  6. package/dist/commands/hydrogen/env/pull.js +53 -25
  7. package/dist/commands/hydrogen/env/pull.test.js +123 -42
  8. package/dist/commands/hydrogen/generate/route.js +31 -132
  9. package/dist/commands/hydrogen/generate/route.test.js +34 -126
  10. package/dist/commands/hydrogen/init.js +46 -127
  11. package/dist/commands/hydrogen/init.test.js +352 -100
  12. package/dist/commands/hydrogen/link.js +70 -69
  13. package/dist/commands/hydrogen/link.test.js +72 -107
  14. package/dist/commands/hydrogen/list.js +22 -12
  15. package/dist/commands/hydrogen/list.test.js +51 -48
  16. package/dist/commands/hydrogen/login.js +31 -0
  17. package/dist/commands/hydrogen/logout.js +21 -0
  18. package/dist/commands/hydrogen/setup/css.js +79 -0
  19. package/dist/commands/hydrogen/setup/markets.js +53 -0
  20. package/dist/commands/hydrogen/setup.js +133 -0
  21. package/dist/commands/hydrogen/shortcut.js +2 -45
  22. package/dist/commands/hydrogen/shortcut.test.js +10 -37
  23. package/dist/generator-templates/assets/css-modules/package.json +6 -0
  24. package/dist/generator-templates/assets/postcss/package.json +10 -0
  25. package/dist/generator-templates/assets/postcss/postcss.config.js +8 -0
  26. package/dist/generator-templates/assets/tailwind/package.json +13 -0
  27. package/dist/generator-templates/assets/tailwind/postcss.config.js +10 -0
  28. package/dist/generator-templates/assets/tailwind/tailwind.config.js +8 -0
  29. package/dist/generator-templates/assets/tailwind/tailwind.css +3 -0
  30. package/dist/generator-templates/assets/vanilla-extract/package.json +9 -0
  31. package/dist/generator-templates/starter/.eslintignore +5 -0
  32. package/dist/generator-templates/starter/.eslintrc.js +18 -0
  33. package/dist/generator-templates/starter/.graphqlrc.yml +1 -0
  34. package/dist/generator-templates/starter/README.md +40 -0
  35. package/dist/generator-templates/starter/app/components/Aside.tsx +47 -0
  36. package/dist/generator-templates/starter/app/components/Cart.tsx +340 -0
  37. package/dist/generator-templates/starter/app/components/Footer.tsx +99 -0
  38. package/dist/generator-templates/starter/app/components/Header.tsx +178 -0
  39. package/dist/generator-templates/starter/app/components/Layout.tsx +95 -0
  40. package/dist/generator-templates/starter/app/components/Search.tsx +480 -0
  41. package/dist/generator-templates/starter/app/entry.client.tsx +12 -0
  42. package/dist/generator-templates/starter/app/entry.server.tsx +33 -0
  43. package/dist/generator-templates/starter/app/root.tsx +270 -0
  44. package/dist/generator-templates/starter/app/routes/$.tsx +7 -0
  45. package/dist/generator-templates/{routes → starter/app/routes}/[robots.txt].tsx +47 -69
  46. package/dist/generator-templates/starter/app/routes/[sitemap.xml].tsx +174 -0
  47. package/dist/generator-templates/starter/app/routes/_index.tsx +145 -0
  48. package/dist/generator-templates/starter/app/routes/account.$.tsx +9 -0
  49. package/dist/generator-templates/starter/app/routes/account.addresses.tsx +563 -0
  50. package/dist/generator-templates/starter/app/routes/account.orders.$id.tsx +309 -0
  51. package/dist/generator-templates/starter/app/routes/account.orders._index.tsx +196 -0
  52. package/dist/generator-templates/starter/app/routes/account.profile.tsx +289 -0
  53. package/dist/generator-templates/starter/app/routes/account.tsx +203 -0
  54. package/dist/generator-templates/starter/app/routes/account_.activate.$id.$activationToken.tsx +157 -0
  55. package/dist/generator-templates/starter/app/routes/account_.login.tsx +143 -0
  56. package/dist/generator-templates/starter/app/routes/account_.logout.tsx +33 -0
  57. package/dist/generator-templates/starter/app/routes/account_.recover.tsx +124 -0
  58. package/dist/generator-templates/starter/app/routes/account_.register.tsx +207 -0
  59. package/dist/generator-templates/starter/app/routes/account_.reset.$id.$resetToken.tsx +136 -0
  60. package/dist/generator-templates/starter/app/routes/api.predictive-search.tsx +342 -0
  61. package/dist/generator-templates/starter/app/routes/blogs.$blogHandle.$articleHandle.tsx +88 -0
  62. package/dist/generator-templates/starter/app/routes/blogs.$blogHandle._index.tsx +162 -0
  63. package/dist/generator-templates/starter/app/routes/blogs._index.tsx +94 -0
  64. package/dist/generator-templates/starter/app/routes/cart.tsx +104 -0
  65. package/dist/generator-templates/starter/app/routes/collections.$handle.tsx +184 -0
  66. package/dist/generator-templates/starter/app/routes/collections._index.tsx +120 -0
  67. package/dist/generator-templates/starter/app/routes/pages.$handle.tsx +57 -0
  68. package/dist/generator-templates/starter/app/routes/policies.$handle.tsx +94 -0
  69. package/dist/generator-templates/starter/app/routes/policies._index.tsx +63 -0
  70. package/dist/generator-templates/starter/app/routes/products.$handle.tsx +418 -0
  71. package/dist/generator-templates/starter/app/routes/search.tsx +168 -0
  72. package/dist/generator-templates/starter/app/styles/app.css +473 -0
  73. package/dist/generator-templates/starter/app/styles/reset.css +129 -0
  74. package/dist/generator-templates/starter/app/utils.ts +46 -0
  75. package/dist/generator-templates/starter/package.json +43 -0
  76. package/dist/generator-templates/starter/public/favicon.svg +28 -0
  77. package/dist/generator-templates/starter/remix.config.js +26 -0
  78. package/dist/generator-templates/starter/remix.env.d.ts +39 -0
  79. package/dist/generator-templates/starter/server.ts +253 -0
  80. package/dist/generator-templates/starter/storefrontapi.generated.d.ts +1906 -0
  81. package/dist/generator-templates/starter/tsconfig.json +22 -0
  82. package/dist/lib/auth.js +123 -0
  83. package/dist/lib/auth.test.js +157 -0
  84. package/dist/lib/build.js +51 -0
  85. package/dist/lib/check-version.js +3 -3
  86. package/dist/lib/check-version.test.js +24 -0
  87. package/dist/lib/codegen.js +26 -17
  88. package/dist/lib/environment-variables.js +68 -0
  89. package/dist/lib/environment-variables.test.js +147 -0
  90. package/dist/lib/file.js +41 -0
  91. package/dist/lib/file.test.js +69 -0
  92. package/dist/lib/flags.js +39 -2
  93. package/dist/lib/format-code.js +26 -0
  94. package/dist/lib/gid.js +12 -0
  95. package/dist/lib/{graphql.test.js → gid.test.js} +1 -1
  96. package/dist/lib/graphql/admin/client.js +27 -0
  97. package/dist/lib/graphql/admin/client.test.js +51 -0
  98. package/dist/lib/graphql/admin/create-storefront.js +13 -15
  99. package/dist/lib/graphql/admin/create-storefront.test.js +64 -0
  100. package/dist/lib/graphql/admin/fetch-job.js +6 -15
  101. package/dist/lib/graphql/admin/link-storefront.js +7 -11
  102. package/dist/lib/graphql/admin/link-storefront.test.js +38 -0
  103. package/dist/lib/graphql/admin/list-environments.js +2 -2
  104. package/dist/lib/graphql/admin/list-environments.test.js +44 -0
  105. package/dist/lib/graphql/admin/list-storefronts.js +7 -11
  106. package/dist/lib/graphql/admin/list-storefronts.test.js +44 -0
  107. package/dist/lib/graphql/admin/pull-variables.js +3 -3
  108. package/dist/lib/graphql/admin/pull-variables.test.js +37 -0
  109. package/dist/lib/graphql/business-platform/user-account.js +83 -0
  110. package/dist/lib/graphql/business-platform/user-account.test.js +80 -0
  111. package/dist/lib/log.js +185 -9
  112. package/dist/lib/log.test.js +92 -0
  113. package/dist/lib/mini-oxygen.js +19 -9
  114. package/dist/lib/missing-routes.js +0 -2
  115. package/dist/lib/onboarding/common.js +456 -0
  116. package/dist/lib/onboarding/index.js +2 -0
  117. package/dist/lib/onboarding/local.js +229 -0
  118. package/dist/lib/onboarding/remote.js +89 -0
  119. package/dist/lib/remix-version-interop.js +5 -5
  120. package/dist/lib/remix-version-interop.test.js +11 -1
  121. package/dist/lib/render-errors.js +13 -11
  122. package/dist/lib/setups/css/assets.js +89 -0
  123. package/dist/lib/setups/css/css-modules.js +22 -0
  124. package/dist/lib/setups/css/index.js +44 -0
  125. package/dist/lib/setups/css/postcss.js +34 -0
  126. package/dist/lib/setups/css/replacers.js +137 -0
  127. package/dist/lib/setups/css/tailwind.js +54 -0
  128. package/dist/lib/setups/css/vanilla-extract.js +22 -0
  129. package/dist/lib/setups/i18n/domains.test.js +25 -0
  130. package/dist/lib/setups/i18n/index.js +46 -0
  131. package/dist/lib/setups/i18n/replacers.js +227 -0
  132. package/dist/lib/setups/i18n/subdomains.test.js +25 -0
  133. package/dist/lib/setups/i18n/subfolders.test.js +25 -0
  134. package/dist/lib/setups/i18n/templates/domains.js +14 -0
  135. package/dist/lib/setups/i18n/templates/domains.ts +25 -0
  136. package/dist/lib/setups/i18n/templates/subdomains.js +14 -0
  137. package/dist/lib/setups/i18n/templates/subdomains.ts +24 -0
  138. package/dist/lib/setups/i18n/templates/subfolders.js +14 -0
  139. package/dist/lib/setups/i18n/templates/subfolders.ts +28 -0
  140. package/dist/lib/setups/routes/generate.js +244 -0
  141. package/dist/lib/setups/routes/generate.test.js +313 -0
  142. package/dist/lib/shell.js +52 -5
  143. package/dist/lib/shell.test.js +42 -16
  144. package/dist/lib/shopify-config.js +23 -18
  145. package/dist/lib/shopify-config.test.js +63 -73
  146. package/dist/lib/template-downloader.js +9 -7
  147. package/dist/lib/transpile-ts.js +9 -29
  148. package/dist/virtual-routes/routes/index.jsx +40 -19
  149. package/oclif.manifest.json +710 -1
  150. package/package.json +16 -16
  151. package/dist/commands/hydrogen/build.d.ts +0 -23
  152. package/dist/commands/hydrogen/check.d.ts +0 -15
  153. package/dist/commands/hydrogen/codegen-unstable.d.ts +0 -15
  154. package/dist/commands/hydrogen/dev.d.ts +0 -21
  155. package/dist/commands/hydrogen/env/list.d.ts +0 -18
  156. package/dist/commands/hydrogen/env/pull.d.ts +0 -22
  157. package/dist/commands/hydrogen/g.d.ts +0 -10
  158. package/dist/commands/hydrogen/generate/route.d.ts +0 -32
  159. package/dist/commands/hydrogen/generate/route.test.d.ts +0 -1
  160. package/dist/commands/hydrogen/generate/routes.d.ts +0 -16
  161. package/dist/commands/hydrogen/init.d.ts +0 -24
  162. package/dist/commands/hydrogen/init.test.d.ts +0 -1
  163. package/dist/commands/hydrogen/link.d.ts +0 -23
  164. package/dist/commands/hydrogen/link.test.d.ts +0 -1
  165. package/dist/commands/hydrogen/list.d.ts +0 -21
  166. package/dist/commands/hydrogen/list.test.d.ts +0 -1
  167. package/dist/commands/hydrogen/preview.d.ts +0 -17
  168. package/dist/commands/hydrogen/shortcut.d.ts +0 -9
  169. package/dist/commands/hydrogen/shortcut.test.d.ts +0 -1
  170. package/dist/commands/hydrogen/unlink.d.ts +0 -16
  171. package/dist/commands/hydrogen/unlink.test.d.ts +0 -1
  172. package/dist/create-app.d.ts +0 -1
  173. package/dist/generator-templates/routes/[sitemap.xml].tsx +0 -235
  174. package/dist/generator-templates/routes/account/login.tsx +0 -103
  175. package/dist/generator-templates/routes/account/register.tsx +0 -103
  176. package/dist/generator-templates/routes/cart.tsx +0 -81
  177. package/dist/generator-templates/routes/collections/$collectionHandle.tsx +0 -104
  178. package/dist/generator-templates/routes/collections/index.tsx +0 -102
  179. package/dist/generator-templates/routes/graphiql.tsx +0 -10
  180. package/dist/generator-templates/routes/index.tsx +0 -40
  181. package/dist/generator-templates/routes/pages/$pageHandle.tsx +0 -112
  182. package/dist/generator-templates/routes/policies/$policyHandle.tsx +0 -140
  183. package/dist/generator-templates/routes/policies/index.tsx +0 -117
  184. package/dist/generator-templates/routes/products/$productHandle.tsx +0 -92
  185. package/dist/hooks/init.d.ts +0 -5
  186. package/dist/lib/admin-session.d.ts +0 -6
  187. package/dist/lib/admin-session.js +0 -16
  188. package/dist/lib/admin-session.test.d.ts +0 -1
  189. package/dist/lib/admin-session.test.js +0 -27
  190. package/dist/lib/admin-urls.d.ts +0 -8
  191. package/dist/lib/check-lockfile.d.ts +0 -3
  192. package/dist/lib/check-lockfile.test.d.ts +0 -1
  193. package/dist/lib/check-version.d.ts +0 -16
  194. package/dist/lib/check-version.test.d.ts +0 -1
  195. package/dist/lib/codegen.d.ts +0 -26
  196. package/dist/lib/combined-environment-variables.d.ts +0 -8
  197. package/dist/lib/combined-environment-variables.js +0 -57
  198. package/dist/lib/combined-environment-variables.test.d.ts +0 -1
  199. package/dist/lib/combined-environment-variables.test.js +0 -111
  200. package/dist/lib/config.d.ts +0 -20
  201. package/dist/lib/flags.d.ts +0 -27
  202. package/dist/lib/flags.test.d.ts +0 -1
  203. package/dist/lib/graphql/admin/create-storefront.d.ts +0 -17
  204. package/dist/lib/graphql/admin/fetch-job.d.ts +0 -23
  205. package/dist/lib/graphql/admin/link-storefront.d.ts +0 -14
  206. package/dist/lib/graphql/admin/list-environments.d.ts +0 -21
  207. package/dist/lib/graphql/admin/list-storefronts.d.ts +0 -25
  208. package/dist/lib/graphql/admin/pull-variables.d.ts +0 -21
  209. package/dist/lib/graphql.d.ts +0 -21
  210. package/dist/lib/graphql.js +0 -18
  211. package/dist/lib/graphql.test.d.ts +0 -1
  212. package/dist/lib/log.d.ts +0 -6
  213. package/dist/lib/mini-oxygen.d.ts +0 -22
  214. package/dist/lib/missing-routes.d.ts +0 -8
  215. package/dist/lib/missing-routes.test.d.ts +0 -1
  216. package/dist/lib/missing-storefronts.d.ts +0 -5
  217. package/dist/lib/missing-storefronts.js +0 -18
  218. package/dist/lib/process.d.ts +0 -6
  219. package/dist/lib/pull-environment-variables.d.ts +0 -20
  220. package/dist/lib/pull-environment-variables.js +0 -57
  221. package/dist/lib/pull-environment-variables.test.d.ts +0 -1
  222. package/dist/lib/pull-environment-variables.test.js +0 -174
  223. package/dist/lib/remix-version-interop.d.ts +0 -11
  224. package/dist/lib/remix-version-interop.test.d.ts +0 -1
  225. package/dist/lib/render-errors.d.ts +0 -16
  226. package/dist/lib/shell.d.ts +0 -11
  227. package/dist/lib/shell.test.d.ts +0 -1
  228. package/dist/lib/shop.d.ts +0 -7
  229. package/dist/lib/shop.js +0 -32
  230. package/dist/lib/shop.test.d.ts +0 -1
  231. package/dist/lib/shop.test.js +0 -78
  232. package/dist/lib/shopify-config.d.ts +0 -35
  233. package/dist/lib/shopify-config.test.d.ts +0 -1
  234. package/dist/lib/string.d.ts +0 -3
  235. package/dist/lib/string.test.d.ts +0 -1
  236. package/dist/lib/template-downloader.d.ts +0 -6
  237. package/dist/lib/transpile-ts.d.ts +0 -16
  238. package/dist/lib/user-errors.d.ts +0 -9
  239. package/dist/lib/user-errors.js +0 -11
  240. package/dist/lib/virtual-routes.d.ts +0 -7
  241. package/dist/lib/virtual-routes.test.d.ts +0 -1
  242. /package/dist/{commands/hydrogen/env/list.test.d.ts → lib/setups/css/common.js} +0 -0
  243. /package/dist/{commands/hydrogen/env/pull.test.d.ts → lib/setups/i18n/mock-i18n-types.js} +0 -0
@@ -10,12 +10,12 @@ async function startMiniOxygen({
10
10
  watch = false,
11
11
  buildPathWorkerFile,
12
12
  buildPathClient,
13
- environmentVariables = {}
13
+ env
14
14
  }) {
15
- const { default: miniOxygen } = await import('@shopify/mini-oxygen');
16
- const miniOxygenPreview = miniOxygen.default ?? miniOxygen;
15
+ const { default: miniOxygenImport } = await import('@shopify/mini-oxygen');
16
+ const miniOxygenPreview = miniOxygenImport.default ?? miniOxygenImport;
17
17
  const dotenvPath = resolvePath(root, ".env");
18
- const { port: actualPort } = await miniOxygenPreview({
18
+ const miniOxygen = await miniOxygenPreview({
19
19
  workerFile: buildPathWorkerFile,
20
20
  assetsDir: buildPathClient,
21
21
  publicPath: "",
@@ -24,10 +24,10 @@ async function startMiniOxygen({
24
24
  autoReload: watch,
25
25
  modules: true,
26
26
  env: {
27
- ...environmentVariables,
27
+ ...env,
28
28
  ...process.env
29
29
  },
30
- envPath: !Object.keys(environmentVariables).length && await fileExists(dotenvPath) ? dotenvPath : void 0,
30
+ envPath: !env && await fileExists(dotenvPath) ? dotenvPath : void 0,
31
31
  log: () => {
32
32
  },
33
33
  buildWatchPaths: watch ? [resolvePath(root, buildPathWorkerFile)] : void 0,
@@ -36,18 +36,28 @@ async function startMiniOxygen({
36
36
  response
37
37
  )
38
38
  });
39
- const listeningAt = `http://localhost:${actualPort}`;
39
+ const listeningAt = `http://localhost:${miniOxygen.port}`;
40
40
  return {
41
41
  listeningAt,
42
- port: actualPort,
42
+ port: miniOxygen.port,
43
+ reload(nextOptions) {
44
+ return miniOxygen.reload({
45
+ env: {
46
+ ...nextOptions?.env ?? env,
47
+ ...process.env
48
+ }
49
+ });
50
+ },
43
51
  showBanner(options) {
52
+ console.log("");
44
53
  renderSuccess({
45
54
  headline: `${options?.headlinePrefix ?? ""}MiniOxygen ${options?.mode ?? "development"} server running.`,
46
55
  body: [
47
- `View Hydrogen app: ${listeningAt}`,
56
+ `View ${options?.appName ?? "Hydrogen"} app: ${listeningAt}`,
48
57
  ...options?.extraLines ?? []
49
58
  ]
50
59
  });
60
+ console.log("");
51
61
  }
52
62
  };
53
63
  }
@@ -3,7 +3,6 @@ import { renderWarning, renderSuccess } from '@shopify/cli-kit/node/ui';
3
3
  const REQUIRED_ROUTES = [
4
4
  "",
5
5
  "cart",
6
- "products",
7
6
  "products/:productHandle",
8
7
  "collections",
9
8
  "collections/:collectionHandle",
@@ -12,7 +11,6 @@ const REQUIRED_ROUTES = [
12
11
  "pages/:pageHandle",
13
12
  "policies/:policyHandle",
14
13
  "search",
15
- "discount/:discountCode",
16
14
  "account",
17
15
  "account/login",
18
16
  "account/register",
@@ -0,0 +1,456 @@
1
+ import { readdir } from 'node:fs/promises';
2
+ import { packageManagerUsedForCreating, installNodeModules } from '@shopify/cli-kit/node/node-package-manager';
3
+ import { renderConfirmationPrompt, renderInfo, renderTextPrompt, renderSelectPrompt, renderFatalError, renderWarning, renderSuccess } from '@shopify/cli-kit/node/ui';
4
+ import { hyphenate, capitalize } from '@shopify/cli-kit/common/string';
5
+ import { resolvePath, basename, joinPath } from '@shopify/cli-kit/node/path';
6
+ import { initializeGitRepository, addAllToGitFromDirectory, createGitCommit } from '@shopify/cli-kit/node/git';
7
+ import { AbortError } from '@shopify/cli-kit/node/error';
8
+ import { rmdir, writeFile, fileExists, isDirectory } from '@shopify/cli-kit/node/fs';
9
+ import { outputDebug, outputContent, outputToken, formatPackageManagerCommand } from '@shopify/cli-kit/node/output';
10
+ import colors from '@shopify/cli-kit/node/colors';
11
+ import { login, renderLoginSuccess } from '../auth.js';
12
+ import { renderI18nPrompt, setupI18nStrategy, I18N_STRATEGY_NAME_MAP } from '../setups/i18n/index.js';
13
+ import { titleize } from '../string.js';
14
+ import { ALIAS_NAME, createPlatformShortcut, getCliCommand } from '../shell.js';
15
+ import { transpileProject } from '../transpile-ts.js';
16
+ import { renderCssPrompt, setupCssStrategy, CSS_STRATEGY_NAME_MAP } from '../setups/css/index.js';
17
+ import { renderRoutePrompt, generateRoutes, generateProjectFile } from '../setups/routes/generate.js';
18
+ import { execAsync } from '../process.js';
19
+
20
+ const LANGUAGES = {
21
+ js: "JavaScript",
22
+ ts: "TypeScript"
23
+ };
24
+ async function handleI18n(controller, cliCommand, flagI18n) {
25
+ let selection = flagI18n ?? await renderI18nPrompt({
26
+ abortSignal: controller.signal,
27
+ extraChoices: {
28
+ none: "Set up later " + colors.dim(`(run \`${cliCommand} setup markets\`)`)
29
+ }
30
+ });
31
+ const i18nStrategy = selection === "none" ? void 0 : selection;
32
+ return {
33
+ i18nStrategy,
34
+ setupI18n: async (options) => {
35
+ if (i18nStrategy) {
36
+ await setupI18nStrategy(i18nStrategy, options);
37
+ }
38
+ }
39
+ };
40
+ }
41
+ async function handleRouteGeneration(controller, flagRoutes) {
42
+ const routesToScaffold = flagRoutes ? "all" : await renderRoutePrompt({
43
+ abortSignal: controller.signal
44
+ });
45
+ const needsRouteGeneration = routesToScaffold === "all" || routesToScaffold.length > 0;
46
+ return {
47
+ needsRouteGeneration,
48
+ setupRoutes: async (directory, language, i18nStrategy) => {
49
+ if (needsRouteGeneration) {
50
+ const result = await generateRoutes({
51
+ routeName: routesToScaffold,
52
+ directory,
53
+ force: true,
54
+ typescript: language === "ts",
55
+ localePrefix: i18nStrategy === "subfolders" ? "locale" : false,
56
+ signal: controller.signal
57
+ });
58
+ return result.routeGroups;
59
+ }
60
+ }
61
+ };
62
+ }
63
+ function generateProjectEntries(options) {
64
+ return Promise.all(
65
+ ["root", "entry.server", "entry.client"].map(
66
+ (filename) => generateProjectFile(filename, {
67
+ v2Flags: {
68
+ isV2ErrorBoundary: true,
69
+ isV2Meta: true,
70
+ isV2RouteConvention: true
71
+ },
72
+ ...options
73
+ })
74
+ )
75
+ );
76
+ }
77
+ async function handleCliShortcut(controller, cliCommand, flagShortcut) {
78
+ const shouldCreateShortcut = flagShortcut ?? await renderConfirmationPrompt({
79
+ confirmationMessage: "Yes",
80
+ cancellationMessage: "No",
81
+ message: [
82
+ "Create a global",
83
+ { command: ALIAS_NAME },
84
+ "alias to run commands instead of",
85
+ { command: cliCommand },
86
+ "?"
87
+ ],
88
+ abortSignal: controller.signal
89
+ });
90
+ if (!shouldCreateShortcut)
91
+ return {};
92
+ return {
93
+ createShortcut: async () => {
94
+ try {
95
+ const shortcuts = await createPlatformShortcut();
96
+ return shortcuts.length > 0;
97
+ } catch (error) {
98
+ outputDebug(
99
+ "Failed to create shortcut." + (error?.stack ?? error?.message ?? error)
100
+ );
101
+ return false;
102
+ }
103
+ },
104
+ showShortcutBanner: () => renderInfo({
105
+ body: `You'll need to restart your terminal session to make \`${ALIAS_NAME}\` alias available.`
106
+ })
107
+ };
108
+ }
109
+ async function handleStorefrontLink(controller) {
110
+ const { session, config } = await login();
111
+ renderLoginSuccess(config);
112
+ const title = await renderTextPrompt({
113
+ message: "New storefront name",
114
+ defaultValue: titleize(config.shopName),
115
+ abortSignal: controller.signal
116
+ });
117
+ return { ...config, title, session };
118
+ }
119
+ async function handleProjectLocation({
120
+ storefrontInfo,
121
+ controller,
122
+ force,
123
+ path: flagPath
124
+ }) {
125
+ const storefrontDirectory = storefrontInfo && hyphenate(storefrontInfo.title);
126
+ let location = flagPath ?? storefrontDirectory ?? await renderTextPrompt({
127
+ message: "Where would you like to create your storefront?",
128
+ defaultValue: "hydrogen-storefront",
129
+ abortSignal: controller.signal
130
+ });
131
+ let directory = resolvePath(process.cwd(), location);
132
+ if (await projectExists(directory)) {
133
+ if (!force && storefrontDirectory) {
134
+ location = await renderTextPrompt({
135
+ message: `There's already a folder called \`${storefrontDirectory}\`. Where do you want to create the app?`,
136
+ defaultValue: storefrontDirectory,
137
+ abortSignal: controller.signal
138
+ });
139
+ directory = resolvePath(process.cwd(), location);
140
+ if (!await projectExists(directory)) {
141
+ force = true;
142
+ }
143
+ }
144
+ if (!force) {
145
+ const deleteFiles = await renderConfirmationPrompt({
146
+ message: `The directory ${colors.cyan(
147
+ location
148
+ )} is not empty. Do you want to delete the existing files and continue?`,
149
+ defaultValue: false,
150
+ abortSignal: controller.signal
151
+ });
152
+ if (!deleteFiles) {
153
+ renderInfo({
154
+ body: `Destination path ${colors.cyan(
155
+ location
156
+ )} already exists and is not an empty directory. You may use \`--force\` or \`-f\` to override it.`
157
+ });
158
+ return;
159
+ }
160
+ }
161
+ await rmdir(directory);
162
+ }
163
+ return {
164
+ name: basename(location),
165
+ location,
166
+ directory,
167
+ storefrontTitle: storefrontInfo?.title
168
+ };
169
+ }
170
+ async function handleLanguage(projectDir, controller, flagLanguage) {
171
+ const language = flagLanguage ?? await renderSelectPrompt({
172
+ message: "Select a language",
173
+ choices: [
174
+ { label: "JavaScript", value: "js" },
175
+ { label: "TypeScript", value: "ts" }
176
+ ],
177
+ defaultValue: "js",
178
+ abortSignal: controller.signal
179
+ });
180
+ return {
181
+ language,
182
+ async transpileProject() {
183
+ if (language === "js") {
184
+ await transpileProject(projectDir);
185
+ }
186
+ }
187
+ };
188
+ }
189
+ async function handleCssStrategy(projectDir, controller, flagStyling) {
190
+ const selection = flagStyling ? flagStyling : await renderCssPrompt({
191
+ abortSignal: controller.signal,
192
+ extraChoices: { none: "Skip and set up later" }
193
+ });
194
+ const cssStrategy = selection === "none" ? void 0 : selection;
195
+ return {
196
+ cssStrategy,
197
+ async setupCss() {
198
+ if (cssStrategy) {
199
+ const result = await setupCssStrategy(
200
+ cssStrategy,
201
+ {
202
+ rootDirectory: projectDir,
203
+ appDirectory: joinPath(projectDir, "app")
204
+ },
205
+ true
206
+ );
207
+ if (result) {
208
+ await result.workPromise;
209
+ }
210
+ }
211
+ }
212
+ };
213
+ }
214
+ async function handleDependencies(projectDir, controller, shouldInstallDeps) {
215
+ const detectedPackageManager = await packageManagerUsedForCreating();
216
+ let actualPackageManager = "npm";
217
+ if (shouldInstallDeps !== false) {
218
+ if (detectedPackageManager === "unknown") {
219
+ const result = await renderSelectPrompt({
220
+ message: `Select package manager to install dependencies`,
221
+ choices: [
222
+ { label: "NPM", value: "npm" },
223
+ { label: "PNPM", value: "pnpm" },
224
+ { label: "Yarn v1", value: "yarn" },
225
+ { label: "Skip and install later", value: "no" }
226
+ ],
227
+ defaultValue: "npm",
228
+ abortSignal: controller.signal
229
+ });
230
+ if (result === "no") {
231
+ shouldInstallDeps = false;
232
+ } else {
233
+ actualPackageManager = result;
234
+ shouldInstallDeps = true;
235
+ }
236
+ } else if (shouldInstallDeps === void 0) {
237
+ actualPackageManager = detectedPackageManager;
238
+ shouldInstallDeps = await renderConfirmationPrompt({
239
+ message: `Install dependencies with ${detectedPackageManager}?`,
240
+ confirmationMessage: "Yes",
241
+ cancellationMessage: "No",
242
+ abortSignal: controller.signal
243
+ });
244
+ }
245
+ }
246
+ return {
247
+ packageManager: actualPackageManager,
248
+ shouldInstallDeps,
249
+ installDeps: shouldInstallDeps ? async () => {
250
+ await installNodeModules({
251
+ directory: projectDir,
252
+ packageManager: actualPackageManager,
253
+ args: [],
254
+ signal: controller.signal
255
+ });
256
+ } : () => {
257
+ }
258
+ };
259
+ }
260
+ const gitIgnoreContent = `
261
+ node_modules
262
+ /.cache
263
+ /build
264
+ /dist
265
+ /public/build
266
+ /.mf
267
+ .env
268
+ .shopify
269
+ `.slice(1);
270
+ async function createInitialCommit(directory) {
271
+ try {
272
+ await initializeGitRepository(directory);
273
+ await writeFile(joinPath(directory, ".gitignore"), gitIgnoreContent);
274
+ if (process.env.NODE_ENV === "test" && process.env.CI) {
275
+ await execAsync(`git config --global user.name "hydrogen"`);
276
+ await execAsync(`git config --global user.email "hydrogen@shopify.com"`);
277
+ }
278
+ return commitAll(directory, "Scaffold Storefront");
279
+ } catch (error) {
280
+ outputDebug(
281
+ "Failed to initialize Git.\n" + error?.stack
282
+ );
283
+ }
284
+ }
285
+ async function commitAll(directory, message) {
286
+ try {
287
+ await addAllToGitFromDirectory(directory);
288
+ await createGitCommit(message, { directory });
289
+ } catch (error) {
290
+ outputDebug(
291
+ "Failed to commit code.\n" + error?.stack
292
+ );
293
+ }
294
+ }
295
+ async function renderProjectReady(project, {
296
+ language,
297
+ packageManager,
298
+ depsInstalled,
299
+ cssStrategy,
300
+ hasCreatedShortcut,
301
+ routes,
302
+ i18n,
303
+ depsError,
304
+ i18nError,
305
+ routesError
306
+ }) {
307
+ const hasErrors = Boolean(depsError || i18nError || routesError);
308
+ const bodyLines = [];
309
+ if (project.storefrontTitle) {
310
+ bodyLines.push(["Shopify", project.storefrontTitle]);
311
+ }
312
+ if (language) {
313
+ bodyLines.push(["Language", LANGUAGES[language]]);
314
+ }
315
+ if (cssStrategy) {
316
+ bodyLines.push(["Styling", CSS_STRATEGY_NAME_MAP[cssStrategy]]);
317
+ }
318
+ if (!i18nError && i18n) {
319
+ bodyLines.push(["Markets", I18N_STRATEGY_NAME_MAP[i18n].split(" (")[0]]);
320
+ }
321
+ let routeSummary = "";
322
+ if (!routesError && routes && Object.keys(routes).length) {
323
+ bodyLines.push(["Routes", ""]);
324
+ for (let [routeName, routePaths] of Object.entries(routes)) {
325
+ routePaths = Array.isArray(routePaths) ? routePaths : [routePaths];
326
+ let urls = [
327
+ ...new Set(routePaths.map((item) => "/" + normalizeRoutePath(item)))
328
+ ].sort();
329
+ if (urls.length > 2) {
330
+ const prefixesSet = new Set(urls.map((url) => url.split("/")[1] ?? ""));
331
+ urls = [...prefixesSet].map((item) => "/" + item + "/*");
332
+ }
333
+ routeSummary += `
334
+ \u2022 ${capitalize(routeName)} ${colors.dim(
335
+ "(" + urls.join(" & ") + ")"
336
+ )}`;
337
+ }
338
+ }
339
+ const padMin = 1 + bodyLines.reduce((max, [label]) => Math.max(max, label.length), 0);
340
+ const cliCommand = hasCreatedShortcut ? ALIAS_NAME : await getCliCommand(project.directory, packageManager);
341
+ const render = hasErrors ? renderWarning : renderSuccess;
342
+ render({
343
+ headline: `Storefront setup complete` + (hasErrors ? " with errors (see warnings below)." : "!"),
344
+ body: bodyLines.map(
345
+ ([label, value]) => ` ${(label + ":").padEnd(padMin, " ")} ${colors.dim(value)}`
346
+ ).join("\n") + routeSummary,
347
+ customSections: [
348
+ hasErrors && {
349
+ title: "Warnings\n",
350
+ body: [
351
+ {
352
+ list: {
353
+ items: [
354
+ depsError && [
355
+ "Failed to install dependencies:",
356
+ { subdued: depsError.message }
357
+ ],
358
+ i18nError && [
359
+ "Failed to scaffold Markets:",
360
+ { subdued: i18nError.message }
361
+ ],
362
+ routesError && [
363
+ "Failed to scaffold routes:",
364
+ { subdued: routesError.message }
365
+ ]
366
+ ].filter((step) => Boolean(step))
367
+ }
368
+ }
369
+ ]
370
+ },
371
+ {
372
+ title: "Help\n",
373
+ body: {
374
+ list: {
375
+ items: [
376
+ {
377
+ link: {
378
+ label: "Guides",
379
+ url: "https://shopify.dev/docs/custom-storefronts/hydrogen/building"
380
+ }
381
+ },
382
+ {
383
+ link: {
384
+ label: "API reference",
385
+ url: "https://shopify.dev/docs/api/storefront"
386
+ }
387
+ },
388
+ {
389
+ link: {
390
+ label: "Demo Store code",
391
+ url: "https://github.com/Shopify/hydrogen/tree/HEAD/templates/demo-store"
392
+ }
393
+ },
394
+ [
395
+ "Run",
396
+ {
397
+ command: `${cliCommand} --help`
398
+ }
399
+ ]
400
+ ]
401
+ }
402
+ }
403
+ },
404
+ {
405
+ title: "Next steps\n",
406
+ body: [
407
+ {
408
+ list: {
409
+ items: [
410
+ [
411
+ "Run",
412
+ {
413
+ command: outputContent`${outputToken.genericShellCommand(
414
+ [
415
+ project.directory === process.cwd() ? void 0 : `cd ${project.location.replace(/^\.\//, "")}`,
416
+ depsInstalled ? void 0 : `${packageManager} install`,
417
+ formatPackageManagerCommand(packageManager, "dev")
418
+ ].filter(Boolean).join(" && ")
419
+ )}`.value
420
+ }
421
+ ]
422
+ ].filter((step) => Boolean(step))
423
+ }
424
+ }
425
+ ]
426
+ }
427
+ ].filter((step) => Boolean(step))
428
+ });
429
+ }
430
+ function createAbortHandler(controller, project) {
431
+ return async function abort(error) {
432
+ controller.abort();
433
+ if (typeof project !== "undefined") {
434
+ await rmdir(project.directory, { force: true }).catch(() => {
435
+ });
436
+ }
437
+ renderFatalError(
438
+ new AbortError(
439
+ "Failed to initialize project: " + error?.message,
440
+ error?.tryMessage ?? error?.stack
441
+ )
442
+ );
443
+ if (process.env.NODE_ENV === "test") {
444
+ console.error(error);
445
+ }
446
+ process.exit(1);
447
+ };
448
+ }
449
+ async function projectExists(projectDir) {
450
+ return await fileExists(projectDir) && await isDirectory(projectDir) && (await readdir(projectDir)).length > 0;
451
+ }
452
+ function normalizeRoutePath(routePath) {
453
+ return routePath.replace(/(^|\.)_index$/, "").replace(/((^|\.)[^\.]+)_\./g, "$1.").replace(/\.(?!\w+\])/g, "/").replace(/\$$/g, ":catchAll").replace(/\$/g, ":").replace(/[\[\]]/g, "").replace(/:\w*Handle/i, ":handle");
454
+ }
455
+
456
+ export { LANGUAGES, commitAll, createAbortHandler, createInitialCommit, generateProjectEntries, handleCliShortcut, handleCssStrategy, handleDependencies, handleI18n, handleLanguage, handleProjectLocation, handleRouteGeneration, handleStorefrontLink, renderProjectReady };
@@ -0,0 +1,2 @@
1
+ export { setupLocalStarterTemplate } from './local.js';
2
+ export { setupRemoteTemplate } from './remote.js';