@shopify/cli-hydrogen 6.0.2 → 6.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 (30) hide show
  1. package/dist/commands/hydrogen/deploy.js +72 -8
  2. package/dist/commands/hydrogen/deploy.test.js +111 -9
  3. package/dist/commands/hydrogen/dev.js +33 -23
  4. package/dist/commands/hydrogen/preview.js +20 -10
  5. package/dist/commands/hydrogen/shortcut.js +1 -0
  6. package/dist/commands/hydrogen/upgrade.js +705 -0
  7. package/dist/commands/hydrogen/upgrade.test.js +786 -0
  8. package/dist/generator-templates/starter/CHANGELOG.md +70 -0
  9. package/dist/generator-templates/starter/app/components/Footer.tsx +3 -1
  10. package/dist/generator-templates/starter/app/components/Layout.tsx +13 -10
  11. package/dist/generator-templates/starter/app/routes/[robots.txt].tsx +0 -27
  12. package/dist/generator-templates/starter/package.json +10 -9
  13. package/dist/generator-templates/starter/remix.env.d.ts +2 -0
  14. package/dist/lib/check-lockfile.js +1 -0
  15. package/dist/lib/codegen.js +1 -0
  16. package/dist/lib/flags.js +13 -2
  17. package/dist/lib/log.js +1 -0
  18. package/dist/lib/mini-oxygen/assets.js +118 -0
  19. package/dist/lib/mini-oxygen/common.js +2 -1
  20. package/dist/lib/mini-oxygen/index.js +3 -0
  21. package/dist/lib/mini-oxygen/node.js +15 -3
  22. package/dist/lib/mini-oxygen/workerd-inspector-logs.js +227 -0
  23. package/dist/lib/mini-oxygen/workerd-inspector-proxy.js +200 -0
  24. package/dist/lib/mini-oxygen/workerd-inspector.js +62 -235
  25. package/dist/lib/mini-oxygen/workerd.js +54 -47
  26. package/dist/lib/render-errors.js +2 -0
  27. package/dist/lib/setups/i18n/replacers.test.js +2 -0
  28. package/dist/lib/shell.js +1 -1
  29. package/oclif.manifest.json +90 -8
  30. package/package.json +10 -21
@@ -1,5 +1,75 @@
1
1
  # skeleton
2
2
 
3
+ ## 1.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Sync up environment variable names across all example & type files. ([#1542](https://github.com/Shopify/hydrogen/pull/1542)) by [@michenly](https://github.com/michenly)
8
+
9
+ - Remove error boundary from robots.txt file in the Skeleton template ([#1492](https://github.com/Shopify/hydrogen/pull/1492)) by [@andrewcohen](https://github.com/andrewcohen)
10
+
11
+ - Use the worker runtime by default when running the `dev` or `preview` commands. ([#1525](https://github.com/Shopify/hydrogen/pull/1525)) by [@frandiox](https://github.com/frandiox)
12
+
13
+ Enable it in your project by adding the `--worker` flag to your package.json scripts:
14
+
15
+ ```diff
16
+ "scripts": {
17
+ "build": "shopify hydrogen build",
18
+ - "dev": "shopify hydrogen dev --codegen",
19
+ + "dev": "shopify hydrogen dev --worker --codegen",
20
+ - "preview": "npm run build && shopify hydrogen preview",
21
+ + "preview": "npm run build && shopify hydrogen preview --worker",
22
+ ...
23
+ }
24
+ ```
25
+
26
+ - Update to the latest version of `@shopify/oxygen-workers-types`. ([#1494](https://github.com/Shopify/hydrogen/pull/1494)) by [@frandiox](https://github.com/frandiox)
27
+
28
+ In TypeScript projects, when updating to the latest `@shopify/remix-oxygen` adapter release, you should also update to the latest version of `@shopify/oxygen-workers-types`:
29
+
30
+ ```diff
31
+ "devDependencies": {
32
+ "@remix-run/dev": "2.1.0",
33
+ "@remix-run/eslint-config": "2.1.0",
34
+ - "@shopify/oxygen-workers-types": "^3.17.3",
35
+ + "@shopify/oxygen-workers-types": "^4.0.0",
36
+ "@shopify/prettier-config": "^1.1.2",
37
+ ...
38
+ },
39
+ ```
40
+
41
+ - Update internal dependencies for bug resolution. ([#1496](https://github.com/Shopify/hydrogen/pull/1496)) by [@vincentezw](https://github.com/vincentezw)
42
+
43
+ Update your `@shopify/cli` dependency to avoid duplicated sub-dependencies:
44
+
45
+ ```diff
46
+ "dependencies": {
47
+ - "@shopify/cli": "3.50.2",
48
+ + "@shopify/cli": "3.51.0",
49
+ }
50
+ ```
51
+
52
+ - Update all Node.js dependencies to version 18. (Not a breaking change, since Node.js 18 is already required by Remix v2.) ([#1543](https://github.com/Shopify/hydrogen/pull/1543)) by [@michenly](https://github.com/michenly)
53
+
54
+ - 🐛 fix undefined menu error ([#1533](https://github.com/Shopify/hydrogen/pull/1533)) by [@michenly](https://github.com/michenly)
55
+
56
+ - Add `@remix-run/server-runtime` dependency. ([#1489](https://github.com/Shopify/hydrogen/pull/1489)) by [@frandiox](https://github.com/frandiox)
57
+
58
+ Since Remix is now a peer dependency of `@shopify/remix-oxygen`, you need to add `@remix-run/server-runtime` to your dependencies, with the same version as the rest of your Remix dependencies.
59
+
60
+ ```diff
61
+ "dependencies": {
62
+ "@remix-run/react": "2.1.0"
63
+ + "@remix-run/server-runtime": "2.1.0"
64
+ ...
65
+ }
66
+ ```
67
+
68
+ - Updated dependencies [[`b2a350a7`](https://github.com/Shopify/hydrogen/commit/b2a350a754ea2d29bc267c260dc298a02f8f4470), [`9b4f4534`](https://github.com/Shopify/hydrogen/commit/9b4f453407338874bd8f1a1f619b607670e021d0), [`74ea1dba`](https://github.com/Shopify/hydrogen/commit/74ea1dba9af37a146882df7ed9674be5659862b5), [`2be9ce82`](https://github.com/Shopify/hydrogen/commit/2be9ce82fd4a5121f1772bbb7349e96ed530e84e), [`a9b8bcde`](https://github.com/Shopify/hydrogen/commit/a9b8bcde96c22cedef7d87631d429199810b4a7a), [`bca112ed`](https://github.com/Shopify/hydrogen/commit/bca112ed7db49e533fe49898b663fa0dd318e6ba), [`848c6260`](https://github.com/Shopify/hydrogen/commit/848c6260a2db3a9cb0c86351f0f7128f61e028f0), [`d53b4ed7`](https://github.com/Shopify/hydrogen/commit/d53b4ed752eb0530622a666ea7dcf4b40239cafa), [`961fd8c6`](https://github.com/Shopify/hydrogen/commit/961fd8c630727784f77b9f693d2e8ff8601969fc), [`2bff9fc7`](https://github.com/Shopify/hydrogen/commit/2bff9fc75916fa95f9a9279d069408fb7a33755c), [`c8e8f6fd`](https://github.com/Shopify/hydrogen/commit/c8e8f6fd233e52cf5570b1904af710d6b907aae5), [`8fce70de`](https://github.com/Shopify/hydrogen/commit/8fce70de32bd61ee86a6d895ac43cc1f78f1bf49), [`f90e4d47`](https://github.com/Shopify/hydrogen/commit/f90e4d4713c6c1fc1e921a7ecd08e95fe5da1744), [`e8cc49fe`](https://github.com/Shopify/hydrogen/commit/e8cc49feff18f5ee72d5f6965ff2094addc23466)]:
69
+ - @shopify/cli-hydrogen@6.1.0
70
+ - @shopify/remix-oxygen@2.0.2
71
+ - @shopify/hydrogen@2023.10.3
72
+
3
73
  ## 1.0.0
4
74
 
5
75
  ### Major Changes
@@ -8,7 +8,9 @@ export function Footer({
8
8
  }: FooterQuery & {shop: HeaderQuery['shop']}) {
9
9
  return (
10
10
  <footer className="footer">
11
- <FooterMenu menu={menu} primaryDomainUrl={shop.primaryDomain.url} />
11
+ {menu && shop?.primaryDomain?.url && (
12
+ <FooterMenu menu={menu} primaryDomainUrl={shop.primaryDomain.url} />
13
+ )}
12
14
  </footer>
13
15
  );
14
16
  }
@@ -33,12 +33,12 @@ export function Layout({
33
33
  <>
34
34
  <CartAside cart={cart} />
35
35
  <SearchAside />
36
- <MobileMenuAside menu={header.menu} shop={header.shop} />
37
- <Header header={header} cart={cart} isLoggedIn={isLoggedIn} />
36
+ <MobileMenuAside menu={header?.menu} shop={header?.shop} />
37
+ {header && <Header header={header} cart={cart} isLoggedIn={isLoggedIn} />}
38
38
  <main>{children}</main>
39
39
  <Suspense>
40
40
  <Await resolve={footer}>
41
- {(footer) => <Footer menu={footer.menu} shop={header.shop} />}
41
+ {(footer) => <Footer menu={footer?.menu} shop={header?.shop} />}
42
42
  </Await>
43
43
  </Suspense>
44
44
  </>
@@ -94,12 +94,15 @@ function MobileMenuAside({
94
94
  shop: HeaderQuery['shop'];
95
95
  }) {
96
96
  return (
97
- <Aside id="mobile-menu-aside" heading="MENU">
98
- <HeaderMenu
99
- menu={menu}
100
- viewport="mobile"
101
- primaryDomainUrl={shop.primaryDomain.url}
102
- />
103
- </Aside>
97
+ menu &&
98
+ shop?.primaryDomain?.url && (
99
+ <Aside id="mobile-menu-aside" heading="MENU">
100
+ <HeaderMenu
101
+ menu={menu}
102
+ viewport="mobile"
103
+ primaryDomainUrl={shop.primaryDomain.url}
104
+ />
105
+ </Aside>
106
+ )
104
107
  );
105
108
  }
@@ -20,33 +20,6 @@ export async function loader({request, context}: LoaderFunctionArgs) {
20
20
  });
21
21
  }
22
22
 
23
- export function ErrorBoundary() {
24
- const error = useRouteError();
25
-
26
- if (isRouteErrorResponse(error)) {
27
- return (
28
- <div>
29
- <h1>Oops</h1>
30
- <p>Status: {error.status}</p>
31
- <p>{error.data.message}</p>
32
- </div>
33
- );
34
- }
35
-
36
- let errorMessage = 'Unknown error';
37
- if (error instanceof Error) {
38
- errorMessage = error.message;
39
- }
40
-
41
- return (
42
- <div>
43
- <h1>Uh oh ...</h1>
44
- <p>Something went wrong.</p>
45
- <pre>{errorMessage}</pre>
46
- </div>
47
- );
48
- }
49
-
50
23
  function robotsTxtData({url, shopId}: {shopId?: string; url?: string}) {
51
24
  const sitemapUrl = url ? `${url}/sitemap.xml` : undefined;
52
25
 
@@ -2,11 +2,11 @@
2
2
  "name": "skeleton",
3
3
  "private": true,
4
4
  "sideEffects": false,
5
- "version": "1.0.0",
5
+ "version": "1.0.1",
6
6
  "scripts": {
7
7
  "build": "shopify hydrogen build",
8
- "dev": "shopify hydrogen dev --codegen",
9
- "preview": "npm run build && shopify hydrogen preview",
8
+ "dev": "shopify hydrogen dev --worker --codegen",
9
+ "preview": "npm run build && shopify hydrogen preview --worker",
10
10
  "lint": "eslint --no-error-on-unmatched-pattern --ext .js,.ts,.jsx,.tsx .",
11
11
  "typecheck": "tsc --noEmit",
12
12
  "codegen": "shopify hydrogen codegen"
@@ -14,10 +14,11 @@
14
14
  "prettier": "@shopify/prettier-config",
15
15
  "dependencies": {
16
16
  "@remix-run/react": "2.1.0",
17
- "@shopify/cli": "3.50.0",
18
- "@shopify/cli-hydrogen": "^6.0.0",
19
- "@shopify/hydrogen": "^2023.10.0",
20
- "@shopify/remix-oxygen": "^2.0.0",
17
+ "@remix-run/server-runtime": "2.1.0",
18
+ "@shopify/cli": "3.51.0",
19
+ "@shopify/cli-hydrogen": "^6.1.0",
20
+ "@shopify/hydrogen": "~2023.10.3",
21
+ "@shopify/remix-oxygen": "^2.0.2",
21
22
  "graphql": "^16.6.0",
22
23
  "graphql-tag": "^2.12.6",
23
24
  "isbot": "^3.6.6",
@@ -27,7 +28,7 @@
27
28
  "devDependencies": {
28
29
  "@remix-run/dev": "2.1.0",
29
30
  "@remix-run/eslint-config": "2.1.0",
30
- "@shopify/oxygen-workers-types": "^3.17.3",
31
+ "@shopify/oxygen-workers-types": "^4.0.0",
31
32
  "@shopify/prettier-config": "^1.1.2",
32
33
  "@total-typescript/ts-reset": "^0.4.2",
33
34
  "@types/eslint": "^8.4.10",
@@ -39,6 +40,6 @@
39
40
  "typescript": "^5.2.2"
40
41
  },
41
42
  "engines": {
42
- "node": ">=16.13"
43
+ "node": ">=18.0.0"
43
44
  }
44
45
  }
@@ -24,6 +24,8 @@ declare global {
24
24
  PRIVATE_STOREFRONT_API_TOKEN: string;
25
25
  PUBLIC_STORE_DOMAIN: string;
26
26
  PUBLIC_STOREFRONT_ID: string;
27
+ PUBLIC_CUSTOMER_ACCOUNT_API_CLIENT_ID: string;
28
+ PUBLIC_CUSTOMER_ACCOUNT_API_URL: string;
27
29
  }
28
30
  }
29
31
 
@@ -25,6 +25,7 @@ function missingLockfileWarning(shouldExit) {
25
25
  }
26
26
  function multipleLockfilesWarning(lockfiles2, shouldExit) {
27
27
  const packageManagers = {
28
+ "bun.lockb": "bun",
28
29
  "yarn.lock": "yarn",
29
30
  "package-lock.json": "npm",
30
31
  "pnpm-lock.yaml": "pnpm"
@@ -55,6 +55,7 @@ function spawnCodegenProcess({
55
55
  type: 0,
56
56
  name: "CodegenError",
57
57
  message: `Codegen process exited with code ${code}`,
58
+ skipOclifErrorHandling: true,
58
59
  tryMessage: "Try restarting the dev server."
59
60
  });
60
61
  process.exit(code);
package/dist/lib/flags.js CHANGED
@@ -5,6 +5,7 @@ import { normalizeStoreFqdn } from '@shopify/cli-kit/node/context/fqdn';
5
5
  import colors from '@shopify/cli-kit/node/colors';
6
6
  import { STYLING_CHOICES } from './setups/css/index.js';
7
7
  import { I18N_CHOICES } from './setups/i18n/index.js';
8
+ import { DEFAULT_INSPECTOR_PORT } from './mini-oxygen/common.js';
8
9
 
9
10
  const DEFAULT_PORT = 3e3;
10
11
  const commonFlags = {
@@ -18,8 +19,8 @@ const commonFlags = {
18
19
  default: DEFAULT_PORT
19
20
  }),
20
21
  workerRuntime: Flags.boolean({
21
- description: "Run the app in a worker environment closer to Oxygen production instead of a Node.js sandbox. This flag is unstable and may change without notice.",
22
- env: "SHOPIFY_HYDROGEN_FLAG_WORKER_UNSTABLE"
22
+ description: "Run the app in a worker environment closer to Oxygen production instead of a Node.js sandbox.",
23
+ env: "SHOPIFY_HYDROGEN_FLAG_WORKER"
23
24
  }),
24
25
  force: Flags.boolean({
25
26
  description: "Overwrite the destination directory and files if they already exist.",
@@ -78,6 +79,16 @@ const commonFlags = {
78
79
  description: "Create a shortcut to the Shopify Hydrogen CLI.",
79
80
  env: "SHOPIFY_HYDROGEN_FLAG_SHORTCUT",
80
81
  allowNo: true
82
+ }),
83
+ debug: Flags.boolean({
84
+ description: "Enables inspector connections with a debugger.",
85
+ env: "SHOPIFY_HYDROGEN_FLAG_DEBUG",
86
+ default: false
87
+ }),
88
+ inspectorPort: Flags.integer({
89
+ description: "Port where the inspector will be available.",
90
+ env: "SHOPIFY_HYDROGEN_FLAG_INSPECTOR_PORT",
91
+ default: DEFAULT_INSPECTOR_PORT
81
92
  })
82
93
  };
83
94
  function flagsToCamelObject(obj) {
package/dist/lib/log.js CHANGED
@@ -266,6 +266,7 @@ function createRemixLogger() {
266
266
  name: "error",
267
267
  type: 0,
268
268
  message: buildMessageBody(message, options?.details),
269
+ skipOclifErrorHandling: true,
269
270
  tryMessage: ""
270
271
  });
271
272
  }
@@ -0,0 +1,118 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { createServer } from 'node:http';
4
+ import { lookupMimeType } from '@shopify/cli-kit/node/mimes';
5
+
6
+ const html = String.raw;
7
+ const artificialAssetPrefix = "mini-oxygen/00000/11111/22222/33333";
8
+ function buildAssetsUrl(assetsPort) {
9
+ return `http://localhost:${assetsPort}/${artificialAssetPrefix}/`;
10
+ }
11
+ function createAssetsServer(buildPathClient) {
12
+ return createServer(async (req, res) => {
13
+ res.setHeader("Access-Control-Allow-Origin", "*");
14
+ res.setHeader("X-Content-Type-Options", "nosniff");
15
+ const pathname = req.url?.split("?")[0] || "";
16
+ const isValidAssetPath = pathname.startsWith(`/${artificialAssetPrefix}/`) && !pathname.includes("..");
17
+ const relativeAssetPath = isValidAssetPath ? pathname.replace(`/${artificialAssetPrefix}`, "") : pathname;
18
+ if (isValidAssetPath) {
19
+ const filePath = path.join(buildPathClient, relativeAssetPath);
20
+ const file = await fs.open(filePath).catch(() => {
21
+ });
22
+ const stat = await file?.stat().catch(() => {
23
+ });
24
+ if (file && stat?.isFile()) {
25
+ res.setHeader("Content-Length", stat.size);
26
+ res.setHeader(
27
+ "Content-Type",
28
+ lookupMimeType(filePath) || "application/octet-stream"
29
+ );
30
+ return file.createReadStream().pipe(res);
31
+ }
32
+ }
33
+ res.setHeader("Content-Type", "text/html; charset=utf-8");
34
+ res.writeHead(404);
35
+ res.end(
36
+ html`<html>
37
+ <head>
38
+ <title>404: Page not found</title>
39
+ </head>
40
+ <body
41
+ style="display: flex; flex-direction: column; align-items: center; padding-top: 20px; font-family: Arial"
42
+ >
43
+ <h2>404 NOT FOUND</h2>
44
+ <p>
45
+ ${isValidAssetPath ? "This file was not found in the build output directory:" : "The following URL pathname is not valid:"}
46
+ </p>
47
+ <pre>${relativeAssetPath}</pre>
48
+ </body>
49
+ </html>`
50
+ );
51
+ });
52
+ }
53
+ const STATIC_ASSET_EXTENSIONS = Object.freeze([
54
+ "7Z",
55
+ "CSV",
56
+ "GIF",
57
+ "MIDI",
58
+ "PNG",
59
+ "TIF",
60
+ "ZIP",
61
+ "AVI",
62
+ "DOC",
63
+ "GZ",
64
+ "MKV",
65
+ "PPT",
66
+ "TIFF",
67
+ "ZST",
68
+ "AVIF",
69
+ "DOCX",
70
+ "ICO",
71
+ "MP3",
72
+ "PPTX",
73
+ "TTF",
74
+ "APK",
75
+ "DMG",
76
+ "ISO",
77
+ "MP4",
78
+ "PS",
79
+ "WEBM",
80
+ "BIN",
81
+ "EJS",
82
+ "JAR",
83
+ "OGG",
84
+ "RAR",
85
+ "WEBP",
86
+ "BMP",
87
+ "EOT",
88
+ "JPG",
89
+ "OTF",
90
+ "SVG",
91
+ "WOFF",
92
+ "BZ2",
93
+ "EPS",
94
+ "JPEG",
95
+ "PDF",
96
+ "SVGZ",
97
+ "WOFF2",
98
+ "CLASS",
99
+ "EXE",
100
+ "JS",
101
+ "PICT",
102
+ "SWF",
103
+ "XLS",
104
+ "CSS",
105
+ "FLAC",
106
+ "MID",
107
+ "PLS",
108
+ "TAR",
109
+ "XLSX",
110
+ "TXT",
111
+ "XML",
112
+ "MAP",
113
+ "HTML",
114
+ "GLB",
115
+ "JSON"
116
+ ]);
117
+
118
+ export { STATIC_ASSET_EXTENSIONS, buildAssetsUrl, createAssetsServer };
@@ -2,6 +2,7 @@ import { outputToken, outputInfo, outputContent } from '@shopify/cli-kit/node/ou
2
2
  import colors from '@shopify/cli-kit/node/colors';
3
3
  import { DEV_ROUTES } from '../request-events.js';
4
4
 
5
+ const DEFAULT_INSPECTOR_PORT = 9229;
5
6
  function logRequestLine(request, {
6
7
  responseStatus = 200,
7
8
  durationMs = 0
@@ -55,4 +56,4 @@ const OXYGEN_HEADERS_MAP = {
55
56
  }
56
57
  };
57
58
 
58
- export { OXYGEN_HEADERS_MAP, logRequestLine };
59
+ export { DEFAULT_INSPECTOR_PORT, OXYGEN_HEADERS_MAP, logRequestLine };
@@ -1,3 +1,6 @@
1
+ export { DEFAULT_INSPECTOR_PORT } from './common.js';
2
+ export { buildAssetsUrl } from './assets.js';
3
+
1
4
  async function startMiniOxygen(options, useWorkerd = false) {
2
5
  if (useWorkerd) {
3
6
  const { startWorkerdServer } = await import('./workerd.js');
@@ -12,7 +12,9 @@ async function startNodeServer({
12
12
  watch = false,
13
13
  buildPathWorkerFile,
14
14
  buildPathClient,
15
- env
15
+ env,
16
+ debug = false,
17
+ inspectorPort
16
18
  }) {
17
19
  const oxygenHeaders = Object.fromEntries(
18
20
  Object.entries(OXYGEN_HEADERS_MAP).map(([key, value]) => {
@@ -33,6 +35,9 @@ async function startNodeServer({
33
35
  )
34
36
  }
35
37
  };
38
+ if (debug) {
39
+ (await import('node:inspector')).open(inspectorPort);
40
+ }
36
41
  const miniOxygen = await startServer({
37
42
  script: await readFile(buildPathWorkerFile),
38
43
  workerFile: buildPathWorkerFile,
@@ -90,10 +95,17 @@ async function startNodeServer({
90
95
  showBanner(options) {
91
96
  console.log("");
92
97
  renderSuccess({
93
- headline: `${options?.headlinePrefix ?? ""}MiniOxygen ${options?.mode ?? "development"} server running.`,
98
+ headline: `${options?.headlinePrefix ?? ""}MiniOxygen (Node Sandbox) ${options?.mode ?? "development"} server running.`,
94
99
  body: [
95
100
  `View ${options?.appName ?? "Hydrogen"} app: ${listeningAt}`,
96
- ...options?.extraLines ?? []
101
+ ...options?.extraLines ?? [],
102
+ ...debug ? [
103
+ {
104
+ warn: `
105
+
106
+ Debugger listening on ws://localhost:${inspectorPort}`
107
+ }
108
+ ] : []
97
109
  ]
98
110
  });
99
111
  console.log("");