@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
@@ -5,11 +5,12 @@ import { rmdir, fileSize, glob, removeFile, copyFile } from '@shopify/cli-kit/no
5
5
  import { resolvePath, relativePath, joinPath } from '@shopify/cli-kit/node/path';
6
6
  import { getPackageManager } from '@shopify/cli-kit/node/node-package-manager';
7
7
  import colors from '@shopify/cli-kit/node/colors';
8
- import { getProjectPaths, getRemixConfig } from '../../lib/config.js';
8
+ import { getProjectPaths, getRemixConfig, assertOxygenChecks } from '../../lib/remix-config.js';
9
9
  import { commonFlags, deprecated, flagsToCamelObject } from '../../lib/flags.js';
10
10
  import { checkLockfileStatus } from '../../lib/check-lockfile.js';
11
11
  import { findMissingRoutes } from '../../lib/missing-routes.js';
12
- import { warnOnce } from '../../lib/log.js';
12
+ import { muteRemixLogs, createRemixLogger } from '../../lib/log.js';
13
+ import { codegen } from '../../lib/codegen.js';
13
14
 
14
15
  const LOG_WORKER_BUILT = "\u{1F4E6} Worker built";
15
16
  class Build extends Command {
@@ -25,6 +26,12 @@ class Build extends Command {
25
26
  description: "Disable warning about missing standard routes.",
26
27
  env: "SHOPIFY_HYDROGEN_FLAG_DISABLE_ROUTE_WARNING"
27
28
  }),
29
+ ["codegen-unstable"]: Flags.boolean({
30
+ description: "Generate types for the Storefront API queries found in your project.",
31
+ required: false,
32
+ default: false
33
+ }),
34
+ ["codegen-config-path"]: commonFlags.codegenConfigPath,
28
35
  base: deprecated("--base")(),
29
36
  entry: deprecated("--entry")(),
30
37
  target: deprecated("--target")()
@@ -32,11 +39,17 @@ class Build extends Command {
32
39
  async run() {
33
40
  const { flags } = await this.parse(Build);
34
41
  const directory = flags.path ? resolvePath(flags.path) : process.cwd();
35
- await runBuild({ ...flagsToCamelObject(flags), path: directory });
42
+ await runBuild({
43
+ ...flagsToCamelObject(flags),
44
+ useCodegen: flags["codegen-unstable"],
45
+ path: directory
46
+ });
36
47
  }
37
48
  }
38
49
  async function runBuild({
39
50
  path: appPath,
51
+ useCodegen = false,
52
+ codegenConfigPath,
40
53
  sourcemap = false,
41
54
  disableRouteWarning = false
42
55
  }) {
@@ -44,7 +57,7 @@ async function runBuild({
44
57
  process.env.NODE_ENV = "production";
45
58
  }
46
59
  const { root, buildPath, buildPathClient, buildPathWorkerFile, publicPath } = getProjectPaths(appPath);
47
- await checkLockfileStatus(root);
60
+ await Promise.all([checkLockfileStatus(root), muteRemixLogs()]);
48
61
  console.time(LOG_WORKER_BUILT);
49
62
  outputInfo(`
50
63
  \u{1F3D7}\uFE0F Building in ${process.env.NODE_ENV} mode...`);
@@ -55,20 +68,22 @@ async function runBuild({
55
68
  import('@remix-run/dev/dist/compiler/fileWatchCache.js'),
56
69
  rmdir(buildPath, { force: true })
57
70
  ]);
71
+ assertOxygenChecks(remixConfig);
58
72
  await Promise.all([
59
73
  copyPublicFiles(publicPath, buildPathClient),
60
74
  build({
61
75
  config: remixConfig,
62
76
  options: {
63
77
  mode: process.env.NODE_ENV,
64
- onWarning: warnOnce,
65
78
  sourcemap
66
79
  },
80
+ logger: createRemixLogger(),
67
81
  fileWatchCache: createFileWatchCache()
68
82
  }).catch((thrown) => {
69
83
  logThrown(thrown);
70
84
  process.exit(1);
71
- })
85
+ }),
86
+ useCodegen && codegen({ ...remixConfig, configFilePath: codegenConfigPath })
72
87
  ]);
73
88
  if (process.env.NODE_ENV !== "development") {
74
89
  console.timeEnd(LOG_WORKER_BUILT);
@@ -1,7 +1,7 @@
1
1
  import Command from '@shopify/cli-kit/node/base-command';
2
2
  import { resolvePath } from '@shopify/cli-kit/node/path';
3
3
  import { commonFlags } from '../../lib/flags.js';
4
- import { getRemixConfig } from '../../lib/config.js';
4
+ import { getRemixConfig } from '../../lib/remix-config.js';
5
5
  import { logMissingRoutes, findMissingRoutes } from '../../lib/missing-routes.js';
6
6
  import { Args } from '@oclif/core';
7
7
 
@@ -29,7 +29,7 @@ class GenerateRoute extends Command {
29
29
  }
30
30
  }
31
31
  async function runCheckRoutes({ directory }) {
32
- const remixConfig = await getRemixConfig(directory, true);
32
+ const remixConfig = await getRemixConfig(directory);
33
33
  logMissingRoutes(findMissingRoutes(remixConfig));
34
34
  }
35
35
 
@@ -1,11 +1,10 @@
1
1
  import path from 'path';
2
2
  import Command from '@shopify/cli-kit/node/base-command';
3
- import { AbortError } from '@shopify/cli-kit/node/error';
4
3
  import { renderSuccess } from '@shopify/cli-kit/node/ui';
5
4
  import { Flags } from '@oclif/core';
6
- import { getProjectPaths, getRemixConfig } from '../../lib/config.js';
5
+ import { getProjectPaths, getRemixConfig } from '../../lib/remix-config.js';
7
6
  import { commonFlags, flagsToCamelObject } from '../../lib/flags.js';
8
- import { patchGqlPluck, generateTypes, normalizeCodegenError } from '../../lib/codegen.js';
7
+ import { codegen } from '../../lib/codegen.js';
9
8
 
10
9
  class Codegen extends Command {
11
10
  static description = "Generate types for the Storefront API queries found in your project.";
@@ -42,29 +41,19 @@ async function runCodegen({
42
41
  }) {
43
42
  const { root } = getProjectPaths(appPath);
44
43
  const remixConfig = await getRemixConfig(root);
45
- await patchGqlPluck();
46
- try {
47
- const generatedFiles = await generateTypes({
48
- ...remixConfig,
49
- configFilePath: codegenConfigPath,
50
- forceSfapiVersion,
51
- watch
44
+ console.log("");
45
+ const generatedFiles = await codegen({
46
+ ...remixConfig,
47
+ configFilePath: codegenConfigPath,
48
+ forceSfapiVersion,
49
+ watch
50
+ });
51
+ if (!watch) {
52
+ renderSuccess({
53
+ headline: "Generated types for GraphQL:",
54
+ body: generatedFiles.map((file) => `- ${file}`).join("\n")
52
55
  });
53
- if (!watch) {
54
- console.log("");
55
- renderSuccess({
56
- headline: "Generated types for GraphQL:",
57
- body: generatedFiles.map((file) => `- ${file}`).join("\n")
58
- });
59
- }
60
- } catch (error) {
61
- const { message, details } = normalizeCodegenError(
62
- error.message,
63
- remixConfig.rootDirectory
64
- );
65
- console.log("");
66
- throw new AbortError(message, details);
67
56
  }
68
57
  }
69
58
 
70
- export { Codegen as default };
59
+ export { Codegen as default, runCodegen };
@@ -1,12 +1,12 @@
1
1
  import path from 'path';
2
2
  import fs from 'fs/promises';
3
- import { outputInfo } from '@shopify/cli-kit/node/output';
3
+ import { outputInfo, outputDebug } from '@shopify/cli-kit/node/output';
4
4
  import { fileExists } from '@shopify/cli-kit/node/fs';
5
5
  import { renderFatalError } from '@shopify/cli-kit/node/ui';
6
6
  import colors from '@shopify/cli-kit/node/colors';
7
7
  import { copyPublicFiles } from './build.js';
8
- import { getProjectPaths, getRemixConfig } from '../../lib/config.js';
9
- import { muteDevLogs, warnOnce } from '../../lib/log.js';
8
+ import { getProjectPaths, assertOxygenChecks, getRemixConfig } from '../../lib/remix-config.js';
9
+ import { muteDevLogs, muteRemixLogs, createRemixLogger, enhanceH2Logs } from '../../lib/log.js';
10
10
  import { commonFlags, deprecated, flagsToCamelObject } from '../../lib/flags.js';
11
11
  import Command from '@shopify/cli-kit/node/base-command';
12
12
  import { Flags } from '@oclif/core';
@@ -14,8 +14,9 @@ import { startMiniOxygen } from '../../lib/mini-oxygen.js';
14
14
  import { checkHydrogenVersion } from '../../lib/check-version.js';
15
15
  import { addVirtualRoutes } from '../../lib/virtual-routes.js';
16
16
  import { spawnCodegenProcess } from '../../lib/codegen.js';
17
- import { combinedEnvironmentVariables } from '../../lib/combined-environment-variables.js';
17
+ import { getAllEnvironmentVariables } from '../../lib/environment-variables.js';
18
18
  import { getConfig } from '../../lib/shopify-config.js';
19
+ import { checkRemixVersions } from '../../lib/remix-version-check.js';
19
20
 
20
21
  const LOG_REBUILDING = "\u{1F9F1} Rebuilding...";
21
22
  const LOG_REBUILT = "\u{1F680} Rebuilt";
@@ -29,32 +30,27 @@ class Dev extends Command {
29
30
  required: false,
30
31
  default: false
31
32
  }),
32
- ["codegen-config-path"]: Flags.string({
33
- description: "Specify a path to a codegen configuration file. Defaults to `<root>/codegen.ts` if it exists.",
34
- required: false,
35
- dependsOn: ["codegen-unstable"]
36
- }),
33
+ ["codegen-config-path"]: commonFlags.codegenConfigPath,
37
34
  sourcemap: commonFlags.sourcemap,
38
35
  "disable-virtual-routes": Flags.boolean({
39
36
  description: "Disable rendering fallback routes when a route file doesn't exist.",
40
37
  env: "SHOPIFY_HYDROGEN_FLAG_DISABLE_VIRTUAL_ROUTES",
41
38
  default: false
42
39
  }),
43
- shop: commonFlags.shop,
44
40
  debug: Flags.boolean({
45
41
  description: "Attaches a Node inspector",
46
42
  env: "SHOPIFY_HYDROGEN_FLAG_DEBUG",
47
43
  default: false
48
44
  }),
49
45
  host: deprecated("--host")(),
50
- ["env-branch"]: commonFlags["env-branch"]
46
+ ["env-branch"]: commonFlags.envBranch
51
47
  };
52
48
  async run() {
53
49
  const { flags } = await this.parse(Dev);
54
50
  const directory = flags.path ? path.resolve(flags.path) : process.cwd();
55
51
  await runDev({
56
52
  ...flagsToCamelObject(flags),
57
- codegen: flags["codegen-unstable"],
53
+ useCodegen: flags["codegen-unstable"],
58
54
  path: directory
59
55
  });
60
56
  }
@@ -62,10 +58,9 @@ class Dev extends Command {
62
58
  async function runDev({
63
59
  port,
64
60
  path: appPath,
65
- codegen = false,
61
+ useCodegen = false,
66
62
  codegenConfigPath,
67
63
  disableVirtualRoutes,
68
- shop,
69
64
  envBranch,
70
65
  debug = false,
71
66
  sourcemap = true
@@ -73,6 +68,7 @@ async function runDev({
73
68
  if (!process.env.NODE_ENV)
74
69
  process.env.NODE_ENV = "development";
75
70
  muteDevLogs();
71
+ await muteRemixLogs();
76
72
  if (debug)
77
73
  (await import('node:inspector')).open();
78
74
  const { root, publicPath, buildPathClient, buildPathWorkerFile } = getProjectPaths(appPath);
@@ -80,19 +76,25 @@ async function runDev({
80
76
  const copyingFiles = copyPublicFiles(publicPath, buildPathClient);
81
77
  const reloadConfig = async () => {
82
78
  const config = await getRemixConfig(root);
83
- return disableVirtualRoutes ? config : addVirtualRoutes(config);
79
+ return disableVirtualRoutes ? config : addVirtualRoutes(config).catch((error) => {
80
+ outputDebug(
81
+ "Could not add virtual routes: " + (error?.stack ?? error?.message ?? error)
82
+ );
83
+ return config;
84
+ });
84
85
  };
85
86
  const getFilePaths = (file) => {
86
87
  const fileRelative = path.relative(root, file);
87
88
  return [fileRelative, path.resolve(root, fileRelative)];
88
89
  };
89
90
  const serverBundleExists = () => fileExists(buildPathWorkerFile);
90
- const hasLinkedStorefront = !!(await getConfig(root))?.storefront?.id;
91
- const environmentVariables = hasLinkedStorefront ? await combinedEnvironmentVariables({
92
- root,
93
- shop,
94
- envBranch
95
- }) : void 0;
91
+ const [remixConfig, { shop, storefront }] = await Promise.all([
92
+ reloadConfig(),
93
+ getConfig(root)
94
+ ]);
95
+ assertOxygenChecks(remixConfig);
96
+ const fetchRemote = !!shop && !!storefront?.id;
97
+ const envPromise = getAllEnvironmentVariables({ root, fetchRemote, envBranch });
96
98
  const [{ watch }, { createFileWatchCache }] = await Promise.all([
97
99
  import('@remix-run/dev/dist/compiler/watch.js'),
98
100
  import('@remix-run/dev/dist/compiler/fileWatchCache.js')
@@ -100,54 +102,53 @@ async function runDev({
100
102
  let isInitialBuild = true;
101
103
  let initialBuildDurationMs = 0;
102
104
  let initialBuildStartTimeMs = Date.now();
103
- let isMiniOxygenStarted = false;
105
+ let miniOxygen;
104
106
  async function safeStartMiniOxygen() {
105
- if (isMiniOxygenStarted)
107
+ if (miniOxygen)
106
108
  return;
107
- const miniOxygen = await startMiniOxygen({
109
+ miniOxygen = await startMiniOxygen({
108
110
  root,
109
111
  port,
110
112
  watch: true,
111
113
  buildPathWorkerFile,
112
114
  buildPathClient,
113
- environmentVariables
115
+ env: await envPromise
114
116
  });
115
- isMiniOxygenStarted = true;
117
+ const graphiqlUrl = `${miniOxygen.listeningAt}/graphiql`;
118
+ enhanceH2Logs({ graphiqlUrl, ...remixConfig });
116
119
  miniOxygen.showBanner({
120
+ appName: storefront ? colors.cyan(storefront?.title) : void 0,
117
121
  headlinePrefix: initialBuildDurationMs > 0 ? `Initial build: ${initialBuildDurationMs}ms
118
122
  ` : "",
119
- extraLines: [
120
- colors.dim(
121
- `
122
- View GraphiQL API browser: ${miniOxygen.listeningAt}/graphiql`
123
- )
124
- ]
123
+ extraLines: [colors.dim(`
124
+ View GraphiQL API browser: ${graphiqlUrl}`)]
125
125
  });
126
+ if (useCodegen) {
127
+ spawnCodegenProcess({ ...remixConfig, configFilePath: codegenConfigPath });
128
+ }
129
+ checkRemixVersions();
126
130
  const showUpgrade = await checkingHydrogenVersion;
127
131
  if (showUpgrade)
128
132
  showUpgrade();
129
133
  }
130
- const remixConfig = await reloadConfig();
131
- if (codegen) {
132
- spawnCodegenProcess({ ...remixConfig, configFilePath: codegenConfigPath });
133
- }
134
134
  const fileWatchCache = createFileWatchCache();
135
+ let skipRebuildLogs = false;
135
136
  await watch(
136
137
  {
137
138
  config: remixConfig,
138
139
  options: {
139
140
  mode: process.env.NODE_ENV,
140
- onWarning: warnOnce,
141
141
  sourcemap
142
142
  },
143
- fileWatchCache
143
+ fileWatchCache,
144
+ logger: createRemixLogger()
144
145
  },
145
146
  {
146
147
  reloadConfig,
147
148
  onBuildStart() {
148
- if (!isInitialBuild) {
149
- console.time(LOG_REBUILT);
149
+ if (!isInitialBuild && !skipRebuildLogs) {
150
150
  outputInfo(LOG_REBUILDING);
151
+ console.time(LOG_REBUILT);
151
152
  }
152
153
  },
153
154
  async onBuildFinish() {
@@ -155,12 +156,13 @@ View GraphiQL API browser: ${miniOxygen.listeningAt}/graphiql`
155
156
  await copyingFiles;
156
157
  initialBuildDurationMs = Date.now() - initialBuildStartTimeMs;
157
158
  isInitialBuild = false;
158
- } else {
159
+ } else if (!skipRebuildLogs) {
160
+ skipRebuildLogs = false;
159
161
  console.timeEnd(LOG_REBUILT);
160
- if (!isMiniOxygenStarted)
162
+ if (!miniOxygen)
161
163
  console.log("");
162
164
  }
163
- if (!isMiniOxygenStarted) {
165
+ if (!miniOxygen) {
164
166
  if (!await serverBundleExists()) {
165
167
  return renderFatalError({
166
168
  name: "BuildError",
@@ -188,6 +190,16 @@ View GraphiQL API browser: ${miniOxygen.listeningAt}/graphiql`
188
190
  const [relative, absolute] = getFilePaths(file);
189
191
  outputInfo(`
190
192
  \u{1F4C4} File changed: ${relative}`);
193
+ if (relative.endsWith(".env")) {
194
+ skipRebuildLogs = true;
195
+ await miniOxygen.reload({
196
+ env: await getAllEnvironmentVariables({
197
+ root,
198
+ fetchRemote,
199
+ envBranch
200
+ })
201
+ });
202
+ }
191
203
  if (absolute.startsWith(publicPath)) {
192
204
  await copyPublicFiles(
193
205
  absolute,
@@ -2,53 +2,54 @@ import Command from '@shopify/cli-kit/node/base-command';
2
2
  import { renderConfirmationPrompt } from '@shopify/cli-kit/node/ui';
3
3
  import { pluralize } from '@shopify/cli-kit/common/string';
4
4
  import colors from '@shopify/cli-kit/node/colors';
5
- import { outputContent, outputToken, outputNewline, outputInfo } from '@shopify/cli-kit/node/output';
5
+ import { outputNewline, outputInfo, outputContent } from '@shopify/cli-kit/node/output';
6
6
  import { linkStorefront } from '../link.js';
7
7
  import { commonFlags } from '../../../lib/flags.js';
8
- import { getHydrogenShop } from '../../../lib/shop.js';
9
- import { getAdminSession } from '../../../lib/admin-session.js';
10
8
  import { getStorefrontEnvironments } from '../../../lib/graphql/admin/list-environments.js';
11
- import { getConfig } from '../../../lib/shopify-config.js';
12
9
  import { renderMissingLink, renderMissingStorefront } from '../../../lib/render-errors.js';
10
+ import { login } from '../../../lib/auth.js';
11
+ import { getCliCommand } from '../../../lib/shell.js';
13
12
 
14
13
  class EnvList extends Command {
15
14
  static description = "List the environments on your linked Hydrogen storefront.";
16
15
  static flags = {
17
- path: commonFlags.path,
18
- shop: commonFlags.shop
16
+ path: commonFlags.path
19
17
  };
20
18
  async run() {
21
19
  const { flags } = await this.parse(EnvList);
22
- await listEnvironments(flags);
20
+ await runEnvList(flags);
23
21
  }
24
22
  }
25
- async function listEnvironments({ path, shop: flagShop }) {
26
- const shop = await getHydrogenShop({ path, shop: flagShop });
27
- const adminSession = await getAdminSession(shop);
28
- const actualPath = path ?? process.cwd();
29
- let configStorefront = (await getConfig(actualPath)).storefront;
23
+ async function runEnvList({ path: root = process.cwd() }) {
24
+ const [{ session, config }, cliCommand] = await Promise.all([
25
+ login(root),
26
+ getCliCommand()
27
+ ]);
28
+ let configStorefront = config.storefront;
30
29
  if (!configStorefront?.id) {
31
- renderMissingLink({ adminSession });
30
+ renderMissingLink({ session, cliCommand });
32
31
  const runLink = await renderConfirmationPrompt({
33
- message: outputContent`Run ${outputToken.genericShellCommand(
34
- `npx shopify hydrogen link`
35
- )}?`.value
32
+ message: ["Run", { command: `${cliCommand} link` }, "?"]
36
33
  });
37
34
  if (!runLink) {
38
35
  return;
39
36
  }
40
- await linkStorefront({ path, shop: flagShop, silent: true });
37
+ configStorefront = await linkStorefront(root, session, config, {
38
+ cliCommand
39
+ });
41
40
  }
42
- configStorefront = (await getConfig(actualPath)).storefront;
43
- if (!configStorefront) {
41
+ if (!configStorefront)
44
42
  return;
45
- }
46
- const { storefront } = await getStorefrontEnvironments(
47
- adminSession,
43
+ const storefront = await getStorefrontEnvironments(
44
+ session,
48
45
  configStorefront.id
49
46
  );
50
47
  if (!storefront) {
51
- renderMissingStorefront({ adminSession, storefront: configStorefront });
48
+ renderMissingStorefront({
49
+ session,
50
+ storefront: configStorefront,
51
+ cliCommand
52
+ });
52
53
  return;
53
54
  }
54
55
  const previewEnvironmentIndex = storefront.environments.findIndex(
@@ -91,4 +92,4 @@ const pluralizedEnvironments = ({
91
92
  );
92
93
  };
93
94
 
94
- export { EnvList as default, listEnvironments };
95
+ export { EnvList as default, runEnvList };
@@ -3,11 +3,10 @@ import { mockAndCaptureOutput } from '@shopify/cli-kit/node/testing/output';
3
3
  import { inTemporaryDirectory } from '@shopify/cli-kit/node/fs';
4
4
  import { renderConfirmationPrompt } from '@shopify/cli-kit/node/ui';
5
5
  import { getStorefrontEnvironments } from '../../../lib/graphql/admin/list-environments.js';
6
- import { getAdminSession } from '../../../lib/admin-session.js';
7
- import { getConfig } from '../../../lib/shopify-config.js';
6
+ import { login } from '../../../lib/auth.js';
8
7
  import { renderMissingLink, renderMissingStorefront } from '../../../lib/render-errors.js';
9
8
  import { linkStorefront } from '../link.js';
10
- import { listEnvironments } from './list.js';
9
+ import { runEnvList } from './list.js';
11
10
 
12
11
  const SHOP = "my-shop";
13
12
  vi.mock("@shopify/cli-kit/node/ui", async () => {
@@ -18,20 +17,25 @@ vi.mock("@shopify/cli-kit/node/ui", async () => {
18
17
  };
19
18
  });
20
19
  vi.mock("../link.js");
21
- vi.mock("../../../lib/admin-session.js");
20
+ vi.mock("../../../lib/auth.js");
22
21
  vi.mock("../../../lib/shopify-config.js");
23
22
  vi.mock("../../../lib/render-errors.js");
24
- vi.mock("../../../lib/graphql/admin/list-environments.js", () => {
25
- return { getStorefrontEnvironments: vi.fn() };
26
- });
27
- vi.mock("../../../lib/shop.js", () => ({
28
- getHydrogenShop: () => SHOP
29
- }));
23
+ vi.mock("../../../lib/graphql/admin/list-environments.js");
24
+ vi.mock("../../../lib/shell.js", () => ({ getCliCommand: () => "h2" }));
30
25
  describe("listEnvironments", () => {
31
26
  const ADMIN_SESSION = {
32
27
  token: "abc123",
33
28
  storeFqdn: SHOP
34
29
  };
30
+ const SHOPIFY_CONFIG = {
31
+ shop: SHOP,
32
+ shopName: "My Shop",
33
+ email: "email",
34
+ storefront: {
35
+ id: "gid://shopify/HydrogenStorefront/1",
36
+ title: "Existing Link"
37
+ }
38
+ };
35
39
  const PRODUCTION_ENVIRONMENT = {
36
40
  id: "gid://shopify/HydrogenStorefrontEnvironment/1",
37
41
  branch: "main",
@@ -57,44 +61,39 @@ describe("listEnvironments", () => {
57
61
  url: null
58
62
  };
59
63
  beforeEach(async () => {
60
- vi.mocked(getAdminSession).mockResolvedValue(ADMIN_SESSION);
61
- vi.mocked(getConfig).mockResolvedValue({
62
- storefront: {
63
- id: "gid://shopify/HydrogenStorefront/1",
64
- title: "Existing Link"
65
- }
64
+ vi.mocked(login).mockResolvedValue({
65
+ session: ADMIN_SESSION,
66
+ config: SHOPIFY_CONFIG
66
67
  });
67
68
  vi.mocked(getStorefrontEnvironments).mockResolvedValue({
68
- storefront: {
69
- id: "gid://shopify/HydrogenStorefront/1",
70
- productionUrl: "https://example.com",
71
- environments: [
72
- PRODUCTION_ENVIRONMENT,
73
- CUSTOM_ENVIRONMENT,
74
- PREVIEW_ENVIRONMENT
75
- ]
76
- }
69
+ id: "gid://shopify/HydrogenStorefront/1",
70
+ productionUrl: "https://example.com",
71
+ environments: [
72
+ PRODUCTION_ENVIRONMENT,
73
+ CUSTOM_ENVIRONMENT,
74
+ PREVIEW_ENVIRONMENT
75
+ ]
77
76
  });
78
77
  });
79
78
  afterEach(() => {
80
79
  vi.resetAllMocks();
81
80
  mockAndCaptureOutput().clear();
82
81
  });
83
- it("makes a GraphQL call to fetch environment variables", async () => {
82
+ it("fetchs environment variables", async () => {
84
83
  await inTemporaryDirectory(async (tmpDir) => {
85
- await listEnvironments({ path: tmpDir });
84
+ await runEnvList({ path: tmpDir });
86
85
  expect(getStorefrontEnvironments).toHaveBeenCalledWith(
87
86
  ADMIN_SESSION,
88
- "gid://shopify/HydrogenStorefront/1"
87
+ SHOPIFY_CONFIG.storefront.id
89
88
  );
90
89
  });
91
90
  });
92
91
  it("lists the environments", async () => {
93
92
  await inTemporaryDirectory(async (tmpDir) => {
94
93
  const output = mockAndCaptureOutput();
95
- await listEnvironments({ path: tmpDir });
94
+ await runEnvList({ path: tmpDir });
96
95
  expect(output.info()).toMatch(
97
- /Showing 3 environments for the Hydrogen storefront Existing Link/
96
+ /Showing 3 environments for the Hydrogen storefront Existing Link/i
98
97
  );
99
98
  expect(output.info()).toMatch(/Production \(Branch: main\)/);
100
99
  expect(output.info()).toMatch(/https:\/\/example\.com/);
@@ -105,39 +104,43 @@ describe("listEnvironments", () => {
105
104
  });
106
105
  describe("when there is no linked storefront", () => {
107
106
  beforeEach(() => {
108
- vi.mocked(getConfig).mockResolvedValue({
109
- storefront: void 0
107
+ vi.mocked(login).mockResolvedValue({
108
+ session: ADMIN_SESSION,
109
+ config: {
110
+ ...SHOPIFY_CONFIG,
111
+ storefront: void 0
112
+ }
110
113
  });
111
114
  });
112
115
  it("calls renderMissingLink", async () => {
113
116
  await inTemporaryDirectory(async (tmpDir) => {
114
- await listEnvironments({ path: tmpDir });
117
+ await runEnvList({ path: tmpDir });
115
118
  expect(renderMissingLink).toHaveBeenCalledOnce();
116
119
  });
117
120
  });
118
121
  it("prompts the user to create a link", async () => {
119
122
  vi.mocked(renderConfirmationPrompt).mockResolvedValue(true);
120
123
  await inTemporaryDirectory(async (tmpDir) => {
121
- await listEnvironments({ path: tmpDir });
124
+ await runEnvList({ path: tmpDir });
122
125
  expect(renderConfirmationPrompt).toHaveBeenCalledWith({
123
- message: expect.stringMatching(/Run .*npx shopify hydrogen link.*\?/)
124
- });
125
- expect(linkStorefront).toHaveBeenCalledWith({
126
- path: tmpDir,
127
- silent: true
126
+ message: expect.arrayContaining([{ command: "h2 link" }])
128
127
  });
128
+ expect(linkStorefront).toHaveBeenCalledWith(
129
+ tmpDir,
130
+ ADMIN_SESSION,
131
+ { ...SHOPIFY_CONFIG, storefront: void 0 },
132
+ expect.anything()
133
+ );
129
134
  });
130
135
  });
131
136
  });
132
137
  describe("when there is no matching storefront in the shop", () => {
133
138
  beforeEach(() => {
134
- vi.mocked(getStorefrontEnvironments).mockResolvedValue({
135
- storefront: null
136
- });
139
+ vi.mocked(getStorefrontEnvironments).mockResolvedValue(null);
137
140
  });
138
141
  it("calls renderMissingStorefront", async () => {
139
142
  await inTemporaryDirectory(async (tmpDir) => {
140
- await listEnvironments({ path: tmpDir });
143
+ await runEnvList({ path: tmpDir });
141
144
  expect(renderMissingStorefront).toHaveBeenCalledOnce();
142
145
  });
143
146
  });