@shopify/cli-hydrogen 5.0.2 → 5.1.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.js +16 -2
- package/dist/commands/hydrogen/codegen-unstable.js +13 -24
- package/dist/commands/hydrogen/dev.js +45 -39
- package/dist/commands/hydrogen/env/list.js +25 -24
- package/dist/commands/hydrogen/env/list.test.js +46 -43
- package/dist/commands/hydrogen/env/pull.js +53 -25
- package/dist/commands/hydrogen/env/pull.test.js +123 -42
- package/dist/commands/hydrogen/generate/route.js +31 -132
- package/dist/commands/hydrogen/generate/route.test.js +34 -126
- package/dist/commands/hydrogen/init.js +46 -127
- package/dist/commands/hydrogen/init.test.js +352 -100
- package/dist/commands/hydrogen/link.js +70 -69
- package/dist/commands/hydrogen/link.test.js +72 -107
- package/dist/commands/hydrogen/list.js +22 -12
- package/dist/commands/hydrogen/list.test.js +51 -48
- package/dist/commands/hydrogen/login.js +31 -0
- package/dist/commands/hydrogen/logout.js +21 -0
- package/dist/commands/hydrogen/setup/css.js +79 -0
- package/dist/commands/hydrogen/setup/markets.js +53 -0
- package/dist/commands/hydrogen/setup.js +133 -0
- package/dist/commands/hydrogen/shortcut.js +2 -45
- package/dist/commands/hydrogen/shortcut.test.js +10 -37
- package/dist/generator-templates/assets/css-modules/package.json +6 -0
- package/dist/generator-templates/assets/postcss/package.json +10 -0
- package/dist/generator-templates/assets/postcss/postcss.config.js +8 -0
- package/dist/generator-templates/assets/tailwind/package.json +13 -0
- package/dist/generator-templates/assets/tailwind/postcss.config.js +10 -0
- package/dist/generator-templates/assets/tailwind/tailwind.config.js +8 -0
- package/dist/generator-templates/assets/tailwind/tailwind.css +3 -0
- package/dist/generator-templates/assets/vanilla-extract/package.json +9 -0
- package/dist/generator-templates/starter/.eslintignore +5 -0
- package/dist/generator-templates/starter/.eslintrc.js +18 -0
- package/dist/generator-templates/starter/.graphqlrc.yml +1 -0
- package/dist/generator-templates/starter/README.md +40 -0
- package/dist/generator-templates/starter/app/components/Aside.tsx +47 -0
- package/dist/generator-templates/starter/app/components/Cart.tsx +340 -0
- package/dist/generator-templates/starter/app/components/Footer.tsx +99 -0
- package/dist/generator-templates/starter/app/components/Header.tsx +178 -0
- package/dist/generator-templates/starter/app/components/Layout.tsx +95 -0
- package/dist/generator-templates/starter/app/components/Search.tsx +480 -0
- package/dist/generator-templates/starter/app/entry.client.tsx +12 -0
- package/dist/generator-templates/starter/app/entry.server.tsx +33 -0
- package/dist/generator-templates/starter/app/root.tsx +270 -0
- package/dist/generator-templates/starter/app/routes/$.tsx +7 -0
- package/dist/generator-templates/{routes → starter/app/routes}/[robots.txt].tsx +47 -69
- package/dist/generator-templates/starter/app/routes/[sitemap.xml].tsx +174 -0
- package/dist/generator-templates/starter/app/routes/_index.tsx +145 -0
- package/dist/generator-templates/starter/app/routes/account.$.tsx +9 -0
- package/dist/generator-templates/starter/app/routes/account.addresses.tsx +563 -0
- package/dist/generator-templates/starter/app/routes/account.orders.$id.tsx +309 -0
- package/dist/generator-templates/starter/app/routes/account.orders._index.tsx +196 -0
- package/dist/generator-templates/starter/app/routes/account.profile.tsx +289 -0
- package/dist/generator-templates/starter/app/routes/account.tsx +203 -0
- package/dist/generator-templates/starter/app/routes/account_.activate.$id.$activationToken.tsx +157 -0
- package/dist/generator-templates/starter/app/routes/account_.login.tsx +143 -0
- package/dist/generator-templates/starter/app/routes/account_.logout.tsx +33 -0
- package/dist/generator-templates/starter/app/routes/account_.recover.tsx +124 -0
- package/dist/generator-templates/starter/app/routes/account_.register.tsx +207 -0
- package/dist/generator-templates/starter/app/routes/account_.reset.$id.$resetToken.tsx +136 -0
- package/dist/generator-templates/starter/app/routes/api.predictive-search.tsx +342 -0
- package/dist/generator-templates/starter/app/routes/blogs.$blogHandle.$articleHandle.tsx +88 -0
- package/dist/generator-templates/starter/app/routes/blogs.$blogHandle._index.tsx +162 -0
- package/dist/generator-templates/starter/app/routes/blogs._index.tsx +94 -0
- package/dist/generator-templates/starter/app/routes/cart.tsx +104 -0
- package/dist/generator-templates/starter/app/routes/collections.$handle.tsx +184 -0
- package/dist/generator-templates/starter/app/routes/collections._index.tsx +120 -0
- package/dist/generator-templates/starter/app/routes/pages.$handle.tsx +57 -0
- package/dist/generator-templates/starter/app/routes/policies.$handle.tsx +94 -0
- package/dist/generator-templates/starter/app/routes/policies._index.tsx +63 -0
- package/dist/generator-templates/starter/app/routes/products.$handle.tsx +418 -0
- package/dist/generator-templates/starter/app/routes/search.tsx +168 -0
- package/dist/generator-templates/starter/app/styles/app.css +473 -0
- package/dist/generator-templates/starter/app/styles/reset.css +129 -0
- package/dist/generator-templates/starter/app/utils.ts +46 -0
- package/dist/generator-templates/starter/package.json +43 -0
- package/dist/generator-templates/starter/public/favicon.svg +28 -0
- package/dist/generator-templates/starter/remix.config.js +26 -0
- package/dist/generator-templates/starter/remix.env.d.ts +39 -0
- package/dist/generator-templates/starter/server.ts +253 -0
- package/dist/generator-templates/starter/storefrontapi.generated.d.ts +1906 -0
- package/dist/generator-templates/starter/tsconfig.json +22 -0
- package/dist/lib/auth.js +123 -0
- package/dist/lib/auth.test.js +157 -0
- package/dist/lib/build.js +51 -0
- package/dist/lib/check-version.js +3 -3
- package/dist/lib/check-version.test.js +24 -0
- package/dist/lib/codegen.js +26 -17
- package/dist/lib/environment-variables.js +68 -0
- package/dist/lib/environment-variables.test.js +147 -0
- package/dist/lib/file.js +41 -0
- package/dist/lib/file.test.js +69 -0
- package/dist/lib/flags.js +39 -2
- package/dist/lib/format-code.js +26 -0
- package/dist/lib/gid.js +12 -0
- package/dist/lib/{graphql.test.js → gid.test.js} +1 -1
- package/dist/lib/graphql/admin/client.js +27 -0
- package/dist/lib/graphql/admin/client.test.js +51 -0
- package/dist/lib/graphql/admin/create-storefront.js +13 -15
- package/dist/lib/graphql/admin/create-storefront.test.js +64 -0
- package/dist/lib/graphql/admin/fetch-job.js +6 -15
- package/dist/lib/graphql/admin/link-storefront.js +7 -11
- package/dist/lib/graphql/admin/link-storefront.test.js +38 -0
- package/dist/lib/graphql/admin/list-environments.js +2 -2
- package/dist/lib/graphql/admin/list-environments.test.js +44 -0
- package/dist/lib/graphql/admin/list-storefronts.js +7 -11
- package/dist/lib/graphql/admin/list-storefronts.test.js +44 -0
- package/dist/lib/graphql/admin/pull-variables.js +3 -3
- package/dist/lib/graphql/admin/pull-variables.test.js +37 -0
- package/dist/lib/graphql/business-platform/user-account.js +83 -0
- package/dist/lib/graphql/business-platform/user-account.test.js +80 -0
- package/dist/lib/log.js +185 -9
- package/dist/lib/log.test.js +92 -0
- package/dist/lib/mini-oxygen.js +19 -9
- package/dist/lib/missing-routes.js +0 -2
- package/dist/lib/onboarding/common.js +456 -0
- package/dist/lib/onboarding/index.js +2 -0
- package/dist/lib/onboarding/local.js +229 -0
- package/dist/lib/onboarding/remote.js +89 -0
- package/dist/lib/remix-version-interop.js +5 -5
- package/dist/lib/remix-version-interop.test.js +11 -1
- package/dist/lib/render-errors.js +13 -11
- package/dist/lib/setups/css/assets.js +89 -0
- package/dist/lib/setups/css/css-modules.js +22 -0
- package/dist/lib/setups/css/index.js +44 -0
- package/dist/lib/setups/css/postcss.js +34 -0
- package/dist/lib/setups/css/replacers.js +137 -0
- package/dist/lib/setups/css/tailwind.js +54 -0
- package/dist/lib/setups/css/vanilla-extract.js +22 -0
- package/dist/lib/setups/i18n/domains.test.js +25 -0
- package/dist/lib/setups/i18n/index.js +46 -0
- package/dist/lib/setups/i18n/replacers.js +227 -0
- package/dist/lib/setups/i18n/subdomains.test.js +25 -0
- package/dist/lib/setups/i18n/subfolders.test.js +25 -0
- package/dist/lib/setups/i18n/templates/domains.js +14 -0
- package/dist/lib/setups/i18n/templates/domains.ts +25 -0
- package/dist/lib/setups/i18n/templates/subdomains.js +14 -0
- package/dist/lib/setups/i18n/templates/subdomains.ts +24 -0
- package/dist/lib/setups/i18n/templates/subfolders.js +14 -0
- package/dist/lib/setups/i18n/templates/subfolders.ts +28 -0
- package/dist/lib/setups/routes/generate.js +244 -0
- package/dist/lib/setups/routes/generate.test.js +313 -0
- package/dist/lib/shell.js +52 -5
- package/dist/lib/shell.test.js +42 -16
- package/dist/lib/shopify-config.js +23 -18
- package/dist/lib/shopify-config.test.js +63 -73
- package/dist/lib/template-downloader.js +9 -7
- package/dist/lib/transpile-ts.js +9 -29
- package/dist/virtual-routes/routes/index.jsx +40 -19
- package/oclif.manifest.json +710 -1
- package/package.json +16 -16
- package/dist/commands/hydrogen/build.d.ts +0 -23
- package/dist/commands/hydrogen/check.d.ts +0 -15
- package/dist/commands/hydrogen/codegen-unstable.d.ts +0 -15
- package/dist/commands/hydrogen/dev.d.ts +0 -21
- package/dist/commands/hydrogen/env/list.d.ts +0 -18
- package/dist/commands/hydrogen/env/pull.d.ts +0 -22
- package/dist/commands/hydrogen/g.d.ts +0 -10
- package/dist/commands/hydrogen/generate/route.d.ts +0 -32
- package/dist/commands/hydrogen/generate/route.test.d.ts +0 -1
- package/dist/commands/hydrogen/generate/routes.d.ts +0 -16
- package/dist/commands/hydrogen/init.d.ts +0 -24
- package/dist/commands/hydrogen/init.test.d.ts +0 -1
- package/dist/commands/hydrogen/link.d.ts +0 -23
- package/dist/commands/hydrogen/link.test.d.ts +0 -1
- package/dist/commands/hydrogen/list.d.ts +0 -21
- package/dist/commands/hydrogen/list.test.d.ts +0 -1
- package/dist/commands/hydrogen/preview.d.ts +0 -17
- package/dist/commands/hydrogen/shortcut.d.ts +0 -9
- package/dist/commands/hydrogen/shortcut.test.d.ts +0 -1
- package/dist/commands/hydrogen/unlink.d.ts +0 -16
- package/dist/commands/hydrogen/unlink.test.d.ts +0 -1
- package/dist/create-app.d.ts +0 -1
- package/dist/generator-templates/routes/[sitemap.xml].tsx +0 -235
- package/dist/generator-templates/routes/account/login.tsx +0 -103
- package/dist/generator-templates/routes/account/register.tsx +0 -103
- package/dist/generator-templates/routes/cart.tsx +0 -81
- package/dist/generator-templates/routes/collections/$collectionHandle.tsx +0 -104
- package/dist/generator-templates/routes/collections/index.tsx +0 -102
- package/dist/generator-templates/routes/graphiql.tsx +0 -10
- package/dist/generator-templates/routes/index.tsx +0 -40
- package/dist/generator-templates/routes/pages/$pageHandle.tsx +0 -112
- package/dist/generator-templates/routes/policies/$policyHandle.tsx +0 -140
- package/dist/generator-templates/routes/policies/index.tsx +0 -117
- package/dist/generator-templates/routes/products/$productHandle.tsx +0 -92
- package/dist/hooks/init.d.ts +0 -5
- package/dist/lib/admin-session.d.ts +0 -6
- package/dist/lib/admin-session.js +0 -16
- package/dist/lib/admin-session.test.d.ts +0 -1
- package/dist/lib/admin-session.test.js +0 -27
- package/dist/lib/admin-urls.d.ts +0 -8
- package/dist/lib/check-lockfile.d.ts +0 -3
- package/dist/lib/check-lockfile.test.d.ts +0 -1
- package/dist/lib/check-version.d.ts +0 -16
- package/dist/lib/check-version.test.d.ts +0 -1
- package/dist/lib/codegen.d.ts +0 -26
- package/dist/lib/combined-environment-variables.d.ts +0 -8
- package/dist/lib/combined-environment-variables.js +0 -57
- package/dist/lib/combined-environment-variables.test.d.ts +0 -1
- package/dist/lib/combined-environment-variables.test.js +0 -111
- package/dist/lib/config.d.ts +0 -20
- package/dist/lib/flags.d.ts +0 -27
- package/dist/lib/flags.test.d.ts +0 -1
- package/dist/lib/graphql/admin/create-storefront.d.ts +0 -17
- package/dist/lib/graphql/admin/fetch-job.d.ts +0 -23
- package/dist/lib/graphql/admin/link-storefront.d.ts +0 -14
- package/dist/lib/graphql/admin/list-environments.d.ts +0 -21
- package/dist/lib/graphql/admin/list-storefronts.d.ts +0 -25
- package/dist/lib/graphql/admin/pull-variables.d.ts +0 -21
- package/dist/lib/graphql.d.ts +0 -21
- package/dist/lib/graphql.js +0 -18
- package/dist/lib/graphql.test.d.ts +0 -1
- package/dist/lib/log.d.ts +0 -6
- package/dist/lib/mini-oxygen.d.ts +0 -22
- package/dist/lib/missing-routes.d.ts +0 -8
- package/dist/lib/missing-routes.test.d.ts +0 -1
- package/dist/lib/missing-storefronts.d.ts +0 -5
- package/dist/lib/missing-storefronts.js +0 -18
- package/dist/lib/process.d.ts +0 -6
- package/dist/lib/pull-environment-variables.d.ts +0 -20
- package/dist/lib/pull-environment-variables.js +0 -57
- package/dist/lib/pull-environment-variables.test.d.ts +0 -1
- package/dist/lib/pull-environment-variables.test.js +0 -174
- package/dist/lib/remix-version-interop.d.ts +0 -11
- package/dist/lib/remix-version-interop.test.d.ts +0 -1
- package/dist/lib/render-errors.d.ts +0 -16
- package/dist/lib/shell.d.ts +0 -11
- package/dist/lib/shell.test.d.ts +0 -1
- package/dist/lib/shop.d.ts +0 -7
- package/dist/lib/shop.js +0 -32
- package/dist/lib/shop.test.d.ts +0 -1
- package/dist/lib/shop.test.js +0 -78
- package/dist/lib/shopify-config.d.ts +0 -35
- package/dist/lib/shopify-config.test.d.ts +0 -1
- package/dist/lib/string.d.ts +0 -3
- package/dist/lib/string.test.d.ts +0 -1
- package/dist/lib/template-downloader.d.ts +0 -6
- package/dist/lib/transpile-ts.d.ts +0 -16
- package/dist/lib/user-errors.d.ts +0 -9
- package/dist/lib/user-errors.js +0 -11
- package/dist/lib/virtual-routes.d.ts +0 -7
- package/dist/lib/virtual-routes.test.d.ts +0 -1
- /package/dist/{commands/hydrogen/env/list.test.d.ts → lib/setups/css/common.js} +0 -0
- /package/dist/{commands/hydrogen/env/pull.test.d.ts → lib/setups/i18n/mock-i18n-types.js} +0 -0
package/dist/lib/mini-oxygen.js
CHANGED
|
@@ -10,12 +10,12 @@ async function startMiniOxygen({
|
|
|
10
10
|
watch = false,
|
|
11
11
|
buildPathWorkerFile,
|
|
12
12
|
buildPathClient,
|
|
13
|
-
|
|
13
|
+
env
|
|
14
14
|
}) {
|
|
15
|
-
const { default:
|
|
16
|
-
const miniOxygenPreview =
|
|
15
|
+
const { default: miniOxygenImport } = await import('@shopify/mini-oxygen');
|
|
16
|
+
const miniOxygenPreview = miniOxygenImport.default ?? miniOxygenImport;
|
|
17
17
|
const dotenvPath = resolvePath(root, ".env");
|
|
18
|
-
const
|
|
18
|
+
const miniOxygen = await miniOxygenPreview({
|
|
19
19
|
workerFile: buildPathWorkerFile,
|
|
20
20
|
assetsDir: buildPathClient,
|
|
21
21
|
publicPath: "",
|
|
@@ -24,10 +24,10 @@ async function startMiniOxygen({
|
|
|
24
24
|
autoReload: watch,
|
|
25
25
|
modules: true,
|
|
26
26
|
env: {
|
|
27
|
-
...
|
|
27
|
+
...env,
|
|
28
28
|
...process.env
|
|
29
29
|
},
|
|
30
|
-
envPath: !
|
|
30
|
+
envPath: !env && await fileExists(dotenvPath) ? dotenvPath : void 0,
|
|
31
31
|
log: () => {
|
|
32
32
|
},
|
|
33
33
|
buildWatchPaths: watch ? [resolvePath(root, buildPathWorkerFile)] : void 0,
|
|
@@ -36,18 +36,28 @@ async function startMiniOxygen({
|
|
|
36
36
|
response
|
|
37
37
|
)
|
|
38
38
|
});
|
|
39
|
-
const listeningAt = `http://localhost:${
|
|
39
|
+
const listeningAt = `http://localhost:${miniOxygen.port}`;
|
|
40
40
|
return {
|
|
41
41
|
listeningAt,
|
|
42
|
-
port:
|
|
42
|
+
port: miniOxygen.port,
|
|
43
|
+
reload(nextOptions) {
|
|
44
|
+
return miniOxygen.reload({
|
|
45
|
+
env: {
|
|
46
|
+
...nextOptions?.env ?? env,
|
|
47
|
+
...process.env
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
},
|
|
43
51
|
showBanner(options) {
|
|
52
|
+
console.log("");
|
|
44
53
|
renderSuccess({
|
|
45
54
|
headline: `${options?.headlinePrefix ?? ""}MiniOxygen ${options?.mode ?? "development"} server running.`,
|
|
46
55
|
body: [
|
|
47
|
-
`View Hydrogen app: ${listeningAt}`,
|
|
56
|
+
`View ${options?.appName ?? "Hydrogen"} app: ${listeningAt}`,
|
|
48
57
|
...options?.extraLines ?? []
|
|
49
58
|
]
|
|
50
59
|
});
|
|
60
|
+
console.log("");
|
|
51
61
|
}
|
|
52
62
|
};
|
|
53
63
|
}
|
|
@@ -3,7 +3,6 @@ import { renderWarning, renderSuccess } from '@shopify/cli-kit/node/ui';
|
|
|
3
3
|
const REQUIRED_ROUTES = [
|
|
4
4
|
"",
|
|
5
5
|
"cart",
|
|
6
|
-
"products",
|
|
7
6
|
"products/:productHandle",
|
|
8
7
|
"collections",
|
|
9
8
|
"collections/:collectionHandle",
|
|
@@ -12,7 +11,6 @@ const REQUIRED_ROUTES = [
|
|
|
12
11
|
"pages/:pageHandle",
|
|
13
12
|
"policies/:policyHandle",
|
|
14
13
|
"search",
|
|
15
|
-
"discount/:discountCode",
|
|
16
14
|
"account",
|
|
17
15
|
"account/login",
|
|
18
16
|
"account/register",
|
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
import { readdir } from 'node:fs/promises';
|
|
2
|
+
import { packageManagerUsedForCreating, installNodeModules } from '@shopify/cli-kit/node/node-package-manager';
|
|
3
|
+
import { renderConfirmationPrompt, renderInfo, renderTextPrompt, renderSelectPrompt, renderFatalError, renderWarning, renderSuccess } from '@shopify/cli-kit/node/ui';
|
|
4
|
+
import { hyphenate, capitalize } from '@shopify/cli-kit/common/string';
|
|
5
|
+
import { resolvePath, basename, joinPath } from '@shopify/cli-kit/node/path';
|
|
6
|
+
import { initializeGitRepository, addAllToGitFromDirectory, createGitCommit } from '@shopify/cli-kit/node/git';
|
|
7
|
+
import { AbortError } from '@shopify/cli-kit/node/error';
|
|
8
|
+
import { rmdir, writeFile, fileExists, isDirectory } from '@shopify/cli-kit/node/fs';
|
|
9
|
+
import { outputDebug, outputContent, outputToken, formatPackageManagerCommand } from '@shopify/cli-kit/node/output';
|
|
10
|
+
import colors from '@shopify/cli-kit/node/colors';
|
|
11
|
+
import { login, renderLoginSuccess } from '../auth.js';
|
|
12
|
+
import { renderI18nPrompt, setupI18nStrategy, I18N_STRATEGY_NAME_MAP } from '../setups/i18n/index.js';
|
|
13
|
+
import { titleize } from '../string.js';
|
|
14
|
+
import { ALIAS_NAME, createPlatformShortcut, getCliCommand } from '../shell.js';
|
|
15
|
+
import { transpileProject } from '../transpile-ts.js';
|
|
16
|
+
import { renderCssPrompt, setupCssStrategy, CSS_STRATEGY_NAME_MAP } from '../setups/css/index.js';
|
|
17
|
+
import { renderRoutePrompt, generateRoutes, generateProjectFile } from '../setups/routes/generate.js';
|
|
18
|
+
import { execAsync } from '../process.js';
|
|
19
|
+
|
|
20
|
+
const LANGUAGES = {
|
|
21
|
+
js: "JavaScript",
|
|
22
|
+
ts: "TypeScript"
|
|
23
|
+
};
|
|
24
|
+
async function handleI18n(controller, cliCommand, flagI18n) {
|
|
25
|
+
let selection = flagI18n ?? await renderI18nPrompt({
|
|
26
|
+
abortSignal: controller.signal,
|
|
27
|
+
extraChoices: {
|
|
28
|
+
none: "Set up later " + colors.dim(`(run \`${cliCommand} setup markets\`)`)
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
const i18nStrategy = selection === "none" ? void 0 : selection;
|
|
32
|
+
return {
|
|
33
|
+
i18nStrategy,
|
|
34
|
+
setupI18n: async (options) => {
|
|
35
|
+
if (i18nStrategy) {
|
|
36
|
+
await setupI18nStrategy(i18nStrategy, options);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
async function handleRouteGeneration(controller, flagRoutes) {
|
|
42
|
+
const routesToScaffold = flagRoutes ? "all" : await renderRoutePrompt({
|
|
43
|
+
abortSignal: controller.signal
|
|
44
|
+
});
|
|
45
|
+
const needsRouteGeneration = routesToScaffold === "all" || routesToScaffold.length > 0;
|
|
46
|
+
return {
|
|
47
|
+
needsRouteGeneration,
|
|
48
|
+
setupRoutes: async (directory, language, i18nStrategy) => {
|
|
49
|
+
if (needsRouteGeneration) {
|
|
50
|
+
const result = await generateRoutes({
|
|
51
|
+
routeName: routesToScaffold,
|
|
52
|
+
directory,
|
|
53
|
+
force: true,
|
|
54
|
+
typescript: language === "ts",
|
|
55
|
+
localePrefix: i18nStrategy === "subfolders" ? "locale" : false,
|
|
56
|
+
signal: controller.signal
|
|
57
|
+
});
|
|
58
|
+
return result.routeGroups;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function generateProjectEntries(options) {
|
|
64
|
+
return Promise.all(
|
|
65
|
+
["root", "entry.server", "entry.client"].map(
|
|
66
|
+
(filename) => generateProjectFile(filename, {
|
|
67
|
+
v2Flags: {
|
|
68
|
+
isV2ErrorBoundary: true,
|
|
69
|
+
isV2Meta: true,
|
|
70
|
+
isV2RouteConvention: true
|
|
71
|
+
},
|
|
72
|
+
...options
|
|
73
|
+
})
|
|
74
|
+
)
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
async function handleCliShortcut(controller, cliCommand, flagShortcut) {
|
|
78
|
+
const shouldCreateShortcut = flagShortcut ?? await renderConfirmationPrompt({
|
|
79
|
+
confirmationMessage: "Yes",
|
|
80
|
+
cancellationMessage: "No",
|
|
81
|
+
message: [
|
|
82
|
+
"Create a global",
|
|
83
|
+
{ command: ALIAS_NAME },
|
|
84
|
+
"alias to run commands instead of",
|
|
85
|
+
{ command: cliCommand },
|
|
86
|
+
"?"
|
|
87
|
+
],
|
|
88
|
+
abortSignal: controller.signal
|
|
89
|
+
});
|
|
90
|
+
if (!shouldCreateShortcut)
|
|
91
|
+
return {};
|
|
92
|
+
return {
|
|
93
|
+
createShortcut: async () => {
|
|
94
|
+
try {
|
|
95
|
+
const shortcuts = await createPlatformShortcut();
|
|
96
|
+
return shortcuts.length > 0;
|
|
97
|
+
} catch (error) {
|
|
98
|
+
outputDebug(
|
|
99
|
+
"Failed to create shortcut." + (error?.stack ?? error?.message ?? error)
|
|
100
|
+
);
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
showShortcutBanner: () => renderInfo({
|
|
105
|
+
body: `You'll need to restart your terminal session to make \`${ALIAS_NAME}\` alias available.`
|
|
106
|
+
})
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
async function handleStorefrontLink(controller) {
|
|
110
|
+
const { session, config } = await login();
|
|
111
|
+
renderLoginSuccess(config);
|
|
112
|
+
const title = await renderTextPrompt({
|
|
113
|
+
message: "New storefront name",
|
|
114
|
+
defaultValue: titleize(config.shopName),
|
|
115
|
+
abortSignal: controller.signal
|
|
116
|
+
});
|
|
117
|
+
return { ...config, title, session };
|
|
118
|
+
}
|
|
119
|
+
async function handleProjectLocation({
|
|
120
|
+
storefrontInfo,
|
|
121
|
+
controller,
|
|
122
|
+
force,
|
|
123
|
+
path: flagPath
|
|
124
|
+
}) {
|
|
125
|
+
const storefrontDirectory = storefrontInfo && hyphenate(storefrontInfo.title);
|
|
126
|
+
let location = flagPath ?? storefrontDirectory ?? await renderTextPrompt({
|
|
127
|
+
message: "Where would you like to create your storefront?",
|
|
128
|
+
defaultValue: "hydrogen-storefront",
|
|
129
|
+
abortSignal: controller.signal
|
|
130
|
+
});
|
|
131
|
+
let directory = resolvePath(process.cwd(), location);
|
|
132
|
+
if (await projectExists(directory)) {
|
|
133
|
+
if (!force && storefrontDirectory) {
|
|
134
|
+
location = await renderTextPrompt({
|
|
135
|
+
message: `There's already a folder called \`${storefrontDirectory}\`. Where do you want to create the app?`,
|
|
136
|
+
defaultValue: storefrontDirectory,
|
|
137
|
+
abortSignal: controller.signal
|
|
138
|
+
});
|
|
139
|
+
directory = resolvePath(process.cwd(), location);
|
|
140
|
+
if (!await projectExists(directory)) {
|
|
141
|
+
force = true;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (!force) {
|
|
145
|
+
const deleteFiles = await renderConfirmationPrompt({
|
|
146
|
+
message: `The directory ${colors.cyan(
|
|
147
|
+
location
|
|
148
|
+
)} is not empty. Do you want to delete the existing files and continue?`,
|
|
149
|
+
defaultValue: false,
|
|
150
|
+
abortSignal: controller.signal
|
|
151
|
+
});
|
|
152
|
+
if (!deleteFiles) {
|
|
153
|
+
renderInfo({
|
|
154
|
+
body: `Destination path ${colors.cyan(
|
|
155
|
+
location
|
|
156
|
+
)} already exists and is not an empty directory. You may use \`--force\` or \`-f\` to override it.`
|
|
157
|
+
});
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
await rmdir(directory);
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
name: basename(location),
|
|
165
|
+
location,
|
|
166
|
+
directory,
|
|
167
|
+
storefrontTitle: storefrontInfo?.title
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
async function handleLanguage(projectDir, controller, flagLanguage) {
|
|
171
|
+
const language = flagLanguage ?? await renderSelectPrompt({
|
|
172
|
+
message: "Select a language",
|
|
173
|
+
choices: [
|
|
174
|
+
{ label: "JavaScript", value: "js" },
|
|
175
|
+
{ label: "TypeScript", value: "ts" }
|
|
176
|
+
],
|
|
177
|
+
defaultValue: "js",
|
|
178
|
+
abortSignal: controller.signal
|
|
179
|
+
});
|
|
180
|
+
return {
|
|
181
|
+
language,
|
|
182
|
+
async transpileProject() {
|
|
183
|
+
if (language === "js") {
|
|
184
|
+
await transpileProject(projectDir);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
async function handleCssStrategy(projectDir, controller, flagStyling) {
|
|
190
|
+
const selection = flagStyling ? flagStyling : await renderCssPrompt({
|
|
191
|
+
abortSignal: controller.signal,
|
|
192
|
+
extraChoices: { none: "Skip and set up later" }
|
|
193
|
+
});
|
|
194
|
+
const cssStrategy = selection === "none" ? void 0 : selection;
|
|
195
|
+
return {
|
|
196
|
+
cssStrategy,
|
|
197
|
+
async setupCss() {
|
|
198
|
+
if (cssStrategy) {
|
|
199
|
+
const result = await setupCssStrategy(
|
|
200
|
+
cssStrategy,
|
|
201
|
+
{
|
|
202
|
+
rootDirectory: projectDir,
|
|
203
|
+
appDirectory: joinPath(projectDir, "app")
|
|
204
|
+
},
|
|
205
|
+
true
|
|
206
|
+
);
|
|
207
|
+
if (result) {
|
|
208
|
+
await result.workPromise;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
async function handleDependencies(projectDir, controller, shouldInstallDeps) {
|
|
215
|
+
const detectedPackageManager = await packageManagerUsedForCreating();
|
|
216
|
+
let actualPackageManager = "npm";
|
|
217
|
+
if (shouldInstallDeps !== false) {
|
|
218
|
+
if (detectedPackageManager === "unknown") {
|
|
219
|
+
const result = await renderSelectPrompt({
|
|
220
|
+
message: `Select package manager to install dependencies`,
|
|
221
|
+
choices: [
|
|
222
|
+
{ label: "NPM", value: "npm" },
|
|
223
|
+
{ label: "PNPM", value: "pnpm" },
|
|
224
|
+
{ label: "Yarn v1", value: "yarn" },
|
|
225
|
+
{ label: "Skip and install later", value: "no" }
|
|
226
|
+
],
|
|
227
|
+
defaultValue: "npm",
|
|
228
|
+
abortSignal: controller.signal
|
|
229
|
+
});
|
|
230
|
+
if (result === "no") {
|
|
231
|
+
shouldInstallDeps = false;
|
|
232
|
+
} else {
|
|
233
|
+
actualPackageManager = result;
|
|
234
|
+
shouldInstallDeps = true;
|
|
235
|
+
}
|
|
236
|
+
} else if (shouldInstallDeps === void 0) {
|
|
237
|
+
actualPackageManager = detectedPackageManager;
|
|
238
|
+
shouldInstallDeps = await renderConfirmationPrompt({
|
|
239
|
+
message: `Install dependencies with ${detectedPackageManager}?`,
|
|
240
|
+
confirmationMessage: "Yes",
|
|
241
|
+
cancellationMessage: "No",
|
|
242
|
+
abortSignal: controller.signal
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return {
|
|
247
|
+
packageManager: actualPackageManager,
|
|
248
|
+
shouldInstallDeps,
|
|
249
|
+
installDeps: shouldInstallDeps ? async () => {
|
|
250
|
+
await installNodeModules({
|
|
251
|
+
directory: projectDir,
|
|
252
|
+
packageManager: actualPackageManager,
|
|
253
|
+
args: [],
|
|
254
|
+
signal: controller.signal
|
|
255
|
+
});
|
|
256
|
+
} : () => {
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
const gitIgnoreContent = `
|
|
261
|
+
node_modules
|
|
262
|
+
/.cache
|
|
263
|
+
/build
|
|
264
|
+
/dist
|
|
265
|
+
/public/build
|
|
266
|
+
/.mf
|
|
267
|
+
.env
|
|
268
|
+
.shopify
|
|
269
|
+
`.slice(1);
|
|
270
|
+
async function createInitialCommit(directory) {
|
|
271
|
+
try {
|
|
272
|
+
await initializeGitRepository(directory);
|
|
273
|
+
await writeFile(joinPath(directory, ".gitignore"), gitIgnoreContent);
|
|
274
|
+
if (process.env.NODE_ENV === "test" && process.env.CI) {
|
|
275
|
+
await execAsync(`git config --global user.name "hydrogen"`);
|
|
276
|
+
await execAsync(`git config --global user.email "hydrogen@shopify.com"`);
|
|
277
|
+
}
|
|
278
|
+
return commitAll(directory, "Scaffold Storefront");
|
|
279
|
+
} catch (error) {
|
|
280
|
+
outputDebug(
|
|
281
|
+
"Failed to initialize Git.\n" + error?.stack
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
async function commitAll(directory, message) {
|
|
286
|
+
try {
|
|
287
|
+
await addAllToGitFromDirectory(directory);
|
|
288
|
+
await createGitCommit(message, { directory });
|
|
289
|
+
} catch (error) {
|
|
290
|
+
outputDebug(
|
|
291
|
+
"Failed to commit code.\n" + error?.stack
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
async function renderProjectReady(project, {
|
|
296
|
+
language,
|
|
297
|
+
packageManager,
|
|
298
|
+
depsInstalled,
|
|
299
|
+
cssStrategy,
|
|
300
|
+
hasCreatedShortcut,
|
|
301
|
+
routes,
|
|
302
|
+
i18n,
|
|
303
|
+
depsError,
|
|
304
|
+
i18nError,
|
|
305
|
+
routesError
|
|
306
|
+
}) {
|
|
307
|
+
const hasErrors = Boolean(depsError || i18nError || routesError);
|
|
308
|
+
const bodyLines = [];
|
|
309
|
+
if (project.storefrontTitle) {
|
|
310
|
+
bodyLines.push(["Shopify", project.storefrontTitle]);
|
|
311
|
+
}
|
|
312
|
+
if (language) {
|
|
313
|
+
bodyLines.push(["Language", LANGUAGES[language]]);
|
|
314
|
+
}
|
|
315
|
+
if (cssStrategy) {
|
|
316
|
+
bodyLines.push(["Styling", CSS_STRATEGY_NAME_MAP[cssStrategy]]);
|
|
317
|
+
}
|
|
318
|
+
if (!i18nError && i18n) {
|
|
319
|
+
bodyLines.push(["Markets", I18N_STRATEGY_NAME_MAP[i18n].split(" (")[0]]);
|
|
320
|
+
}
|
|
321
|
+
let routeSummary = "";
|
|
322
|
+
if (!routesError && routes && Object.keys(routes).length) {
|
|
323
|
+
bodyLines.push(["Routes", ""]);
|
|
324
|
+
for (let [routeName, routePaths] of Object.entries(routes)) {
|
|
325
|
+
routePaths = Array.isArray(routePaths) ? routePaths : [routePaths];
|
|
326
|
+
let urls = [
|
|
327
|
+
...new Set(routePaths.map((item) => "/" + normalizeRoutePath(item)))
|
|
328
|
+
].sort();
|
|
329
|
+
if (urls.length > 2) {
|
|
330
|
+
const prefixesSet = new Set(urls.map((url) => url.split("/")[1] ?? ""));
|
|
331
|
+
urls = [...prefixesSet].map((item) => "/" + item + "/*");
|
|
332
|
+
}
|
|
333
|
+
routeSummary += `
|
|
334
|
+
\u2022 ${capitalize(routeName)} ${colors.dim(
|
|
335
|
+
"(" + urls.join(" & ") + ")"
|
|
336
|
+
)}`;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
const padMin = 1 + bodyLines.reduce((max, [label]) => Math.max(max, label.length), 0);
|
|
340
|
+
const cliCommand = hasCreatedShortcut ? ALIAS_NAME : await getCliCommand(project.directory, packageManager);
|
|
341
|
+
const render = hasErrors ? renderWarning : renderSuccess;
|
|
342
|
+
render({
|
|
343
|
+
headline: `Storefront setup complete` + (hasErrors ? " with errors (see warnings below)." : "!"),
|
|
344
|
+
body: bodyLines.map(
|
|
345
|
+
([label, value]) => ` ${(label + ":").padEnd(padMin, " ")} ${colors.dim(value)}`
|
|
346
|
+
).join("\n") + routeSummary,
|
|
347
|
+
customSections: [
|
|
348
|
+
hasErrors && {
|
|
349
|
+
title: "Warnings\n",
|
|
350
|
+
body: [
|
|
351
|
+
{
|
|
352
|
+
list: {
|
|
353
|
+
items: [
|
|
354
|
+
depsError && [
|
|
355
|
+
"Failed to install dependencies:",
|
|
356
|
+
{ subdued: depsError.message }
|
|
357
|
+
],
|
|
358
|
+
i18nError && [
|
|
359
|
+
"Failed to scaffold Markets:",
|
|
360
|
+
{ subdued: i18nError.message }
|
|
361
|
+
],
|
|
362
|
+
routesError && [
|
|
363
|
+
"Failed to scaffold routes:",
|
|
364
|
+
{ subdued: routesError.message }
|
|
365
|
+
]
|
|
366
|
+
].filter((step) => Boolean(step))
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
]
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
title: "Help\n",
|
|
373
|
+
body: {
|
|
374
|
+
list: {
|
|
375
|
+
items: [
|
|
376
|
+
{
|
|
377
|
+
link: {
|
|
378
|
+
label: "Guides",
|
|
379
|
+
url: "https://shopify.dev/docs/custom-storefronts/hydrogen/building"
|
|
380
|
+
}
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
link: {
|
|
384
|
+
label: "API reference",
|
|
385
|
+
url: "https://shopify.dev/docs/api/storefront"
|
|
386
|
+
}
|
|
387
|
+
},
|
|
388
|
+
{
|
|
389
|
+
link: {
|
|
390
|
+
label: "Demo Store code",
|
|
391
|
+
url: "https://github.com/Shopify/hydrogen/tree/HEAD/templates/demo-store"
|
|
392
|
+
}
|
|
393
|
+
},
|
|
394
|
+
[
|
|
395
|
+
"Run",
|
|
396
|
+
{
|
|
397
|
+
command: `${cliCommand} --help`
|
|
398
|
+
}
|
|
399
|
+
]
|
|
400
|
+
]
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
title: "Next steps\n",
|
|
406
|
+
body: [
|
|
407
|
+
{
|
|
408
|
+
list: {
|
|
409
|
+
items: [
|
|
410
|
+
[
|
|
411
|
+
"Run",
|
|
412
|
+
{
|
|
413
|
+
command: outputContent`${outputToken.genericShellCommand(
|
|
414
|
+
[
|
|
415
|
+
project.directory === process.cwd() ? void 0 : `cd ${project.location.replace(/^\.\//, "")}`,
|
|
416
|
+
depsInstalled ? void 0 : `${packageManager} install`,
|
|
417
|
+
formatPackageManagerCommand(packageManager, "dev")
|
|
418
|
+
].filter(Boolean).join(" && ")
|
|
419
|
+
)}`.value
|
|
420
|
+
}
|
|
421
|
+
]
|
|
422
|
+
].filter((step) => Boolean(step))
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
]
|
|
426
|
+
}
|
|
427
|
+
].filter((step) => Boolean(step))
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
function createAbortHandler(controller, project) {
|
|
431
|
+
return async function abort(error) {
|
|
432
|
+
controller.abort();
|
|
433
|
+
if (typeof project !== "undefined") {
|
|
434
|
+
await rmdir(project.directory, { force: true }).catch(() => {
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
renderFatalError(
|
|
438
|
+
new AbortError(
|
|
439
|
+
"Failed to initialize project: " + error?.message,
|
|
440
|
+
error?.tryMessage ?? error?.stack
|
|
441
|
+
)
|
|
442
|
+
);
|
|
443
|
+
if (process.env.NODE_ENV === "test") {
|
|
444
|
+
console.error(error);
|
|
445
|
+
}
|
|
446
|
+
process.exit(1);
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
async function projectExists(projectDir) {
|
|
450
|
+
return await fileExists(projectDir) && await isDirectory(projectDir) && (await readdir(projectDir)).length > 0;
|
|
451
|
+
}
|
|
452
|
+
function normalizeRoutePath(routePath) {
|
|
453
|
+
return routePath.replace(/(^|\.)_index$/, "").replace(/((^|\.)[^\.]+)_\./g, "$1.").replace(/\.(?!\w+\])/g, "/").replace(/\$$/g, ":catchAll").replace(/\$/g, ":").replace(/[\[\]]/g, "").replace(/:\w*Handle/i, ":handle");
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
export { LANGUAGES, commitAll, createAbortHandler, createInitialCommit, generateProjectEntries, handleCliShortcut, handleCssStrategy, handleDependencies, handleI18n, handleLanguage, handleProjectLocation, handleRouteGeneration, handleStorefrontLink, renderProjectReady };
|