@shopify/cli-hydrogen 5.0.2 → 5.1.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.js +21 -6
- package/dist/commands/hydrogen/check.js +2 -2
- package/dist/commands/hydrogen/codegen-unstable.js +14 -25
- package/dist/commands/hydrogen/dev.js +55 -43
- 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/preview.js +1 -1
- 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 +264 -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 +216 -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-config.js +135 -0
- package/dist/lib/remix-version-check.js +51 -0
- package/dist/lib/remix-version-check.test.js +38 -0
- package/dist/lib/remix-version-interop.js +6 -6
- package/dist/lib/remix-version-interop.test.js +12 -2
- 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 +20 -21
- 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/config.js +0 -141
- 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
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { copy } from 'fs-extra/esm';
|
|
2
|
+
import { writeFile } from '@shopify/cli-kit/node/fs';
|
|
3
|
+
import { relativePath, joinPath } from '@shopify/cli-kit/node/path';
|
|
4
|
+
import { hyphenate } from '@shopify/cli-kit/common/string';
|
|
5
|
+
import colors from '@shopify/cli-kit/node/colors';
|
|
6
|
+
import { renderSelectPrompt, renderSuccess, renderConfirmationPrompt, renderTasks } from '@shopify/cli-kit/node/ui';
|
|
7
|
+
import { handleStorefrontLink, handleProjectLocation, createAbortHandler, generateProjectEntries, handleLanguage, createInitialCommit, handleCssStrategy, commitAll, handleDependencies, handleCliShortcut, handleI18n, handleRouteGeneration, renderProjectReady } from './common.js';
|
|
8
|
+
import { createStorefront } from '../graphql/admin/create-storefront.js';
|
|
9
|
+
import { waitForJob } from '../graphql/admin/fetch-job.js';
|
|
10
|
+
import { getStarterDir } from '../build.js';
|
|
11
|
+
import { replaceFileContent } from '../file.js';
|
|
12
|
+
import { setUserAccount, setStorefront } from '../shopify-config.js';
|
|
13
|
+
import { getCliCommand, ALIAS_NAME } from '../shell.js';
|
|
14
|
+
import { CSS_STRATEGY_NAME_MAP } from '../setups/css/index.js';
|
|
15
|
+
|
|
16
|
+
async function setupLocalStarterTemplate(options, controller) {
|
|
17
|
+
const templateAction = options.mockShop ? "mock" : await renderSelectPrompt({
|
|
18
|
+
message: "Connect to Shopify",
|
|
19
|
+
choices: [
|
|
20
|
+
{
|
|
21
|
+
label: "Use sample data from Mock.shop (no login required)",
|
|
22
|
+
value: "mock"
|
|
23
|
+
},
|
|
24
|
+
{ label: "Link your Shopify account", value: "link" }
|
|
25
|
+
],
|
|
26
|
+
defaultValue: "mock",
|
|
27
|
+
abortSignal: controller.signal
|
|
28
|
+
});
|
|
29
|
+
const storefrontInfo = templateAction === "link" ? await handleStorefrontLink(controller) : void 0;
|
|
30
|
+
const project = await handleProjectLocation({
|
|
31
|
+
...options,
|
|
32
|
+
storefrontInfo,
|
|
33
|
+
controller
|
|
34
|
+
});
|
|
35
|
+
if (!project)
|
|
36
|
+
return;
|
|
37
|
+
if (templateAction === "mock")
|
|
38
|
+
project.storefrontTitle = "Mock.shop";
|
|
39
|
+
const abort = createAbortHandler(controller, project);
|
|
40
|
+
const createStorefrontPromise = storefrontInfo && createStorefront(storefrontInfo.session, storefrontInfo.title).then(async ({ storefront, jobId }) => {
|
|
41
|
+
if (jobId)
|
|
42
|
+
await waitForJob(storefrontInfo.session, jobId);
|
|
43
|
+
return storefront;
|
|
44
|
+
}).catch(abort);
|
|
45
|
+
const templateDir = getStarterDir();
|
|
46
|
+
let backgroundWorkPromise = copy(
|
|
47
|
+
templateDir,
|
|
48
|
+
project.directory,
|
|
49
|
+
{
|
|
50
|
+
filter: (filepath) => !/^(app|dist|node_modules)\//i.test(
|
|
51
|
+
relativePath(templateDir, filepath)
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
).then(
|
|
55
|
+
() => generateProjectEntries({
|
|
56
|
+
rootDirectory: project.directory,
|
|
57
|
+
appDirectory: joinPath(project.directory, "app"),
|
|
58
|
+
typescript: true
|
|
59
|
+
})
|
|
60
|
+
).catch(abort);
|
|
61
|
+
const tasks = [
|
|
62
|
+
{
|
|
63
|
+
title: "Creating storefront",
|
|
64
|
+
task: async () => {
|
|
65
|
+
await createStorefrontPromise;
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
title: "Setting up project",
|
|
70
|
+
task: async () => {
|
|
71
|
+
await backgroundWorkPromise;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
];
|
|
75
|
+
backgroundWorkPromise = backgroundWorkPromise.then(() => {
|
|
76
|
+
const promises = [
|
|
77
|
+
replaceFileContent(
|
|
78
|
+
joinPath(project.directory, "package.json"),
|
|
79
|
+
false,
|
|
80
|
+
(content) => content.replace(
|
|
81
|
+
/"name": "[^"]+"/,
|
|
82
|
+
`"name": "${hyphenate(storefrontInfo?.title ?? project.name)}"`
|
|
83
|
+
)
|
|
84
|
+
)
|
|
85
|
+
];
|
|
86
|
+
const envLeadingComment = "# The variables added in this file are only available locally in MiniOxygen\n";
|
|
87
|
+
if (storefrontInfo && createStorefrontPromise) {
|
|
88
|
+
promises.push(
|
|
89
|
+
setUserAccount(project.directory, storefrontInfo),
|
|
90
|
+
createStorefrontPromise.then(
|
|
91
|
+
(storefront) => setStorefront(project.directory, storefront)
|
|
92
|
+
),
|
|
93
|
+
writeFile(joinPath(project.directory, ".env"), envLeadingComment)
|
|
94
|
+
);
|
|
95
|
+
} else if (templateAction === "mock") {
|
|
96
|
+
promises.push(
|
|
97
|
+
writeFile(
|
|
98
|
+
joinPath(project.directory, ".env"),
|
|
99
|
+
envLeadingComment + "\n" + [
|
|
100
|
+
["SESSION_SECRET", "foobar"],
|
|
101
|
+
["PUBLIC_STORE_DOMAIN", "mock.shop"]
|
|
102
|
+
].map(([key, value]) => `${key}="${value}"`).join("\n") + "\n"
|
|
103
|
+
)
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
return Promise.all(promises).catch(abort);
|
|
107
|
+
});
|
|
108
|
+
const { language, transpileProject } = await handleLanguage(
|
|
109
|
+
project.directory,
|
|
110
|
+
controller,
|
|
111
|
+
options.language
|
|
112
|
+
);
|
|
113
|
+
backgroundWorkPromise = backgroundWorkPromise.then(() => transpileProject().catch(abort)).then(
|
|
114
|
+
() => options.git ? createInitialCommit(project.directory) : void 0
|
|
115
|
+
);
|
|
116
|
+
const { setupCss, cssStrategy } = await handleCssStrategy(
|
|
117
|
+
project.directory,
|
|
118
|
+
controller,
|
|
119
|
+
options.styling
|
|
120
|
+
);
|
|
121
|
+
if (cssStrategy) {
|
|
122
|
+
backgroundWorkPromise = backgroundWorkPromise.then(() => setupCss().catch(abort)).then(
|
|
123
|
+
() => options.git ? commitAll(
|
|
124
|
+
project.directory,
|
|
125
|
+
"Setup " + CSS_STRATEGY_NAME_MAP[cssStrategy]
|
|
126
|
+
) : void 0
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
const { packageManager, shouldInstallDeps, installDeps } = await handleDependencies(
|
|
130
|
+
project.directory,
|
|
131
|
+
controller,
|
|
132
|
+
options.installDeps
|
|
133
|
+
);
|
|
134
|
+
const setupSummary = {
|
|
135
|
+
language,
|
|
136
|
+
packageManager,
|
|
137
|
+
cssStrategy,
|
|
138
|
+
depsInstalled: false,
|
|
139
|
+
hasCreatedShortcut: false
|
|
140
|
+
};
|
|
141
|
+
if (shouldInstallDeps) {
|
|
142
|
+
const installingDepsPromise = backgroundWorkPromise.then(async () => {
|
|
143
|
+
try {
|
|
144
|
+
await installDeps();
|
|
145
|
+
setupSummary.depsInstalled = true;
|
|
146
|
+
} catch (error) {
|
|
147
|
+
setupSummary.depsError = error;
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
tasks.push({
|
|
151
|
+
title: "Installing dependencies. This could take a few minutes",
|
|
152
|
+
task: async () => {
|
|
153
|
+
await installingDepsPromise;
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
const pkgManagerCommand = await getCliCommand("", packageManager);
|
|
158
|
+
const { createShortcut, showShortcutBanner } = await handleCliShortcut(
|
|
159
|
+
controller,
|
|
160
|
+
pkgManagerCommand,
|
|
161
|
+
options.shortcut
|
|
162
|
+
);
|
|
163
|
+
if (createShortcut) {
|
|
164
|
+
backgroundWorkPromise = backgroundWorkPromise.then(async () => {
|
|
165
|
+
setupSummary.hasCreatedShortcut = await createShortcut();
|
|
166
|
+
});
|
|
167
|
+
showShortcutBanner();
|
|
168
|
+
}
|
|
169
|
+
const cliCommand = createShortcut ? ALIAS_NAME : pkgManagerCommand;
|
|
170
|
+
renderSuccess({
|
|
171
|
+
headline: [
|
|
172
|
+
{ userInput: storefrontInfo?.title ?? project.name },
|
|
173
|
+
"is ready to build."
|
|
174
|
+
]
|
|
175
|
+
});
|
|
176
|
+
const continueWithSetup = (options.i18n ?? options.routes) !== void 0 || await renderConfirmationPrompt({
|
|
177
|
+
message: "Do you want to scaffold routes and core functionality?",
|
|
178
|
+
confirmationMessage: "Yes, set up now",
|
|
179
|
+
cancellationMessage: "No, set up later " + colors.dim(`(run \`${cliCommand} setup\`)`),
|
|
180
|
+
abortSignal: controller.signal
|
|
181
|
+
});
|
|
182
|
+
if (continueWithSetup) {
|
|
183
|
+
const { i18nStrategy, setupI18n } = await handleI18n(
|
|
184
|
+
controller,
|
|
185
|
+
cliCommand,
|
|
186
|
+
options.i18n
|
|
187
|
+
);
|
|
188
|
+
const { setupRoutes } = await handleRouteGeneration(
|
|
189
|
+
controller,
|
|
190
|
+
options.routes || true
|
|
191
|
+
);
|
|
192
|
+
setupSummary.i18n = i18nStrategy;
|
|
193
|
+
backgroundWorkPromise = backgroundWorkPromise.then(async () => {
|
|
194
|
+
await setupI18n({
|
|
195
|
+
rootDirectory: project.directory,
|
|
196
|
+
serverEntryPoint: language === "ts" ? "server.ts" : "server.js"
|
|
197
|
+
}).then(
|
|
198
|
+
() => options.git ? commitAll(
|
|
199
|
+
project.directory,
|
|
200
|
+
`Setup markets support using ${i18nStrategy}`
|
|
201
|
+
) : void 0
|
|
202
|
+
).catch((error) => {
|
|
203
|
+
setupSummary.i18nError = error;
|
|
204
|
+
});
|
|
205
|
+
await setupRoutes(project.directory, language, i18nStrategy).then((routes) => {
|
|
206
|
+
setupSummary.routes = routes;
|
|
207
|
+
if (options.git && routes) {
|
|
208
|
+
return commitAll(
|
|
209
|
+
project.directory,
|
|
210
|
+
`Generate routes for core functionality`
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
}).catch((error) => {
|
|
214
|
+
setupSummary.routesError = error;
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
await renderTasks(tasks);
|
|
219
|
+
if (options.git) {
|
|
220
|
+
await commitAll(project.directory, "Lockfile");
|
|
221
|
+
}
|
|
222
|
+
await renderProjectReady(project, setupSummary);
|
|
223
|
+
return {
|
|
224
|
+
...project,
|
|
225
|
+
...setupSummary
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export { setupLocalStarterTemplate };
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { AbortError } from '@shopify/cli-kit/node/error';
|
|
2
|
+
import { copyFile } from '@shopify/cli-kit/node/fs';
|
|
3
|
+
import { joinPath } from '@shopify/cli-kit/node/path';
|
|
4
|
+
import { renderTasks, renderInfo } from '@shopify/cli-kit/node/ui';
|
|
5
|
+
import { getLatestTemplates } from '../template-downloader.js';
|
|
6
|
+
import { handleProjectLocation, createAbortHandler, handleLanguage, createInitialCommit, handleDependencies, renderProjectReady } from './common.js';
|
|
7
|
+
|
|
8
|
+
async function setupRemoteTemplate(options, controller) {
|
|
9
|
+
const isOfficialTemplate = options.template === "demo-store" || options.template === "hello-world";
|
|
10
|
+
if (!isOfficialTemplate) {
|
|
11
|
+
throw new AbortError(
|
|
12
|
+
"Only `demo-store` and `hello-world` are supported in --template flag for now.",
|
|
13
|
+
"Skip the --template flag to run the setup flow."
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
const appTemplate = options.template;
|
|
17
|
+
const backgroundDownloadPromise = getLatestTemplates({
|
|
18
|
+
signal: controller.signal
|
|
19
|
+
}).catch((error) => {
|
|
20
|
+
throw abort(error);
|
|
21
|
+
});
|
|
22
|
+
const project = await handleProjectLocation({ ...options, controller });
|
|
23
|
+
if (!project)
|
|
24
|
+
return;
|
|
25
|
+
const abort = createAbortHandler(controller, project);
|
|
26
|
+
let backgroundWorkPromise = backgroundDownloadPromise.then(
|
|
27
|
+
({ templatesDir }) => copyFile(joinPath(templatesDir, appTemplate), project.directory).catch(
|
|
28
|
+
abort
|
|
29
|
+
)
|
|
30
|
+
);
|
|
31
|
+
const { language, transpileProject } = await handleLanguage(
|
|
32
|
+
project.directory,
|
|
33
|
+
controller,
|
|
34
|
+
options.language
|
|
35
|
+
);
|
|
36
|
+
backgroundWorkPromise = backgroundWorkPromise.then(() => transpileProject().catch(abort)).then(() => createInitialCommit(project.directory));
|
|
37
|
+
const { packageManager, shouldInstallDeps, installDeps } = await handleDependencies(
|
|
38
|
+
project.directory,
|
|
39
|
+
controller,
|
|
40
|
+
options.installDeps
|
|
41
|
+
);
|
|
42
|
+
const setupSummary = {
|
|
43
|
+
language,
|
|
44
|
+
packageManager,
|
|
45
|
+
depsInstalled: false,
|
|
46
|
+
hasCreatedShortcut: false
|
|
47
|
+
};
|
|
48
|
+
const tasks = [
|
|
49
|
+
{
|
|
50
|
+
title: "Downloading template",
|
|
51
|
+
task: async () => {
|
|
52
|
+
await backgroundDownloadPromise;
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
title: "Setting up project",
|
|
57
|
+
task: async () => {
|
|
58
|
+
await backgroundWorkPromise;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
];
|
|
62
|
+
if (shouldInstallDeps) {
|
|
63
|
+
tasks.push({
|
|
64
|
+
title: "Installing dependencies. This could take a few minutes",
|
|
65
|
+
task: async () => {
|
|
66
|
+
try {
|
|
67
|
+
await installDeps();
|
|
68
|
+
setupSummary.depsInstalled = true;
|
|
69
|
+
} catch (error) {
|
|
70
|
+
setupSummary.depsError = error;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
await renderTasks(tasks);
|
|
76
|
+
await renderProjectReady(project, setupSummary);
|
|
77
|
+
if (isOfficialTemplate) {
|
|
78
|
+
renderInfo({
|
|
79
|
+
headline: `Your project will display inventory from the Hydrogen Demo Store.`,
|
|
80
|
+
body: `To connect this project to your Shopify store\u2019s inventory, update \`${project.name}/.env\` with your store ID and Storefront API key.`
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
...project,
|
|
85
|
+
...setupSummary
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export { setupRemoteTemplate };
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { readdir } from 'node:fs/promises';
|
|
5
|
+
import { AbortError } from '@shopify/cli-kit/node/error';
|
|
6
|
+
import { outputWarn } from '@shopify/cli-kit/node/output';
|
|
7
|
+
import { fileExists } from '@shopify/cli-kit/node/fs';
|
|
8
|
+
|
|
9
|
+
const BUILD_DIR = "dist";
|
|
10
|
+
const CLIENT_SUBDIR = "client";
|
|
11
|
+
const WORKER_SUBDIR = "worker";
|
|
12
|
+
const oxygenServerMainFields = ["browser", "module", "main"];
|
|
13
|
+
function getProjectPaths(appPath, entry) {
|
|
14
|
+
const root = appPath ?? process.cwd();
|
|
15
|
+
const publicPath = path.join(root, "public");
|
|
16
|
+
const buildPath = path.join(root, BUILD_DIR);
|
|
17
|
+
const buildPathClient = path.join(buildPath, CLIENT_SUBDIR);
|
|
18
|
+
const buildPathWorkerFile = path.join(buildPath, WORKER_SUBDIR, "index.js");
|
|
19
|
+
return {
|
|
20
|
+
root,
|
|
21
|
+
buildPath,
|
|
22
|
+
buildPathClient,
|
|
23
|
+
buildPathWorkerFile,
|
|
24
|
+
publicPath
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
async function getRemixConfig(root, mode = process.env.NODE_ENV) {
|
|
28
|
+
const { readConfig } = await import('@remix-run/dev/dist/config.js');
|
|
29
|
+
const config = await readConfig(root, mode);
|
|
30
|
+
if (process.env.LOCAL_DEV) {
|
|
31
|
+
const packagesPath = fileURLToPath(new URL("../../..", import.meta.url));
|
|
32
|
+
config.watchPaths ??= [];
|
|
33
|
+
config.watchPaths.push(
|
|
34
|
+
...(await readdir(packagesPath)).map(
|
|
35
|
+
(pkg) => pkg === "hydrogen-react" ? path.resolve(packagesPath, pkg, "dist", "browser-dev", "index.mjs") : path.resolve(packagesPath, pkg, "dist", "development", "index.js")
|
|
36
|
+
)
|
|
37
|
+
);
|
|
38
|
+
config.watchPaths.push(
|
|
39
|
+
path.join(packagesPath, "cli", "dist", "virtual-routes", "**", "*")
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
return config;
|
|
43
|
+
}
|
|
44
|
+
function assertOxygenChecks(config) {
|
|
45
|
+
try {
|
|
46
|
+
createRequire(import.meta.url).resolve("@shopify/remix-oxygen");
|
|
47
|
+
} catch {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (!config.serverEntryPoint) {
|
|
51
|
+
throw new AbortError(
|
|
52
|
+
"Could not find a server entry point.",
|
|
53
|
+
"Please add a server option to your remix.config.js pointing to an Oxygen worker entry file."
|
|
54
|
+
);
|
|
55
|
+
} else {
|
|
56
|
+
assertEntryFileExists(config.rootDirectory, config.serverEntryPoint);
|
|
57
|
+
}
|
|
58
|
+
if (config.serverPlatform !== "neutral") {
|
|
59
|
+
throw new AbortError(
|
|
60
|
+
'The serverPlatform in remix.config.js must be "neutral".'
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
if (config.serverModuleFormat !== "esm") {
|
|
64
|
+
throw new AbortError(
|
|
65
|
+
'The serverModuleFormat in remix.config.js must be "esm".'
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
if (config.serverDependenciesToBundle !== "all") {
|
|
69
|
+
throw new AbortError(
|
|
70
|
+
'The serverDependenciesToBundle in remix.config.js must be "all".'
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
if (!config.serverConditions?.includes("worker")) {
|
|
74
|
+
throw new AbortError(
|
|
75
|
+
'The serverConditions in remix.config.js must include "worker".'
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
if (process.env.NODE_ENV === "development" && !config.serverConditions?.includes("development")) {
|
|
79
|
+
outputWarn(
|
|
80
|
+
"Add `process.env.NODE_ENV` value to serverConditions in remix.config.js to enable debugging features in development."
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
if (!config.serverMainFields || !oxygenServerMainFields.every((v, i) => config.serverMainFields?.[i] === v)) {
|
|
84
|
+
throw new AbortError(
|
|
85
|
+
`The serverMainFields in remix.config.js must be ${JSON.stringify(
|
|
86
|
+
oxygenServerMainFields
|
|
87
|
+
)}.`
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
const cdnUrl = process.env.HYDROGEN_ASSET_BASE_URL;
|
|
91
|
+
if (cdnUrl && !config.publicPath.startsWith(cdnUrl)) {
|
|
92
|
+
throw new AbortError(
|
|
93
|
+
"The publicPath in remix.config.js must be prepended with the value of `process.env.HYDROGEN_ASSET_BASE_URL`."
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
const expectedServerBuildPath = path.join(
|
|
97
|
+
BUILD_DIR,
|
|
98
|
+
WORKER_SUBDIR,
|
|
99
|
+
"index.js"
|
|
100
|
+
);
|
|
101
|
+
if (config.serverBuildPath !== path.resolve(config.rootDirectory, expectedServerBuildPath)) {
|
|
102
|
+
throw new AbortError(
|
|
103
|
+
`The serverBuildPath in remix.config.js must be "${expectedServerBuildPath}".`
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
const expectedAssetsBuildDirectory = path.join(BUILD_DIR, CLIENT_SUBDIR);
|
|
107
|
+
if (!config.assetsBuildDirectory.startsWith(
|
|
108
|
+
path.resolve(config.rootDirectory, expectedAssetsBuildDirectory)
|
|
109
|
+
)) {
|
|
110
|
+
throw new AbortError(
|
|
111
|
+
`The assetsBuildDirectory in remix.config.js must be in "${expectedAssetsBuildDirectory}".`
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async function assertEntryFileExists(root, fileRelative) {
|
|
116
|
+
const fileAbsolute = path.resolve(root, fileRelative);
|
|
117
|
+
const exists = await fileExists(fileAbsolute);
|
|
118
|
+
if (!exists) {
|
|
119
|
+
if (!path.extname(fileAbsolute)) {
|
|
120
|
+
const files = await readdir(path.dirname(fileAbsolute));
|
|
121
|
+
const exists2 = files.some((file) => {
|
|
122
|
+
const { name, ext } = path.parse(file);
|
|
123
|
+
return name === path.basename(fileAbsolute) && /^\.[jt]s$/.test(ext);
|
|
124
|
+
});
|
|
125
|
+
if (exists2)
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
throw new AbortError(
|
|
129
|
+
`Entry file "${fileRelative}" not found.`,
|
|
130
|
+
"Please ensure the file exists and that the path is correctly added to the `server` property in remix.config.js."
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export { assertOxygenChecks, getProjectPaths, getRemixConfig };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { renderWarning } from '@shopify/cli-kit/node/ui';
|
|
4
|
+
|
|
5
|
+
function checkRemixVersions() {
|
|
6
|
+
const require2 = createRequire(import.meta.url);
|
|
7
|
+
const hydrogenPkgJson = require2(fileURLToPath(
|
|
8
|
+
new URL("../../package.json", import.meta.url)
|
|
9
|
+
));
|
|
10
|
+
const requiredVersionInHydrogen = hydrogenPkgJson.dependencies["@remix-run/dev"];
|
|
11
|
+
const pkgs = [
|
|
12
|
+
"dev",
|
|
13
|
+
"react",
|
|
14
|
+
"server-runtime",
|
|
15
|
+
"css-bundle",
|
|
16
|
+
"node",
|
|
17
|
+
"express",
|
|
18
|
+
"eslint-config"
|
|
19
|
+
].map((name) => getRemixPackageVersion(require2, name));
|
|
20
|
+
const outOfSyncPkgs = pkgs.filter(
|
|
21
|
+
(pkg) => pkg.version && pkg.version !== requiredVersionInHydrogen
|
|
22
|
+
);
|
|
23
|
+
if (outOfSyncPkgs.length === 0)
|
|
24
|
+
return;
|
|
25
|
+
const items = outOfSyncPkgs.reduce((acc, item) => {
|
|
26
|
+
if (item.version) {
|
|
27
|
+
acc.push(`${item.name}@${item.version}`);
|
|
28
|
+
}
|
|
29
|
+
return acc;
|
|
30
|
+
}, []);
|
|
31
|
+
renderWarning({
|
|
32
|
+
headline: `The current version of Hydrogen requires Remix @${requiredVersionInHydrogen}. The following packages are out of sync:`,
|
|
33
|
+
body: [
|
|
34
|
+
{ list: { items } },
|
|
35
|
+
"\nPlease ensure your Remix packages have the same version and are in sync with Hydrogen."
|
|
36
|
+
]
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
function getRemixPackageVersion(require2, name) {
|
|
40
|
+
const pkgName = "@remix-run/" + name;
|
|
41
|
+
const result = { name: pkgName, version: "" };
|
|
42
|
+
try {
|
|
43
|
+
const pkgJsonPath = require2.resolve(`${pkgName}/package.json`);
|
|
44
|
+
const pkgJson = require2(pkgJsonPath);
|
|
45
|
+
result.version = pkgJson.version;
|
|
46
|
+
} catch {
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export { checkRemixVersions };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { vi, describe, it, expect } from 'vitest';
|
|
2
|
+
import { mockAndCaptureOutput } from '@shopify/cli-kit/node/testing/output';
|
|
3
|
+
import { checkRemixVersions } from './remix-version-check.js';
|
|
4
|
+
|
|
5
|
+
const requireMock = vi.fn();
|
|
6
|
+
vi.mock("node:module", async () => {
|
|
7
|
+
const { createRequire } = await vi.importActual(
|
|
8
|
+
"node:module"
|
|
9
|
+
);
|
|
10
|
+
return {
|
|
11
|
+
createRequire: (url) => {
|
|
12
|
+
const actualRequire = createRequire(url);
|
|
13
|
+
requireMock.mockImplementation((mod) => actualRequire(mod));
|
|
14
|
+
const require2 = requireMock;
|
|
15
|
+
require2.resolve = actualRequire.resolve.bind(actualRequire);
|
|
16
|
+
return require2;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
});
|
|
20
|
+
describe("remix-version-check", () => {
|
|
21
|
+
it("does nothing when versions are in sync", () => {
|
|
22
|
+
const outputMock = mockAndCaptureOutput();
|
|
23
|
+
checkRemixVersions();
|
|
24
|
+
expect(outputMock.warn()).toBe("");
|
|
25
|
+
});
|
|
26
|
+
it("warns when versions are out of sync", () => {
|
|
27
|
+
const expectedVersion = "42.0.0-test";
|
|
28
|
+
vi.mocked(requireMock).mockReturnValueOnce({
|
|
29
|
+
dependencies: { "@remix-run/dev": expectedVersion }
|
|
30
|
+
});
|
|
31
|
+
const outputMock = mockAndCaptureOutput();
|
|
32
|
+
checkRemixVersions();
|
|
33
|
+
const output = outputMock.warn();
|
|
34
|
+
expect(output).toMatch(`Hydrogen requires Remix @${expectedVersion}`);
|
|
35
|
+
expect(output).toMatch(`@remix-run/dev@`);
|
|
36
|
+
expect(output).toMatch(`@remix-run/react@`);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRequire } from 'module';
|
|
2
|
-
import { getRemixConfig } from './config.js';
|
|
2
|
+
import { getRemixConfig } from './remix-config.js';
|
|
3
3
|
|
|
4
4
|
function isRemixV2() {
|
|
5
5
|
try {
|
|
@@ -10,10 +10,10 @@ function isRemixV2() {
|
|
|
10
10
|
return false;
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
|
-
async function getV2Flags(root) {
|
|
13
|
+
async function getV2Flags(root, remixConfigFuture) {
|
|
14
14
|
const isV2 = isRemixV2();
|
|
15
15
|
const futureFlags = {
|
|
16
|
-
...!isV2 && (await getRemixConfig(root
|
|
16
|
+
...!isV2 && (remixConfigFuture ?? (await getRemixConfig(root)).future)
|
|
17
17
|
};
|
|
18
18
|
return {
|
|
19
19
|
isV2Meta: isV2 || !!futureFlags.v2_meta,
|
|
@@ -21,8 +21,8 @@ async function getV2Flags(root) {
|
|
|
21
21
|
isV2RouteConvention: isV2 ? !isV1RouteConventionInstalled() : !!futureFlags.v2_routeConvention
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
|
-
function
|
|
25
|
-
return route.replace(
|
|
24
|
+
function convertRouteToV1(route) {
|
|
25
|
+
return route.replace(/(^|\.)_index$/, "$1index").replace(/\.(?!\w+\])/g, "/");
|
|
26
26
|
}
|
|
27
27
|
function convertTemplateToRemixVersion(template, { isV2Meta, isV2ErrorBoundary }) {
|
|
28
28
|
template = isV2Meta ? convertToMetaV2(template) : convertToMetaV1(template);
|
|
@@ -51,4 +51,4 @@ function isV1RouteConventionInstalled() {
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
export {
|
|
54
|
+
export { convertRouteToV1, convertTemplateToRemixVersion, getV2Flags, isRemixV2 };
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { convertTemplateToRemixVersion } from './remix-version-interop.js';
|
|
2
|
+
import { convertRouteToV1, convertTemplateToRemixVersion } from './remix-version-interop.js';
|
|
3
3
|
|
|
4
4
|
describe("remix-version-interop", () => {
|
|
5
|
+
describe("v2_routeConvention", () => {
|
|
6
|
+
it("converts routes to v1", () => {
|
|
7
|
+
expect(convertRouteToV1("_index")).toEqual("index");
|
|
8
|
+
expect(convertRouteToV1("path.to.file")).toEqual("path/to/file");
|
|
9
|
+
expect(convertRouteToV1("path.to._index")).toEqual("path/to/index");
|
|
10
|
+
expect(convertRouteToV1("patht.to.[sitemap.xml]")).toEqual(
|
|
11
|
+
"patht/to/[sitemap.xml]"
|
|
12
|
+
);
|
|
13
|
+
});
|
|
14
|
+
});
|
|
5
15
|
describe("v2_meta", () => {
|
|
6
16
|
const META_TEMPLATE = `
|
|
7
17
|
import {type MetaFunction} from '@shopify/remix-oxygen';
|
|
@@ -48,7 +58,7 @@ describe("remix-version-interop", () => {
|
|
|
48
58
|
return <div>stuff</div>;
|
|
49
59
|
}
|
|
50
60
|
|
|
51
|
-
export const ErrorBoundaryV1
|
|
61
|
+
export const ErrorBoundaryV1 = ({error}: {error: Error}) => {
|
|
52
62
|
console.error(error);
|
|
53
63
|
|
|
54
64
|
return <div>There was an error.</div>;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { renderFatalError } from '@shopify/cli-kit/node/ui';
|
|
2
2
|
import { outputContent, outputToken } from '@shopify/cli-kit/node/output';
|
|
3
3
|
import { hydrogenStorefrontsUrl } from './admin-urls.js';
|
|
4
|
-
import { parseGid } from './
|
|
4
|
+
import { parseGid } from './gid.js';
|
|
5
5
|
|
|
6
6
|
function renderMissingStorefront({
|
|
7
|
-
|
|
8
|
-
storefront
|
|
7
|
+
session,
|
|
8
|
+
storefront,
|
|
9
|
+
cliCommand
|
|
9
10
|
}) {
|
|
10
11
|
renderFatalError({
|
|
11
12
|
name: "NoStorefrontError",
|
|
@@ -15,22 +16,23 @@ function renderMissingStorefront({
|
|
|
15
16
|
)}`.value,
|
|
16
17
|
tryMessage: outputContent`Couldn’t find ${storefront.title} (ID: ${parseGid(
|
|
17
18
|
storefront.id
|
|
18
|
-
)}) on ${
|
|
19
|
-
|
|
19
|
+
)}) on ${session.storeFqdn}. Check that the storefront exists and run ${outputToken.genericShellCommand(
|
|
20
|
+
`${cliCommand} link`
|
|
20
21
|
)} to link this project to it.\n\n${outputToken.link(
|
|
21
22
|
"Hydrogen Storefronts Admin",
|
|
22
|
-
hydrogenStorefrontsUrl(
|
|
23
|
+
hydrogenStorefrontsUrl(session)
|
|
23
24
|
)}`.value
|
|
24
25
|
});
|
|
25
26
|
}
|
|
26
|
-
function renderMissingLink({
|
|
27
|
+
function renderMissingLink({ session, cliCommand }) {
|
|
27
28
|
renderFatalError({
|
|
28
29
|
name: "NoLinkedStorefrontError",
|
|
29
30
|
type: 0,
|
|
30
|
-
message: `No linked Hydrogen storefront on ${
|
|
31
|
-
tryMessage:
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
message: `No linked Hydrogen storefront on ${session.storeFqdn}`,
|
|
32
|
+
tryMessage: [
|
|
33
|
+
"To pull environment variables, link this project to a Hydrogen storefront. To select a storefront to link, run",
|
|
34
|
+
{ command: `${cliCommand} link` }
|
|
35
|
+
]
|
|
34
36
|
});
|
|
35
37
|
}
|
|
36
38
|
|