@shopify/cli-hydrogen 8.2.0 → 8.4.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 (75) hide show
  1. package/dist/assets/hydrogen/i18n/domains.ts +4 -11
  2. package/dist/assets/hydrogen/i18n/mock-i18n-types.ts +4 -2
  3. package/dist/assets/hydrogen/i18n/subdomains.ts +4 -11
  4. package/dist/assets/hydrogen/i18n/subfolders.ts +4 -11
  5. package/dist/assets/hydrogen/starter/.graphqlrc.ts +27 -0
  6. package/dist/assets/hydrogen/starter/CHANGELOG.md +174 -0
  7. package/dist/assets/hydrogen/starter/app/components/CartLineItem.tsx +5 -2
  8. package/dist/assets/hydrogen/starter/app/components/CartMain.tsx +2 -2
  9. package/dist/assets/hydrogen/starter/app/components/PageLayout.tsx +65 -19
  10. package/dist/assets/hydrogen/starter/app/components/PaginatedResourceSection.tsx +42 -0
  11. package/dist/assets/hydrogen/starter/app/components/SearchForm.tsx +68 -0
  12. package/dist/assets/hydrogen/starter/app/components/SearchFormPredictive.tsx +76 -0
  13. package/dist/assets/hydrogen/starter/app/components/SearchResults.tsx +164 -0
  14. package/dist/assets/hydrogen/starter/app/components/SearchResultsPredictive.tsx +322 -0
  15. package/dist/assets/hydrogen/starter/app/entry.client.tsx +10 -8
  16. package/dist/assets/hydrogen/starter/app/entry.server.tsx +1 -1
  17. package/dist/assets/hydrogen/starter/app/lib/context.ts +43 -0
  18. package/dist/assets/hydrogen/starter/app/lib/fragments.ts +53 -0
  19. package/dist/assets/hydrogen/starter/app/lib/search.ts +74 -24
  20. package/dist/assets/hydrogen/starter/app/root.tsx +4 -7
  21. package/dist/assets/hydrogen/starter/app/routes/account.addresses.tsx +2 -3
  22. package/dist/assets/hydrogen/starter/app/routes/account.orders._index.tsx +5 -19
  23. package/dist/assets/hydrogen/starter/app/routes/blogs.$blogHandle._index.tsx +11 -24
  24. package/dist/assets/hydrogen/starter/app/routes/blogs._index.tsx +14 -27
  25. package/dist/assets/hydrogen/starter/app/routes/collections.$handle.tsx +12 -30
  26. package/dist/assets/hydrogen/starter/app/routes/collections._index.tsx +13 -27
  27. package/dist/assets/hydrogen/starter/app/routes/collections.all.tsx +9 -31
  28. package/dist/assets/hydrogen/starter/app/routes/search.tsx +312 -73
  29. package/dist/assets/hydrogen/starter/app/styles/reset.css +12 -2
  30. package/dist/assets/hydrogen/starter/env.d.ts +11 -30
  31. package/dist/assets/hydrogen/starter/guides/predictiveSearch/predictiveSearch.jpg +0 -0
  32. package/dist/assets/hydrogen/starter/guides/predictiveSearch/predictiveSearch.md +391 -0
  33. package/dist/assets/hydrogen/starter/guides/search/search.jpg +0 -0
  34. package/dist/assets/hydrogen/starter/guides/search/search.md +333 -0
  35. package/dist/assets/hydrogen/starter/package.json +4 -4
  36. package/dist/assets/hydrogen/starter/server.ts +18 -74
  37. package/dist/assets/hydrogen/starter/storefrontapi.generated.d.ts +242 -172
  38. package/dist/assets/hydrogen/virtual-routes/components/{PageLayout.jsx → Layout.jsx} +2 -2
  39. package/dist/assets/hydrogen/virtual-routes/virtual-root.jsx +7 -6
  40. package/dist/commands/hydrogen/build.js +4 -2
  41. package/dist/commands/hydrogen/codegen.js +11 -3
  42. package/dist/commands/hydrogen/debug/cpu.js +2 -3
  43. package/dist/commands/hydrogen/deploy.js +8 -6
  44. package/dist/commands/hydrogen/dev.js +13 -11
  45. package/dist/commands/hydrogen/env/pull.js +5 -3
  46. package/dist/commands/hydrogen/env/push.js +2 -5
  47. package/dist/commands/hydrogen/login.js +4 -0
  48. package/dist/commands/hydrogen/logout.js +2 -0
  49. package/dist/commands/hydrogen/preview.js +11 -7
  50. package/dist/commands/hydrogen/setup.js +2 -4
  51. package/dist/hooks/init.js +6 -3
  52. package/dist/index.d.ts +5 -1
  53. package/dist/lib/auth.js +3 -63
  54. package/dist/lib/classic-compiler/dev.js +8 -4
  55. package/dist/lib/codegen.js +68 -33
  56. package/dist/lib/dev-shared.js +17 -15
  57. package/dist/lib/environment-variables.js +5 -4
  58. package/dist/lib/flags.js +7 -0
  59. package/dist/lib/import-utils.js +8 -2
  60. package/dist/lib/log.js +7 -38
  61. package/dist/lib/onboarding/common.js +2 -0
  62. package/dist/lib/onboarding/local.js +22 -7
  63. package/dist/lib/remix-config.js +8 -3
  64. package/dist/lib/setups/css/replacers.js +2 -2
  65. package/dist/lib/setups/i18n/index.js +3 -6
  66. package/dist/lib/setups/i18n/replacers.js +62 -134
  67. package/dist/lib/template-diff.js +15 -0
  68. package/dist/lib/transpile/morph/functions.js +3 -2
  69. package/dist/lib/transpile/morph/typedefs.js +4 -1
  70. package/dist/lib/vite-config.js +13 -1
  71. package/oclif.manifest.json +39 -2
  72. package/package.json +3 -3
  73. package/dist/assets/hydrogen/starter/.graphqlrc.yml +0 -12
  74. package/dist/assets/hydrogen/starter/app/components/Search.tsx +0 -514
  75. package/dist/assets/hydrogen/starter/app/routes/api.predictive-search.tsx +0 -318
@@ -2,13 +2,14 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import {
3
3
  Links,
4
4
  Meta,
5
+ Outlet,
5
6
  Scripts,
6
7
  ScrollRestoration,
7
8
  isRouteErrorResponse,
8
9
  useRouteError
9
10
  } from "@remix-run/react";
10
11
  import favicon from "./assets/favicon.svg";
11
- import { PageLayout } from "./components/PageLayout.jsx";
12
+ import { Layout } from "./components/Layout.jsx";
12
13
  import { useNonce } from "@shopify/hydrogen";
13
14
  import styles from "./assets/styles.css?url";
14
15
  const links = () => {
@@ -17,7 +18,7 @@ const links = () => {
17
18
  { rel: "icon", type: "image/svg+xml", href: favicon }
18
19
  ];
19
20
  };
20
- function Layout({ children }) {
21
+ function App() {
21
22
  const nonce = useNonce();
22
23
  return /* @__PURE__ */ jsxs("html", { lang: "en", children: [
23
24
  /* @__PURE__ */ jsxs("head", { children: [
@@ -35,7 +36,7 @@ function Layout({ children }) {
35
36
  /* @__PURE__ */ jsx(Links, {})
36
37
  ] }),
37
38
  /* @__PURE__ */ jsxs("body", { children: [
38
- /* @__PURE__ */ jsx(PageLayout, { children }),
39
+ /* @__PURE__ */ jsx(Layout, { children: /* @__PURE__ */ jsx(Outlet, {}) }),
39
40
  /* @__PURE__ */ jsx(ScrollRestoration, { nonce }),
40
41
  /* @__PURE__ */ jsx(Scripts, { nonce })
41
42
  ] })
@@ -51,14 +52,14 @@ function ErrorBoundary() {
51
52
  } else if (error instanceof Error) {
52
53
  errorMessage = error.message;
53
54
  }
54
- return /* @__PURE__ */ jsxs("div", { className: "route-error", children: [
55
+ return /* @__PURE__ */ jsx(Layout, { children: /* @__PURE__ */ jsxs("div", { className: "route-error", children: [
55
56
  /* @__PURE__ */ jsx("h1", { children: "Please report this error" }),
56
57
  /* @__PURE__ */ jsx("h2", { children: errorStatus }),
57
58
  errorMessage && /* @__PURE__ */ jsx("fieldset", { children: /* @__PURE__ */ jsx("pre", { children: errorMessage }) })
58
- ] });
59
+ ] }) });
59
60
  }
60
61
  export {
61
62
  ErrorBoundary,
62
- Layout,
63
+ App as default,
63
64
  links
64
65
  };
@@ -6,7 +6,7 @@ import { removeFile, fileSize } from '@shopify/cli-kit/node/fs';
6
6
  import { getPackageManager } from '@shopify/cli-kit/node/node-package-manager';
7
7
  import { commonFlags, flagsToCamelObject } from '../../lib/flags.js';
8
8
  import { prepareDiffDirectory } from '../../lib/template-diff.js';
9
- import { hasViteConfig, getViteConfig } from '../../lib/vite-config.js';
9
+ import { isViteProject, getViteConfig } from '../../lib/vite-config.js';
10
10
  import { checkLockfileStatus } from '../../lib/check-lockfile.js';
11
11
  import { findMissingRoutes } from '../../lib/missing-routes.js';
12
12
  import { runClassicCompilerBuild } from '../../lib/classic-compiler/build.js';
@@ -49,13 +49,14 @@ class Build extends Command {
49
49
  useCodegen: flags.codegen,
50
50
  directory
51
51
  };
52
- const result = await hasViteConfig(directory) ? await runBuild(buildParams) : await runClassicCompilerBuild(buildParams);
52
+ const result = await isViteProject(directory) ? await runBuild(buildParams) : await runClassicCompilerBuild(buildParams);
53
53
  if (buildParams.watch) {
54
54
  if (diff || result?.close) {
55
55
  setupResourceCleanup(async () => {
56
56
  await result?.close();
57
57
  if (diff) {
58
58
  await diff.copyDiffBuild();
59
+ if (flags.codegen) await diff.copyDiffCodegen();
59
60
  await diff.cleanup();
60
61
  }
61
62
  });
@@ -63,6 +64,7 @@ class Build extends Command {
63
64
  } else {
64
65
  if (diff) {
65
66
  await diff.copyDiffBuild();
67
+ if (flags.codegen) await diff.copyDiffCodegen();
66
68
  await diff.cleanup();
67
69
  }
68
70
  process.exit(0);
@@ -1,11 +1,12 @@
1
- import path from 'path';
2
1
  import Command from '@shopify/cli-kit/node/base-command';
3
2
  import { renderSuccess } from '@shopify/cli-kit/node/ui';
4
3
  import colors from '@shopify/cli-kit/node/colors';
4
+ import { resolvePath } from '@shopify/cli-kit/node/path';
5
5
  import { Flags } from '@oclif/core';
6
6
  import { getProjectPaths, getRemixConfig } from '../../lib/remix-config.js';
7
7
  import { commonFlags, flagsToCamelObject } from '../../lib/flags.js';
8
8
  import { codegen } from '../../lib/codegen.js';
9
+ import { prepareDiffDirectory } from '../../lib/template-diff.js';
9
10
 
10
11
  class Codegen extends Command {
11
12
  static descriptionWithMarkdown = "Automatically generates GraphQL types for your project\u2019s Storefront API queries.";
@@ -24,15 +25,22 @@ class Codegen extends Command {
24
25
  description: "Watch the project for changes to update types on file save.",
25
26
  required: false,
26
27
  default: false
27
- })
28
+ }),
29
+ ...commonFlags.diff
28
30
  };
29
31
  async run() {
30
32
  const { flags } = await this.parse(Codegen);
31
- const directory = flags.path ? path.resolve(flags.path) : process.cwd();
33
+ const originalDirectory = flags.path ? resolvePath(flags.path) : process.cwd();
34
+ const diff = flags.diff ? await prepareDiffDirectory(originalDirectory, flags.watch) : void 0;
35
+ const directory = diff?.targetDirectory ?? originalDirectory;
32
36
  await runCodegen({
33
37
  ...flagsToCamelObject(flags),
34
38
  directory
35
39
  });
40
+ if (diff) {
41
+ await diff.copyDiffCodegen();
42
+ await diff.cleanup();
43
+ }
36
44
  }
37
45
  }
38
46
  async function runCodegen({
@@ -5,7 +5,7 @@ import { outputInfo } from '@shopify/cli-kit/node/output';
5
5
  import { writeFile } from '@shopify/cli-kit/node/fs';
6
6
  import colors from '@shopify/cli-kit/node/colors';
7
7
  import ansiEscapes from 'ansi-escapes';
8
- import { getProjectPaths, hasRemixConfigFile } from '../../../lib/remix-config.js';
8
+ import { getProjectPaths, isClassicProject } from '../../../lib/remix-config.js';
9
9
  import { muteDevLogs } from '../../../lib/log.js';
10
10
  import { commonFlags, flagsToCamelObject } from '../../../lib/flags.js';
11
11
  import { prepareDiffDirectory } from '../../../lib/template-diff.js';
@@ -50,7 +50,6 @@ async function runDebugCpu({ directory, entry, output }) {
50
50
  if (!process.env.NODE_ENV) process.env.NODE_ENV = "production";
51
51
  muteDevLogs({ workerReload: false });
52
52
  let { buildPath, buildPathWorkerFile } = getProjectPaths(directory);
53
- const isClassicProject = await hasRemixConfigFile(directory);
54
53
  outputInfo(
55
54
  "\u23F3\uFE0F Starting profiler for CPU startup... Profile will be written to:\n" + colors.dim(output)
56
55
  );
@@ -80,7 +79,7 @@ ${colors.dim(output)}`
80
79
  Waiting for changes...`);
81
80
  }
82
81
  };
83
- if (isClassicProject) {
82
+ if (await isClassicProject(directory)) {
84
83
  return runClassicCompilerDebugCpu({
85
84
  directory,
86
85
  output,
@@ -12,13 +12,13 @@ import { ciPlatform } from '@shopify/cli-kit/node/context/local';
12
12
  import { parseToken, createDeploy } from '@shopify/oxygen-cli/deploy';
13
13
  import { findEnvironmentOrThrow, findEnvironmentByBranchOrThrow, orderEnvironmentsBySafety, createEnvironmentCliChoiceLabel } from '../../lib/common.js';
14
14
  import { execAsync } from '../../lib/process.js';
15
- import { commonFlags, flagsToCamelObject } from '../../lib/flags.js';
15
+ import { commonFlags, overrideFlag, flagsToCamelObject } from '../../lib/flags.js';
16
16
  import { getOxygenDeploymentData } from '../../lib/get-oxygen-deployment-data.js';
17
17
  import { runClassicCompilerBuild } from '../../lib/classic-compiler/build.js';
18
18
  import { runBuild } from './build.js';
19
19
  import { getViteConfig } from '../../lib/vite-config.js';
20
20
  import { prepareDiffDirectory } from '../../lib/template-diff.js';
21
- import { hasRemixConfigFile } from '../../lib/remix-config.js';
21
+ import { isClassicProject } from '../../lib/remix-config.js';
22
22
  import { packageManagers } from '../../lib/package-managers.js';
23
23
  import { setupResourceCleanup } from '../../lib/resource-cleanup.js';
24
24
 
@@ -35,9 +35,11 @@ class Deploy extends Command {
35
35
  ...commonFlags.entry,
36
36
  ...commonFlags.env,
37
37
  ...commonFlags.envBranch,
38
- "env-file": Flags.string({
39
- description: "Path to an environment file to override existing environment variables for the deployment.",
40
- required: false
38
+ ...overrideFlag(commonFlags.envFile, {
39
+ "env-file": {
40
+ description: "Path to an environment file to override existing environment variables for the deployment.",
41
+ default: void 0
42
+ }
41
43
  }),
42
44
  preview: Flags.boolean({
43
45
  description: "Deploys to the Preview environment. Overrides --env-branch and Git metadata.",
@@ -329,7 +331,7 @@ ${changedFiles.trimEnd()}`;
329
331
  }
330
332
  let assetsDir = "dist/client";
331
333
  let workerDir = "dist/worker";
332
- const isClassicCompiler = await hasRemixConfigFile(root);
334
+ const isClassicCompiler = await isClassicProject(root);
333
335
  if (!isClassicCompiler) {
334
336
  const viteConfig = await getViteConfig(root, ssrEntry).catch(() => null);
335
337
  if (viteConfig) {
@@ -16,7 +16,7 @@ import { getDevConfigInBackground, TUNNEL_DOMAIN, startTunnelAndPushConfig, isMo
16
16
  import { getCliCommand } from '../../lib/shell.js';
17
17
  import { findPort } from '../../lib/find-port.js';
18
18
  import { logRequestLine } from '../../lib/mini-oxygen/common.js';
19
- import { hasViteConfig, findHydrogenPlugin, findOxygenPlugin } from '../../lib/vite-config.js';
19
+ import { isViteProject, findHydrogenPlugin, findOxygenPlugin } from '../../lib/vite-config.js';
20
20
  import { runClassicCompilerDev } from '../../lib/classic-compiler/dev.js';
21
21
  import { importVite } from '../../lib/import-utils.js';
22
22
  import { createEntryPointErrorHandler } from '../../lib/deps-optimizer.js';
@@ -45,6 +45,7 @@ class Dev extends Command {
45
45
  ...commonFlags.inspectorPort,
46
46
  ...commonFlags.env,
47
47
  ...commonFlags.envBranch,
48
+ ...commonFlags.envFile,
48
49
  "disable-version-check": Flags.boolean({
49
50
  description: "Skip the version check when running `hydrogen dev`",
50
51
  default: false,
@@ -87,7 +88,7 @@ class Dev extends Command {
87
88
  path: directory,
88
89
  cliConfig: this.config
89
90
  };
90
- const { close } = await hasViteConfig(directory) ? await runDev(devParams) : await runClassicCompilerDev(devParams);
91
+ const { close } = await isViteProject(directory) ? await runDev(devParams) : await runClassicCompilerDev(devParams);
91
92
  setupResourceCleanup(async () => {
92
93
  await close();
93
94
  if (diff) {
@@ -112,6 +113,7 @@ async function runDev({
112
113
  disableVersionCheck = false,
113
114
  inspectorPort,
114
115
  customerAccountPush: customerAccountPushFlag = false,
116
+ envFile,
115
117
  cliConfig,
116
118
  verbose
117
119
  }) {
@@ -122,7 +124,8 @@ async function runDev({
122
124
  const cliCommandPromise = getCliCommand(root);
123
125
  const backgroundPromise = getDevConfigInBackground(
124
126
  root,
125
- customerAccountPushFlag
127
+ customerAccountPushFlag,
128
+ envFile
126
129
  );
127
130
  const envPromise = backgroundPromise.then(
128
131
  ({ fetchRemote, localVariables }) => getAllEnvironmentVariables({
@@ -130,7 +133,8 @@ async function runDev({
130
133
  envBranch,
131
134
  envHandle,
132
135
  fetchRemote,
133
- localVariables
136
+ localVariables,
137
+ envFile
134
138
  })
135
139
  );
136
140
  if (debug && !inspectorPort) {
@@ -140,19 +144,17 @@ async function runDev({
140
144
  if (hydrogenPackagesPath) {
141
145
  await removeFile(joinPath(root, "node_modules/.vite"));
142
146
  }
143
- const customLogger = vite.createLogger();
144
- if (process.env.SHOPIFY_UNIT_TEST) {
145
- customLogger.info = (msg) => collectLog("info", msg);
146
- customLogger.warn = (msg) => collectLog("warn", msg);
147
- customLogger.error = (msg) => collectLog("error", msg);
148
- }
149
147
  const formatOptionsPromise = Promise.resolve().then(
150
148
  () => getCodeFormatOptions(root)
151
149
  );
152
150
  const viteServer = await vite.createServer({
153
151
  root,
154
- customLogger,
155
152
  clearScreen: false,
153
+ customLogger: process.env.SHOPIFY_UNIT_TEST ? Object.assign(vite.createLogger(), {
154
+ info: (msg) => collectLog("info", msg),
155
+ warn: (msg) => collectLog("warn", msg),
156
+ error: (msg) => collectLog("error", msg)
157
+ }) : void 0,
156
158
  server: {
157
159
  host: host ? true : void 0,
158
160
  // Allow Vite to read files from the Hydrogen packages in local development.
@@ -21,6 +21,7 @@ class EnvPull extends Command {
21
21
  static flags = {
22
22
  ...commonFlags.env,
23
23
  ...commonFlags.envBranch,
24
+ ...commonFlags.envFile,
24
25
  ...commonFlags.path,
25
26
  ...commonFlags.force
26
27
  };
@@ -33,6 +34,7 @@ async function runEnvPull({
33
34
  env: envHandle,
34
35
  envBranch,
35
36
  path: root = process.cwd(),
37
+ envFile,
36
38
  force
37
39
  }) {
38
40
  const [{ session, config }, cliCommand] = await Promise.all([
@@ -77,8 +79,8 @@ async function runEnvPull({
77
79
  }
78
80
  const variables = storefront.environmentVariables;
79
81
  if (!variables.length) return;
80
- const fileName = colors.whiteBright(`.env`);
81
- const dotEnvPath = resolvePath(root, ".env");
82
+ const fileName = colors.whiteBright(envFile);
83
+ const dotEnvPath = resolvePath(root, envFile);
82
84
  const fetchedEnv = {};
83
85
  variables.forEach(({ isSecret, key, value }) => {
84
86
  fetchedEnv[key] = isSecret ? `""` : value;
@@ -96,7 +98,7 @@ async function runEnvPull({
96
98
  const overwrite = await renderConfirmationPrompt({
97
99
  confirmationMessage: `Yes, confirm changes`,
98
100
  cancellationMessage: `No, make changes later`,
99
- message: outputContent`We'll make the following changes to your .env file:
101
+ message: outputContent`We'll make the following changes to your ${fileName} file:
100
102
 
101
103
  ${outputToken.linesDiff(diff)}
102
104
  Continue?`.value
@@ -1,6 +1,5 @@
1
1
  import Command from '@shopify/cli-kit/node/base-command';
2
2
  import { diffLines } from 'diff';
3
- import { Flags } from '@oclif/core';
4
3
  import { commonFlags, flagsToCamelObject } from '../../../lib/flags.js';
5
4
  import { login } from '../../../lib/auth.js';
6
5
  import { getCliCommand } from '../../../lib/shell.js';
@@ -19,9 +18,7 @@ class EnvPush extends Command {
19
18
  static description = "Push environment variables from the local .env file to your linked Hydrogen storefront.";
20
19
  static flags = {
21
20
  ...commonFlags.env,
22
- "env-file": Flags.string({
23
- description: "Path to an environment file to override existing environment variables for the selected environment. Defaults to the '.env' located in your project path `--path`."
24
- }),
21
+ ...commonFlags.envFile,
25
22
  ...commonFlags.path
26
23
  };
27
24
  async run() {
@@ -35,7 +32,7 @@ async function runEnvPush({
35
32
  path = process.cwd()
36
33
  }) {
37
34
  let validatedEnvironment;
38
- const dotEnvPath = envFile || resolvePath(path, ".env");
35
+ const dotEnvPath = resolvePath(path, envFile);
39
36
  const { variables: localVariables } = await readAndParseDotEnv(dotEnvPath);
40
37
  const [{ session, config }, cliCommand] = await Promise.all([
41
38
  login(path),
@@ -1,6 +1,8 @@
1
1
  import Command from '@shopify/cli-kit/node/base-command';
2
+ import { outputNewline } from '@shopify/cli-kit/node/output';
2
3
  import { commonFlags } from '../../lib/flags.js';
3
4
  import { login, renderLoginSuccess } from '../../lib/auth.js';
5
+ import { enhanceAuthLogs } from '../../lib/log.js';
4
6
 
5
7
  class Login extends Command {
6
8
  static descriptionWithMarkdown = "Logs in to the specified shop and saves the shop domain to the project.";
@@ -18,6 +20,8 @@ async function runLogin({
18
20
  path: root = process.cwd(),
19
21
  shop: shopFlag
20
22
  }) {
23
+ outputNewline();
24
+ enhanceAuthLogs(true);
21
25
  const { config } = await login(root, shopFlag ?? true);
22
26
  renderLoginSuccess(config);
23
27
  }
@@ -1,5 +1,6 @@
1
1
  import Command from '@shopify/cli-kit/node/base-command';
2
2
  import { renderSuccess } from '@shopify/cli-kit/node/ui';
3
+ import { outputNewline } from '@shopify/cli-kit/node/output';
3
4
  import { commonFlags } from '../../lib/flags.js';
4
5
  import { logout } from '../../lib/auth.js';
5
6
 
@@ -15,6 +16,7 @@ class Logout extends Command {
15
16
  }
16
17
  }
17
18
  async function runLogout({ path: root = process.cwd() }) {
19
+ outputNewline();
18
20
  await logout(root);
19
21
  renderSuccess({ body: "You are logged out from Shopify." });
20
22
  }
@@ -4,7 +4,7 @@ import { AbortError } from '@shopify/cli-kit/node/error';
4
4
  import { outputInfo } from '@shopify/cli-kit/node/output';
5
5
  import { resolvePath, joinPath } from '@shopify/cli-kit/node/path';
6
6
  import { setH2OVerbose, isH2Verbose, muteDevLogs } from '../../lib/log.js';
7
- import { getProjectPaths, hasRemixConfigFile } from '../../lib/remix-config.js';
7
+ import { getProjectPaths, isClassicProject } from '../../lib/remix-config.js';
8
8
  import { commonFlags, deprecated, overrideFlag, flagsToCamelObject, DEFAULT_APP_PORT } from '../../lib/flags.js';
9
9
  import { startMiniOxygen } from '../../lib/mini-oxygen/index.js';
10
10
  import { getAllEnvironmentVariables } from '../../lib/environment-variables.js';
@@ -27,6 +27,7 @@ class Preview extends Command {
27
27
  ...commonFlags.legacyRuntime,
28
28
  ...commonFlags.env,
29
29
  ...commonFlags.envBranch,
30
+ ...commonFlags.envFile,
30
31
  ...commonFlags.inspectorPort,
31
32
  ...commonFlags.debug,
32
33
  ...commonFlags.verbose,
@@ -65,6 +66,7 @@ class Preview extends Command {
65
66
  await close();
66
67
  if (diff) {
67
68
  await diff.copyDiffBuild();
69
+ if (flags.codegen) await diff.copyDiffCodegen();
68
70
  await diff.cleanup();
69
71
  }
70
72
  });
@@ -83,15 +85,16 @@ async function runPreview({
83
85
  watch = false,
84
86
  codegen: useCodegen = false,
85
87
  codegenConfigPath,
86
- entry
88
+ entry,
89
+ envFile
87
90
  }) {
88
91
  if (!process.env.NODE_ENV)
89
92
  process.env.NODE_ENV = watch ? "development" : "production";
90
93
  if (verbose) setH2OVerbose();
91
94
  if (!isH2Verbose()) muteDevLogs();
92
95
  let { root, buildPath, buildPathWorkerFile, buildPathClient } = getProjectPaths(directory);
93
- const isClassicProject = await hasRemixConfigFile(root);
94
- if (watch && isClassicProject) {
96
+ const useClassicCompiler = await isClassicProject(root);
97
+ if (watch && useClassicCompiler) {
95
98
  throw new AbortError(
96
99
  "Preview in watch mode is not supported for classic Remix projects.",
97
100
  "Please use the dev command instead, which is the equivalent for classic projects."
@@ -109,7 +112,7 @@ async function runPreview({
109
112
  useCodegen,
110
113
  codegenConfigPath
111
114
  };
112
- const buildProcess = shouldBuild ? isClassicProject ? await runClassicCompilerBuild({
115
+ const buildProcess = shouldBuild ? useClassicCompiler ? await runClassicCompilerBuild({
113
116
  ...buildOptions
114
117
  }).then(projectBuild.resolve) : await runBuild({
115
118
  ...buildOptions,
@@ -123,7 +126,7 @@ async function runPreview({
123
126
  await miniOxygen?.reload();
124
127
  }
125
128
  }) : projectBuild.resolve();
126
- if (!isClassicProject) {
129
+ if (!useClassicCompiler) {
127
130
  const maybeResult = await getViteConfig(root).catch(() => null);
128
131
  buildPathWorkerFile = maybeResult?.serverOutFile ?? joinPath(buildPath, "server", "index.js");
129
132
  }
@@ -134,7 +137,8 @@ async function runPreview({
134
137
  root,
135
138
  fetchRemote,
136
139
  envBranch,
137
- envHandle
140
+ envHandle,
141
+ envFile
138
142
  }
139
143
  );
140
144
  if (!appPort) {
@@ -32,9 +32,7 @@ class Setup extends Command {
32
32
  }
33
33
  async function runSetup(options) {
34
34
  const controller = new AbortController();
35
- const { rootDirectory, appDirectory, serverEntryPoint } = await getRemixConfig(
36
- options.directory
37
- );
35
+ const { rootDirectory, appDirectory } = await getRemixConfig(options.directory);
38
36
  const location = basename(rootDirectory);
39
37
  const cliCommandPromise = getCliCommand();
40
38
  let backgroundWorkPromise = Promise.resolve();
@@ -88,7 +86,7 @@ async function runSetup(options) {
88
86
  }
89
87
  if (i18n) {
90
88
  backgroundWorkPromise = backgroundWorkPromise.then(
91
- () => setupI18nStrategy(i18n, { rootDirectory, serverEntryPoint })
89
+ () => setupI18nStrategy(i18n, { rootDirectory })
92
90
  );
93
91
  }
94
92
  let cliCommand = await Promise.resolve(cliCommandPromise);
@@ -53,9 +53,12 @@ function commandNeedsVM(id = "", argv = []) {
53
53
  function isHydrogenProject(projectPath) {
54
54
  try {
55
55
  const require2 = createRequire(import.meta.url);
56
- const { dependencies } = require2(joinPath(projectPath, "package.json"));
57
- return !!dependencies["@shopify/hydrogen"] || // Diff examples only have this package as a dependency
58
- !!dependencies["@shopify/cli-hydrogen"];
56
+ const { dependencies, scripts } = require2(joinPath(
57
+ projectPath,
58
+ "package.json"
59
+ ));
60
+ return !!dependencies?.["@shopify/hydrogen"] || // Diff examples don't have dependencies:
61
+ !!scripts?.dev?.includes("--diff");
59
62
  } catch {
60
63
  return false;
61
64
  }
package/dist/index.d.ts CHANGED
@@ -39,6 +39,7 @@ declare class Codegen extends Command {
39
39
  static descriptionWithMarkdown: string;
40
40
  static description: string;
41
41
  static flags: {
42
+ diff: _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
42
43
  'codegen-config-path': _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
43
44
  'force-sfapi-version': _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
44
45
  watch: _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
@@ -122,6 +123,7 @@ declare class Dev extends Command {
122
123
  'customer-account-push__unstable': _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
123
124
  diff: _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
124
125
  'disable-version-check': _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
126
+ 'env-file': _oclif_core_lib_interfaces_parser_js.OptionFlag<string, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
125
127
  'env-branch': _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
126
128
  env: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
127
129
  'inspector-port': _oclif_core_lib_interfaces_parser_js.OptionFlag<number | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
@@ -151,6 +153,7 @@ declare class EnvPull extends Command {
151
153
  static flags: {
152
154
  force: _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
153
155
  path: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
156
+ 'env-file': _oclif_core_lib_interfaces_parser_js.OptionFlag<string, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
154
157
  'env-branch': _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
155
158
  env: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
156
159
  };
@@ -161,7 +164,7 @@ declare class EnvPush extends Command {
161
164
  static description: string;
162
165
  static flags: {
163
166
  path: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
164
- 'env-file': _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
167
+ 'env-file': _oclif_core_lib_interfaces_parser_js.OptionFlag<string, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
165
168
  env: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
166
169
  };
167
170
  run(): Promise<void>;
@@ -256,6 +259,7 @@ declare class Preview extends Command {
256
259
  verbose: _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
257
260
  debug: _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
258
261
  'inspector-port': _oclif_core_lib_interfaces_parser_js.OptionFlag<number | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
262
+ 'env-file': _oclif_core_lib_interfaces_parser_js.OptionFlag<string, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
259
263
  'env-branch': _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
260
264
  env: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
261
265
  'legacy-runtime': _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
package/dist/lib/auth.js CHANGED
@@ -1,20 +1,17 @@
1
- import { renderSelectPrompt, renderInfo, renderTasks, renderSuccess } from '@shopify/cli-kit/node/ui';
1
+ import { renderSelectPrompt, renderSuccess } from '@shopify/cli-kit/node/ui';
2
2
  import { AbortError } from '@shopify/cli-kit/node/error';
3
3
  import { logout as logout$1, ensureAuthenticatedBusinessPlatform, ensureAuthenticatedAdmin } from '@shopify/cli-kit/node/session';
4
4
  import { normalizeStoreFqdn } from '@shopify/cli-kit/node/context/fqdn';
5
- import { outputContent, outputToken } from '@shopify/cli-kit/node/output';
6
- import colors from '@shopify/cli-kit/node/colors';
7
- import ansiEscapes from 'ansi-escapes';
8
5
  import { resetConfig, getConfig, setUserAccount } from './shopify-config.js';
9
6
  import { getUserAccount } from './graphql/business-platform/user-account.js';
10
- import { muteAuthLogs } from './log.js';
11
- import { deferPromise } from './defer.js';
7
+ import { enhanceAuthLogs } from './log.js';
12
8
 
13
9
  async function logout(root) {
14
10
  await logout$1();
15
11
  await resetConfig(root);
16
12
  }
17
13
  async function login(root, shop) {
14
+ enhanceAuthLogs(false);
18
15
  const forcePrompt = shop === true;
19
16
  const existingConfig = root ? await getConfig(root) : {};
20
17
  let { email, shopName } = existingConfig;
@@ -22,7 +19,6 @@ async function login(root, shop) {
22
19
  shop = existingConfig.shop;
23
20
  }
24
21
  if (shop) shop = await normalizeStoreFqdn(shop);
25
- const hideLoginInfo = showLoginInfo();
26
22
  if (!shop || !shopName || !email || forcePrompt || shop !== existingConfig.shop) {
27
23
  const token = await ensureAuthenticatedBusinessPlatform().catch(() => {
28
24
  throw new AbortError(
@@ -30,7 +26,6 @@ async function login(root, shop) {
30
26
  );
31
27
  });
32
28
  const userAccount = await getUserAccount(token);
33
- await hideLoginInfo();
34
29
  const preselected = !forcePrompt && shop && userAccount.activeShops.find(({ fqdn }) => shop === fqdn);
35
30
  const selected = preselected || await renderSelectPrompt({
36
31
  message: "Select a shop to log in to",
@@ -48,64 +43,9 @@ async function login(root, shop) {
48
43
  `Ensure the shop that you specified is correct (you are trying to use: ${shop})`
49
44
  ]);
50
45
  });
51
- await hideLoginInfo();
52
46
  const config = root ? await setUserAccount(root, { shop, shopName, email }) : { shop, shopName, email };
53
47
  return { session, config };
54
48
  }
55
- function showLoginInfo() {
56
- const deferred = deferPromise();
57
- console.log("");
58
- let hasLoggedTimeout = false;
59
- let hasLoggedPressKey = false;
60
- const restoreLogs = muteAuthLogs({
61
- onKeyTimeout: (link) => {
62
- if (link) {
63
- hasLoggedTimeout = true;
64
- process.stdout.write(ansiEscapes.eraseLines(9));
65
- try {
66
- const secureLink = link.replace("http://", "https://");
67
- const url = new URL(secureLink);
68
- const label = url.origin + "/..." + url.search.slice(-14);
69
- renderInfo({
70
- headline: "Log in to Shopify",
71
- body: outputContent`Timed out. Click to open your browser:\n${outputToken.link(
72
- colors.white(label),
73
- secureLink
74
- )}`.value
75
- });
76
- } catch {
77
- }
78
- }
79
- },
80
- onPressKey: () => {
81
- hasLoggedPressKey = true;
82
- renderInfo({
83
- headline: "Log in to Shopify",
84
- body: "Press any key to login with your default browser"
85
- });
86
- process.stdin.once("data", () => {
87
- renderTasks([
88
- {
89
- title: "Waiting for Shopify authentication",
90
- task: async () => {
91
- await deferred.promise;
92
- }
93
- }
94
- ]);
95
- });
96
- }
97
- });
98
- deferred.promise.then(() => {
99
- restoreLogs();
100
- if (hasLoggedPressKey) {
101
- process.stdout.write(ansiEscapes.eraseLines(hasLoggedTimeout ? 11 : 10));
102
- }
103
- });
104
- return async () => {
105
- deferred.resolve();
106
- await new Promise((resolve) => setTimeout(resolve, 0));
107
- };
108
- }
109
49
  function renderLoginSuccess(config) {
110
50
  renderSuccess({
111
51
  headline: "Shopify authentication complete",
@@ -36,6 +36,7 @@ async function runClassicCompilerDev({
36
36
  inspectorPort,
37
37
  customerAccountPush: customerAccountPushFlag = false,
38
38
  shouldLiveReload = true,
39
+ envFile,
39
40
  cliConfig,
40
41
  verbose
41
42
  }) {
@@ -71,7 +72,8 @@ async function runClassicCompilerDev({
71
72
  }
72
73
  const backgroundPromise = getDevConfigInBackground(
73
74
  root,
74
- customerAccountPushFlag
75
+ customerAccountPushFlag,
76
+ envFile
75
77
  );
76
78
  const tunnelPromise = cliConfig && backgroundPromise.then(({ customerAccountPush, storefrontId }) => {
77
79
  if (customerAccountPush) {
@@ -91,7 +93,8 @@ async function runClassicCompilerDev({
91
93
  fetchRemote,
92
94
  envBranch,
93
95
  envHandle,
94
- localVariables
96
+ localVariables,
97
+ envFile
95
98
  })
96
99
  );
97
100
  const [{ watch }, { createFileWatchCache }] = await Promise.all([
@@ -215,14 +218,15 @@ async function runClassicCompilerDev({
215
218
  const [relative, absolute] = getFilePaths(file);
216
219
  outputInfo(`
217
220
  \u{1F4C4} File changed: ${relative}`);
218
- if (relative.endsWith(".env")) {
221
+ if (relative.endsWith(envFile)) {
219
222
  skipRebuildLogs = true;
220
223
  const { fetchRemote } = await backgroundPromise;
221
224
  const { allVariables, logInjectedVariables } = await getAllEnvironmentVariables({
222
225
  root,
223
226
  fetchRemote,
224
227
  envBranch,
225
- envHandle
228
+ envHandle,
229
+ envFile
226
230
  });
227
231
  logInjectedVariables();
228
232
  await miniOxygen.reload({