@shopify/cli-hydrogen 7.1.0 → 7.1.2
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 +131 -0
- package/dist/commands/hydrogen/build.js +6 -15
- package/dist/commands/hydrogen/check.js +1 -1
- package/dist/commands/hydrogen/codegen.js +3 -3
- package/dist/commands/hydrogen/debug/cpu.js +1 -1
- package/dist/commands/hydrogen/deploy.js +46 -31
- package/dist/commands/hydrogen/deploy.test.js +35 -49
- package/dist/commands/hydrogen/dev-vite.js +159 -0
- package/dist/commands/hydrogen/dev.js +11 -14
- package/dist/commands/hydrogen/env/list.js +1 -1
- package/dist/commands/hydrogen/env/pull.js +3 -3
- package/dist/commands/hydrogen/env/pull.test.js +2 -0
- package/dist/commands/hydrogen/env/push__unstable.js +190 -0
- package/dist/commands/hydrogen/env/push__unstable.test.js +383 -0
- package/dist/commands/hydrogen/generate/route.js +2 -2
- package/dist/commands/hydrogen/init.d.ts +69 -0
- package/dist/commands/hydrogen/init.js +5 -5
- package/dist/commands/hydrogen/init.test.js +2 -2
- package/dist/commands/hydrogen/link.js +2 -2
- package/dist/commands/hydrogen/list.js +1 -1
- package/dist/commands/hydrogen/login.js +2 -9
- package/dist/commands/hydrogen/logout.js +1 -1
- package/dist/commands/hydrogen/preview.js +15 -7
- package/dist/commands/hydrogen/setup/css.js +3 -3
- package/dist/commands/hydrogen/setup/markets.js +4 -4
- package/dist/commands/hydrogen/setup/vite.js +209 -0
- package/dist/commands/hydrogen/setup.js +8 -6
- package/dist/commands/hydrogen/unlink.js +1 -1
- package/dist/commands/hydrogen/upgrade.js +5 -3
- package/dist/generator-templates/assets/vite/package.json +15 -0
- package/dist/generator-templates/assets/vite/vite.config.js +13 -0
- package/dist/generator-templates/starter/CHANGELOG.md +49 -0
- package/dist/generator-templates/starter/app/components/Search.tsx +12 -7
- package/dist/generator-templates/starter/app/root.tsx +1 -2
- package/dist/generator-templates/starter/app/routes/api.predictive-search.tsx +8 -15
- package/dist/generator-templates/starter/package.json +9 -8
- package/dist/generator-templates/starter/public/.gitkeep +0 -0
- package/dist/lib/build.js +2 -1
- package/dist/lib/codegen.js +8 -3
- package/dist/lib/environment-variables.test.js +4 -2
- package/dist/lib/flags.js +149 -95
- package/dist/lib/graphql/admin/pull-variables.js +1 -0
- package/dist/lib/graphql/admin/pull-variables.test.js +7 -1
- package/dist/lib/graphql/admin/push-variables.js +35 -0
- package/dist/lib/log.js +1 -0
- package/dist/lib/mini-oxygen/common.js +2 -1
- package/dist/lib/mini-oxygen/node.js +2 -2
- package/dist/lib/mini-oxygen/workerd-inspector.js +1 -1
- package/dist/lib/mini-oxygen/workerd.js +29 -17
- package/dist/lib/onboarding/common.js +0 -3
- package/dist/lib/onboarding/local.js +4 -1
- package/dist/lib/onboarding/remote.js +16 -11
- package/dist/lib/remix-config.js +1 -1
- package/dist/lib/request-events.js +3 -3
- package/dist/lib/setups/css/assets.js +7 -2
- package/dist/lib/template-diff.js +26 -11
- package/dist/lib/template-downloader.js +11 -2
- package/dist/lib/vite/hydrogen-middleware.js +82 -0
- package/dist/lib/vite/mini-oxygen.js +152 -0
- package/dist/lib/vite/plugins.d.ts +27 -0
- package/dist/lib/vite/plugins.js +139 -0
- package/dist/lib/vite/shared.js +10 -0
- package/dist/lib/vite/utils.js +55 -0
- package/dist/lib/vite/worker-entry.js +1518 -0
- package/dist/lib/vite-config.js +45 -0
- package/dist/virtual-routes/lib/useDebugNetworkServer.jsx +4 -2
- package/dist/virtual-routes/routes/index.jsx +5 -5
- package/dist/virtual-routes/routes/subrequest-profiler.jsx +1 -1
- package/dist/virtual-routes/virtual-root.jsx +1 -1
- package/oclif.manifest.json +1127 -494
- package/package.json +36 -11
- /package/dist/generator-templates/starter/{public → app/assets}/favicon.svg +0 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { muteDevLogs, enhanceH2Logs } from '../../lib/log.js';
|
|
4
|
+
import { commonFlags, overrideFlag, flagsToCamelObject } from '../../lib/flags.js';
|
|
5
|
+
import Command from '@shopify/cli-kit/node/base-command';
|
|
6
|
+
import colors from '@shopify/cli-kit/node/colors';
|
|
7
|
+
import { renderInfo } from '@shopify/cli-kit/node/ui';
|
|
8
|
+
import { AbortError } from '@shopify/cli-kit/node/error';
|
|
9
|
+
import { Flags } from '@oclif/core';
|
|
10
|
+
import { spawnCodegenProcess } from '../../lib/codegen.js';
|
|
11
|
+
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
|
+
import { displayDevUpgradeNotice } from './upgrade.js';
|
|
15
|
+
import { prepareDiffDirectory } from '../../lib/template-diff.js';
|
|
16
|
+
import { setH2OPluginContext } from '../../lib/vite/shared.js';
|
|
17
|
+
import { getGraphiQLUrl } from '../../lib/graphiql-url.js';
|
|
18
|
+
import { getDebugBannerLine } from '../../lib/mini-oxygen/workerd.js';
|
|
19
|
+
|
|
20
|
+
class DevVite extends Command {
|
|
21
|
+
static description = "Runs Hydrogen storefront in an Oxygen worker for development.";
|
|
22
|
+
static flags = {
|
|
23
|
+
...commonFlags.path,
|
|
24
|
+
...commonFlags.entry,
|
|
25
|
+
...overrideFlag(commonFlags.port, {
|
|
26
|
+
port: { default: void 0, required: false }
|
|
27
|
+
}),
|
|
28
|
+
...commonFlags.codegen,
|
|
29
|
+
"disable-virtual-routes": Flags.boolean({
|
|
30
|
+
description: "Disable rendering fallback routes when a route file doesn't exist.",
|
|
31
|
+
env: "SHOPIFY_HYDROGEN_FLAG_DISABLE_VIRTUAL_ROUTES",
|
|
32
|
+
default: false
|
|
33
|
+
}),
|
|
34
|
+
...commonFlags.debug,
|
|
35
|
+
...commonFlags.inspectorPort,
|
|
36
|
+
host: Flags.boolean({
|
|
37
|
+
description: "Expose the server to the network",
|
|
38
|
+
default: false,
|
|
39
|
+
required: false
|
|
40
|
+
}),
|
|
41
|
+
...commonFlags.envBranch,
|
|
42
|
+
"disable-version-check": Flags.boolean({
|
|
43
|
+
description: "Skip the version check when running `hydrogen dev`",
|
|
44
|
+
default: false,
|
|
45
|
+
required: false
|
|
46
|
+
}),
|
|
47
|
+
...commonFlags.diff
|
|
48
|
+
};
|
|
49
|
+
async run() {
|
|
50
|
+
const { flags } = await this.parse(DevVite);
|
|
51
|
+
let directory = flags.path ? path.resolve(flags.path) : process.cwd();
|
|
52
|
+
if (flags.diff) {
|
|
53
|
+
directory = await prepareDiffDirectory(directory, true);
|
|
54
|
+
}
|
|
55
|
+
await runDev({
|
|
56
|
+
...flagsToCamelObject(flags),
|
|
57
|
+
path: directory,
|
|
58
|
+
isLocalDev: flags.diff
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async function runDev({
|
|
63
|
+
entry: ssrEntry,
|
|
64
|
+
port: appPort,
|
|
65
|
+
path: appPath,
|
|
66
|
+
host,
|
|
67
|
+
codegen: useCodegen = false,
|
|
68
|
+
codegenConfigPath,
|
|
69
|
+
disableVirtualRoutes,
|
|
70
|
+
envBranch,
|
|
71
|
+
debug = false,
|
|
72
|
+
disableVersionCheck = false,
|
|
73
|
+
inspectorPort,
|
|
74
|
+
isLocalDev = false
|
|
75
|
+
}) {
|
|
76
|
+
if (!process.env.NODE_ENV)
|
|
77
|
+
process.env.NODE_ENV = "development";
|
|
78
|
+
muteDevLogs();
|
|
79
|
+
const root = appPath ?? process.cwd();
|
|
80
|
+
const envPromise = getConfig(root).then(({ shop, storefront }) => {
|
|
81
|
+
const fetchRemote = !!shop && !!storefront?.id;
|
|
82
|
+
return getAllEnvironmentVariables({ root, fetchRemote, envBranch });
|
|
83
|
+
});
|
|
84
|
+
const vite = await import('vite');
|
|
85
|
+
const fs = isLocalDev ? { allow: [root, fileURLToPath(new URL("../../../../", import.meta.url))] } : void 0;
|
|
86
|
+
const viteServer = await vite.createServer({
|
|
87
|
+
root,
|
|
88
|
+
server: { fs, host: host ? true : void 0 },
|
|
89
|
+
...setH2OPluginContext({
|
|
90
|
+
cliOptions: {
|
|
91
|
+
debug,
|
|
92
|
+
ssrEntry,
|
|
93
|
+
envPromise,
|
|
94
|
+
inspectorPort,
|
|
95
|
+
disableVirtualRoutes
|
|
96
|
+
}
|
|
97
|
+
})
|
|
98
|
+
});
|
|
99
|
+
process.once("SIGTERM", async () => {
|
|
100
|
+
try {
|
|
101
|
+
await viteServer.close();
|
|
102
|
+
} finally {
|
|
103
|
+
process.exit();
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
if (!viteServer.config.plugins.find((plugin) => plugin.name === "hydrogen:main")) {
|
|
107
|
+
await viteServer.close();
|
|
108
|
+
throw new AbortError(
|
|
109
|
+
"Hydrogen plugin not found.",
|
|
110
|
+
"Add `hydrogen()` plugin to your Vite config."
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
const codegenProcess = useCodegen ? spawnCodegenProcess({
|
|
114
|
+
rootDirectory: root,
|
|
115
|
+
configFilePath: codegenConfigPath
|
|
116
|
+
}) : void 0;
|
|
117
|
+
process.on("unhandledRejection", (err) => {
|
|
118
|
+
console.log("Unhandled Rejection: ", err);
|
|
119
|
+
});
|
|
120
|
+
const publicPort = appPort ?? viteServer.config.server.port ?? 3e3;
|
|
121
|
+
await viteServer.listen(publicPort);
|
|
122
|
+
const publicUrl = new URL(
|
|
123
|
+
viteServer.resolvedUrls.local[0] ?? viteServer.resolvedUrls.network[0]
|
|
124
|
+
);
|
|
125
|
+
enhanceH2Logs({ rootDirectory: root, host: publicUrl.toString() });
|
|
126
|
+
await envPromise;
|
|
127
|
+
console.log("");
|
|
128
|
+
viteServer.printUrls();
|
|
129
|
+
viteServer.bindCLIShortcuts({ print: true });
|
|
130
|
+
console.log("\n");
|
|
131
|
+
const infoLines = [];
|
|
132
|
+
if (!disableVirtualRoutes) {
|
|
133
|
+
infoLines.push(
|
|
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
|
+
);
|
|
140
|
+
}
|
|
141
|
+
if (debug) {
|
|
142
|
+
infoLines.push({ warn: getDebugBannerLine(inspectorPort) });
|
|
143
|
+
}
|
|
144
|
+
if (infoLines.length > 0) {
|
|
145
|
+
renderInfo({ body: infoLines });
|
|
146
|
+
}
|
|
147
|
+
checkRemixVersions();
|
|
148
|
+
if (!disableVersionCheck) {
|
|
149
|
+
displayDevUpgradeNotice({ targetPath: root });
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
async close() {
|
|
153
|
+
codegenProcess?.kill(0);
|
|
154
|
+
await viteServer.close();
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export { DevVite as default, runDev };
|
|
@@ -7,7 +7,7 @@ import colors from '@shopify/cli-kit/node/colors';
|
|
|
7
7
|
import { copyPublicFiles } from './build.js';
|
|
8
8
|
import { getProjectPaths, assertOxygenChecks, handleRemixImportFail, getRemixConfig } from '../../lib/remix-config.js';
|
|
9
9
|
import { muteDevLogs, createRemixLogger, enhanceH2Logs } from '../../lib/log.js';
|
|
10
|
-
import { commonFlags, deprecated,
|
|
10
|
+
import { commonFlags, deprecated, flagsToCamelObject } from '../../lib/flags.js';
|
|
11
11
|
import Command from '@shopify/cli-kit/node/base-command';
|
|
12
12
|
import { Flags } from '@oclif/core';
|
|
13
13
|
import { buildAssetsUrl, startMiniOxygen } from '../../lib/mini-oxygen/index.js';
|
|
@@ -27,29 +27,26 @@ const LOG_REBUILT = "\u{1F680} Rebuilt";
|
|
|
27
27
|
class Dev extends Command {
|
|
28
28
|
static description = "Runs Hydrogen storefront in an Oxygen worker for development.";
|
|
29
29
|
static flags = {
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
...commonFlags.path,
|
|
31
|
+
...commonFlags.port,
|
|
32
32
|
worker: deprecated("--worker", { isBoolean: true }),
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}),
|
|
37
|
-
"codegen-config-path": commonFlags.codegenConfigPath,
|
|
38
|
-
sourcemap: commonFlags.sourcemap,
|
|
33
|
+
...commonFlags.legacyRuntime,
|
|
34
|
+
...commonFlags.codegen,
|
|
35
|
+
...commonFlags.sourcemap,
|
|
39
36
|
"disable-virtual-routes": Flags.boolean({
|
|
40
37
|
description: "Disable rendering fallback routes when a route file doesn't exist.",
|
|
41
38
|
env: "SHOPIFY_HYDROGEN_FLAG_DISABLE_VIRTUAL_ROUTES",
|
|
42
39
|
default: false
|
|
43
40
|
}),
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
...commonFlags.debug,
|
|
42
|
+
...commonFlags.inspectorPort,
|
|
43
|
+
...commonFlags.envBranch,
|
|
44
|
+
"disable-version-check": Flags.boolean({
|
|
48
45
|
description: "Skip the version check when running `hydrogen dev`",
|
|
49
46
|
default: false,
|
|
50
47
|
required: false
|
|
51
48
|
}),
|
|
52
|
-
|
|
49
|
+
...commonFlags.diff
|
|
53
50
|
};
|
|
54
51
|
async run() {
|
|
55
52
|
const { flags } = await this.parse(Dev);
|
|
@@ -13,7 +13,7 @@ import { getCliCommand } from '../../../lib/shell.js';
|
|
|
13
13
|
class EnvList extends Command {
|
|
14
14
|
static description = "List the environments on your linked Hydrogen storefront.";
|
|
15
15
|
static flags = {
|
|
16
|
-
|
|
16
|
+
...commonFlags.path
|
|
17
17
|
};
|
|
18
18
|
async run() {
|
|
19
19
|
const { flags } = await this.parse(EnvList);
|
|
@@ -16,9 +16,9 @@ import { getStorefrontEnvVariables } from '../../../lib/graphql/admin/pull-varia
|
|
|
16
16
|
class EnvPull extends Command {
|
|
17
17
|
static description = "Populate your .env with variables from your Hydrogen storefront.";
|
|
18
18
|
static flags = {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
...commonFlags.envBranch,
|
|
20
|
+
...commonFlags.path,
|
|
21
|
+
...commonFlags.force
|
|
22
22
|
};
|
|
23
23
|
async run() {
|
|
24
24
|
const { flags } = await this.parse(EnvPull);
|
|
@@ -46,12 +46,14 @@ describe("pullVariables", () => {
|
|
|
46
46
|
id: "gid://shopify/HydrogenStorefrontEnvironmentVariable/1",
|
|
47
47
|
key: "PUBLIC_API_TOKEN",
|
|
48
48
|
value: "abc123",
|
|
49
|
+
readOnly: true,
|
|
49
50
|
isSecret: false
|
|
50
51
|
},
|
|
51
52
|
{
|
|
52
53
|
id: "gid://shopify/HydrogenStorefrontEnvironmentVariable/2",
|
|
53
54
|
key: "PRIVATE_API_TOKEN",
|
|
54
55
|
value: "",
|
|
56
|
+
readOnly: true,
|
|
55
57
|
isSecret: true
|
|
56
58
|
}
|
|
57
59
|
]
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import Command from '@shopify/cli-kit/node/base-command';
|
|
2
|
+
import { diffLines } from 'diff';
|
|
3
|
+
import { Flags } from '@oclif/core';
|
|
4
|
+
import { commonFlags, flagsToCamelObject } from '../../../lib/flags.js';
|
|
5
|
+
import { login } from '../../../lib/auth.js';
|
|
6
|
+
import { getCliCommand } from '../../../lib/shell.js';
|
|
7
|
+
import { resolvePath } from '@shopify/cli-kit/node/path';
|
|
8
|
+
import { renderConfirmationPrompt, renderSelectPrompt, renderInfo, renderSuccess } from '@shopify/cli-kit/node/ui';
|
|
9
|
+
import { outputContent, outputToken, outputWarn } from '@shopify/cli-kit/node/output';
|
|
10
|
+
import { renderMissingLink } from '../../../lib/render-errors.js';
|
|
11
|
+
import { getStorefrontEnvironments } from '../../../lib/graphql/admin/list-environments.js';
|
|
12
|
+
import { linkStorefront } from '../link.js';
|
|
13
|
+
import { getStorefrontEnvVariables } from '../../../lib/graphql/admin/pull-variables.js';
|
|
14
|
+
import { pushStorefrontEnvVariables } from '../../../lib/graphql/admin/push-variables.js';
|
|
15
|
+
import { AbortError } from '@shopify/cli-kit/node/error';
|
|
16
|
+
import { readAndParseDotEnv } from '@shopify/cli-kit/node/dot-env';
|
|
17
|
+
|
|
18
|
+
class EnvPush extends Command {
|
|
19
|
+
static description = "Push environment variables from the local .env file to your linked Hydrogen storefront.";
|
|
20
|
+
static hidden = true;
|
|
21
|
+
static flags = {
|
|
22
|
+
...commonFlags.env,
|
|
23
|
+
"env-file": Flags.string({
|
|
24
|
+
description: "Specify the environment variable file name. Default value is '.env'.",
|
|
25
|
+
env: "SHOPIFY_HYDROGEN_ENVIRONMENT_FILENAME"
|
|
26
|
+
}),
|
|
27
|
+
...commonFlags.path
|
|
28
|
+
};
|
|
29
|
+
async run() {
|
|
30
|
+
const { flags } = await this.parse(EnvPush);
|
|
31
|
+
await runEnvPush({ ...flagsToCamelObject(flags) });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async function runEnvPush({
|
|
35
|
+
env: environmentName,
|
|
36
|
+
envFile = ".env",
|
|
37
|
+
path = process.cwd()
|
|
38
|
+
}) {
|
|
39
|
+
let validatedEnvironment = {};
|
|
40
|
+
const dotEnvPath = resolvePath(path, envFile);
|
|
41
|
+
const { variables: localVariables } = await readAndParseDotEnv(dotEnvPath);
|
|
42
|
+
const [{ session, config }, cliCommand] = await Promise.all([
|
|
43
|
+
login(path),
|
|
44
|
+
getCliCommand()
|
|
45
|
+
]);
|
|
46
|
+
if (!config.storefront?.id) {
|
|
47
|
+
renderMissingLink({ session, cliCommand });
|
|
48
|
+
const runLink = await renderConfirmationPrompt({
|
|
49
|
+
message: outputContent`Run ${outputToken.genericShellCommand(
|
|
50
|
+
`${cliCommand} link`
|
|
51
|
+
)}?`.value
|
|
52
|
+
});
|
|
53
|
+
if (!runLink)
|
|
54
|
+
return;
|
|
55
|
+
config.storefront = await linkStorefront(path, session, config, {
|
|
56
|
+
cliCommand
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
if (!config.storefront?.id)
|
|
60
|
+
return;
|
|
61
|
+
const { environments: environmentsData } = await getStorefrontEnvironments(session, config.storefront.id) ?? {};
|
|
62
|
+
if (!environmentsData) {
|
|
63
|
+
throw new AbortError("Failed to fetch environments");
|
|
64
|
+
}
|
|
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
|
+
];
|
|
72
|
+
if (environments.length === 0) {
|
|
73
|
+
throw new AbortError("No environments found");
|
|
74
|
+
}
|
|
75
|
+
if (environmentName) {
|
|
76
|
+
const matchedEnvironments = environments.filter(
|
|
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
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
const choices = [
|
|
102
|
+
...environments.map(({ id: id2, name: name2, branch: branch2 }) => ({
|
|
103
|
+
label: branch2 ? `${name2} (${branch2})` : name2,
|
|
104
|
+
value: id2
|
|
105
|
+
}))
|
|
106
|
+
];
|
|
107
|
+
const pushToBranchSelection = await renderSelectPrompt({
|
|
108
|
+
message: "Select a set of environment variables to overwrite:",
|
|
109
|
+
choices
|
|
110
|
+
});
|
|
111
|
+
const { id, name, branch, type } = environments.find(({ id: id2 }) => id2 === pushToBranchSelection) ?? {};
|
|
112
|
+
validatedEnvironment = { id, name, branch, type };
|
|
113
|
+
}
|
|
114
|
+
const { environmentVariables = [] } = await getStorefrontEnvVariables(
|
|
115
|
+
session,
|
|
116
|
+
config.storefront.id,
|
|
117
|
+
validatedEnvironment.branch ?? void 0
|
|
118
|
+
) ?? {};
|
|
119
|
+
const remoteVars = environmentVariables.filter(
|
|
120
|
+
({ isSecret, readOnly }) => !isSecret && !readOnly
|
|
121
|
+
);
|
|
122
|
+
const comparableRemoteVars = remoteVars.sort((a, b) => a.key.localeCompare(b.key)).map(({ key, value }) => `${key}=${value}`).join("\n") + "\n";
|
|
123
|
+
const compareableLocalVars = Object.keys(localVariables).sort((a, b) => a.localeCompare(b)).reduce((acc, key) => {
|
|
124
|
+
const { isSecret, readOnly } = environmentVariables.find((variable) => variable.key === key) ?? {};
|
|
125
|
+
if (isSecret || readOnly)
|
|
126
|
+
return acc;
|
|
127
|
+
return [...acc, `${key}=${localVariables[key]}`];
|
|
128
|
+
}, []).join("\n") + "\n";
|
|
129
|
+
if (!validatedEnvironment.name)
|
|
130
|
+
throw new AbortError("Missing environment name");
|
|
131
|
+
const remoteReadOnlyOrSecrets = environmentVariables.reduce(
|
|
132
|
+
(acc, { isSecret, readOnly, key }) => {
|
|
133
|
+
if (!isSecret && !readOnly)
|
|
134
|
+
return acc;
|
|
135
|
+
const localVar = localVariables[key];
|
|
136
|
+
const remoteVar = environmentVariables.find(
|
|
137
|
+
(variable) => variable.key === key
|
|
138
|
+
);
|
|
139
|
+
if (localVar === remoteVar?.value)
|
|
140
|
+
return acc;
|
|
141
|
+
return [...acc, key];
|
|
142
|
+
},
|
|
143
|
+
[]
|
|
144
|
+
);
|
|
145
|
+
if (remoteReadOnlyOrSecrets.length) {
|
|
146
|
+
outputWarn(
|
|
147
|
+
`Variables that are read only or contain secret values cannot be pushed from the CLI: ${remoteReadOnlyOrSecrets.join(
|
|
148
|
+
", "
|
|
149
|
+
)}.
|
|
150
|
+
`
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
if (compareableLocalVars === comparableRemoteVars) {
|
|
154
|
+
renderInfo({
|
|
155
|
+
body: "No changes to your environment variables."
|
|
156
|
+
});
|
|
157
|
+
return;
|
|
158
|
+
} else {
|
|
159
|
+
const diff = diffLines(comparableRemoteVars, compareableLocalVars);
|
|
160
|
+
const confirmPush = await renderConfirmationPrompt({
|
|
161
|
+
confirmationMessage: "Yes, confirm changes",
|
|
162
|
+
cancellationMessage: "No, make changes later",
|
|
163
|
+
message: outputContent`We'll make the following changes to your environment variables for ${validatedEnvironment.name}:
|
|
164
|
+
|
|
165
|
+
${outputToken.linesDiff(diff)}
|
|
166
|
+
Continue?`.value
|
|
167
|
+
});
|
|
168
|
+
if (!confirmPush)
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
if (!validatedEnvironment.id)
|
|
172
|
+
throw new AbortError("Missing environment ID");
|
|
173
|
+
const { userErrors } = await pushStorefrontEnvVariables(
|
|
174
|
+
session,
|
|
175
|
+
config.storefront.id,
|
|
176
|
+
validatedEnvironment.id,
|
|
177
|
+
Object.entries(localVariables).map(([key, value]) => ({ key, value }))
|
|
178
|
+
);
|
|
179
|
+
if (userErrors.length) {
|
|
180
|
+
throw new AbortError(
|
|
181
|
+
"Failed to upload and save environment variables.",
|
|
182
|
+
userErrors[0]?.message
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
renderSuccess({
|
|
186
|
+
body: `Environment variables push to ${validatedEnvironment.name ?? "Preview"} was successful.`
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export { EnvPush as default, runEnvPush };
|