@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
package/dist/lib/flags.js
CHANGED
|
@@ -3,11 +3,10 @@ import { camelize } from '@shopify/cli-kit/common/string';
|
|
|
3
3
|
import { renderInfo } from '@shopify/cli-kit/node/ui';
|
|
4
4
|
import { normalizeStoreFqdn } from '@shopify/cli-kit/node/context/fqdn';
|
|
5
5
|
import colors from '@shopify/cli-kit/node/colors';
|
|
6
|
-
import { STYLING_CHOICES } from './setups/css/index.js';
|
|
7
6
|
import { I18N_CHOICES } from './setups/i18n/index.js';
|
|
8
|
-
import { DEFAULT_INSPECTOR_PORT } from './mini-oxygen/common.js';
|
|
9
7
|
|
|
10
|
-
const
|
|
8
|
+
const DEFAULT_APP_PORT = 3e3;
|
|
9
|
+
const DEFAULT_INSPECTOR_PORT = 9229;
|
|
11
10
|
const commonFlags = {
|
|
12
11
|
path: {
|
|
13
12
|
path: Flags.string({
|
|
@@ -17,9 +16,8 @@ const commonFlags = {
|
|
|
17
16
|
},
|
|
18
17
|
port: {
|
|
19
18
|
port: Flags.integer({
|
|
20
|
-
description: `The port to run the server on. Defaults to ${
|
|
21
|
-
env: "SHOPIFY_HYDROGEN_FLAG_PORT"
|
|
22
|
-
default: DEFAULT_PORT
|
|
19
|
+
description: `The port to run the server on. Defaults to ${DEFAULT_APP_PORT}.`,
|
|
20
|
+
env: "SHOPIFY_HYDROGEN_FLAG_PORT"
|
|
23
21
|
})
|
|
24
22
|
},
|
|
25
23
|
legacyRuntime: {
|
|
@@ -50,17 +48,23 @@ const commonFlags = {
|
|
|
50
48
|
allowNo: true
|
|
51
49
|
})
|
|
52
50
|
},
|
|
51
|
+
env: {
|
|
52
|
+
env: Flags.string({
|
|
53
|
+
description: "Specifies the environment to perform the operation using its handle. Fetch the handle using the `env list` command.",
|
|
54
|
+
exclusive: ["env-branch"]
|
|
55
|
+
})
|
|
56
|
+
},
|
|
57
|
+
/**
|
|
58
|
+
* @deprecated use `env` instead.
|
|
59
|
+
*/
|
|
53
60
|
envBranch: {
|
|
54
61
|
"env-branch": Flags.string({
|
|
55
|
-
description: "Specifies the environment to
|
|
62
|
+
description: "Specifies the environment to perform the operation using its Git branch name.",
|
|
56
63
|
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"
|
|
64
|
+
deprecated: {
|
|
65
|
+
to: "env",
|
|
66
|
+
message: "--env-branch is deprecated. Use --env instead."
|
|
67
|
+
}
|
|
64
68
|
})
|
|
65
69
|
},
|
|
66
70
|
sourcemap: {
|
|
@@ -83,15 +87,6 @@ const commonFlags = {
|
|
|
83
87
|
dependsOn: ["codegen"]
|
|
84
88
|
})
|
|
85
89
|
},
|
|
86
|
-
styling: {
|
|
87
|
-
styling: Flags.string({
|
|
88
|
-
description: `Sets the styling strategy to use. One of ${STYLING_CHOICES.map(
|
|
89
|
-
(item) => `\`${item}\``
|
|
90
|
-
).join(", ")}.`,
|
|
91
|
-
choices: STYLING_CHOICES,
|
|
92
|
-
env: "SHOPIFY_HYDROGEN_FLAG_STYLING"
|
|
93
|
-
})
|
|
94
|
-
},
|
|
95
90
|
markets: {
|
|
96
91
|
markets: Flags.string({
|
|
97
92
|
description: `Sets the URL structure to support multiple markets. Must be one of: ${I18N_CHOICES.map(
|
|
@@ -118,8 +113,7 @@ const commonFlags = {
|
|
|
118
113
|
inspectorPort: {
|
|
119
114
|
"inspector-port": Flags.integer({
|
|
120
115
|
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
|
|
116
|
+
env: "SHOPIFY_HYDROGEN_FLAG_INSPECTOR_PORT"
|
|
123
117
|
})
|
|
124
118
|
},
|
|
125
119
|
diff: {
|
|
@@ -149,6 +143,23 @@ const commonFlags = {
|
|
|
149
143
|
description: "Disables any warnings about missing standard routes.",
|
|
150
144
|
env: "SHOPIFY_HYDROGEN_FLAG_DISABLE_ROUTE_WARNING"
|
|
151
145
|
})
|
|
146
|
+
},
|
|
147
|
+
customerAccountPush: {
|
|
148
|
+
"customer-account-push__unstable": Flags.boolean({
|
|
149
|
+
hidden: true,
|
|
150
|
+
description: "Use tunneling for local development and push the tunneling domain to admin. Required to use Customer Account API's Oauth flow",
|
|
151
|
+
required: false,
|
|
152
|
+
default: false,
|
|
153
|
+
env: "SHOPIFY_HYDROGEN_FLAG_CUSTOMER_ACCOUNT_PUSH"
|
|
154
|
+
})
|
|
155
|
+
},
|
|
156
|
+
verbose: {
|
|
157
|
+
verbose: Flags.boolean({
|
|
158
|
+
description: "Outputs more information about the command's execution.",
|
|
159
|
+
required: false,
|
|
160
|
+
default: false,
|
|
161
|
+
env: "SHOPIFY_HYDROGEN_FLAG_VERBOSE"
|
|
162
|
+
})
|
|
152
163
|
}
|
|
153
164
|
};
|
|
154
165
|
function flagsToCamelObject(obj) {
|
|
@@ -202,4 +213,4 @@ function overrideFlag(flags, extra) {
|
|
|
202
213
|
);
|
|
203
214
|
}
|
|
204
215
|
|
|
205
|
-
export {
|
|
216
|
+
export { DEFAULT_APP_PORT, DEFAULT_INSPECTOR_PORT, commonFlags, deprecated, flagsToCamelObject, overrideFlag, parseProcessFlags };
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { renderConfirmationPrompt } from '@shopify/cli-kit/node/ui';
|
|
2
1
|
import { outputWarn } from '@shopify/cli-kit/node/output';
|
|
3
|
-
import { linkStorefront } from '../commands/hydrogen/link.js';
|
|
4
2
|
import { login } from './auth.js';
|
|
5
3
|
import { getCliCommand } from './shell.js';
|
|
6
|
-
import {
|
|
4
|
+
import { renderMissingStorefront } from './render-errors.js';
|
|
7
5
|
import { getOxygenData } from './graphql/admin/get-oxygen-data.js';
|
|
6
|
+
import { verifyLinkedStorefront } from './verify-linked-storefront.js';
|
|
8
7
|
|
|
9
8
|
async function getOxygenDeploymentData({
|
|
10
9
|
root
|
|
@@ -13,21 +12,15 @@ async function getOxygenDeploymentData({
|
|
|
13
12
|
login(root),
|
|
14
13
|
getCliCommand()
|
|
15
14
|
]);
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
config.storefront = await linkStorefront(root, session, config, {
|
|
25
|
-
cliCommand
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
if (!config.storefront) {
|
|
15
|
+
const linkedStorefront = await verifyLinkedStorefront({
|
|
16
|
+
root,
|
|
17
|
+
session,
|
|
18
|
+
config,
|
|
19
|
+
cliCommand
|
|
20
|
+
});
|
|
21
|
+
if (!linkedStorefront)
|
|
29
22
|
return;
|
|
30
|
-
|
|
23
|
+
config.storefront = linkedStorefront;
|
|
31
24
|
const { storefront } = await getOxygenData(session, config.storefront.id);
|
|
32
25
|
if (!storefront) {
|
|
33
26
|
renderMissingStorefront({
|
|
@@ -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 };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { adminRequest } from './client.js';
|
|
2
2
|
|
|
3
3
|
const PullVariablesQuery = `#graphql
|
|
4
|
-
query PullVariables($id: ID!, $
|
|
4
|
+
query PullVariables($id: ID!, $handle: String) {
|
|
5
5
|
hydrogenStorefront(id: $id) {
|
|
6
6
|
id
|
|
7
|
-
environmentVariables(
|
|
7
|
+
environmentVariables(handle: $handle) {
|
|
8
8
|
id
|
|
9
9
|
isSecret
|
|
10
10
|
readOnly
|
|
@@ -14,13 +14,13 @@ const PullVariablesQuery = `#graphql
|
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
`;
|
|
17
|
-
async function getStorefrontEnvVariables(adminSession, storefrontId,
|
|
17
|
+
async function getStorefrontEnvVariables(adminSession, storefrontId, envHandle) {
|
|
18
18
|
const { hydrogenStorefront } = await adminRequest(
|
|
19
19
|
PullVariablesQuery,
|
|
20
20
|
adminSession,
|
|
21
21
|
{
|
|
22
22
|
id: storefrontId,
|
|
23
|
-
|
|
23
|
+
handle: envHandle
|
|
24
24
|
}
|
|
25
25
|
);
|
|
26
26
|
return hydrogenStorefront;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
function dummyListEnvironments(storefrontId) {
|
|
2
|
+
return {
|
|
3
|
+
id: storefrontId,
|
|
4
|
+
productionUrl: "https://my-shop.myshopify.com",
|
|
5
|
+
environments: [
|
|
6
|
+
{
|
|
7
|
+
id: "gid://shopify/HydrogenStorefrontEnvironment/1",
|
|
8
|
+
branch: "main",
|
|
9
|
+
type: "PRODUCTION",
|
|
10
|
+
name: "Production",
|
|
11
|
+
handle: "production",
|
|
12
|
+
createdAt: "2023-02-16T22:35:42Z",
|
|
13
|
+
url: "https://oxygen-123.example.com"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
id: "gid://shopify/HydrogenStorefrontEnvironment/2",
|
|
17
|
+
branch: null,
|
|
18
|
+
type: "PREVIEW",
|
|
19
|
+
name: "Preview",
|
|
20
|
+
handle: "preview",
|
|
21
|
+
createdAt: "2023-02-16T22:35:42Z",
|
|
22
|
+
url: null
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: "gid://shopify/HydrogenStorefrontEnvironment/3",
|
|
26
|
+
branch: "staging",
|
|
27
|
+
type: "CUSTOM",
|
|
28
|
+
name: "Staging",
|
|
29
|
+
handle: "staging",
|
|
30
|
+
createdAt: "2023-05-08T20:52:29Z",
|
|
31
|
+
url: "https://oxygen-456.example.com"
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export { dummyListEnvironments };
|
package/dist/lib/log.js
CHANGED
|
@@ -34,16 +34,19 @@ function debounceMessage(args, debounceFor) {
|
|
|
34
34
|
}
|
|
35
35
|
function warningDebouncer([first]) {
|
|
36
36
|
return typeof first === "string" && // Show these warnings only once.
|
|
37
|
-
|
|
37
|
+
/\[h2:(warn|info):(createStorefrontClient|createCustomerAccountClient)\]/.test(
|
|
38
|
+
first
|
|
39
|
+
) ? true : void 0;
|
|
38
40
|
}
|
|
39
41
|
function injectLogReplacer(method, debouncer) {
|
|
40
42
|
if (!methodsReplaced.has(method)) {
|
|
41
43
|
methodsReplaced.add(method);
|
|
42
44
|
console[method] = (...args) => {
|
|
43
|
-
if (debounceMessage(args, debouncer?.(args)))
|
|
45
|
+
if (debouncer !== false && debounceMessage(args, debouncer?.(args))) {
|
|
44
46
|
return;
|
|
47
|
+
}
|
|
45
48
|
const replacers = messageReplacers.reduce((acc, [matcher, replacer]) => {
|
|
46
|
-
if (matcher(args))
|
|
49
|
+
if (matcher(args, acc.length))
|
|
47
50
|
acc.push(replacer);
|
|
48
51
|
return acc;
|
|
49
52
|
}, []);
|
|
@@ -62,6 +65,7 @@ function muteDevLogs({ workerReload } = {}) {
|
|
|
62
65
|
injectLogReplacer("log");
|
|
63
66
|
injectLogReplacer("error");
|
|
64
67
|
injectLogReplacer("warn", warningDebouncer);
|
|
68
|
+
injectLogReplacer("debug", false);
|
|
65
69
|
let isFirstWorkerReload = true;
|
|
66
70
|
addMessageReplacers("dev-node", [
|
|
67
71
|
([first]) => typeof first === "string" && first.includes("[mf:"),
|
|
@@ -114,6 +118,60 @@ function muteDevLogs({ workerReload } = {}) {
|
|
|
114
118
|
}
|
|
115
119
|
]
|
|
116
120
|
);
|
|
121
|
+
let isLastLineBlank = false;
|
|
122
|
+
let isLastLineRequestLog = false;
|
|
123
|
+
addMessageReplacers(
|
|
124
|
+
"dev-vite",
|
|
125
|
+
// Vite logs
|
|
126
|
+
[
|
|
127
|
+
// This log must come from Rollup and does not go through Vite's customLogger
|
|
128
|
+
([first]) => typeof first === "string" && /^Sourcemap for .*@remix-run/i.test(first),
|
|
129
|
+
() => {
|
|
130
|
+
}
|
|
131
|
+
],
|
|
132
|
+
[
|
|
133
|
+
// Log generated from Workerd HMR connection to Vite
|
|
134
|
+
([first]) => typeof first === "string" && /^\[vite\] (connected|program reload)/i.test(first),
|
|
135
|
+
() => {
|
|
136
|
+
}
|
|
137
|
+
],
|
|
138
|
+
[
|
|
139
|
+
// Log that gets entangled with our initial dev logs
|
|
140
|
+
([first]) => typeof first === "string" && /^Re-optimizing dependencies because/i.test(first),
|
|
141
|
+
() => {
|
|
142
|
+
}
|
|
143
|
+
],
|
|
144
|
+
[
|
|
145
|
+
// This error is fixed in new Remix versions:
|
|
146
|
+
// https://github.com/remix-run/remix/pull/9194
|
|
147
|
+
([first]) => {
|
|
148
|
+
const message = first?.message ?? first;
|
|
149
|
+
return /virtual-routes/.test(message) && /(Failed to load url|Could not resolve module for file)/i.test(
|
|
150
|
+
message
|
|
151
|
+
);
|
|
152
|
+
},
|
|
153
|
+
() => {
|
|
154
|
+
}
|
|
155
|
+
],
|
|
156
|
+
[
|
|
157
|
+
// Log new lines between Request logs and other logs
|
|
158
|
+
([first], existingMatches) => {
|
|
159
|
+
if (existingMatches === 0 && typeof first === "string") {
|
|
160
|
+
const isRequestLog = /^\s+[A-Z]+\s+\d{3}\s+[a-z]+\s+\//.test(
|
|
161
|
+
// Clear ANSI colors before matching
|
|
162
|
+
first.replace(/\u001b\[.*?m/g, "")
|
|
163
|
+
);
|
|
164
|
+
if (!isLastLineBlank && (isRequestLog && !isLastLineRequestLog || !isRequestLog && isLastLineRequestLog)) {
|
|
165
|
+
process.stdout.write("\n");
|
|
166
|
+
}
|
|
167
|
+
isLastLineRequestLog = isRequestLog;
|
|
168
|
+
isLastLineBlank = /\n$/.test(first);
|
|
169
|
+
}
|
|
170
|
+
return false;
|
|
171
|
+
},
|
|
172
|
+
(params) => params
|
|
173
|
+
]
|
|
174
|
+
);
|
|
117
175
|
}
|
|
118
176
|
const originalWrite = process.stdout.write;
|
|
119
177
|
function muteAuthLogs({
|
|
@@ -126,7 +184,7 @@ function muteAuthLogs({
|
|
|
126
184
|
if (typeof item !== "string")
|
|
127
185
|
return write(item, cb);
|
|
128
186
|
const replacers = messageReplacers.reduce((acc, [matcher, replacer]) => {
|
|
129
|
-
if (matcher([item]))
|
|
187
|
+
if (matcher([item], acc.length))
|
|
130
188
|
acc.push(replacer);
|
|
131
189
|
return acc;
|
|
132
190
|
}, []);
|
|
@@ -175,6 +233,7 @@ function enhanceH2Logs(options) {
|
|
|
175
233
|
injectLogReplacer("error");
|
|
176
234
|
injectLogReplacer("warn", warningDebouncer);
|
|
177
235
|
injectLogReplacer("log", warningDebouncer);
|
|
236
|
+
injectLogReplacer("info", warningDebouncer);
|
|
178
237
|
addMessageReplacers("h2-warn", [
|
|
179
238
|
([first]) => {
|
|
180
239
|
const message = first?.message ?? first;
|
|
@@ -183,7 +242,10 @@ function enhanceH2Logs(options) {
|
|
|
183
242
|
(args) => {
|
|
184
243
|
const firstArg = args[0];
|
|
185
244
|
const errorObject = typeof firstArg === "object" && !!firstArg.stack ? firstArg : void 0;
|
|
186
|
-
|
|
245
|
+
let stringArg = errorObject?.message ?? firstArg;
|
|
246
|
+
if (stringArg.startsWith("[h2:info:createStorefrontClient]") && stringArg.includes("defaulting to mock.shop")) {
|
|
247
|
+
stringArg += "\nRun `h2 link` to link your store.";
|
|
248
|
+
}
|
|
187
249
|
const [, type, scope, message] = stringArg.match(/\[h2:([^:]+):([^\]]+)\]\s+(.*)$/ims) || [];
|
|
188
250
|
if (!type || !scope || !message)
|
|
189
251
|
return args;
|
|
@@ -191,9 +253,15 @@ function enhanceH2Logs(options) {
|
|
|
191
253
|
|
|
192
254
|
`;
|
|
193
255
|
const lines = message.split("\n");
|
|
194
|
-
|
|
256
|
+
let lastLine = lines.at(-1) ?? "";
|
|
195
257
|
const hasLinks = /https?:\/\//.test(lastLine);
|
|
196
258
|
const hasCommands = /`h2 [^`]+`/.test(lastLine);
|
|
259
|
+
if (hasCommands && lastLine) {
|
|
260
|
+
lastLine = lastLine.replace(
|
|
261
|
+
/`(h2) ([^`]+)`/g,
|
|
262
|
+
colors.magentaBright(`\`${options.cliCommand ?? "$1"} $2\``)
|
|
263
|
+
);
|
|
264
|
+
}
|
|
197
265
|
if (hasLinks || hasCommands)
|
|
198
266
|
lines.pop();
|
|
199
267
|
if (type === "error" || errorObject) {
|
|
@@ -248,12 +316,7 @@ function enhanceH2Logs(options) {
|
|
|
248
316
|
render({
|
|
249
317
|
body: headline + colors.bold(lines.join("\n")),
|
|
250
318
|
reference,
|
|
251
|
-
nextSteps: hasCommands ? [
|
|
252
|
-
lastLine.replace(
|
|
253
|
-
/`h2 [^`]+`/g,
|
|
254
|
-
(cmd) => colors.bold(colors.yellow(cmd))
|
|
255
|
-
)
|
|
256
|
-
] : void 0
|
|
319
|
+
nextSteps: hasCommands ? [lastLine] : void 0
|
|
257
320
|
});
|
|
258
321
|
return;
|
|
259
322
|
}
|
|
@@ -298,5 +361,15 @@ async function muteRemixLogs() {
|
|
|
298
361
|
} catch {
|
|
299
362
|
}
|
|
300
363
|
}
|
|
364
|
+
function setH2OVerbose() {
|
|
365
|
+
if (!process.env.DEBUG || process.env.DEBUG === "*") {
|
|
366
|
+
process.env.DEBUG = "h2:*,o2:*";
|
|
367
|
+
} else {
|
|
368
|
+
process.env.DEBUG += ",h2:*,o2:*";
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
function isH2Verbose() {
|
|
372
|
+
return !!(process.env.DEBUG === "*" || process.env.DEBUG?.includes("h2:*"));
|
|
373
|
+
}
|
|
301
374
|
|
|
302
|
-
export { addMessageReplacers, createRemixLogger, enhanceH2Logs, muteAuthLogs, muteDevLogs, muteRemixLogs, resetAllLogs, warnOnce };
|
|
375
|
+
export { addMessageReplacers, createRemixLogger, enhanceH2Logs, isH2Verbose, muteAuthLogs, muteDevLogs, muteRemixLogs, resetAllLogs, setH2OVerbose, warnOnce };
|
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
import { outputToken, outputInfo, outputContent } from '@shopify/cli-kit/node/output';
|
|
2
2
|
import colors from '@shopify/cli-kit/node/colors';
|
|
3
3
|
import { DEV_ROUTES } from '../request-events.js';
|
|
4
|
+
import { AbortError } from '@shopify/cli-kit/node/error';
|
|
4
5
|
|
|
5
6
|
const DEFAULT_INSPECTOR_PORT = 9229;
|
|
6
7
|
const SUBREQUEST_PROFILER_ENDPOINT = "/debug-network-server";
|
|
7
|
-
function
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
function handleMiniOxygenImportFail() {
|
|
9
|
+
throw new AbortError(
|
|
10
|
+
"Could not load MiniOxygen.",
|
|
11
|
+
"Please make sure you have `@shopify/mini-oxygen` installed."
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
function logRequestLine({
|
|
15
|
+
request,
|
|
16
|
+
response,
|
|
17
|
+
meta
|
|
18
|
+
}) {
|
|
11
19
|
try {
|
|
12
20
|
const url = new URL(request.url);
|
|
13
|
-
if (DEV_ROUTES.has(url.pathname))
|
|
21
|
+
if (DEV_ROUTES.has(url.pathname) || url.pathname === "/favicon.ico")
|
|
14
22
|
return;
|
|
15
23
|
const isDataRequest = url.searchParams.has("_data");
|
|
16
24
|
let route = request.url.replace(url.origin, "");
|
|
@@ -22,39 +30,17 @@ function logRequestLine(request, {
|
|
|
22
30
|
route = url.pathname;
|
|
23
31
|
info = `[${dataParam}]`;
|
|
24
32
|
}
|
|
25
|
-
const colorizeStatus =
|
|
33
|
+
const colorizeStatus = response.status < 300 ? outputToken.green : response.status < 400 ? outputToken.cyan : outputToken.errorText;
|
|
26
34
|
outputInfo(
|
|
27
35
|
outputContent`${request.method.padStart(6)} ${colorizeStatus(
|
|
28
|
-
String(
|
|
29
|
-
)} ${outputToken.italic(type.padEnd(7, " "))} ${route} ${durationMs > 0 ? colors.dim(` ${durationMs}ms`) : ""}${info ? " " + colors.dim(info) : ""}${request.headers
|
|
36
|
+
String(response.status)
|
|
37
|
+
)} ${outputToken.italic(type.padEnd(7, " "))} ${route} ${meta.durationMs > 0 ? colors.dim(` ${meta.durationMs}ms`) : ""}${info ? " " + colors.dim(info) : ""}${request.headers["purpose"] === "prefetch" ? outputToken.italic(colors.dim(" prefetch")) : ""}`
|
|
30
38
|
);
|
|
31
39
|
} catch {
|
|
32
|
-
if (request &&
|
|
33
|
-
outputInfo(`${request.method} ${
|
|
40
|
+
if (request && response?.status) {
|
|
41
|
+
outputInfo(`${request.method} ${response.status} ${request.url}`);
|
|
34
42
|
}
|
|
35
43
|
}
|
|
36
44
|
}
|
|
37
|
-
const OXYGEN_HEADERS_MAP = {
|
|
38
|
-
ip: { name: "oxygen-buyer-ip", defaultValue: "127.0.0.1" },
|
|
39
|
-
longitude: { name: "oxygen-buyer-longitude", defaultValue: "-122.40140" },
|
|
40
|
-
latitude: { name: "oxygen-buyer-latitude", defaultValue: "37.78855" },
|
|
41
|
-
continent: { name: "oxygen-buyer-continent", defaultValue: "NA" },
|
|
42
|
-
country: { name: "oxygen-buyer-country", defaultValue: "US" },
|
|
43
|
-
region: { name: "oxygen-buyer-region", defaultValue: "California" },
|
|
44
|
-
regionCode: { name: "oxygen-buyer-region-code", defaultValue: "CA" },
|
|
45
|
-
city: { name: "oxygen-buyer-city", defaultValue: "San Francisco" },
|
|
46
|
-
isEuCountry: { name: "oxygen-buyer-is-eu-country", defaultValue: "" },
|
|
47
|
-
timezone: {
|
|
48
|
-
name: "oxygen-buyer-timezone",
|
|
49
|
-
defaultValue: "America/Los_Angeles"
|
|
50
|
-
},
|
|
51
|
-
// Not documented but available in Oxygen:
|
|
52
|
-
deploymentId: { name: "oxygen-buyer-deployment-id", defaultValue: "local" },
|
|
53
|
-
shopId: { name: "oxygen-buyer-shop-id", defaultValue: "development" },
|
|
54
|
-
storefrontId: {
|
|
55
|
-
name: "oxygen-buyer-storefront-id",
|
|
56
|
-
defaultValue: "development"
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
45
|
|
|
60
|
-
export { DEFAULT_INSPECTOR_PORT,
|
|
46
|
+
export { DEFAULT_INSPECTOR_PORT, SUBREQUEST_PROFILER_ENDPOINT, handleMiniOxygenImportFail, logRequestLine };
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import { handleMiniOxygenImportFail } from './common.js';
|
|
1
2
|
export { DEFAULT_INSPECTOR_PORT } from './common.js';
|
|
2
|
-
export { buildAssetsUrl } from './assets.js';
|
|
3
3
|
|
|
4
|
+
async function buildAssetsUrl(port) {
|
|
5
|
+
const { buildAssetsUrl: _buildAssetsUrl } = await import('@shopify/mini-oxygen').catch(handleMiniOxygenImportFail);
|
|
6
|
+
return _buildAssetsUrl(port);
|
|
7
|
+
}
|
|
4
8
|
async function startMiniOxygen(options, useNodeRuntime = false) {
|
|
5
9
|
if (useNodeRuntime) {
|
|
6
10
|
process.env.MINIFLARE_SUBREQUEST_LIMIT = 100;
|
|
@@ -11,4 +15,4 @@ async function startMiniOxygen(options, useNodeRuntime = false) {
|
|
|
11
15
|
return startWorkerdServer(options);
|
|
12
16
|
}
|
|
13
17
|
|
|
14
|
-
export { startMiniOxygen };
|
|
18
|
+
export { buildAssetsUrl, startMiniOxygen };
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto';
|
|
2
1
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
3
2
|
import { readFile } from '@shopify/cli-kit/node/fs';
|
|
4
3
|
import { renderSuccess } from '@shopify/cli-kit/node/ui';
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
4
|
+
import colors from '@shopify/cli-kit/node/colors';
|
|
5
|
+
import { DEFAULT_INSPECTOR_PORT } from '../flags.js';
|
|
6
|
+
import { handleMiniOxygenImportFail, SUBREQUEST_PROFILER_ENDPOINT, logRequestLine } from './common.js';
|
|
8
7
|
import { setConstructors, createLogRequestEvent, handleDebugNetworkRequest, H2O_BINDING_NAME } from '../request-events.js';
|
|
8
|
+
import { findPort } from '../find-port.js';
|
|
9
|
+
import { getUtilityBannerlines } from '../dev-shared.js';
|
|
10
|
+
import { outputNewline } from '@shopify/cli-kit/node/output';
|
|
9
11
|
|
|
10
12
|
async function startNodeServer({
|
|
11
|
-
|
|
13
|
+
appPort,
|
|
12
14
|
watch = false,
|
|
13
15
|
buildPathWorkerFile,
|
|
14
16
|
buildPathClient,
|
|
@@ -16,11 +18,7 @@ async function startNodeServer({
|
|
|
16
18
|
debug = false,
|
|
17
19
|
inspectorPort
|
|
18
20
|
}) {
|
|
19
|
-
const
|
|
20
|
-
Object.entries(OXYGEN_HEADERS_MAP).map(([key, value]) => {
|
|
21
|
-
return [key, value.defaultValue];
|
|
22
|
-
})
|
|
23
|
-
);
|
|
21
|
+
const { startServer, Request, Response } = await import('@shopify/mini-oxygen/node').catch(handleMiniOxygenImportFail);
|
|
24
22
|
setConstructors({ Response });
|
|
25
23
|
const logRequestEvent = createLogRequestEvent();
|
|
26
24
|
const asyncLocalStorage = new AsyncLocalStorage();
|
|
@@ -38,6 +36,8 @@ async function startNodeServer({
|
|
|
38
36
|
}
|
|
39
37
|
};
|
|
40
38
|
if (debug) {
|
|
39
|
+
if (!inspectorPort)
|
|
40
|
+
inspectorPort = await findPort(DEFAULT_INSPECTOR_PORT);
|
|
41
41
|
(await import('node:inspector')).open(inspectorPort);
|
|
42
42
|
}
|
|
43
43
|
const miniOxygen = await startServer({
|
|
@@ -45,7 +45,7 @@ async function startNodeServer({
|
|
|
45
45
|
workerFile: buildPathWorkerFile,
|
|
46
46
|
assetsDir: buildPathClient,
|
|
47
47
|
publicPath: "",
|
|
48
|
-
port,
|
|
48
|
+
port: appPort,
|
|
49
49
|
watch,
|
|
50
50
|
autoReload: watch,
|
|
51
51
|
modules: true,
|
|
@@ -56,25 +56,34 @@ async function startNodeServer({
|
|
|
56
56
|
},
|
|
57
57
|
log: () => {
|
|
58
58
|
},
|
|
59
|
-
oxygenHeaders,
|
|
60
59
|
async onRequest(request, defaultDispatcher) {
|
|
61
60
|
const url = new URL(request.url);
|
|
62
61
|
if (url.pathname === SUBREQUEST_PROFILER_ENDPOINT) {
|
|
63
62
|
return handleDebugNetworkRequest(request);
|
|
64
63
|
}
|
|
65
|
-
|
|
66
|
-
if (!requestId) {
|
|
67
|
-
requestId = randomUUID();
|
|
68
|
-
request.headers.set("request-id", requestId);
|
|
69
|
-
}
|
|
64
|
+
const requestId = request.headers.get("request-id");
|
|
70
65
|
const startTimeMs = Date.now();
|
|
71
66
|
const response = await asyncLocalStorage.run(
|
|
72
67
|
{ requestId, purpose: request.headers.get("purpose") },
|
|
73
68
|
() => defaultDispatcher(request)
|
|
74
69
|
);
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
70
|
+
const endTimeMs = Date.now();
|
|
71
|
+
logRequestLine({
|
|
72
|
+
request: {
|
|
73
|
+
url: request.url,
|
|
74
|
+
method: request.method,
|
|
75
|
+
headers: Object.fromEntries(request.headers.entries())
|
|
76
|
+
},
|
|
77
|
+
response: {
|
|
78
|
+
status: response.status,
|
|
79
|
+
statusText: response.statusText,
|
|
80
|
+
headers: Object.fromEntries(response.headers.entries())
|
|
81
|
+
},
|
|
82
|
+
meta: {
|
|
83
|
+
startTimeMs,
|
|
84
|
+
endTimeMs,
|
|
85
|
+
durationMs: startTimeMs > 0 ? endTimeMs - startTimeMs : 0
|
|
86
|
+
}
|
|
78
87
|
});
|
|
79
88
|
return response;
|
|
80
89
|
}
|
|
@@ -95,20 +104,23 @@ async function startNodeServer({
|
|
|
95
104
|
await miniOxygen.reload(nextOptions);
|
|
96
105
|
},
|
|
97
106
|
showBanner(options) {
|
|
98
|
-
|
|
107
|
+
outputNewline();
|
|
108
|
+
const customSections = [];
|
|
109
|
+
if (options?.host) {
|
|
110
|
+
customSections.push({ body: getUtilityBannerlines(options.host) });
|
|
111
|
+
}
|
|
112
|
+
if (debug && inspectorPort) {
|
|
113
|
+
customSections.push({
|
|
114
|
+
body: { warn: `Debugger listening on ws://localhost:${inspectorPort}` }
|
|
115
|
+
});
|
|
116
|
+
}
|
|
99
117
|
renderSuccess({
|
|
100
118
|
headline: `${options?.headlinePrefix ?? ""}MiniOxygen (Node Sandbox) ${options?.mode ?? "development"} server running.`,
|
|
101
119
|
body: [
|
|
102
|
-
`View ${options?.appName
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
warn: `
|
|
107
|
-
|
|
108
|
-
Debugger listening on ws://localhost:${inspectorPort}`
|
|
109
|
-
}
|
|
110
|
-
] : []
|
|
111
|
-
]
|
|
120
|
+
`View ${options?.appName ? colors.cyan(options?.appName) : "Hydrogen"} app:`,
|
|
121
|
+
{ link: { url: options?.host || listeningAt } }
|
|
122
|
+
],
|
|
123
|
+
customSections
|
|
112
124
|
});
|
|
113
125
|
console.log("");
|
|
114
126
|
},
|