@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,5 +1,6 @@
|
|
|
1
1
|
import * as _oclif_core_lib_interfaces_parser_js from '@oclif/core/lib/interfaces/parser.js';
|
|
2
2
|
import Command from '@shopify/cli-kit/node/base-command';
|
|
3
|
+
import { PackageManager } from '@shopify/cli-kit/node/node-package-manager';
|
|
3
4
|
|
|
4
5
|
declare const GENERATOR_SETUP_ASSETS_SUB_DIRS: readonly ["tailwind", "css-modules", "vanilla-extract", "postcss", "vite"];
|
|
5
6
|
type AssetDir = (typeof GENERATOR_SETUP_ASSETS_SUB_DIRS)[number];
|
|
@@ -25,6 +26,8 @@ type InitOptions = {
|
|
|
25
26
|
shortcut?: boolean;
|
|
26
27
|
installDeps?: boolean;
|
|
27
28
|
git?: boolean;
|
|
29
|
+
quickstart?: boolean;
|
|
30
|
+
packageManager?: PackageManager;
|
|
28
31
|
};
|
|
29
32
|
declare const LANGUAGES: {
|
|
30
33
|
readonly js: "JavaScript";
|
|
@@ -33,10 +36,13 @@ declare const LANGUAGES: {
|
|
|
33
36
|
type Language = keyof typeof LANGUAGES;
|
|
34
37
|
|
|
35
38
|
declare class Init extends Command {
|
|
39
|
+
static descriptionWithMarkdown: string;
|
|
36
40
|
static description: string;
|
|
37
41
|
static flags: {
|
|
38
42
|
routes: _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
|
|
39
43
|
git: _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
|
|
44
|
+
quickstart: _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
|
|
45
|
+
'package-manager': _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
|
40
46
|
shortcut: _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
|
|
41
47
|
markets: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
|
42
48
|
styling: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
|
@@ -49,11 +55,13 @@ declare class Init extends Command {
|
|
|
49
55
|
};
|
|
50
56
|
run(): Promise<void>;
|
|
51
57
|
}
|
|
52
|
-
declare function runInit(options?: InitOptions
|
|
58
|
+
declare function runInit({ markets, ...options }?: InitOptions & {
|
|
59
|
+
markets?: InitOptions['i18n'];
|
|
60
|
+
}): Promise<{
|
|
53
61
|
language?: "js" | "ts" | undefined;
|
|
54
|
-
packageManager: "npm" | "
|
|
62
|
+
packageManager: "npm" | "yarn" | "pnpm" | "unknown" | "bun";
|
|
55
63
|
cssStrategy?: CssStrategy | undefined;
|
|
56
|
-
cliCommand: "h2" | "
|
|
64
|
+
cliCommand: "h2" | "yarn shopify hydrogen" | "pnpm shopify hydrogen" | "bun shopify hydrogen" | "npx shopify hydrogen";
|
|
57
65
|
depsInstalled: boolean;
|
|
58
66
|
depsError?: Error | undefined;
|
|
59
67
|
i18n?: "subfolders" | "domains" | "subdomains" | undefined;
|
|
@@ -3,7 +3,7 @@ import { resolvePath } from '@shopify/cli-kit/node/path';
|
|
|
3
3
|
import { checkIfIgnoredInGitRepository } from '@shopify/cli-kit/node/git';
|
|
4
4
|
import { renderWarning } from '@shopify/cli-kit/node/ui';
|
|
5
5
|
import { AbortError } from '@shopify/cli-kit/node/error';
|
|
6
|
-
import {
|
|
6
|
+
import { packageManagers } from './package-managers.js';
|
|
7
7
|
|
|
8
8
|
function missingLockfileWarning(shouldExit) {
|
|
9
9
|
const headline = "No lockfile found";
|
|
@@ -23,15 +23,9 @@ function missingLockfileWarning(shouldExit) {
|
|
|
23
23
|
renderWarning({ headline, body, nextSteps });
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
function multipleLockfilesWarning(
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
"yarn.lock": "yarn",
|
|
30
|
-
"package-lock.json": "npm",
|
|
31
|
-
"pnpm-lock.yaml": "pnpm"
|
|
32
|
-
};
|
|
33
|
-
const lockfileList = lockfiles2.map((lockfile) => {
|
|
34
|
-
return `${lockfile} (created by ${packageManagers[lockfile]})`;
|
|
26
|
+
function multipleLockfilesWarning(packageManagers2, shouldExit) {
|
|
27
|
+
const lockfileList = packageManagers2.map(({ name, lockfile }) => {
|
|
28
|
+
return `${lockfile} (created by ${name})`;
|
|
35
29
|
});
|
|
36
30
|
const headline = "Multiple lockfiles found";
|
|
37
31
|
const body = [
|
|
@@ -61,19 +55,19 @@ function lockfileIgnoredWarning(lockfile) {
|
|
|
61
55
|
async function checkLockfileStatus(directory, shouldExit = false) {
|
|
62
56
|
if (process.env.LOCAL_DEV)
|
|
63
57
|
return;
|
|
64
|
-
const
|
|
65
|
-
for (const
|
|
66
|
-
if (await fileExists(resolvePath(directory,
|
|
67
|
-
|
|
58
|
+
const foundPackageManagers = [];
|
|
59
|
+
for (const packageManager of packageManagers) {
|
|
60
|
+
if (await fileExists(resolvePath(directory, packageManager.lockfile))) {
|
|
61
|
+
foundPackageManagers.push(packageManager);
|
|
68
62
|
}
|
|
69
63
|
}
|
|
70
|
-
if (
|
|
64
|
+
if (foundPackageManagers.length === 0) {
|
|
71
65
|
return missingLockfileWarning(shouldExit);
|
|
72
66
|
}
|
|
73
|
-
if (
|
|
74
|
-
return multipleLockfilesWarning(
|
|
67
|
+
if (foundPackageManagers.length > 1) {
|
|
68
|
+
return multipleLockfilesWarning(foundPackageManagers, shouldExit);
|
|
75
69
|
}
|
|
76
|
-
const lockfile =
|
|
70
|
+
const lockfile = foundPackageManagers[0].lockfile;
|
|
77
71
|
const ignoredLockfile = await checkIfIgnoredInGitRepository(directory, [
|
|
78
72
|
lockfile
|
|
79
73
|
]).catch(() => {
|
package/dist/lib/codegen.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
2
|
import { fileURLToPath } from 'node:url';
|
|
3
3
|
import { getCodeFormatOptions, formatCode } from './format-code.js';
|
|
4
|
-
import { renderWarning
|
|
4
|
+
import { renderWarning } from '@shopify/cli-kit/node/ui';
|
|
5
5
|
import { relativePath, joinPath, resolvePath, basename } from '@shopify/cli-kit/node/path';
|
|
6
6
|
import { AbortError } from '@shopify/cli-kit/node/error';
|
|
7
7
|
|
|
@@ -17,6 +17,13 @@ if (isStandaloneProcess) {
|
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
19
|
function normalizeCodegenError(errorMessage, rootDirectory) {
|
|
20
|
+
if (errorMessage.includes("AbortError: ")) {
|
|
21
|
+
const parsedError = errorMessage.split("AbortError: ")[1] ?? "";
|
|
22
|
+
const message2 = parsedError.split("\n")[0];
|
|
23
|
+
const details2 = parsedError.match(/tryMessage: '(.*)',$/m)?.[1];
|
|
24
|
+
if (message2)
|
|
25
|
+
return { message: message2, details: details2 };
|
|
26
|
+
}
|
|
20
27
|
const [first = "", ...rest] = errorMessage.replaceAll("[FAILED]", "").replace(/\s{2,}/g, "\n").replace(/\n,\n/, "\n").trim().split("\n");
|
|
21
28
|
const message = "[Codegen] " + first;
|
|
22
29
|
let details = rest.join("\n");
|
|
@@ -48,25 +55,27 @@ function spawnCodegenProcess({
|
|
|
48
55
|
const { message, details } = normalizeCodegenError(dataString, rootDirectory);
|
|
49
56
|
if (/`punycode`/.test(message))
|
|
50
57
|
return;
|
|
58
|
+
if (/\.body\[\d\]/.test(message))
|
|
59
|
+
return;
|
|
60
|
+
if (/console\.time(End)?\(\)/.test(message))
|
|
61
|
+
return;
|
|
51
62
|
console.log("");
|
|
52
63
|
renderWarning({ headline: message, body: details });
|
|
53
64
|
});
|
|
54
65
|
child.on("close", (code) => {
|
|
55
66
|
if (code && code > 0) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
message: `Codegen process exited with code ${code}`,
|
|
60
|
-
skipOclifErrorHandling: true,
|
|
61
|
-
tryMessage: "Try restarting the dev server."
|
|
67
|
+
renderWarning({
|
|
68
|
+
headline: "Codegen process exited with code " + code,
|
|
69
|
+
body: "There should be more logs above."
|
|
62
70
|
});
|
|
63
|
-
process.exit(code);
|
|
64
71
|
}
|
|
65
72
|
});
|
|
66
73
|
return child;
|
|
67
74
|
}
|
|
68
75
|
function codegen(options) {
|
|
69
76
|
return generateTypes(options).catch((error) => {
|
|
77
|
+
if (error instanceof AbortError)
|
|
78
|
+
throw error;
|
|
70
79
|
const { message, details } = normalizeCodegenError(
|
|
71
80
|
error.message,
|
|
72
81
|
options.rootDirectory
|
|
@@ -80,7 +89,12 @@ async function generateTypes({
|
|
|
80
89
|
forceSfapiVersion,
|
|
81
90
|
...dirs
|
|
82
91
|
}) {
|
|
83
|
-
const { generate, loadCodegenConfig, CodegenContext } = await import('@graphql-codegen/cli')
|
|
92
|
+
const { generate, loadCodegenConfig, CodegenContext } = await import('@graphql-codegen/cli').catch(() => {
|
|
93
|
+
throw new AbortError(
|
|
94
|
+
"Could not load GraphQL Codegen CLI.",
|
|
95
|
+
"Please make sure you have `@graphql-codegen/cli` installed as a dev dependency."
|
|
96
|
+
);
|
|
97
|
+
});
|
|
84
98
|
const { config: codegenConfig } = (
|
|
85
99
|
// Load <root>/codegen.ts if available
|
|
86
100
|
await loadCodegenConfig({
|
|
@@ -116,8 +130,18 @@ async function generateDefaultConfig({
|
|
|
116
130
|
rootDirectory,
|
|
117
131
|
appDirectory = resolvePath(rootDirectory, "app")
|
|
118
132
|
}, forceSfapiVersion) {
|
|
119
|
-
const { getSchema, preset, pluckConfig } = await import('@shopify/hydrogen-codegen')
|
|
120
|
-
|
|
133
|
+
const { getSchema, preset, pluckConfig } = await import('@shopify/hydrogen-codegen').catch(() => {
|
|
134
|
+
throw new AbortError(
|
|
135
|
+
"Could not load Hydrogen Codegen.",
|
|
136
|
+
"Please make sure you have `@shopify/hydrogen-codegen` installed as a dev dependency."
|
|
137
|
+
);
|
|
138
|
+
});
|
|
139
|
+
const { loadConfig } = await import('graphql-config').catch(() => {
|
|
140
|
+
throw new AbortError(
|
|
141
|
+
"Could not load GraphQL Config.",
|
|
142
|
+
"Please make sure you have `graphql-config` installed as a dev dependency."
|
|
143
|
+
);
|
|
144
|
+
});
|
|
121
145
|
const gqlConfig = await loadConfig({
|
|
122
146
|
rootDir: rootDirectory,
|
|
123
147
|
throwOnEmpty: false,
|
|
@@ -128,8 +152,8 @@ async function generateDefaultConfig({
|
|
|
128
152
|
const sfapiProject = findGqlProject(sfapiSchema, gqlConfig);
|
|
129
153
|
const defaultGlob = "*!(*.d).{ts,tsx,js,jsx}";
|
|
130
154
|
const appDirRelative = relativePath(rootDirectory, appDirectory);
|
|
131
|
-
const caapiSchema = getSchema("customer-account");
|
|
132
|
-
const caapiProject = findGqlProject(caapiSchema, gqlConfig);
|
|
155
|
+
const caapiSchema = getSchema("customer-account", { throwIfMissing: false });
|
|
156
|
+
const caapiProject = caapiSchema ? findGqlProject(caapiSchema, gqlConfig) : void 0;
|
|
133
157
|
const customerAccountAPIConfig = caapiProject?.documents ? {
|
|
134
158
|
["customer-accountapi.generated.d.ts"]: {
|
|
135
159
|
preset,
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { AbortError } from '@shopify/cli-kit/node/error';
|
|
2
|
+
import colors from '@shopify/cli-kit/node/colors';
|
|
3
|
+
|
|
4
|
+
function orderEnvironmentsBySafety(environments) {
|
|
5
|
+
return [
|
|
6
|
+
...environments.filter((environment) => environment.type === "PREVIEW"),
|
|
7
|
+
...environments.filter((environment) => environment.type === "CUSTOM"),
|
|
8
|
+
...environments.filter((environment) => environment.type === "PRODUCTION")
|
|
9
|
+
];
|
|
10
|
+
}
|
|
11
|
+
function createEnvironmentCliChoiceLabel(name, handle, branch) {
|
|
12
|
+
const metadataStringified = Object.entries({ handle, branch }).reduce((acc, [key, val]) => {
|
|
13
|
+
if (val) {
|
|
14
|
+
acc.push(`${key}: ${val}`);
|
|
15
|
+
}
|
|
16
|
+
return acc;
|
|
17
|
+
}, []).join(", ");
|
|
18
|
+
return `${name} ${colors.dim(`(${metadataStringified})`)}`;
|
|
19
|
+
}
|
|
20
|
+
function findEnvironmentOrThrow(environments, envHandle) {
|
|
21
|
+
const matchedEnvironment = environments.find(
|
|
22
|
+
({ handle }) => handle === envHandle
|
|
23
|
+
);
|
|
24
|
+
if (!matchedEnvironment) {
|
|
25
|
+
throw environmentNotFound("handle", envHandle);
|
|
26
|
+
}
|
|
27
|
+
return matchedEnvironment;
|
|
28
|
+
}
|
|
29
|
+
function findEnvironmentByBranchOrThrow(environments, branch) {
|
|
30
|
+
const matchedEnvironment = environments.find(({ branch: b }) => b === branch);
|
|
31
|
+
if (!matchedEnvironment) {
|
|
32
|
+
throw environmentNotFound("branch", branch);
|
|
33
|
+
}
|
|
34
|
+
return matchedEnvironment;
|
|
35
|
+
}
|
|
36
|
+
function environmentNotFound(criterion, value) {
|
|
37
|
+
return new AbortError(
|
|
38
|
+
"Environment not found",
|
|
39
|
+
`We could not find an environment matching the ${criterion} '${value}'.`,
|
|
40
|
+
[
|
|
41
|
+
[
|
|
42
|
+
"Run",
|
|
43
|
+
{ command: "env list" },
|
|
44
|
+
"to view a list of available environments."
|
|
45
|
+
]
|
|
46
|
+
]
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export { createEnvironmentCliChoiceLabel, findEnvironmentByBranchOrThrow, findEnvironmentOrThrow, orderEnvironmentsBySafety };
|
package/dist/lib/cpu-profiler.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { readFile } from '@shopify/cli-kit/node/fs';
|
|
2
2
|
import { Session } from 'node:inspector';
|
|
3
|
+
import { handleMiniOxygenImportFail } from './mini-oxygen/common.js';
|
|
3
4
|
|
|
4
5
|
async function createCpuStartupProfiler() {
|
|
5
|
-
const { createMiniOxygen } = await import('@shopify/mini-oxygen')
|
|
6
|
+
const { createMiniOxygen } = await import('@shopify/mini-oxygen/node').catch(
|
|
7
|
+
handleMiniOxygenImportFail
|
|
8
|
+
);
|
|
6
9
|
const miniOxygen = createMiniOxygen({
|
|
7
10
|
script: "export default {}",
|
|
8
11
|
modules: true,
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import colors from '@shopify/cli-kit/node/colors';
|
|
2
|
+
import { outputInfo, outputContent, outputToken } from '@shopify/cli-kit/node/output';
|
|
3
|
+
import { renderInfo } from '@shopify/cli-kit/node/ui';
|
|
4
|
+
import { AbortError } from '@shopify/cli-kit/node/error';
|
|
5
|
+
import { getStorefrontId, runCustomerAccountPush } from '../commands/hydrogen/customer-account/push.js';
|
|
6
|
+
import { getLocalVariables } from '../lib/environment-variables.js';
|
|
7
|
+
import { startTunnelPlugin, pollTunnelURL } from './tunneling.js';
|
|
8
|
+
import { getConfig } from './shopify-config.js';
|
|
9
|
+
import { getGraphiQLUrl } from './graphiql-url.js';
|
|
10
|
+
|
|
11
|
+
function isMockShop(envVariables) {
|
|
12
|
+
return envVariables.PUBLIC_STORE_DOMAIN && envVariables.PUBLIC_STORE_DOMAIN.includes("mock.shop");
|
|
13
|
+
}
|
|
14
|
+
function notifyIssueWithTunnelAndMockShop(cliCommand) {
|
|
15
|
+
renderInfo({
|
|
16
|
+
headline: "Using mock.shop with `--customer-account-push` flag is not supported",
|
|
17
|
+
body: "The functionalities of this flag are disabled.",
|
|
18
|
+
nextSteps: [
|
|
19
|
+
"You may continue knowing Customer Account API (/account) interactions will fail.",
|
|
20
|
+
[
|
|
21
|
+
"Or run",
|
|
22
|
+
{ command: `${cliCommand} env pull` },
|
|
23
|
+
"to link to your store credentials."
|
|
24
|
+
]
|
|
25
|
+
]
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function getDevConfigInBackground(root, customerAccountPushFlag) {
|
|
29
|
+
return getLocalVariables(root).then(async ({ variables: localVariables }) => {
|
|
30
|
+
const customerAccountPush = customerAccountPushFlag && !isMockShop(localVariables);
|
|
31
|
+
if (customerAccountPush) {
|
|
32
|
+
await getStorefrontId(root);
|
|
33
|
+
}
|
|
34
|
+
const { shop, storefront } = await getConfig(root);
|
|
35
|
+
const storefrontId = storefront?.id;
|
|
36
|
+
return {
|
|
37
|
+
storefrontId,
|
|
38
|
+
customerAccountPush,
|
|
39
|
+
fetchRemote: !!shop && !!storefrontId,
|
|
40
|
+
localVariables,
|
|
41
|
+
storefrontTitle: storefront?.title
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
const TUNNEL_DOMAIN = Object.freeze({
|
|
46
|
+
ORIGINAL: ".trycloudflare.com",
|
|
47
|
+
REBRANDED: ".tryhydrogen.dev"
|
|
48
|
+
});
|
|
49
|
+
async function startTunnelAndPushConfig(root, cliConfig, port, storefrontId) {
|
|
50
|
+
outputInfo("\nStarting tunnel...\n");
|
|
51
|
+
const tunnel = await startTunnelPlugin(cliConfig, port, "cloudflare");
|
|
52
|
+
const host = await pollTunnelURL(tunnel).then(
|
|
53
|
+
(host2) => (
|
|
54
|
+
// Replace branded tunnel domain:
|
|
55
|
+
host2.replace(TUNNEL_DOMAIN.ORIGINAL, TUNNEL_DOMAIN.REBRANDED)
|
|
56
|
+
)
|
|
57
|
+
);
|
|
58
|
+
const cleanup = await runCustomerAccountPush({
|
|
59
|
+
path: root,
|
|
60
|
+
devOrigin: host,
|
|
61
|
+
storefrontId
|
|
62
|
+
}).catch((error) => {
|
|
63
|
+
if (error instanceof AbortError) {
|
|
64
|
+
renderInfo({
|
|
65
|
+
headline: "Customer Account Application setup update fail.",
|
|
66
|
+
body: error.tryMessage || void 0,
|
|
67
|
+
nextSteps: error.nextSteps
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
return { host, cleanup };
|
|
72
|
+
}
|
|
73
|
+
function getDebugBannerLine(publicInspectorPort) {
|
|
74
|
+
const isVSCode = process.env.TERM_PROGRAM === "vscode";
|
|
75
|
+
const debuggingDocsLink = "https://h2o.fyi/debugging/server-code" + (isVSCode ? "#visual-studio-code" : "#step-2-attach-a-debugger");
|
|
76
|
+
return outputContent`Debugging enabled on port ${String(
|
|
77
|
+
publicInspectorPort
|
|
78
|
+
)}.\nAttach a ${outputToken.link(
|
|
79
|
+
colors.yellow(isVSCode ? "VSCode debugger" : "debugger"),
|
|
80
|
+
debuggingDocsLink
|
|
81
|
+
)} or open DevTools in http://localhost:${String(publicInspectorPort)}.`.value;
|
|
82
|
+
}
|
|
83
|
+
function getUtilityBannerlines(host) {
|
|
84
|
+
host = host.endsWith("/") ? host.slice(0, -1) : host;
|
|
85
|
+
return [
|
|
86
|
+
`View GraphiQL API browser:
|
|
87
|
+
${getGraphiQLUrl({
|
|
88
|
+
host
|
|
89
|
+
})}`,
|
|
90
|
+
`View server network requests:
|
|
91
|
+
${host}/subrequest-profiler`
|
|
92
|
+
].map((value, index) => ({
|
|
93
|
+
subdued: `${index === 0 ? "" : "\n\n"}${value}`
|
|
94
|
+
}));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export { TUNNEL_DOMAIN, getDebugBannerLine, getDevConfigInBackground, getUtilityBannerlines, isMockShop, notifyIssueWithTunnelAndMockShop, startTunnelAndPushConfig };
|
|
@@ -6,6 +6,8 @@ import { readAndParseDotEnv } from '@shopify/cli-kit/node/dot-env';
|
|
|
6
6
|
import { renderWarning } from '@shopify/cli-kit/node/ui';
|
|
7
7
|
import colors from '@shopify/cli-kit/node/colors';
|
|
8
8
|
import { getStorefrontEnvVariables } from './graphql/admin/pull-variables.js';
|
|
9
|
+
import { getStorefrontEnvironments } from './graphql/admin/list-environments.js';
|
|
10
|
+
import { findEnvironmentByBranchOrThrow } from './common.js';
|
|
9
11
|
import { login } from './auth.js';
|
|
10
12
|
|
|
11
13
|
const createEmptyRemoteVars = () => ({
|
|
@@ -14,50 +16,63 @@ const createEmptyRemoteVars = () => ({
|
|
|
14
16
|
});
|
|
15
17
|
async function getAllEnvironmentVariables({
|
|
16
18
|
root,
|
|
19
|
+
envHandle,
|
|
17
20
|
envBranch,
|
|
18
|
-
fetchRemote = true
|
|
21
|
+
fetchRemote = true,
|
|
22
|
+
localVariables: inlineLocalVariables
|
|
19
23
|
}) {
|
|
20
|
-
const dotEnvPath = resolvePath(root, ".env");
|
|
21
24
|
const [{ remoteVariables, remoteSecrets }, { variables: localVariables }] = await Promise.all([
|
|
22
25
|
// Get remote vars
|
|
23
|
-
fetchRemote ? getRemoteVariables(root, envBranch).catch(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
fetchRemote ? getRemoteVariables(root, envHandle, envBranch).catch(
|
|
27
|
+
(error) => {
|
|
28
|
+
renderWarning({
|
|
29
|
+
headline: "Failed to load environment variables from Shopify. The development server will still start, but the following error occurred:",
|
|
30
|
+
body: [error.message, error.tryMessage, error.nextSteps].filter(Boolean).join("\n\n")
|
|
31
|
+
});
|
|
32
|
+
return createEmptyRemoteVars();
|
|
33
|
+
}
|
|
34
|
+
) : createEmptyRemoteVars(),
|
|
30
35
|
// Get local vars
|
|
31
|
-
|
|
32
|
-
(exists) => exists ? readAndParseDotEnv(dotEnvPath) : { variables: {} }
|
|
33
|
-
)
|
|
36
|
+
inlineLocalVariables ? { variables: inlineLocalVariables } : getLocalVariables(root)
|
|
34
37
|
]);
|
|
35
38
|
const remoteSecretKeys = Object.keys(remoteSecrets);
|
|
36
39
|
const remotePublicKeys = Object.keys(remoteVariables);
|
|
37
40
|
const localKeys = Object.keys(localVariables);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
function logInjectedVariables() {
|
|
42
|
+
if (localKeys.length > 0 || remotePublicKeys.length + remoteSecretKeys.length > 0) {
|
|
43
|
+
outputInfo("\nEnvironment variables injected into MiniOxygen:\n");
|
|
44
|
+
outputInfo(
|
|
45
|
+
linesToColumns([
|
|
46
|
+
...remotePublicKeys.filter((key) => !localKeys.includes(key)).map((key) => [key, "from Oxygen"]),
|
|
47
|
+
...localKeys.map((key) => [key, "from local .env"]),
|
|
48
|
+
// Ensure secret variables always get added to the bottom of the list
|
|
49
|
+
...remoteSecretKeys.filter((key) => !localKeys.includes(key)).map((key) => [
|
|
50
|
+
colors.dim(key),
|
|
51
|
+
colors.dim("from Oxygen (Marked as secret)")
|
|
52
|
+
])
|
|
48
53
|
])
|
|
49
|
-
|
|
50
|
-
|
|
54
|
+
);
|
|
55
|
+
}
|
|
51
56
|
}
|
|
52
57
|
return {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
logInjectedVariables,
|
|
59
|
+
remoteVariables,
|
|
60
|
+
remoteSecrets,
|
|
61
|
+
localVariables,
|
|
62
|
+
allVariables: {
|
|
63
|
+
...remoteSecrets,
|
|
64
|
+
...remoteVariables,
|
|
65
|
+
...localVariables
|
|
66
|
+
}
|
|
56
67
|
};
|
|
57
68
|
}
|
|
58
|
-
async function getRemoteVariables(root, envBranch) {
|
|
69
|
+
async function getRemoteVariables(root, envHandle, envBranch) {
|
|
59
70
|
const { session, config } = await login(root);
|
|
60
|
-
|
|
71
|
+
if (envBranch) {
|
|
72
|
+
const environments = (await getStorefrontEnvironments(session, config.storefront.id))?.environments || [];
|
|
73
|
+
envHandle = findEnvironmentByBranchOrThrow(environments, envBranch).handle;
|
|
74
|
+
}
|
|
75
|
+
const envVariables = (await getStorefrontEnvVariables(session, config.storefront.id, envHandle))?.environmentVariables || [];
|
|
61
76
|
const remoteVariables = {};
|
|
62
77
|
const remoteSecrets = {};
|
|
63
78
|
for (const { key, value, isSecret } of envVariables) {
|
|
@@ -68,5 +83,11 @@ async function getRemoteVariables(root, envBranch) {
|
|
|
68
83
|
}
|
|
69
84
|
return { remoteVariables, remoteSecrets };
|
|
70
85
|
}
|
|
86
|
+
async function getLocalVariables(root) {
|
|
87
|
+
const dotEnvPath = resolvePath(root, ".env");
|
|
88
|
+
return await fileExists(dotEnvPath).then(
|
|
89
|
+
(exists) => exists ? readAndParseDotEnv(dotEnvPath) : { variables: {} }
|
|
90
|
+
);
|
|
91
|
+
}
|
|
71
92
|
|
|
72
|
-
export { getAllEnvironmentVariables };
|
|
93
|
+
export { getAllEnvironmentVariables, getLocalVariables };
|
package/dist/lib/file.js
CHANGED
|
@@ -13,7 +13,14 @@ async function replaceFileContent(filepath, formatConfig, replacer) {
|
|
|
13
13
|
}
|
|
14
14
|
return writeFile(filepath, content);
|
|
15
15
|
}
|
|
16
|
-
const DEFAULT_EXTENSIONS = [
|
|
16
|
+
const DEFAULT_EXTENSIONS = [
|
|
17
|
+
"tsx",
|
|
18
|
+
"ts",
|
|
19
|
+
"jsx",
|
|
20
|
+
"js",
|
|
21
|
+
"mjs",
|
|
22
|
+
"cjs"
|
|
23
|
+
];
|
|
17
24
|
async function findFileWithExtension(directory, fileBase, extensions = DEFAULT_EXTENSIONS) {
|
|
18
25
|
const dirFiles = await readdir(directory);
|
|
19
26
|
if (dirFiles.includes(fileBase)) {
|
package/dist/lib/flags.js
CHANGED
|
@@ -5,9 +5,9 @@ import { normalizeStoreFqdn } from '@shopify/cli-kit/node/context/fqdn';
|
|
|
5
5
|
import colors from '@shopify/cli-kit/node/colors';
|
|
6
6
|
import { STYLING_CHOICES } from './setups/css/index.js';
|
|
7
7
|
import { I18N_CHOICES } from './setups/i18n/index.js';
|
|
8
|
-
import { DEFAULT_INSPECTOR_PORT } from './mini-oxygen/common.js';
|
|
9
8
|
|
|
10
|
-
const
|
|
9
|
+
const DEFAULT_APP_PORT = 3e3;
|
|
10
|
+
const DEFAULT_INSPECTOR_PORT = 9229;
|
|
11
11
|
const commonFlags = {
|
|
12
12
|
path: {
|
|
13
13
|
path: Flags.string({
|
|
@@ -17,9 +17,8 @@ const commonFlags = {
|
|
|
17
17
|
},
|
|
18
18
|
port: {
|
|
19
19
|
port: Flags.integer({
|
|
20
|
-
description: `The port to run the server on. Defaults to ${
|
|
21
|
-
env: "SHOPIFY_HYDROGEN_FLAG_PORT"
|
|
22
|
-
default: DEFAULT_PORT
|
|
20
|
+
description: `The port to run the server on. Defaults to ${DEFAULT_APP_PORT}.`,
|
|
21
|
+
env: "SHOPIFY_HYDROGEN_FLAG_PORT"
|
|
23
22
|
})
|
|
24
23
|
},
|
|
25
24
|
legacyRuntime: {
|
|
@@ -50,17 +49,23 @@ const commonFlags = {
|
|
|
50
49
|
allowNo: true
|
|
51
50
|
})
|
|
52
51
|
},
|
|
52
|
+
env: {
|
|
53
|
+
env: Flags.string({
|
|
54
|
+
description: "Specifies the environment to perform the operation using its handle. Fetch the handle using the `env list` command.",
|
|
55
|
+
exclusive: ["env-branch"]
|
|
56
|
+
})
|
|
57
|
+
},
|
|
58
|
+
/**
|
|
59
|
+
* @deprecated use `env` instead.
|
|
60
|
+
*/
|
|
53
61
|
envBranch: {
|
|
54
62
|
"env-branch": Flags.string({
|
|
55
|
-
description: "Specifies the environment to
|
|
63
|
+
description: "Specifies the environment to perform the operation using its Git branch name.",
|
|
56
64
|
env: "SHOPIFY_HYDROGEN_ENVIRONMENT_BRANCH",
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
env: Flags.string({
|
|
62
|
-
description: "Specifies an environment's name when using remote environment variables.",
|
|
63
|
-
env: "SHOPIFY_HYDROGEN_ENVIRONMENT_NAME"
|
|
65
|
+
deprecated: {
|
|
66
|
+
to: "env",
|
|
67
|
+
message: "--env-branch is deprecated. Use --env instead."
|
|
68
|
+
}
|
|
64
69
|
})
|
|
65
70
|
},
|
|
66
71
|
sourcemap: {
|
|
@@ -118,8 +123,7 @@ const commonFlags = {
|
|
|
118
123
|
inspectorPort: {
|
|
119
124
|
"inspector-port": Flags.integer({
|
|
120
125
|
description: `The port where the inspector is available. Defaults to ${DEFAULT_INSPECTOR_PORT}.`,
|
|
121
|
-
env: "SHOPIFY_HYDROGEN_FLAG_INSPECTOR_PORT"
|
|
122
|
-
default: DEFAULT_INSPECTOR_PORT
|
|
126
|
+
env: "SHOPIFY_HYDROGEN_FLAG_INSPECTOR_PORT"
|
|
123
127
|
})
|
|
124
128
|
},
|
|
125
129
|
diff: {
|
|
@@ -149,6 +153,23 @@ const commonFlags = {
|
|
|
149
153
|
description: "Disables any warnings about missing standard routes.",
|
|
150
154
|
env: "SHOPIFY_HYDROGEN_FLAG_DISABLE_ROUTE_WARNING"
|
|
151
155
|
})
|
|
156
|
+
},
|
|
157
|
+
customerAccountPush: {
|
|
158
|
+
"customer-account-push__unstable": Flags.boolean({
|
|
159
|
+
hidden: true,
|
|
160
|
+
description: "Use tunneling for local development and push the tunneling domain to admin. Required to use Customer Account API's Oauth flow",
|
|
161
|
+
required: false,
|
|
162
|
+
default: false,
|
|
163
|
+
env: "SHOPIFY_HYDROGEN_FLAG_CUSTOMER_ACCOUNT_PUSH"
|
|
164
|
+
})
|
|
165
|
+
},
|
|
166
|
+
verbose: {
|
|
167
|
+
verbose: Flags.boolean({
|
|
168
|
+
description: "Outputs more information about the command's execution.",
|
|
169
|
+
required: false,
|
|
170
|
+
default: false,
|
|
171
|
+
env: "SHOPIFY_HYDROGEN_FLAG_VERBOSE"
|
|
172
|
+
})
|
|
152
173
|
}
|
|
153
174
|
};
|
|
154
175
|
function flagsToCamelObject(obj) {
|
|
@@ -202,4 +223,4 @@ function overrideFlag(flags, extra) {
|
|
|
202
223
|
);
|
|
203
224
|
}
|
|
204
225
|
|
|
205
|
-
export {
|
|
226
|
+
export { DEFAULT_APP_PORT, DEFAULT_INSPECTOR_PORT, commonFlags, deprecated, flagsToCamelObject, overrideFlag, parseProcessFlags };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { adminRequest } from './client.js';
|
|
2
|
+
|
|
3
|
+
const CUSTOMER_APPLICATION_URLS_REPLACE = `#graphql
|
|
4
|
+
mutation CustomerApplicationUrlsReplace($storefrontId: ID!, $urlsReplaceInput: HydrogenStorefrontCustomerApplicationUrlsReplaceInput!) {
|
|
5
|
+
hydrogenStorefrontCustomerApplicationUrlsReplace(
|
|
6
|
+
storefrontId: $storefrontId,
|
|
7
|
+
urlsReplaceInput: $urlsReplaceInput,
|
|
8
|
+
) {
|
|
9
|
+
success
|
|
10
|
+
userErrors {
|
|
11
|
+
code
|
|
12
|
+
field
|
|
13
|
+
message
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
`;
|
|
18
|
+
async function replaceCustomerApplicationUrls(adminSession, storefrontId, urlsReplaceInput) {
|
|
19
|
+
const {
|
|
20
|
+
hydrogenStorefrontCustomerApplicationUrlsReplace: { success, userErrors }
|
|
21
|
+
} = await adminRequest(
|
|
22
|
+
CUSTOMER_APPLICATION_URLS_REPLACE,
|
|
23
|
+
adminSession,
|
|
24
|
+
{ storefrontId, urlsReplaceInput }
|
|
25
|
+
);
|
|
26
|
+
return { success, userErrors };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export { CUSTOMER_APPLICATION_URLS_REPLACE, replaceCustomerApplicationUrls };
|