@shopify/cli-hydrogen 12.0.2 → 13.0.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.
@@ -32,7 +32,7 @@
32
32
  "@react-router/fs-routes": "7.16.0",
33
33
  "@shopify/cli": "3.93.2",
34
34
  "@shopify/hydrogen-codegen": "0.3.3",
35
- "@shopify/mini-oxygen": "4.1.0",
35
+ "@shopify/mini-oxygen": "4.2.0",
36
36
  "@shopify/oxygen-workers-types": "^4.1.6",
37
37
  "@shopify/prettier-config": "^1.1.2",
38
38
  "@total-typescript/ts-reset": "^0.6.1",
@@ -21,6 +21,7 @@ import { isClassicProject, getProjectPaths } from '../../lib/remix-config.js';
21
21
  import { packageManagers } from '../../lib/package-managers.js';
22
22
 
23
23
  const DEPLOY_OUTPUT_FILE_HANDLE = "h2_deploy_log.json";
24
+ const DEFAULT_BUILD_COMMAND = "node --run build";
24
25
  const deploymentLogger = (message, level = "info") => {
25
26
  if (level === "error" || level === "warn") {
26
27
  outputWarn(message);
@@ -69,7 +70,17 @@ class Deploy extends Command {
69
70
  dependsOn: ["auth-bypass-token"]
70
71
  }),
71
72
  "build-command": Flags.string({
72
- description: "Specify a build command to run before deploying. If not specified, `shopify hydrogen build` will be used.",
73
+ description: "Specify a build command to run before deploying. If not specified, the Hydrogen build pipeline will be used. When custom output directories are configured, defaults to `node --run build`.",
74
+ required: false
75
+ }),
76
+ "assets-dir": Flags.string({
77
+ description: "Directory containing the client assets to deploy, relative to the project root. Defaults to the detected Vite client output directory, then falls back to `dist/client`.",
78
+ env: "SHOPIFY_HYDROGEN_FLAG_ASSETS_DIR",
79
+ required: false
80
+ }),
81
+ "worker-dir": Flags.string({
82
+ description: "Directory containing the Oxygen worker entry point (`index.js` or `index.mjs`), relative to the project root. Defaults to the detected Vite server output directory, then falls back to `dist/server`.",
83
+ env: "SHOPIFY_HYDROGEN_FLAG_WORKER_DIR",
73
84
  required: false
74
85
  }),
75
86
  ...commonFlags.lockfileCheck,
@@ -162,10 +173,12 @@ async function runDeploy(options) {
162
173
  jsonOutput,
163
174
  path: root,
164
175
  shop,
176
+ assetsDir: assetsDirFlag,
165
177
  metadataUrl,
166
178
  metadataUser,
167
179
  metadataVersion,
168
- entry: ssrEntry
180
+ entry: ssrEntry,
181
+ workerDir: workerDirFlag
169
182
  } = options;
170
183
  let { metadataDescription } = options;
171
184
  let isCleanGit = true;
@@ -335,16 +348,22 @@ ${changedFiles.trimEnd()}`;
335
348
  let assetsDir = "dist/client";
336
349
  let workerDir = "dist/worker";
337
350
  const isClassicCompiler = await isClassicProject(root);
338
- if (!isClassicCompiler) {
351
+ const metadataHydrogenVersion = getHydrogenVersion({ appPath: root });
352
+ const shouldUseDefaultBuildCommand = !buildCommand && !isClassicCompiler && (assetsDirFlag || workerDirFlag || isHydrogenPreviewVersion(metadataHydrogenVersion));
353
+ if (isClassicCompiler) {
354
+ assetsDir = assetsDirFlag ?? assetsDir;
355
+ workerDir = workerDirFlag ?? workerDir;
356
+ } else {
339
357
  const viteConfig = await getViteConfig(root, ssrEntry).catch(() => null);
340
- if (viteConfig) {
341
- assetsDir = relativePath(root, viteConfig.clientOutDir);
342
- workerDir = relativePath(root, viteConfig.serverOutDir);
343
- } else {
344
- workerDir = "dist/server";
345
- }
358
+ const outputDirs = await resolveDeploymentOutputDirs({
359
+ root,
360
+ viteConfig,
361
+ assetsDir: assetsDirFlag,
362
+ workerDir: workerDirFlag
363
+ });
364
+ assetsDir = outputDirs.assetsDir;
365
+ workerDir = outputDirs.workerDir;
346
366
  }
347
- const metadataHydrogenVersion = await getHydrogenVersion({ appPath: root });
348
367
  const config = {
349
368
  assetsDir,
350
369
  bugsnag: true,
@@ -436,7 +455,7 @@ Continue?`.value
436
455
  );
437
456
  }
438
457
  };
439
- if (buildCommand) {
458
+ if (buildCommand || shouldUseDefaultBuildCommand) {
440
459
  if (forceClientSourcemap) {
441
460
  console.log("");
442
461
  renderInfo({
@@ -444,7 +463,7 @@ Continue?`.value
444
463
  body: "Client sourcemaps will not be generated."
445
464
  });
446
465
  }
447
- config.buildCommand = buildCommand;
466
+ config.buildCommand = buildCommand ?? DEFAULT_BUILD_COMMAND;
448
467
  } else {
449
468
  hooks.buildFunction = async (assetPath) => {
450
469
  outputInfo(
@@ -527,15 +546,41 @@ Continue?`.value
527
546
  });
528
547
  return deployPromise;
529
548
  }
530
- async function getHydrogenVersion({ appPath }) {
549
+ async function resolveDeploymentOutputDirs({
550
+ root,
551
+ viteConfig,
552
+ assetsDir,
553
+ workerDir
554
+ }) {
555
+ const fallbackOutputDirs = {
556
+ assetsDir: "dist/client",
557
+ workerDir: "dist/server"
558
+ };
559
+ const viteOutputDirs = viteConfig ? {
560
+ assetsDir: relativePath(root, viteConfig.clientOutDir),
561
+ workerDir: relativePath(root, viteConfig.serverOutDir)
562
+ } : void 0;
563
+ return {
564
+ assetsDir: assetsDir ?? viteOutputDirs?.assetsDir ?? fallbackOutputDirs.assetsDir,
565
+ workerDir: workerDir ?? viteOutputDirs?.workerDir ?? fallbackOutputDirs.workerDir
566
+ };
567
+ }
568
+ function isHydrogenPreviewVersion(version) {
569
+ return version?.startsWith("0.0.0-preview-") ?? false;
570
+ }
571
+ function getHydrogenVersion({ appPath }) {
531
572
  const { root } = getProjectPaths(appPath);
532
- const require2 = createRequire(import.meta.url);
533
- const { version } = require2(
534
- require2.resolve("@shopify/hydrogen/package.json", {
535
- paths: [root]
536
- })
537
- );
538
- return version;
573
+ try {
574
+ const require2 = createRequire(import.meta.url);
575
+ const packageJson = require2(
576
+ require2.resolve("@shopify/hydrogen/package.json", {
577
+ paths: [root]
578
+ })
579
+ );
580
+ return typeof packageJson.version === "string" ? packageJson.version : void 0;
581
+ } catch {
582
+ return void 0;
583
+ }
539
584
  }
540
585
 
541
- export { Deploy as default, deploymentLogger, getHydrogenVersion, runDeploy };
586
+ export { Deploy as default, deploymentLogger, getHydrogenVersion, resolveDeploymentOutputDirs, runDeploy };
@@ -38,8 +38,8 @@ async function getViteConfig(root, ssrEntryFlag) {
38
38
  mode
39
39
  );
40
40
  const { appDirectory, serverBuildFile, routes } = getReactRouterOrRemixConfigFromVite(resolvedViteConfig);
41
- const serverOutDir = resolvedViteConfig.build.outDir;
42
- const clientOutDir = serverOutDir.replace(/server$/, "client");
41
+ const serverOutDir = resolvedViteConfig.environments.ssr?.build.outDir ?? resolvedViteConfig.build.outDir;
42
+ const clientOutDir = resolvedViteConfig.environments.client?.build.outDir ?? serverOutDir.replace(/server$/, "client");
43
43
  const rollupOutput = resolvedViteConfig.build.rollupOptions.output;
44
44
  const { entryFileNames } = (Array.isArray(rollupOutput) ? rollupOutput[0] : rollupOutput) ?? {};
45
45
  const serverOutFile = joinPath(
@@ -388,13 +388,31 @@
388
388
  "type": "option"
389
389
  },
390
390
  "build-command": {
391
- "description": "Specify a build command to run before deploying. If not specified, `shopify hydrogen build` will be used.",
391
+ "description": "Specify a build command to run before deploying. If not specified, the Hydrogen build pipeline will be used. When custom output directories are configured, defaults to `node --run build`.",
392
392
  "name": "build-command",
393
393
  "required": false,
394
394
  "hasDynamicHelp": false,
395
395
  "multiple": false,
396
396
  "type": "option"
397
397
  },
398
+ "assets-dir": {
399
+ "description": "Directory containing the client assets to deploy, relative to the project root. Defaults to the detected Vite client output directory, then falls back to `dist/client`.",
400
+ "env": "SHOPIFY_HYDROGEN_FLAG_ASSETS_DIR",
401
+ "name": "assets-dir",
402
+ "required": false,
403
+ "hasDynamicHelp": false,
404
+ "multiple": false,
405
+ "type": "option"
406
+ },
407
+ "worker-dir": {
408
+ "description": "Directory containing the Oxygen worker entry point (`index.js` or `index.mjs`), relative to the project root. Defaults to the detected Vite server output directory, then falls back to `dist/server`.",
409
+ "env": "SHOPIFY_HYDROGEN_FLAG_WORKER_DIR",
410
+ "name": "worker-dir",
411
+ "required": false,
412
+ "hasDynamicHelp": false,
413
+ "multiple": false,
414
+ "type": "option"
415
+ },
398
416
  "lockfile-check": {
399
417
  "description": "Checks that there is exactly one valid lockfile in the project. Defaults to `true`. Deactivate with `--no-lockfile-check`.",
400
418
  "env": "SHOPIFY_HYDROGEN_FLAG_LOCKFILE_CHECK",
@@ -1675,5 +1693,5 @@
1675
1693
  ]
1676
1694
  }
1677
1695
  },
1678
- "version": "12.0.2"
1696
+ "version": "13.0.0"
1679
1697
  }
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "access": "public",
5
5
  "@shopify:registry": "https://registry.npmjs.org"
6
6
  },
7
- "version": "12.0.2",
7
+ "version": "13.0.0",
8
8
  "license": "MIT",
9
9
  "type": "module",
10
10
  "repository": {
@@ -59,7 +59,7 @@
59
59
  "graphql-config": "^5.0.3",
60
60
  "vite": "^5.1.0 || ^6.2.0 || ^7.0.0 || ^8.0.0",
61
61
  "@shopify/hydrogen-codegen": "0.3.3",
62
- "@shopify/mini-oxygen": "4.1.0"
62
+ "@shopify/mini-oxygen": "4.2.0"
63
63
  },
64
64
  "peerDependenciesMeta": {
65
65
  "@graphql-codegen/cli": {
@@ -98,7 +98,7 @@
98
98
  "oclif.manifest.json"
99
99
  ],
100
100
  "engines": {
101
- "node": "^20 || ^22 || ^24"
101
+ "node": "^22 || ^24"
102
102
  },
103
103
  "oclif": {
104
104
  "commands": "dist/commands",