@shopify/cli-hydrogen 7.1.2 → 8.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.
- package/dist/commands/hydrogen/build-vite.js +19 -10
- package/dist/commands/hydrogen/build.js +10 -2
- package/dist/commands/hydrogen/check.js +1 -0
- package/dist/commands/hydrogen/codegen.js +1 -0
- package/dist/commands/hydrogen/customer-account/push.js +170 -0
- package/dist/commands/hydrogen/debug/cpu.js +3 -0
- package/dist/commands/hydrogen/deploy.js +121 -36
- package/dist/commands/hydrogen/dev-vite.js +128 -59
- package/dist/commands/hydrogen/dev.js +108 -51
- package/dist/commands/hydrogen/env/list.js +7 -8
- package/dist/commands/hydrogen/env/pull.js +17 -1
- package/dist/commands/hydrogen/env/{push__unstable.js → push.js} +23 -50
- package/dist/commands/hydrogen/generate/route.js +1 -0
- package/dist/commands/hydrogen/init.js +45 -17
- package/dist/commands/hydrogen/link.js +20 -4
- package/dist/commands/hydrogen/list.js +1 -0
- package/dist/commands/hydrogen/login.js +1 -0
- package/dist/commands/hydrogen/logout.js +1 -0
- package/dist/commands/hydrogen/preview.js +31 -16
- package/dist/commands/hydrogen/setup/css.js +8 -1
- package/dist/commands/hydrogen/setup/markets.js +1 -0
- package/dist/commands/hydrogen/setup/vite.js +244 -138
- package/dist/commands/hydrogen/setup.js +21 -22
- package/dist/commands/hydrogen/shortcut.js +10 -0
- package/dist/commands/hydrogen/unlink.js +1 -0
- package/dist/commands/hydrogen/upgrade.js +2 -1
- package/dist/generator-templates/assets/vite/package.json +3 -4
- package/dist/generator-templates/assets/vite/vite.config.js +10 -2
- package/dist/generator-templates/starter/CHANGELOG.md +89 -0
- package/dist/generator-templates/starter/README.md +3 -44
- package/dist/generator-templates/starter/app/graphql/customer-account/CustomerDetailsQuery.ts +1 -0
- package/dist/generator-templates/starter/app/lib/fragments.ts +2 -0
- package/dist/generator-templates/starter/app/root.tsx +2 -5
- package/dist/generator-templates/starter/app/routes/account.orders._index.tsx +1 -1
- package/dist/generator-templates/starter/app/routes/account.tsx +1 -1
- package/dist/generator-templates/starter/app/routes/collections.all.tsx +160 -0
- package/dist/generator-templates/starter/app/routes/products.$handle.tsx +1 -2
- package/dist/generator-templates/starter/customer-accountapi.generated.d.ts +6 -3
- package/dist/generator-templates/starter/{remix.env.d.ts → env.d.ts} +8 -2
- package/dist/generator-templates/starter/package.json +14 -9
- package/dist/generator-templates/starter/server.ts +2 -1
- package/dist/generator-templates/starter/storefrontapi.generated.d.ts +59 -3
- package/dist/generator-templates/starter/vite.config.ts +21 -0
- package/dist/{commands/hydrogen/init.d.ts → init.d.ts} +11 -3
- package/dist/lib/check-lockfile.js +12 -18
- package/dist/lib/codegen.js +37 -13
- package/dist/lib/common.js +50 -0
- package/dist/lib/cpu-profiler.js +4 -1
- package/dist/lib/dev-shared.js +97 -0
- package/dist/lib/environment-variables.js +51 -30
- package/dist/lib/file.js +8 -1
- package/dist/lib/flags.js +37 -16
- package/dist/lib/graphql/admin/customer-application-update.js +29 -0
- package/dist/lib/graphql/admin/get-oxygen-data.js +1 -0
- package/dist/lib/graphql/admin/list-environments.js +1 -0
- package/dist/lib/graphql/admin/pull-variables.js +4 -4
- package/dist/lib/graphql/admin/test-helper.js +37 -0
- package/dist/lib/log.js +86 -13
- package/dist/lib/mini-oxygen/common.js +19 -33
- package/dist/lib/mini-oxygen/index.js +6 -2
- package/dist/lib/mini-oxygen/node.js +43 -31
- package/dist/lib/mini-oxygen/workerd.js +72 -165
- package/dist/lib/missing-routes.js +1 -1
- package/dist/lib/onboarding/common.js +82 -70
- package/dist/lib/onboarding/local.js +19 -9
- package/dist/lib/onboarding/remote.js +35 -30
- package/dist/lib/package-managers.js +24 -0
- package/dist/lib/remix-config.js +17 -1
- package/dist/lib/request-events.js +6 -1
- package/dist/lib/setups/i18n/replacers.js +9 -6
- package/dist/lib/setups/routes/generate.js +1 -0
- package/dist/lib/shell.js +2 -1
- package/dist/lib/shopify-config.js +19 -1
- package/dist/lib/template-diff.js +36 -15
- package/dist/lib/template-downloader.js +35 -5
- package/dist/lib/transpile/morph/typedefs.js +5 -2
- package/dist/lib/transpile/project.js +8 -4
- package/dist/lib/tunneling.js +44 -0
- package/dist/lib/virtual-routes.js +1 -1
- package/dist/lib/vite-config.js +39 -9
- package/oclif.manifest.json +711 -498
- package/package.json +32 -24
- package/dist/commands/hydrogen/deploy.test.js +0 -553
- package/dist/commands/hydrogen/env/list.test.js +0 -148
- package/dist/commands/hydrogen/env/pull.test.js +0 -207
- package/dist/commands/hydrogen/env/push__unstable.test.js +0 -383
- package/dist/commands/hydrogen/generate/route.test.js +0 -43
- package/dist/commands/hydrogen/init.test.js +0 -641
- package/dist/commands/hydrogen/link.test.js +0 -187
- package/dist/commands/hydrogen/list.test.js +0 -111
- package/dist/commands/hydrogen/setup.test.js +0 -61
- package/dist/commands/hydrogen/shortcut.test.js +0 -30
- package/dist/commands/hydrogen/unlink.test.js +0 -36
- package/dist/commands/hydrogen/upgrade.test.js +0 -786
- package/dist/generator-templates/starter/remix.config.js +0 -24
- package/dist/lib/auth.test.js +0 -157
- package/dist/lib/check-lockfile.test.js +0 -81
- package/dist/lib/check-version.test.js +0 -86
- package/dist/lib/environment-variables.test.js +0 -149
- package/dist/lib/file.test.js +0 -68
- package/dist/lib/flags.test.js +0 -43
- package/dist/lib/get-oxygen-deployment-data.test.js +0 -120
- package/dist/lib/gid.test.js +0 -15
- package/dist/lib/graphql/admin/client.test.js +0 -76
- package/dist/lib/graphql/admin/create-storefront.test.js +0 -64
- package/dist/lib/graphql/admin/link-storefront.test.js +0 -38
- package/dist/lib/graphql/admin/list-environments.test.js +0 -44
- package/dist/lib/graphql/admin/list-storefronts.test.js +0 -44
- package/dist/lib/graphql/admin/pull-variables.test.js +0 -43
- package/dist/lib/graphql/business-platform/user-account.test.js +0 -80
- package/dist/lib/log.test.js +0 -92
- package/dist/lib/mini-oxygen/assets.js +0 -134
- package/dist/lib/mini-oxygen/mini-oxygen.test.js +0 -214
- package/dist/lib/mini-oxygen/workerd-inspector-logs.js +0 -227
- package/dist/lib/mini-oxygen/workerd-inspector-proxy.js +0 -200
- package/dist/lib/mini-oxygen/workerd-inspector.js +0 -219
- package/dist/lib/missing-routes.test.js +0 -45
- package/dist/lib/remix-version-check.test.js +0 -39
- package/dist/lib/remix-version-interop.test.js +0 -13
- package/dist/lib/setups/i18n/domains.test.js +0 -39
- package/dist/lib/setups/i18n/replacers.test.js +0 -261
- package/dist/lib/setups/i18n/subdomains.test.js +0 -39
- package/dist/lib/setups/i18n/subfolders.test.js +0 -39
- package/dist/lib/setups/routes/generate.test.js +0 -296
- package/dist/lib/shell.test.js +0 -111
- package/dist/lib/shopify-config.test.js +0 -199
- package/dist/lib/string.test.js +0 -16
- package/dist/lib/virtual-routes.test.js +0 -49
- package/dist/lib/vite/hydrogen-middleware.js +0 -82
- package/dist/lib/vite/mini-oxygen.js +0 -152
- package/dist/lib/vite/plugins.d.ts +0 -27
- package/dist/lib/vite/plugins.js +0 -139
- package/dist/lib/vite/shared.js +0 -10
- package/dist/lib/vite/utils.js +0 -55
- package/dist/lib/vite/worker-entry.js +0 -1518
- /package/dist/generator-templates/starter/{.eslintrc.js → .eslintrc.cjs} +0 -0
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { fileURLToPath } from 'node:url';
|
|
3
|
-
import { muteDevLogs, enhanceH2Logs } from '../../lib/log.js';
|
|
4
|
-
import { commonFlags, overrideFlag, flagsToCamelObject } from '../../lib/flags.js';
|
|
3
|
+
import { setH2OVerbose, isH2Verbose, muteDevLogs, enhanceH2Logs } from '../../lib/log.js';
|
|
4
|
+
import { commonFlags, overrideFlag, flagsToCamelObject, DEFAULT_INSPECTOR_PORT, DEFAULT_APP_PORT } from '../../lib/flags.js';
|
|
5
5
|
import Command from '@shopify/cli-kit/node/base-command';
|
|
6
6
|
import colors from '@shopify/cli-kit/node/colors';
|
|
7
|
-
import {
|
|
7
|
+
import { collectLog } from '@shopify/cli-kit/node/output';
|
|
8
|
+
import { renderSuccess } from '@shopify/cli-kit/node/ui';
|
|
8
9
|
import { AbortError } from '@shopify/cli-kit/node/error';
|
|
9
10
|
import { Flags } from '@oclif/core';
|
|
10
11
|
import { spawnCodegenProcess } from '../../lib/codegen.js';
|
|
11
12
|
import { getAllEnvironmentVariables } from '../../lib/environment-variables.js';
|
|
12
|
-
import { getConfig } from '../../lib/shopify-config.js';
|
|
13
|
-
import { checkRemixVersions } from '../../lib/remix-version-check.js';
|
|
14
13
|
import { displayDevUpgradeNotice } from './upgrade.js';
|
|
15
14
|
import { prepareDiffDirectory } from '../../lib/template-diff.js';
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
15
|
+
import { getDevConfigInBackground, TUNNEL_DOMAIN, startTunnelAndPushConfig, getUtilityBannerlines, getDebugBannerLine, isMockShop, notifyIssueWithTunnelAndMockShop } from '../../lib/dev-shared.js';
|
|
16
|
+
import { getCliCommand } from '../../lib/shell.js';
|
|
17
|
+
import { findPort } from '../../lib/find-port.js';
|
|
18
|
+
import { logRequestLine } from '../../lib/mini-oxygen/common.js';
|
|
19
|
+
import { findHydrogenPlugin, findOxygenPlugin } from '../../lib/vite-config.js';
|
|
19
20
|
|
|
20
21
|
class DevVite extends Command {
|
|
21
22
|
static description = "Runs Hydrogen storefront in an Oxygen worker for development.";
|
|
@@ -28,8 +29,7 @@ class DevVite extends Command {
|
|
|
28
29
|
...commonFlags.codegen,
|
|
29
30
|
"disable-virtual-routes": Flags.boolean({
|
|
30
31
|
description: "Disable rendering fallback routes when a route file doesn't exist.",
|
|
31
|
-
env: "SHOPIFY_HYDROGEN_FLAG_DISABLE_VIRTUAL_ROUTES"
|
|
32
|
-
default: false
|
|
32
|
+
env: "SHOPIFY_HYDROGEN_FLAG_DISABLE_VIRTUAL_ROUTES"
|
|
33
33
|
}),
|
|
34
34
|
...commonFlags.debug,
|
|
35
35
|
...commonFlags.inspectorPort,
|
|
@@ -38,28 +38,34 @@ class DevVite extends Command {
|
|
|
38
38
|
default: false,
|
|
39
39
|
required: false
|
|
40
40
|
}),
|
|
41
|
+
...commonFlags.env,
|
|
41
42
|
...commonFlags.envBranch,
|
|
42
43
|
"disable-version-check": Flags.boolean({
|
|
43
44
|
description: "Skip the version check when running `hydrogen dev`",
|
|
44
45
|
default: false,
|
|
45
46
|
required: false
|
|
46
47
|
}),
|
|
47
|
-
...commonFlags.diff
|
|
48
|
+
...commonFlags.diff,
|
|
49
|
+
...commonFlags.customerAccountPush,
|
|
50
|
+
...commonFlags.verbose
|
|
48
51
|
};
|
|
52
|
+
static hidden = true;
|
|
49
53
|
async run() {
|
|
50
54
|
const { flags } = await this.parse(DevVite);
|
|
51
55
|
let directory = flags.path ? path.resolve(flags.path) : process.cwd();
|
|
52
56
|
if (flags.diff) {
|
|
53
57
|
directory = await prepareDiffDirectory(directory, true);
|
|
54
58
|
}
|
|
55
|
-
await
|
|
59
|
+
await runViteDev({
|
|
56
60
|
...flagsToCamelObject(flags),
|
|
61
|
+
customerAccountPush: flags["customer-account-push__unstable"],
|
|
57
62
|
path: directory,
|
|
58
|
-
isLocalDev: flags.diff
|
|
63
|
+
isLocalDev: flags.diff,
|
|
64
|
+
cliConfig: this.config
|
|
59
65
|
});
|
|
60
66
|
}
|
|
61
67
|
}
|
|
62
|
-
async function
|
|
68
|
+
async function runViteDev({
|
|
63
69
|
entry: ssrEntry,
|
|
64
70
|
port: appPort,
|
|
65
71
|
path: appPath,
|
|
@@ -68,92 +74,155 @@ async function runDev({
|
|
|
68
74
|
codegenConfigPath,
|
|
69
75
|
disableVirtualRoutes,
|
|
70
76
|
envBranch,
|
|
77
|
+
env: envHandle,
|
|
71
78
|
debug = false,
|
|
72
79
|
disableVersionCheck = false,
|
|
73
80
|
inspectorPort,
|
|
74
|
-
isLocalDev = false
|
|
81
|
+
isLocalDev = false,
|
|
82
|
+
customerAccountPush: customerAccountPushFlag = false,
|
|
83
|
+
cliConfig,
|
|
84
|
+
verbose
|
|
75
85
|
}) {
|
|
76
86
|
if (!process.env.NODE_ENV)
|
|
77
87
|
process.env.NODE_ENV = "development";
|
|
78
|
-
|
|
88
|
+
if (verbose)
|
|
89
|
+
setH2OVerbose();
|
|
90
|
+
if (!isH2Verbose())
|
|
91
|
+
muteDevLogs();
|
|
79
92
|
const root = appPath ?? process.cwd();
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
93
|
+
const cliCommandPromise = getCliCommand(root);
|
|
94
|
+
const backgroundPromise = getDevConfigInBackground(
|
|
95
|
+
root,
|
|
96
|
+
customerAccountPushFlag
|
|
97
|
+
);
|
|
98
|
+
const envPromise = backgroundPromise.then(
|
|
99
|
+
({ fetchRemote, localVariables: localVariables2 }) => getAllEnvironmentVariables({
|
|
100
|
+
root,
|
|
101
|
+
envBranch,
|
|
102
|
+
envHandle,
|
|
103
|
+
fetchRemote,
|
|
104
|
+
localVariables: localVariables2
|
|
105
|
+
})
|
|
106
|
+
);
|
|
107
|
+
if (debug && !inspectorPort) {
|
|
108
|
+
inspectorPort = await findPort(DEFAULT_INSPECTOR_PORT);
|
|
109
|
+
}
|
|
84
110
|
const vite = await import('vite');
|
|
85
111
|
const fs = isLocalDev ? { allow: [root, fileURLToPath(new URL("../../../../", import.meta.url))] } : void 0;
|
|
112
|
+
const customLogger = vite.createLogger();
|
|
113
|
+
if (process.env.SHOPIFY_UNIT_TEST) {
|
|
114
|
+
customLogger.info = (msg) => collectLog("info", msg);
|
|
115
|
+
customLogger.warn = (msg) => collectLog("warn", msg);
|
|
116
|
+
customLogger.error = (msg) => collectLog("error", msg);
|
|
117
|
+
}
|
|
86
118
|
const viteServer = await vite.createServer({
|
|
87
119
|
root,
|
|
120
|
+
customLogger,
|
|
121
|
+
clearScreen: false,
|
|
88
122
|
server: { fs, host: host ? true : void 0 },
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
123
|
+
plugins: [
|
|
124
|
+
{
|
|
125
|
+
name: "hydrogen:cli",
|
|
126
|
+
configResolved(config) {
|
|
127
|
+
findHydrogenPlugin(config)?.api?.registerPluginOptions({
|
|
128
|
+
disableVirtualRoutes
|
|
129
|
+
});
|
|
130
|
+
findOxygenPlugin(config)?.api?.registerPluginOptions({
|
|
131
|
+
debug,
|
|
132
|
+
entry: ssrEntry,
|
|
133
|
+
envPromise: envPromise.then(({ allVariables }) => allVariables),
|
|
134
|
+
inspectorPort,
|
|
135
|
+
logRequestLine
|
|
136
|
+
});
|
|
137
|
+
},
|
|
138
|
+
configureServer: (viteDevServer) => {
|
|
139
|
+
if (customerAccountPushFlag) {
|
|
140
|
+
viteDevServer.middlewares.use((req, res, next) => {
|
|
141
|
+
const host2 = req.headers.host;
|
|
142
|
+
if (host2?.includes(TUNNEL_DOMAIN.ORIGINAL)) {
|
|
143
|
+
req.headers.host = host2.replace(
|
|
144
|
+
TUNNEL_DOMAIN.ORIGINAL,
|
|
145
|
+
TUNNEL_DOMAIN.REBRANDED
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
next();
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
96
152
|
}
|
|
97
|
-
|
|
153
|
+
]
|
|
98
154
|
});
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
await viteServer.close();
|
|
102
|
-
} finally {
|
|
103
|
-
process.exit();
|
|
104
|
-
}
|
|
105
|
-
});
|
|
106
|
-
if (!viteServer.config.plugins.find((plugin) => plugin.name === "hydrogen:main")) {
|
|
155
|
+
const h2Plugin = findHydrogenPlugin(viteServer.config);
|
|
156
|
+
if (!h2Plugin) {
|
|
107
157
|
await viteServer.close();
|
|
108
158
|
throw new AbortError(
|
|
109
159
|
"Hydrogen plugin not found.",
|
|
110
160
|
"Add `hydrogen()` plugin to your Vite config."
|
|
111
161
|
);
|
|
112
162
|
}
|
|
163
|
+
const h2PluginOptions = h2Plugin.api?.getPluginOptions?.();
|
|
113
164
|
const codegenProcess = useCodegen ? spawnCodegenProcess({
|
|
114
165
|
rootDirectory: root,
|
|
115
|
-
configFilePath: codegenConfigPath
|
|
166
|
+
configFilePath: codegenConfigPath,
|
|
167
|
+
appDirectory: h2PluginOptions?.remixConfig?.appDirectory
|
|
116
168
|
}) : void 0;
|
|
117
169
|
process.on("unhandledRejection", (err) => {
|
|
118
170
|
console.log("Unhandled Rejection: ", err);
|
|
119
171
|
});
|
|
120
|
-
const publicPort = appPort ?? viteServer.config.server.port ??
|
|
121
|
-
await
|
|
172
|
+
const publicPort = appPort ?? viteServer.config.server.port ?? DEFAULT_APP_PORT;
|
|
173
|
+
const [tunnel, cliCommand] = await Promise.all([
|
|
174
|
+
backgroundPromise.then(
|
|
175
|
+
({ customerAccountPush, storefrontId }) => customerAccountPush ? startTunnelAndPushConfig(root, cliConfig, publicPort, storefrontId) : void 0
|
|
176
|
+
),
|
|
177
|
+
cliCommandPromise,
|
|
178
|
+
viteServer.listen(publicPort)
|
|
179
|
+
]);
|
|
122
180
|
const publicUrl = new URL(
|
|
123
181
|
viteServer.resolvedUrls.local[0] ?? viteServer.resolvedUrls.network[0]
|
|
124
182
|
);
|
|
125
|
-
|
|
126
|
-
|
|
183
|
+
const finalHost = tunnel?.host || publicUrl.toString() || publicUrl.origin;
|
|
184
|
+
enhanceH2Logs({
|
|
185
|
+
rootDirectory: root,
|
|
186
|
+
host: finalHost,
|
|
187
|
+
cliCommand
|
|
188
|
+
});
|
|
189
|
+
const { logInjectedVariables, localVariables } = await envPromise;
|
|
190
|
+
logInjectedVariables();
|
|
127
191
|
console.log("");
|
|
128
192
|
viteServer.printUrls();
|
|
129
193
|
viteServer.bindCLIShortcuts({ print: true });
|
|
130
194
|
console.log("\n");
|
|
131
|
-
const
|
|
132
|
-
if (!disableVirtualRoutes) {
|
|
133
|
-
|
|
134
|
-
`${colors.dim("View GraphiQL API browser:")} ${getGraphiQLUrl({
|
|
135
|
-
host: publicUrl.origin
|
|
136
|
-
})}`,
|
|
137
|
-
`
|
|
138
|
-
${colors.dim("View server network requests:")} ${publicUrl.origin}/subrequest-profiler`
|
|
139
|
-
);
|
|
195
|
+
const customSections = [];
|
|
196
|
+
if (!h2PluginOptions?.disableVirtualRoutes) {
|
|
197
|
+
customSections.push({ body: getUtilityBannerlines(finalHost) });
|
|
140
198
|
}
|
|
141
|
-
if (debug) {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
renderInfo({ body: infoLines });
|
|
199
|
+
if (debug && inspectorPort) {
|
|
200
|
+
customSections.push({
|
|
201
|
+
body: { warn: getDebugBannerLine(inspectorPort) }
|
|
202
|
+
});
|
|
146
203
|
}
|
|
147
|
-
|
|
204
|
+
const { storefrontTitle } = await backgroundPromise;
|
|
205
|
+
renderSuccess({
|
|
206
|
+
body: [
|
|
207
|
+
`View ${storefrontTitle ? colors.cyan(storefrontTitle) : "Hydrogen"} app:`,
|
|
208
|
+
{ link: { url: finalHost } }
|
|
209
|
+
],
|
|
210
|
+
customSections
|
|
211
|
+
});
|
|
148
212
|
if (!disableVersionCheck) {
|
|
149
213
|
displayDevUpgradeNotice({ targetPath: root });
|
|
150
214
|
}
|
|
215
|
+
if (customerAccountPushFlag && isMockShop(localVariables)) {
|
|
216
|
+
notifyIssueWithTunnelAndMockShop(cliCommand);
|
|
217
|
+
}
|
|
151
218
|
return {
|
|
219
|
+
getUrl: () => finalHost,
|
|
152
220
|
async close() {
|
|
153
|
-
codegenProcess?.
|
|
154
|
-
|
|
221
|
+
codegenProcess?.removeAllListeners("close");
|
|
222
|
+
codegenProcess?.kill("SIGINT");
|
|
223
|
+
await Promise.allSettled([viteServer.close(), tunnel?.cleanup?.()]);
|
|
155
224
|
}
|
|
156
225
|
};
|
|
157
226
|
}
|
|
158
227
|
|
|
159
|
-
export { DevVite as default,
|
|
228
|
+
export { DevVite as default, runViteDev };
|
|
@@ -1,30 +1,33 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import fs from 'node:fs/promises';
|
|
3
2
|
import { outputInfo, outputDebug } from '@shopify/cli-kit/node/output';
|
|
4
3
|
import { fileExists } from '@shopify/cli-kit/node/fs';
|
|
5
4
|
import { renderFatalError } from '@shopify/cli-kit/node/ui';
|
|
6
|
-
import
|
|
5
|
+
import { resolvePath, relativePath } from '@shopify/cli-kit/node/path';
|
|
7
6
|
import { copyPublicFiles } from './build.js';
|
|
8
7
|
import { getProjectPaths, assertOxygenChecks, handleRemixImportFail, getRemixConfig } from '../../lib/remix-config.js';
|
|
9
|
-
import { muteDevLogs, createRemixLogger, enhanceH2Logs } from '../../lib/log.js';
|
|
10
|
-
import { commonFlags, deprecated, flagsToCamelObject } from '../../lib/flags.js';
|
|
8
|
+
import { setH2OVerbose, isH2Verbose, muteDevLogs, createRemixLogger, enhanceH2Logs } from '../../lib/log.js';
|
|
9
|
+
import { commonFlags, deprecated, flagsToCamelObject, DEFAULT_APP_PORT } from '../../lib/flags.js';
|
|
11
10
|
import Command from '@shopify/cli-kit/node/base-command';
|
|
12
11
|
import { Flags } from '@oclif/core';
|
|
13
12
|
import { buildAssetsUrl, startMiniOxygen } from '../../lib/mini-oxygen/index.js';
|
|
14
13
|
import { addVirtualRoutes } from '../../lib/virtual-routes.js';
|
|
15
14
|
import { spawnCodegenProcess } from '../../lib/codegen.js';
|
|
16
15
|
import { getAllEnvironmentVariables } from '../../lib/environment-variables.js';
|
|
17
|
-
import { getConfig } from '../../lib/shopify-config.js';
|
|
18
16
|
import { setupLiveReload } from '../../lib/live-reload.js';
|
|
19
17
|
import { checkRemixVersions } from '../../lib/remix-version-check.js';
|
|
20
|
-
import { getGraphiQLUrl } from '../../lib/graphiql-url.js';
|
|
21
18
|
import { displayDevUpgradeNotice } from './upgrade.js';
|
|
22
19
|
import { findPort } from '../../lib/find-port.js';
|
|
23
|
-
import { prepareDiffDirectory } from '../../lib/template-diff.js';
|
|
20
|
+
import { prepareDiffDirectory, copyShopifyConfig } from '../../lib/template-diff.js';
|
|
21
|
+
import { getDevConfigInBackground, startTunnelAndPushConfig, isMockShop, notifyIssueWithTunnelAndMockShop } from '../../lib/dev-shared.js';
|
|
22
|
+
import { getCliCommand } from '../../lib/shell.js';
|
|
23
|
+
import { hasViteConfig } from '../../lib/vite-config.js';
|
|
24
24
|
|
|
25
25
|
const LOG_REBUILDING = "\u{1F9F1} Rebuilding...";
|
|
26
26
|
const LOG_REBUILT = "\u{1F680} Rebuilt";
|
|
27
27
|
class Dev extends Command {
|
|
28
|
+
static descriptionWithMarkdown = `Runs a Hydrogen storefront in a local runtime that emulates an Oxygen worker for development.
|
|
29
|
+
|
|
30
|
+
If your project is [linked](https://shopify.dev/docs/api/shopify-cli/hydrogen/hydrogen-link) to a Hydrogen storefront, then its environment variables will be loaded with the runtime.`;
|
|
28
31
|
static description = "Runs Hydrogen storefront in an Oxygen worker for development.";
|
|
29
32
|
static flags = {
|
|
30
33
|
...commonFlags.path,
|
|
@@ -40,24 +43,43 @@ class Dev extends Command {
|
|
|
40
43
|
}),
|
|
41
44
|
...commonFlags.debug,
|
|
42
45
|
...commonFlags.inspectorPort,
|
|
46
|
+
...commonFlags.env,
|
|
43
47
|
...commonFlags.envBranch,
|
|
44
48
|
"disable-version-check": Flags.boolean({
|
|
45
49
|
description: "Skip the version check when running `hydrogen dev`",
|
|
46
50
|
default: false,
|
|
47
51
|
required: false
|
|
48
52
|
}),
|
|
49
|
-
...commonFlags.diff
|
|
53
|
+
...commonFlags.diff,
|
|
54
|
+
...commonFlags.customerAccountPush,
|
|
55
|
+
...commonFlags.verbose
|
|
50
56
|
};
|
|
51
57
|
async run() {
|
|
52
58
|
const { flags } = await this.parse(Dev);
|
|
53
|
-
|
|
59
|
+
const originalDirectory = flags.path ? resolvePath(flags.path) : process.cwd();
|
|
60
|
+
let directory = originalDirectory;
|
|
54
61
|
if (flags.diff) {
|
|
55
62
|
directory = await prepareDiffDirectory(directory, true);
|
|
56
63
|
}
|
|
57
|
-
|
|
64
|
+
const devParams = {
|
|
58
65
|
...flagsToCamelObject(flags),
|
|
59
|
-
|
|
60
|
-
|
|
66
|
+
customerAccountPush: flags["customer-account-push__unstable"],
|
|
67
|
+
path: directory,
|
|
68
|
+
cliConfig: this.config
|
|
69
|
+
};
|
|
70
|
+
const { close } = await hasViteConfig(directory ?? process.cwd()) ? await import('./dev-vite.js').then(
|
|
71
|
+
({ runViteDev }) => runViteDev(devParams)
|
|
72
|
+
) : await runDev(devParams);
|
|
73
|
+
let closingPromise;
|
|
74
|
+
const processExit = process.exit;
|
|
75
|
+
process.exit = async (code) => {
|
|
76
|
+
closingPromise ??= close();
|
|
77
|
+
await closingPromise;
|
|
78
|
+
return processExit(code);
|
|
79
|
+
};
|
|
80
|
+
if (flags.diff) {
|
|
81
|
+
await copyShopifyConfig(directory, originalDirectory);
|
|
82
|
+
}
|
|
61
83
|
}
|
|
62
84
|
}
|
|
63
85
|
async function runDev({
|
|
@@ -67,17 +89,26 @@ async function runDev({
|
|
|
67
89
|
legacyRuntime = false,
|
|
68
90
|
codegenConfigPath,
|
|
69
91
|
disableVirtualRoutes,
|
|
92
|
+
env: envHandle,
|
|
70
93
|
envBranch,
|
|
71
94
|
debug = false,
|
|
72
95
|
sourcemap = true,
|
|
73
96
|
disableVersionCheck = false,
|
|
74
|
-
inspectorPort
|
|
97
|
+
inspectorPort,
|
|
98
|
+
customerAccountPush: customerAccountPushFlag = false,
|
|
99
|
+
shouldLiveReload = true,
|
|
100
|
+
cliConfig,
|
|
101
|
+
verbose
|
|
75
102
|
}) {
|
|
76
103
|
if (!process.env.NODE_ENV)
|
|
77
104
|
process.env.NODE_ENV = "development";
|
|
78
|
-
|
|
105
|
+
if (verbose)
|
|
106
|
+
setH2OVerbose();
|
|
107
|
+
if (!isH2Verbose())
|
|
108
|
+
muteDevLogs();
|
|
79
109
|
const { root, publicPath, buildPathClient, buildPathWorkerFile } = getProjectPaths(appPath);
|
|
80
|
-
const
|
|
110
|
+
const copyFilesPromise = copyPublicFiles(publicPath, buildPathClient);
|
|
111
|
+
const cliCommandPromise = getCliCommand(root);
|
|
81
112
|
const reloadConfig = async () => {
|
|
82
113
|
const config = await getRemixConfig(root);
|
|
83
114
|
return disableVirtualRoutes ? config : addVirtualRoutes(config).catch((error) => {
|
|
@@ -88,23 +119,42 @@ async function runDev({
|
|
|
88
119
|
});
|
|
89
120
|
};
|
|
90
121
|
const getFilePaths = (file) => {
|
|
91
|
-
const fileRelative =
|
|
92
|
-
return [fileRelative,
|
|
122
|
+
const fileRelative = relativePath(root, file);
|
|
123
|
+
return [fileRelative, resolvePath(root, fileRelative)];
|
|
93
124
|
};
|
|
94
125
|
const serverBundleExists = () => fileExists(buildPathWorkerFile);
|
|
95
|
-
|
|
96
|
-
|
|
126
|
+
if (!appPort) {
|
|
127
|
+
appPort = await findPort(DEFAULT_APP_PORT);
|
|
128
|
+
}
|
|
97
129
|
const assetsPort = legacyRuntime ? 0 : await findPort(appPort + 100);
|
|
98
130
|
if (assetsPort) {
|
|
99
|
-
process.env.HYDROGEN_ASSET_BASE_URL = buildAssetsUrl(assetsPort);
|
|
131
|
+
process.env.HYDROGEN_ASSET_BASE_URL = await buildAssetsUrl(assetsPort);
|
|
100
132
|
}
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
133
|
+
const backgroundPromise = getDevConfigInBackground(
|
|
134
|
+
root,
|
|
135
|
+
customerAccountPushFlag
|
|
136
|
+
);
|
|
137
|
+
const tunnelPromise = cliConfig && backgroundPromise.then(({ customerAccountPush, storefrontId }) => {
|
|
138
|
+
if (customerAccountPush) {
|
|
139
|
+
return startTunnelAndPushConfig(
|
|
140
|
+
root,
|
|
141
|
+
cliConfig,
|
|
142
|
+
appPort,
|
|
143
|
+
storefrontId
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
const remixConfig = await reloadConfig();
|
|
105
148
|
assertOxygenChecks(remixConfig);
|
|
106
|
-
const
|
|
107
|
-
|
|
149
|
+
const envPromise = backgroundPromise.then(
|
|
150
|
+
({ fetchRemote, localVariables }) => getAllEnvironmentVariables({
|
|
151
|
+
root,
|
|
152
|
+
fetchRemote,
|
|
153
|
+
envBranch,
|
|
154
|
+
envHandle,
|
|
155
|
+
localVariables
|
|
156
|
+
})
|
|
157
|
+
);
|
|
108
158
|
const [{ watch }, { createFileWatchCache }] = await Promise.all([
|
|
109
159
|
import('@remix-run/dev/dist/compiler/watch.js'),
|
|
110
160
|
import('@remix-run/dev/dist/compiler/fileWatchCache.js')
|
|
@@ -112,43 +162,37 @@ async function runDev({
|
|
|
112
162
|
let isInitialBuild = true;
|
|
113
163
|
let initialBuildDurationMs = 0;
|
|
114
164
|
let initialBuildStartTimeMs = Date.now();
|
|
115
|
-
const liveReload = await setupLiveReload(remixConfig.dev?.port ?? 8002) ;
|
|
165
|
+
const liveReload = shouldLiveReload ? await setupLiveReload(remixConfig.dev?.port ?? 8002) : void 0;
|
|
116
166
|
let miniOxygen;
|
|
117
167
|
let codegenProcess;
|
|
118
168
|
async function safeStartMiniOxygen() {
|
|
119
169
|
if (miniOxygen)
|
|
120
170
|
return;
|
|
171
|
+
const { allVariables, localVariables, logInjectedVariables } = await envPromise;
|
|
121
172
|
miniOxygen = await startMiniOxygen(
|
|
122
173
|
{
|
|
123
174
|
root,
|
|
124
175
|
debug,
|
|
176
|
+
appPort,
|
|
125
177
|
assetsPort,
|
|
126
178
|
inspectorPort,
|
|
127
|
-
port: appPort,
|
|
128
179
|
watch: !liveReload,
|
|
129
180
|
buildPathWorkerFile,
|
|
130
181
|
buildPathClient,
|
|
131
|
-
env:
|
|
182
|
+
env: allVariables
|
|
132
183
|
},
|
|
133
184
|
legacyRuntime
|
|
134
185
|
);
|
|
135
|
-
|
|
186
|
+
logInjectedVariables();
|
|
187
|
+
const host = (await tunnelPromise)?.host ?? miniOxygen.listeningAt;
|
|
188
|
+
const cliCommand = await cliCommandPromise;
|
|
189
|
+
enhanceH2Logs({ host, cliCommand, ...remixConfig });
|
|
190
|
+
const { storefrontTitle } = await backgroundPromise;
|
|
136
191
|
miniOxygen.showBanner({
|
|
137
|
-
appName:
|
|
192
|
+
appName: storefrontTitle,
|
|
138
193
|
headlinePrefix: initialBuildDurationMs > 0 ? `Initial build: ${initialBuildDurationMs}ms
|
|
139
194
|
` : "",
|
|
140
|
-
|
|
141
|
-
colors.dim(
|
|
142
|
-
`
|
|
143
|
-
View GraphiQL API browser: ${getGraphiQLUrl({
|
|
144
|
-
host: miniOxygen.listeningAt
|
|
145
|
-
})}`
|
|
146
|
-
),
|
|
147
|
-
colors.dim(
|
|
148
|
-
`
|
|
149
|
-
View server network requests: ${miniOxygen.listeningAt}/subrequest-profiler`
|
|
150
|
-
)
|
|
151
|
-
]
|
|
195
|
+
host
|
|
152
196
|
});
|
|
153
197
|
if (useCodegen) {
|
|
154
198
|
codegenProcess = spawnCodegenProcess({
|
|
@@ -160,6 +204,9 @@ View server network requests: ${miniOxygen.listeningAt}/subrequest-profiler`
|
|
|
160
204
|
if (!disableVersionCheck) {
|
|
161
205
|
displayDevUpgradeNotice({ targetPath: appPath });
|
|
162
206
|
}
|
|
207
|
+
if (customerAccountPushFlag && isMockShop(localVariables)) {
|
|
208
|
+
notifyIssueWithTunnelAndMockShop(cliCommand);
|
|
209
|
+
}
|
|
163
210
|
}
|
|
164
211
|
const fileWatchCache = createFileWatchCache();
|
|
165
212
|
let skipRebuildLogs = false;
|
|
@@ -185,7 +232,7 @@ View server network requests: ${miniOxygen.listeningAt}/subrequest-profiler`
|
|
|
185
232
|
onBuildManifest: liveReload?.onBuildManifest,
|
|
186
233
|
async onBuildFinish(context, duration, succeeded) {
|
|
187
234
|
if (isInitialBuild) {
|
|
188
|
-
await
|
|
235
|
+
await copyFilesPromise;
|
|
189
236
|
initialBuildDurationMs = Date.now() - initialBuildStartTimeMs;
|
|
190
237
|
isInitialBuild = false;
|
|
191
238
|
} else if (!skipRebuildLogs) {
|
|
@@ -230,12 +277,16 @@ View server network requests: ${miniOxygen.listeningAt}/subrequest-profiler`
|
|
|
230
277
|
\u{1F4C4} File changed: ${relative}`);
|
|
231
278
|
if (relative.endsWith(".env")) {
|
|
232
279
|
skipRebuildLogs = true;
|
|
280
|
+
const { fetchRemote } = await backgroundPromise;
|
|
281
|
+
const { allVariables, logInjectedVariables } = await getAllEnvironmentVariables({
|
|
282
|
+
root,
|
|
283
|
+
fetchRemote,
|
|
284
|
+
envBranch,
|
|
285
|
+
envHandle
|
|
286
|
+
});
|
|
287
|
+
logInjectedVariables();
|
|
233
288
|
await miniOxygen.reload({
|
|
234
|
-
env:
|
|
235
|
-
root,
|
|
236
|
-
fetchRemote,
|
|
237
|
-
envBranch
|
|
238
|
-
})
|
|
289
|
+
env: allVariables
|
|
239
290
|
});
|
|
240
291
|
}
|
|
241
292
|
if (absolute.startsWith(publicPath)) {
|
|
@@ -257,9 +308,15 @@ View server network requests: ${miniOxygen.listeningAt}/subrequest-profiler`
|
|
|
257
308
|
}
|
|
258
309
|
);
|
|
259
310
|
return {
|
|
311
|
+
getUrl: () => miniOxygen.listeningAt,
|
|
260
312
|
async close() {
|
|
261
|
-
codegenProcess?.
|
|
262
|
-
|
|
313
|
+
codegenProcess?.removeAllListeners("close");
|
|
314
|
+
codegenProcess?.kill("SIGINT");
|
|
315
|
+
await Promise.allSettled([
|
|
316
|
+
closeWatcher(),
|
|
317
|
+
miniOxygen?.close(),
|
|
318
|
+
Promise.resolve(tunnelPromise).then((tunnel) => tunnel?.cleanup?.())
|
|
319
|
+
]);
|
|
263
320
|
}
|
|
264
321
|
};
|
|
265
322
|
}
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
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
|
-
import
|
|
5
|
-
import { outputNewline, outputInfo, outputContent } from '@shopify/cli-kit/node/output';
|
|
4
|
+
import { outputInfo, outputNewline, outputContent } from '@shopify/cli-kit/node/output';
|
|
6
5
|
import { linkStorefront } from '../link.js';
|
|
7
6
|
import { commonFlags } from '../../../lib/flags.js';
|
|
8
7
|
import { getStorefrontEnvironments } from '../../../lib/graphql/admin/list-environments.js';
|
|
8
|
+
import { createEnvironmentCliChoiceLabel } from '../../../lib/common.js';
|
|
9
9
|
import { renderMissingLink, renderMissingStorefront } from '../../../lib/render-errors.js';
|
|
10
10
|
import { login } from '../../../lib/auth.js';
|
|
11
11
|
import { getCliCommand } from '../../../lib/shell.js';
|
|
12
12
|
|
|
13
13
|
class EnvList extends Command {
|
|
14
|
+
static descriptionWithMarkdown = "Lists all environments available on the linked Hydrogen storefront.";
|
|
14
15
|
static description = "List the environments on your linked Hydrogen storefront.";
|
|
15
16
|
static flags = {
|
|
16
17
|
...commonFlags.path
|
|
@@ -60,25 +61,23 @@ async function runEnvList({ path: root = process.cwd() }) {
|
|
|
60
61
|
1
|
|
61
62
|
);
|
|
62
63
|
storefront.environments.push(previewEnvironment[0]);
|
|
63
|
-
outputNewline();
|
|
64
64
|
outputInfo(
|
|
65
65
|
pluralizedEnvironments({
|
|
66
66
|
environments: storefront.environments,
|
|
67
67
|
storefrontTitle: configStorefront.title
|
|
68
68
|
}).toString()
|
|
69
69
|
);
|
|
70
|
-
storefront.environments.forEach(({ name, branch, type, url }) => {
|
|
70
|
+
storefront.environments.forEach(({ name, handle, branch, type, url }) => {
|
|
71
71
|
outputNewline();
|
|
72
72
|
const environmentUrl = type === "PRODUCTION" ? storefront.productionUrl : url;
|
|
73
73
|
outputInfo(
|
|
74
|
-
outputContent`${
|
|
74
|
+
outputContent`${createEnvironmentCliChoiceLabel(name, handle, branch)}`.value
|
|
75
75
|
);
|
|
76
76
|
if (environmentUrl) {
|
|
77
|
-
outputInfo(
|
|
78
|
-
outputContent` ${colors.whiteBright(environmentUrl)}`.value
|
|
79
|
-
);
|
|
77
|
+
outputInfo(outputContent` ${environmentUrl}`.value);
|
|
80
78
|
}
|
|
81
79
|
});
|
|
80
|
+
outputNewline();
|
|
82
81
|
}
|
|
83
82
|
const pluralizedEnvironments = ({
|
|
84
83
|
environments,
|
|
@@ -9,13 +9,17 @@ import colors from '@shopify/cli-kit/node/colors';
|
|
|
9
9
|
import { commonFlags, flagsToCamelObject } from '../../../lib/flags.js';
|
|
10
10
|
import { login } from '../../../lib/auth.js';
|
|
11
11
|
import { getCliCommand } from '../../../lib/shell.js';
|
|
12
|
+
import { findEnvironmentOrThrow, findEnvironmentByBranchOrThrow } from '../../../lib/common.js';
|
|
12
13
|
import { renderMissingLink, renderMissingStorefront } from '../../../lib/render-errors.js';
|
|
13
14
|
import { linkStorefront } from '../link.js';
|
|
15
|
+
import { getStorefrontEnvironments } from '../../../lib/graphql/admin/list-environments.js';
|
|
14
16
|
import { getStorefrontEnvVariables } from '../../../lib/graphql/admin/pull-variables.js';
|
|
15
17
|
|
|
16
18
|
class EnvPull extends Command {
|
|
19
|
+
static descriptionWithMarkdown = "Pulls environment variables from the linked Hydrogen storefront and writes them to an `.env` file.";
|
|
17
20
|
static description = "Populate your .env with variables from your Hydrogen storefront.";
|
|
18
21
|
static flags = {
|
|
22
|
+
...commonFlags.env,
|
|
19
23
|
...commonFlags.envBranch,
|
|
20
24
|
...commonFlags.path,
|
|
21
25
|
...commonFlags.force
|
|
@@ -26,6 +30,7 @@ class EnvPull extends Command {
|
|
|
26
30
|
}
|
|
27
31
|
}
|
|
28
32
|
async function runEnvPull({
|
|
33
|
+
env: envHandle,
|
|
29
34
|
envBranch,
|
|
30
35
|
path: root = process.cwd(),
|
|
31
36
|
force
|
|
@@ -49,10 +54,21 @@ async function runEnvPull({
|
|
|
49
54
|
}
|
|
50
55
|
if (!config.storefront?.id)
|
|
51
56
|
return;
|
|
57
|
+
if (envHandle || envBranch) {
|
|
58
|
+
const environments = (await getStorefrontEnvironments(session, config.storefront.id))?.environments || [];
|
|
59
|
+
if (envHandle) {
|
|
60
|
+
findEnvironmentOrThrow(environments, envHandle);
|
|
61
|
+
} else if (envBranch) {
|
|
62
|
+
envHandle = findEnvironmentByBranchOrThrow(
|
|
63
|
+
environments,
|
|
64
|
+
envBranch
|
|
65
|
+
).handle;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
52
68
|
const storefront = await getStorefrontEnvVariables(
|
|
53
69
|
session,
|
|
54
70
|
config.storefront.id,
|
|
55
|
-
|
|
71
|
+
envHandle
|
|
56
72
|
);
|
|
57
73
|
if (!storefront) {
|
|
58
74
|
renderMissingStorefront({
|