@shopify/cli-hydrogen 7.1.2 → 8.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +10 -1
- package/dist/commands/hydrogen/deploy.js +110 -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 +20 -28
- package/dist/commands/hydrogen/env/pull.js +29 -19
- package/dist/commands/hydrogen/env/{push__unstable.js → push.js} +34 -68
- package/dist/commands/hydrogen/generate/route.js +1 -0
- package/dist/commands/hydrogen/init.js +39 -21
- package/dist/commands/hydrogen/link.js +25 -6
- 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 -23
- 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 +15 -2
- package/dist/generator-templates/starter/CHANGELOG.md +129 -0
- package/dist/generator-templates/starter/README.md +3 -44
- package/dist/generator-templates/starter/app/components/Footer.tsx +1 -1
- package/dist/generator-templates/starter/app/components/Header.tsx +1 -1
- 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/lib/root-data.ts +11 -0
- package/dist/generator-templates/starter/app/root.tsx +4 -20
- 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/blogs.$blogHandle._index.tsx +3 -3
- package/dist/generator-templates/starter/app/routes/cart.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 +26 -0
- package/dist/{commands/hydrogen/init.d.ts → init.d.ts} +11 -4
- 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 +99 -0
- package/dist/lib/environment-variables.js +51 -30
- package/dist/lib/file.js +8 -1
- package/dist/lib/flags.js +37 -26
- package/dist/lib/get-oxygen-deployment-data.js +10 -17
- 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 +85 -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/render-errors.js +17 -10
- 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/functions.js +26 -8
- package/dist/lib/transpile/morph/typedefs.js +6 -4
- package/dist/lib/transpile/project.js +8 -4
- package/dist/lib/tunneling.js +44 -0
- package/dist/lib/verify-linked-storefront.js +24 -0
- package/dist/lib/virtual-routes.js +1 -1
- package/dist/lib/vite-config.js +39 -9
- package/oclif.manifest.json +704 -508
- 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,7 +1,7 @@
|
|
|
1
1
|
import { diffLines } from 'diff';
|
|
2
2
|
import Command from '@shopify/cli-kit/node/base-command';
|
|
3
|
-
import {
|
|
4
|
-
import { outputContent, outputToken
|
|
3
|
+
import { renderInfo, renderConfirmationPrompt, renderWarning, renderSuccess } from '@shopify/cli-kit/node/ui';
|
|
4
|
+
import { outputInfo, outputContent, outputToken } from '@shopify/cli-kit/node/output';
|
|
5
5
|
import { fileExists, readFile, writeFile } from '@shopify/cli-kit/node/fs';
|
|
6
6
|
import { resolvePath } from '@shopify/cli-kit/node/path';
|
|
7
7
|
import { patchEnvFile } from '@shopify/cli-kit/node/dot-env';
|
|
@@ -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 {
|
|
13
|
-
import {
|
|
12
|
+
import { findEnvironmentOrThrow, findEnvironmentByBranchOrThrow } from '../../../lib/common.js';
|
|
13
|
+
import { renderMissingStorefront } from '../../../lib/render-errors.js';
|
|
14
|
+
import { getStorefrontEnvironments } from '../../../lib/graphql/admin/list-environments.js';
|
|
14
15
|
import { getStorefrontEnvVariables } from '../../../lib/graphql/admin/pull-variables.js';
|
|
16
|
+
import { verifyLinkedStorefront } from '../../../lib/verify-linked-storefront.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
|
|
@@ -34,25 +39,30 @@ async function runEnvPull({
|
|
|
34
39
|
login(root),
|
|
35
40
|
getCliCommand()
|
|
36
41
|
]);
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (!runLink)
|
|
45
|
-
return;
|
|
46
|
-
config.storefront = await linkStorefront(root, session, config, {
|
|
47
|
-
cliCommand
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
if (!config.storefront?.id)
|
|
42
|
+
const linkedStorefront = await verifyLinkedStorefront({
|
|
43
|
+
root,
|
|
44
|
+
session,
|
|
45
|
+
config,
|
|
46
|
+
cliCommand
|
|
47
|
+
});
|
|
48
|
+
if (!linkedStorefront)
|
|
51
49
|
return;
|
|
50
|
+
config.storefront = linkedStorefront;
|
|
51
|
+
if (envHandle || envBranch) {
|
|
52
|
+
const environments = (await getStorefrontEnvironments(session, config.storefront.id))?.environments || [];
|
|
53
|
+
if (envHandle) {
|
|
54
|
+
findEnvironmentOrThrow(environments, envHandle);
|
|
55
|
+
} else if (envBranch) {
|
|
56
|
+
envHandle = findEnvironmentByBranchOrThrow(
|
|
57
|
+
environments,
|
|
58
|
+
envBranch
|
|
59
|
+
).handle;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
52
62
|
const storefront = await getStorefrontEnvVariables(
|
|
53
63
|
session,
|
|
54
64
|
config.storefront.id,
|
|
55
|
-
|
|
65
|
+
envHandle
|
|
56
66
|
);
|
|
57
67
|
if (!storefront) {
|
|
58
68
|
renderMissingStorefront({
|
|
@@ -5,24 +5,22 @@ import { commonFlags, flagsToCamelObject } from '../../../lib/flags.js';
|
|
|
5
5
|
import { login } from '../../../lib/auth.js';
|
|
6
6
|
import { getCliCommand } from '../../../lib/shell.js';
|
|
7
7
|
import { resolvePath } from '@shopify/cli-kit/node/path';
|
|
8
|
-
import {
|
|
9
|
-
import { outputContent, outputToken
|
|
10
|
-
import {
|
|
8
|
+
import { renderSelectPrompt, renderInfo, renderConfirmationPrompt, renderSuccess } from '@shopify/cli-kit/node/ui';
|
|
9
|
+
import { outputWarn, outputContent, outputToken } from '@shopify/cli-kit/node/output';
|
|
10
|
+
import { orderEnvironmentsBySafety, findEnvironmentOrThrow, createEnvironmentCliChoiceLabel } from '../../../lib/common.js';
|
|
11
11
|
import { getStorefrontEnvironments } from '../../../lib/graphql/admin/list-environments.js';
|
|
12
|
-
import { linkStorefront } from '../link.js';
|
|
13
12
|
import { getStorefrontEnvVariables } from '../../../lib/graphql/admin/pull-variables.js';
|
|
14
13
|
import { pushStorefrontEnvVariables } from '../../../lib/graphql/admin/push-variables.js';
|
|
15
14
|
import { AbortError } from '@shopify/cli-kit/node/error';
|
|
16
|
-
import { readAndParseDotEnv } from '@shopify/cli-kit/node/dot-env';
|
|
15
|
+
import { readAndParseDotEnv, createDotEnvFileLine } from '@shopify/cli-kit/node/dot-env';
|
|
16
|
+
import { verifyLinkedStorefront } from '../../../lib/verify-linked-storefront.js';
|
|
17
17
|
|
|
18
18
|
class EnvPush extends Command {
|
|
19
19
|
static description = "Push environment variables from the local .env file to your linked Hydrogen storefront.";
|
|
20
|
-
static hidden = true;
|
|
21
20
|
static flags = {
|
|
22
21
|
...commonFlags.env,
|
|
23
22
|
"env-file": Flags.string({
|
|
24
|
-
description: "
|
|
25
|
-
env: "SHOPIFY_HYDROGEN_ENVIRONMENT_FILENAME"
|
|
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`."
|
|
26
24
|
}),
|
|
27
25
|
...commonFlags.path
|
|
28
26
|
};
|
|
@@ -32,99 +30,67 @@ class EnvPush extends Command {
|
|
|
32
30
|
}
|
|
33
31
|
}
|
|
34
32
|
async function runEnvPush({
|
|
35
|
-
env:
|
|
36
|
-
envFile
|
|
33
|
+
env: envHandle,
|
|
34
|
+
envFile,
|
|
37
35
|
path = process.cwd()
|
|
38
36
|
}) {
|
|
39
|
-
let validatedEnvironment
|
|
40
|
-
const dotEnvPath = resolvePath(path,
|
|
37
|
+
let validatedEnvironment;
|
|
38
|
+
const dotEnvPath = envFile || resolvePath(path, ".env");
|
|
41
39
|
const { variables: localVariables } = await readAndParseDotEnv(dotEnvPath);
|
|
42
40
|
const [{ session, config }, cliCommand] = await Promise.all([
|
|
43
41
|
login(path),
|
|
44
42
|
getCliCommand()
|
|
45
43
|
]);
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if (!runLink)
|
|
54
|
-
return;
|
|
55
|
-
config.storefront = await linkStorefront(path, session, config, {
|
|
56
|
-
cliCommand
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
if (!config.storefront?.id)
|
|
44
|
+
const linkedStorefront = await verifyLinkedStorefront({
|
|
45
|
+
root: path,
|
|
46
|
+
session,
|
|
47
|
+
config,
|
|
48
|
+
cliCommand
|
|
49
|
+
});
|
|
50
|
+
if (!linkedStorefront)
|
|
60
51
|
return;
|
|
52
|
+
config.storefront = linkedStorefront;
|
|
61
53
|
const { environments: environmentsData } = await getStorefrontEnvironments(session, config.storefront.id) ?? {};
|
|
62
54
|
if (!environmentsData) {
|
|
63
55
|
throw new AbortError("Failed to fetch environments");
|
|
64
56
|
}
|
|
65
|
-
const environments =
|
|
66
|
-
...environmentsData.filter((environment) => environment.type === "PREVIEW"),
|
|
67
|
-
...environmentsData.filter((environment) => environment.type === "CUSTOM"),
|
|
68
|
-
...environmentsData.filter(
|
|
69
|
-
(environment) => environment.type === "PRODUCTION"
|
|
70
|
-
)
|
|
71
|
-
];
|
|
57
|
+
const environments = orderEnvironmentsBySafety(environmentsData);
|
|
72
58
|
if (environments.length === 0) {
|
|
73
59
|
throw new AbortError("No environments found");
|
|
74
60
|
}
|
|
75
|
-
if (
|
|
76
|
-
|
|
77
|
-
({ name }) => name === environmentName
|
|
78
|
-
);
|
|
79
|
-
if (matchedEnvironments.length === 0) {
|
|
80
|
-
throw new AbortError(
|
|
81
|
-
"Environment not found",
|
|
82
|
-
`We could not find an environment matching the name '${environmentName}'.`
|
|
83
|
-
);
|
|
84
|
-
} else if (matchedEnvironments.length === 1) {
|
|
85
|
-
const { id, name, branch, type } = matchedEnvironments[0] ?? {};
|
|
86
|
-
validatedEnvironment = { id, name, branch, type };
|
|
87
|
-
} else {
|
|
88
|
-
const selection = await renderSelectPrompt({
|
|
89
|
-
message: `There were multiple environments found with the name ${environmentName}:`,
|
|
90
|
-
choices: [
|
|
91
|
-
...matchedEnvironments.map(({ id: id2, name: name2, branch: branch2, type: type2, url }) => ({
|
|
92
|
-
label: `${name2} (${branch2}) ${type2} ${url}`,
|
|
93
|
-
value: id2
|
|
94
|
-
}))
|
|
95
|
-
]
|
|
96
|
-
});
|
|
97
|
-
const { id, name, branch, type } = matchedEnvironments.find(({ id: id2 }) => id2 === selection) ?? {};
|
|
98
|
-
validatedEnvironment = { id, name, branch, type };
|
|
99
|
-
}
|
|
61
|
+
if (envHandle) {
|
|
62
|
+
validatedEnvironment = findEnvironmentOrThrow(environments, envHandle);
|
|
100
63
|
} else {
|
|
101
64
|
const choices = [
|
|
102
|
-
...environments.map(({ id
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
65
|
+
...environments.map(({ id, name, branch, handle }) => {
|
|
66
|
+
return {
|
|
67
|
+
label: createEnvironmentCliChoiceLabel(name, handle, branch),
|
|
68
|
+
value: id
|
|
69
|
+
};
|
|
70
|
+
})
|
|
106
71
|
];
|
|
107
72
|
const pushToBranchSelection = await renderSelectPrompt({
|
|
108
|
-
message: "Select
|
|
73
|
+
message: "Select an environment to overwrite its environment variables:",
|
|
109
74
|
choices
|
|
110
75
|
});
|
|
111
|
-
|
|
112
|
-
|
|
76
|
+
validatedEnvironment = environments.find(
|
|
77
|
+
({ id }) => id === pushToBranchSelection
|
|
78
|
+
);
|
|
113
79
|
}
|
|
114
80
|
const { environmentVariables = [] } = await getStorefrontEnvVariables(
|
|
115
81
|
session,
|
|
116
82
|
config.storefront.id,
|
|
117
|
-
validatedEnvironment.
|
|
83
|
+
validatedEnvironment.handle
|
|
118
84
|
) ?? {};
|
|
119
85
|
const remoteVars = environmentVariables.filter(
|
|
120
86
|
({ isSecret, readOnly }) => !isSecret && !readOnly
|
|
121
87
|
);
|
|
122
|
-
const comparableRemoteVars = remoteVars.sort((a, b) => a.key.localeCompare(b.key)).map(({ key, value }) =>
|
|
88
|
+
const comparableRemoteVars = remoteVars.sort((a, b) => a.key.localeCompare(b.key)).map(({ key, value }) => createDotEnvFileLine(key, value)).join("\n") + "\n";
|
|
123
89
|
const compareableLocalVars = Object.keys(localVariables).sort((a, b) => a.localeCompare(b)).reduce((acc, key) => {
|
|
124
90
|
const { isSecret, readOnly } = environmentVariables.find((variable) => variable.key === key) ?? {};
|
|
125
91
|
if (isSecret || readOnly)
|
|
126
92
|
return acc;
|
|
127
|
-
return [...acc,
|
|
93
|
+
return [...acc, createDotEnvFileLine(key, localVariables[key])];
|
|
128
94
|
}, []).join("\n") + "\n";
|
|
129
95
|
if (!validatedEnvironment.name)
|
|
130
96
|
throw new AbortError("Missing environment name");
|
|
@@ -8,6 +8,7 @@ import { ALL_ROUTE_CHOICES, generateRoutes } from '../../../lib/setups/routes/ge
|
|
|
8
8
|
import { isV1RouteConventionInstalled } from '../../../lib/remix-version-interop.js';
|
|
9
9
|
|
|
10
10
|
class GenerateRoute extends Command {
|
|
11
|
+
static descriptionWithMarkdown = `Generates a set of default routes from the starter template.`;
|
|
11
12
|
static description = "Generates a standard Shopify route.";
|
|
12
13
|
static flags = {
|
|
13
14
|
adapter: Flags.string({
|
|
@@ -6,7 +6,6 @@ import { AbortError } from '@shopify/cli-kit/node/error';
|
|
|
6
6
|
import { AbortController } from '@shopify/cli-kit/node/abort';
|
|
7
7
|
import { commonFlags, flagsToCamelObject, parseProcessFlags } from '../../lib/flags.js';
|
|
8
8
|
import { checkHydrogenVersion } from '../../lib/check-version.js';
|
|
9
|
-
import { STYLING_CHOICES } from './../../lib/setups/css/index.js';
|
|
10
9
|
import { I18N_CHOICES } from '../../lib/setups/i18n/index.js';
|
|
11
10
|
import { supressNodeExperimentalWarnings } from '../../lib/process.js';
|
|
12
11
|
import { setupRemoteTemplate, setupLocalStarterTemplate } from '../../lib/onboarding/index.js';
|
|
@@ -14,6 +13,7 @@ import { LANGUAGES } from '../../lib/onboarding/common.js';
|
|
|
14
13
|
|
|
15
14
|
const FLAG_MAP = { f: "force" };
|
|
16
15
|
class Init extends Command {
|
|
16
|
+
static descriptionWithMarkdown = "Creates a new Hydrogen storefront.";
|
|
17
17
|
static description = "Creates a new Hydrogen storefront.";
|
|
18
18
|
static flags = {
|
|
19
19
|
...commonFlags.force,
|
|
@@ -33,16 +33,13 @@ class Init extends Command {
|
|
|
33
33
|
...commonFlags.installDeps,
|
|
34
34
|
"mock-shop": Flags.boolean({
|
|
35
35
|
description: "Use mock.shop as the data source for the storefront.",
|
|
36
|
-
default: false,
|
|
37
36
|
env: "SHOPIFY_HYDROGEN_FLAG_MOCK_DATA"
|
|
38
37
|
}),
|
|
39
|
-
...commonFlags.styling,
|
|
40
38
|
...commonFlags.markets,
|
|
41
39
|
...commonFlags.shortcut,
|
|
42
40
|
routes: Flags.boolean({
|
|
43
41
|
description: "Generate routes for all pages.",
|
|
44
42
|
env: "SHOPIFY_HYDROGEN_FLAG_ROUTES",
|
|
45
|
-
hidden: true,
|
|
46
43
|
allowNo: true
|
|
47
44
|
}),
|
|
48
45
|
git: Flags.boolean({
|
|
@@ -50,29 +47,49 @@ class Init extends Command {
|
|
|
50
47
|
env: "SHOPIFY_HYDROGEN_FLAG_GIT",
|
|
51
48
|
default: true,
|
|
52
49
|
allowNo: true
|
|
50
|
+
}),
|
|
51
|
+
quickstart: Flags.boolean({
|
|
52
|
+
description: "Scaffolds a new Hydrogen project with a set of sensible defaults. Equivalent to `shopify hydrogen init --path hydrogen-quickstart --mock-shop --language js --shortcut --routes --markets none`",
|
|
53
|
+
env: "SHOPIFY_HYDROGEN_FLAG_QUICKSTART",
|
|
54
|
+
default: false
|
|
55
|
+
}),
|
|
56
|
+
"package-manager": Flags.string({
|
|
57
|
+
env: "SHOPIFY_HYDROGEN_FLAG_PACKAGE_MANAGER",
|
|
58
|
+
hidden: true,
|
|
59
|
+
options: ["npm", "yarn", "pnpm", "unknown"]
|
|
53
60
|
})
|
|
54
61
|
};
|
|
55
62
|
async run() {
|
|
56
|
-
const {
|
|
57
|
-
flags: { markets, ..._flags }
|
|
58
|
-
} = await this.parse(Init);
|
|
59
|
-
const flags = { ..._flags, i18n: markets };
|
|
60
|
-
if (flags.i18n && !I18N_CHOICES.includes(flags.i18n)) {
|
|
61
|
-
throw new AbortError(
|
|
62
|
-
`Invalid URL structure strategy: ${flags.i18n}. Must be one of ${I18N_CHOICES.join(", ")}`
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
if (flags.styling && !STYLING_CHOICES.includes(flags.styling)) {
|
|
66
|
-
throw new AbortError(
|
|
67
|
-
`Invalid styling strategy: ${flags.styling}. Must be one of ${STYLING_CHOICES.join(", ")}`
|
|
68
|
-
);
|
|
69
|
-
}
|
|
63
|
+
const { flags } = await this.parse(Init);
|
|
70
64
|
await runInit(flagsToCamelObject(flags));
|
|
71
65
|
}
|
|
72
66
|
}
|
|
73
|
-
async function runInit(
|
|
67
|
+
async function runInit({
|
|
68
|
+
markets,
|
|
69
|
+
...options
|
|
70
|
+
} = parseProcessFlags(
|
|
71
|
+
process.argv,
|
|
72
|
+
FLAG_MAP
|
|
73
|
+
)) {
|
|
74
74
|
supressNodeExperimentalWarnings();
|
|
75
|
+
if (!options.i18n && markets) {
|
|
76
|
+
options.i18n = markets;
|
|
77
|
+
}
|
|
78
|
+
if (options.i18n && !I18N_CHOICES.includes(options.i18n)) {
|
|
79
|
+
throw new AbortError(
|
|
80
|
+
`Invalid URL structure strategy: ${options.i18n}. Must be one of ${I18N_CHOICES.join(", ")}`
|
|
81
|
+
);
|
|
82
|
+
}
|
|
75
83
|
options.git ??= true;
|
|
84
|
+
if (options.quickstart) {
|
|
85
|
+
options.i18n ??= "none";
|
|
86
|
+
options.installDeps ??= true;
|
|
87
|
+
options.language ??= "js";
|
|
88
|
+
options.mockShop ??= true;
|
|
89
|
+
options.path ??= "./hydrogen-quickstart";
|
|
90
|
+
options.routes ??= true;
|
|
91
|
+
options.shortcut ??= true;
|
|
92
|
+
}
|
|
76
93
|
const showUpgrade = await checkHydrogenVersion(
|
|
77
94
|
// Resolving the CLI package from a local directory might fail because
|
|
78
95
|
// this code could be run from a global dependency (e.g. on `npm create`).
|
|
@@ -81,14 +98,15 @@ async function runInit(options = parseProcessFlags(process.argv, FLAG_MAP)) {
|
|
|
81
98
|
"cli"
|
|
82
99
|
);
|
|
83
100
|
if (showUpgrade) {
|
|
84
|
-
const packageManager = packageManagerFromUserAgent();
|
|
101
|
+
const packageManager = options.packageManager ?? packageManagerFromUserAgent();
|
|
85
102
|
showUpgrade(
|
|
86
103
|
packageManager === "unknown" ? "" : `Please use the latest version with \`${packageManager} create @shopify/hydrogen@latest\``
|
|
87
104
|
);
|
|
88
105
|
}
|
|
89
106
|
const controller = new AbortController();
|
|
90
107
|
try {
|
|
91
|
-
|
|
108
|
+
const template = options.template;
|
|
109
|
+
return template ? await setupRemoteTemplate({ ...options, template }, controller) : await setupLocalStarterTemplate(options, controller);
|
|
92
110
|
} catch (error) {
|
|
93
111
|
controller.abort();
|
|
94
112
|
throw error;
|
|
@@ -11,9 +11,14 @@ import { waitForJob } from '../../lib/graphql/admin/fetch-job.js';
|
|
|
11
11
|
import { titleize } from '../../lib/string.js';
|
|
12
12
|
import { getCliCommand } from '../../lib/shell.js';
|
|
13
13
|
import { login } from '../../lib/auth.js';
|
|
14
|
-
import { handleStorefrontSelection } from '../../lib/onboarding/common.js';
|
|
14
|
+
import { handleStorefrontSelection, generateRandomName } from '../../lib/onboarding/common.js';
|
|
15
15
|
|
|
16
16
|
class Link extends Command {
|
|
17
|
+
static descriptionWithMarkdown = `Links your local development environment to a remote Hydrogen storefront. You can link an unlimited number of development environments to a single Hydrogen storefront.
|
|
18
|
+
|
|
19
|
+
Linking to a Hydrogen storefront enables you to run [dev](https://shopify.dev/docs/api/shopify-cli/hydrogen/hydrogen-dev) and automatically inject your linked Hydrogen storefront's environment variables directly into the server runtime.
|
|
20
|
+
|
|
21
|
+
After you run the \`link\` command, you can access the [env list](https://shopify.dev/docs/api/shopify-cli/hydrogen/hydrogen-env-list), [env pull](https://shopify.dev/docs/api/shopify-cli/hydrogen/hydrogen-env-pull), and [unlink](https://shopify.dev/docs/api/shopify-cli/hydrogen/hydrogen-unlink) commands.`;
|
|
17
22
|
static description = "Link a local project to one of your shop's Hydrogen storefronts.";
|
|
18
23
|
static flags = {
|
|
19
24
|
...commonFlags.force,
|
|
@@ -58,7 +63,8 @@ async function runLink({
|
|
|
58
63
|
async function linkStorefront(root, session, config, {
|
|
59
64
|
force = false,
|
|
60
65
|
flagStorefront,
|
|
61
|
-
cliCommand
|
|
66
|
+
cliCommand,
|
|
67
|
+
storefronts
|
|
62
68
|
}) {
|
|
63
69
|
if (!config.shop) {
|
|
64
70
|
throw new AbortError("No shop found in local config, login first.");
|
|
@@ -71,7 +77,9 @@ async function linkStorefront(root, session, config, {
|
|
|
71
77
|
return;
|
|
72
78
|
}
|
|
73
79
|
}
|
|
74
|
-
|
|
80
|
+
if (!storefronts) {
|
|
81
|
+
storefronts = await getStorefronts(session);
|
|
82
|
+
}
|
|
75
83
|
let selectedStorefront;
|
|
76
84
|
if (flagStorefront) {
|
|
77
85
|
selectedStorefront = storefronts.find(
|
|
@@ -96,17 +104,28 @@ async function linkStorefront(root, session, config, {
|
|
|
96
104
|
} else {
|
|
97
105
|
selectedStorefront = await handleStorefrontSelection(storefronts);
|
|
98
106
|
if (!selectedStorefront) {
|
|
99
|
-
selectedStorefront = await createNewStorefront(
|
|
107
|
+
selectedStorefront = await createNewStorefront(
|
|
108
|
+
root,
|
|
109
|
+
session,
|
|
110
|
+
storefronts
|
|
111
|
+
);
|
|
100
112
|
}
|
|
101
113
|
}
|
|
102
114
|
await setStorefront(root, selectedStorefront);
|
|
103
115
|
return selectedStorefront;
|
|
104
116
|
}
|
|
105
|
-
async function createNewStorefront(root, session) {
|
|
117
|
+
async function createNewStorefront(root, session, storefronts) {
|
|
106
118
|
const projectDirectory = basename(root);
|
|
119
|
+
let defaultProjectName = titleize(projectDirectory);
|
|
120
|
+
const nameAlreadyUsed = storefronts.some(
|
|
121
|
+
({ title }) => title === defaultProjectName
|
|
122
|
+
);
|
|
123
|
+
if (nameAlreadyUsed) {
|
|
124
|
+
defaultProjectName = generateRandomName();
|
|
125
|
+
}
|
|
107
126
|
const projectName = await renderTextPrompt({
|
|
108
127
|
message: "New storefront name",
|
|
109
|
-
defaultValue:
|
|
128
|
+
defaultValue: defaultProjectName
|
|
110
129
|
});
|
|
111
130
|
let storefront;
|
|
112
131
|
let jobId;
|
|
@@ -11,6 +11,7 @@ import { login } from '../../lib/auth.js';
|
|
|
11
11
|
import { getCliCommand } from '../../lib/shell.js';
|
|
12
12
|
|
|
13
13
|
class List extends Command {
|
|
14
|
+
static descriptionWithMarkdown = "Lists all remote Hydrogen storefronts available to link to your local development environment.";
|
|
14
15
|
static description = "Returns a list of Hydrogen storefronts available on a given shop.";
|
|
15
16
|
static flags = {
|
|
16
17
|
...commonFlags.path
|
|
@@ -3,6 +3,7 @@ import { commonFlags } from '../../lib/flags.js';
|
|
|
3
3
|
import { login, renderLoginSuccess } from '../../lib/auth.js';
|
|
4
4
|
|
|
5
5
|
class Login extends Command {
|
|
6
|
+
static descriptionWithMarkdown = "Logs in to the specified shop and saves the shop domain to the project.";
|
|
6
7
|
static description = "Login to your Shopify account.";
|
|
7
8
|
static flags = {
|
|
8
9
|
...commonFlags.path,
|
|
@@ -4,6 +4,7 @@ import { commonFlags } from '../../lib/flags.js';
|
|
|
4
4
|
import { logout } from '../../lib/auth.js';
|
|
5
5
|
|
|
6
6
|
class Logout extends Command {
|
|
7
|
+
static descriptionWithMarkdown = "Log out from the current shop.";
|
|
7
8
|
static description = "Logout of your local session.";
|
|
8
9
|
static flags = {
|
|
9
10
|
...commonFlags.path
|
|
@@ -1,25 +1,27 @@
|
|
|
1
1
|
import Command from '@shopify/cli-kit/node/base-command';
|
|
2
|
-
import { muteDevLogs } from '../../lib/log.js';
|
|
3
|
-
import { getProjectPaths } from '../../lib/remix-config.js';
|
|
4
|
-
import { commonFlags, deprecated, flagsToCamelObject } from '../../lib/flags.js';
|
|
2
|
+
import { setH2OVerbose, isH2Verbose, muteDevLogs } from '../../lib/log.js';
|
|
3
|
+
import { getProjectPaths, hasRemixConfigFile } from '../../lib/remix-config.js';
|
|
4
|
+
import { commonFlags, deprecated, flagsToCamelObject, DEFAULT_APP_PORT } from '../../lib/flags.js';
|
|
5
5
|
import { startMiniOxygen } from '../../lib/mini-oxygen/index.js';
|
|
6
6
|
import { getAllEnvironmentVariables } from '../../lib/environment-variables.js';
|
|
7
7
|
import { getConfig } from '../../lib/shopify-config.js';
|
|
8
8
|
import { findPort } from '../../lib/find-port.js';
|
|
9
|
-
import { fileExists } from '@shopify/cli-kit/node/fs';
|
|
10
9
|
import { joinPath } from '@shopify/cli-kit/node/path';
|
|
11
10
|
import { getViteConfig } from '../../lib/vite-config.js';
|
|
12
11
|
|
|
13
12
|
class Preview extends Command {
|
|
13
|
+
static descriptionWithMarkdown = "Runs a server in your local development environment that serves your Hydrogen app's production build. Requires running the [build](https://shopify.dev/docs/api/shopify-cli/hydrogen/hydrogen-build) command first.";
|
|
14
14
|
static description = "Runs a Hydrogen storefront in an Oxygen worker for production.";
|
|
15
15
|
static flags = {
|
|
16
16
|
...commonFlags.path,
|
|
17
17
|
...commonFlags.port,
|
|
18
18
|
worker: deprecated("--worker", { isBoolean: true }),
|
|
19
19
|
...commonFlags.legacyRuntime,
|
|
20
|
+
...commonFlags.env,
|
|
20
21
|
...commonFlags.envBranch,
|
|
21
22
|
...commonFlags.inspectorPort,
|
|
22
|
-
...commonFlags.debug
|
|
23
|
+
...commonFlags.debug,
|
|
24
|
+
...commonFlags.verbose
|
|
23
25
|
};
|
|
24
26
|
async run() {
|
|
25
27
|
const { flags } = await this.parse(Preview);
|
|
@@ -32,31 +34,44 @@ async function runPreview({
|
|
|
32
34
|
port: appPort,
|
|
33
35
|
path: appPath,
|
|
34
36
|
legacyRuntime = false,
|
|
37
|
+
env: envHandle,
|
|
35
38
|
envBranch,
|
|
36
39
|
inspectorPort,
|
|
37
|
-
debug
|
|
40
|
+
debug,
|
|
41
|
+
verbose
|
|
38
42
|
}) {
|
|
39
43
|
if (!process.env.NODE_ENV)
|
|
40
44
|
process.env.NODE_ENV = "production";
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (!
|
|
45
|
+
if (verbose)
|
|
46
|
+
setH2OVerbose();
|
|
47
|
+
if (!isH2Verbose())
|
|
48
|
+
muteDevLogs();
|
|
49
|
+
let { root, buildPath, buildPathWorkerFile, buildPathClient } = getProjectPaths(appPath);
|
|
50
|
+
if (!await hasRemixConfigFile(root)) {
|
|
44
51
|
const maybeResult = await getViteConfig(root).catch(() => null);
|
|
45
|
-
|
|
46
|
-
buildPathWorkerFile = maybeResult.serverOutFile;
|
|
52
|
+
buildPathWorkerFile = maybeResult?.serverOutFile ?? joinPath(buildPath, "server", "index.js");
|
|
47
53
|
}
|
|
48
54
|
const { shop, storefront } = await getConfig(root);
|
|
49
55
|
const fetchRemote = !!shop && !!storefront?.id;
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
56
|
+
const { allVariables, logInjectedVariables } = await getAllEnvironmentVariables(
|
|
57
|
+
{
|
|
58
|
+
root,
|
|
59
|
+
fetchRemote,
|
|
60
|
+
envBranch,
|
|
61
|
+
envHandle
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
if (!appPort) {
|
|
65
|
+
appPort = await findPort(DEFAULT_APP_PORT);
|
|
66
|
+
}
|
|
53
67
|
const assetsPort = legacyRuntime ? 0 : await findPort(appPort + 100);
|
|
68
|
+
logInjectedVariables();
|
|
54
69
|
const miniOxygen = await startMiniOxygen(
|
|
55
70
|
{
|
|
56
71
|
root,
|
|
57
|
-
|
|
72
|
+
appPort,
|
|
58
73
|
assetsPort,
|
|
59
|
-
env,
|
|
74
|
+
env: allVariables,
|
|
60
75
|
buildPathClient,
|
|
61
76
|
buildPathWorkerFile,
|
|
62
77
|
inspectorPort,
|
|
@@ -4,10 +4,12 @@ import Command from '@shopify/cli-kit/node/base-command';
|
|
|
4
4
|
import { renderTasks, renderSuccess } from '@shopify/cli-kit/node/ui';
|
|
5
5
|
import { getPackageManager, installNodeModules } from '@shopify/cli-kit/node/node-package-manager';
|
|
6
6
|
import { Args } from '@oclif/core';
|
|
7
|
-
import { getRemixConfig } from '../../../lib/remix-config.js';
|
|
7
|
+
import { hasRemixConfigFile, getRemixConfig } from '../../../lib/remix-config.js';
|
|
8
8
|
import { SETUP_CSS_STRATEGIES, renderCssPrompt, setupCssStrategy, CSS_STRATEGY_NAME_MAP } from '../../../lib/setups/css/index.js';
|
|
9
|
+
import { AbortError } from '@shopify/cli-kit/node/error';
|
|
9
10
|
|
|
10
11
|
class SetupCSS extends Command {
|
|
12
|
+
static descriptionWithMarkdown = "Adds support for certain CSS strategies to your project.";
|
|
11
13
|
static description = "Setup CSS strategies for your project.";
|
|
12
14
|
static flags = {
|
|
13
15
|
...commonFlags.path,
|
|
@@ -37,6 +39,11 @@ async function runSetupCSS({
|
|
|
37
39
|
force = false,
|
|
38
40
|
installDeps = true
|
|
39
41
|
}) {
|
|
42
|
+
if (!await hasRemixConfigFile(directory)) {
|
|
43
|
+
throw new AbortError(
|
|
44
|
+
"No remix.config.js file found. This command is not supported in Vite projects."
|
|
45
|
+
);
|
|
46
|
+
}
|
|
40
47
|
const remixConfigPromise = getRemixConfig(directory);
|
|
41
48
|
const strategy = flagStrategy ? flagStrategy : await renderCssPrompt();
|
|
42
49
|
const remixConfig = await remixConfigPromise;
|
|
@@ -7,6 +7,7 @@ import { getRemixConfig } from '../../../lib/remix-config.js';
|
|
|
7
7
|
import { SETUP_I18N_STRATEGIES, renderI18nPrompt, setupI18nStrategy, I18N_STRATEGY_NAME_MAP } from '../../../lib/setups/i18n/index.js';
|
|
8
8
|
|
|
9
9
|
class SetupMarkets extends Command {
|
|
10
|
+
static descriptionWithMarkdown = "Adds support for multiple [markets](https://shopify.dev/docs/custom-storefronts/hydrogen/markets) to your project by using the URL structure.";
|
|
10
11
|
static description = "Setup support for multiple markets in your project.";
|
|
11
12
|
static flags = {
|
|
12
13
|
...commonFlags.path
|