@shopify/cli-hydrogen 5.0.1 → 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 +38 -8
- package/dist/commands/hydrogen/codegen-unstable.js +13 -24
- package/dist/commands/hydrogen/dev.js +61 -41
- 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 +101 -43
- package/dist/commands/hydrogen/link.test.js +108 -74
- 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 +2 -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 +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 +36 -0
- package/dist/lib/graphql/admin/create-storefront.test.js +64 -0
- package/dist/lib/graphql/admin/fetch-job.js +39 -0
- 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 +32 -14
- 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/string.js +7 -0
- package/dist/lib/string.test.js +16 -0
- 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/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 -14
- 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/template-downloader.d.ts +0 -6
- package/dist/lib/transpile-ts.d.ts +0 -16
- 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
|
@@ -1,126 +1,378 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { fileURLToPath } from 'node:url';
|
|
2
|
+
import { vi, describe, beforeEach, it, expect } from 'vitest';
|
|
2
3
|
import { temporaryDirectoryTask } from 'tempy';
|
|
3
4
|
import { runInit } from './init.js';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { exec } from '@shopify/cli-kit/node/system';
|
|
6
|
+
import { mockAndCaptureOutput } from '@shopify/cli-kit/node/testing/output';
|
|
7
|
+
import { readFile, writeFile, isDirectory } from '@shopify/cli-kit/node/fs';
|
|
8
|
+
import { basename, joinPath } from '@shopify/cli-kit/node/path';
|
|
9
|
+
import { checkHydrogenVersion } from '../../lib/check-version.js';
|
|
10
|
+
import { handleProjectLocation } from '../../lib/onboarding/common.js';
|
|
11
|
+
import glob from 'fast-glob';
|
|
12
|
+
import { getSkeletonSourceDir } from '../../lib/build.js';
|
|
13
|
+
import { execAsync } from '../../lib/process.js';
|
|
14
|
+
import { rmdir, symlink } from 'fs-extra';
|
|
7
15
|
|
|
16
|
+
vi.mock("../../lib/template-downloader.js", async () => ({
|
|
17
|
+
getLatestTemplates: () => Promise.resolve({})
|
|
18
|
+
}));
|
|
19
|
+
vi.mock(
|
|
20
|
+
"@shopify/cli-kit/node/node-package-manager",
|
|
21
|
+
async (importOriginal) => {
|
|
22
|
+
const original = await importOriginal();
|
|
23
|
+
return {
|
|
24
|
+
...original,
|
|
25
|
+
installNodeModules: vi.fn(),
|
|
26
|
+
getPackageManager: () => Promise.resolve("npm"),
|
|
27
|
+
packageManagerUsedForCreating: () => Promise.resolve("npm")
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
vi.mock("../../lib/check-version.js");
|
|
32
|
+
const { renderTasksHook } = vi.hoisted(() => {
|
|
33
|
+
return {
|
|
34
|
+
renderTasksHook: vi.fn()
|
|
35
|
+
};
|
|
36
|
+
});
|
|
37
|
+
vi.mock("@shopify/cli-kit/node/ui", async () => {
|
|
38
|
+
const original = await vi.importActual("@shopify/cli-kit/node/ui");
|
|
39
|
+
return {
|
|
40
|
+
...original,
|
|
41
|
+
renderConfirmationPrompt: vi.fn(),
|
|
42
|
+
renderSelectPrompt: vi.fn(),
|
|
43
|
+
renderTextPrompt: vi.fn(),
|
|
44
|
+
renderInfo: vi.fn(),
|
|
45
|
+
renderTasks: vi.fn(async (args) => {
|
|
46
|
+
await original.renderTasks(args);
|
|
47
|
+
renderTasksHook();
|
|
48
|
+
})
|
|
49
|
+
};
|
|
50
|
+
});
|
|
51
|
+
vi.mock("../../lib/onboarding/common.js", async (importOriginal) => {
|
|
52
|
+
const original = await importOriginal();
|
|
53
|
+
return Object.keys(original).reduce((acc, item) => {
|
|
54
|
+
const key = item;
|
|
55
|
+
const value = original[key];
|
|
56
|
+
if (typeof value === "function") {
|
|
57
|
+
acc[key] = vi.fn(value);
|
|
58
|
+
} else {
|
|
59
|
+
acc[key] = value;
|
|
60
|
+
}
|
|
61
|
+
return acc;
|
|
62
|
+
}, {});
|
|
63
|
+
});
|
|
8
64
|
describe("init", () => {
|
|
65
|
+
const outputMock = mockAndCaptureOutput();
|
|
9
66
|
beforeEach(() => {
|
|
10
|
-
vi.
|
|
11
|
-
|
|
12
|
-
vi.mock("../../lib/transpile-ts.js");
|
|
13
|
-
vi.mock("../../lib/template-downloader.js", async () => ({
|
|
14
|
-
getLatestTemplates: () => Promise.resolve({})
|
|
15
|
-
}));
|
|
16
|
-
vi.mock("@shopify/cli-kit/node/node-package-manager");
|
|
17
|
-
vi.mocked(outputContent).mockImplementation(() => ({
|
|
18
|
-
value: ""
|
|
19
|
-
}));
|
|
20
|
-
vi.mock("@shopify/cli-kit/node/ui");
|
|
21
|
-
vi.mock("@shopify/cli-kit/node/fs");
|
|
67
|
+
vi.clearAllMocks();
|
|
68
|
+
outputMock.clear();
|
|
22
69
|
});
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
70
|
+
it("checks Hydrogen version", async () => {
|
|
71
|
+
await temporaryDirectoryTask(async (tmpDir) => {
|
|
72
|
+
const showUpgradeMock = vi.fn((param) => ({
|
|
73
|
+
currentVersion: "1.0.0",
|
|
74
|
+
newVersion: "1.0.1"
|
|
75
|
+
}));
|
|
76
|
+
vi.mocked(checkHydrogenVersion).mockResolvedValueOnce(showUpgradeMock);
|
|
77
|
+
vi.mocked(handleProjectLocation).mockResolvedValueOnce(void 0);
|
|
78
|
+
const project = await runInit({ path: tmpDir, git: false });
|
|
79
|
+
expect(project).toBeFalsy();
|
|
80
|
+
expect(checkHydrogenVersion).toHaveBeenCalledOnce();
|
|
81
|
+
expect(showUpgradeMock).toHaveBeenCalledWith(
|
|
82
|
+
expect.stringContaining("npm create @shopify/hydrogen@latest")
|
|
83
|
+
);
|
|
84
|
+
});
|
|
28
85
|
});
|
|
29
|
-
describe
|
|
30
|
-
{
|
|
31
|
-
flag: "template",
|
|
32
|
-
value: "hello-world",
|
|
33
|
-
condition: { fn: renderSelectPrompt, match: /template/i }
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
flag: "installDeps",
|
|
37
|
-
value: true,
|
|
38
|
-
condition: { fn: renderConfirmationPrompt, match: /install dependencies/i }
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
flag: "language",
|
|
42
|
-
value: "ts",
|
|
43
|
-
condition: { fn: renderSelectPrompt, match: /language/i }
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
flag: "path",
|
|
47
|
-
value: "./my-app",
|
|
48
|
-
condition: { fn: renderTextPrompt, match: /where/i }
|
|
49
|
-
}
|
|
50
|
-
])("flag $flag", ({ flag, value, condition }) => {
|
|
51
|
-
it(`does not prompt the user for ${flag} when a value is passed in options`, async () => {
|
|
86
|
+
describe("local templates", () => {
|
|
87
|
+
it("creates basic projects", async () => {
|
|
52
88
|
await temporaryDirectoryTask(async (tmpDir) => {
|
|
53
|
-
|
|
89
|
+
await runInit({
|
|
54
90
|
path: tmpDir,
|
|
55
|
-
|
|
91
|
+
git: false,
|
|
92
|
+
language: "ts",
|
|
93
|
+
mockShop: true
|
|
94
|
+
});
|
|
95
|
+
const skeletonFiles = await glob("**/*", {
|
|
96
|
+
cwd: getSkeletonSourceDir(),
|
|
97
|
+
ignore: ["**/node_modules/**", "**/dist/**"]
|
|
56
98
|
});
|
|
57
|
-
await
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
99
|
+
const projectFiles = await glob("**/*", { cwd: tmpDir });
|
|
100
|
+
const nonAppFiles = skeletonFiles.filter(
|
|
101
|
+
(item) => !item.startsWith("app/")
|
|
102
|
+
);
|
|
103
|
+
expect(projectFiles).toEqual(expect.arrayContaining(nonAppFiles));
|
|
104
|
+
expect(projectFiles).toContain("app/root.tsx");
|
|
105
|
+
expect(projectFiles).toContain("app/entry.client.tsx");
|
|
106
|
+
expect(projectFiles).toContain("app/entry.server.tsx");
|
|
107
|
+
expect(projectFiles).toContain("app/components/Layout.tsx");
|
|
108
|
+
expect(projectFiles).not.toContain("app/routes/_index.tsx");
|
|
109
|
+
await expect(readFile(`${tmpDir}/server.ts`)).resolves.toEqual(
|
|
110
|
+
await readFile(`${getSkeletonSourceDir()}/server.ts`)
|
|
111
|
+
);
|
|
112
|
+
await expect(readFile(`${tmpDir}/package.json`)).resolves.toMatch(
|
|
113
|
+
`"name": "${basename(tmpDir)}"`
|
|
114
|
+
);
|
|
115
|
+
await expect(readFile(`${tmpDir}/.env`)).resolves.toMatch(
|
|
116
|
+
`PUBLIC_STORE_DOMAIN="mock.shop"`
|
|
117
|
+
);
|
|
118
|
+
const output = outputMock.info();
|
|
119
|
+
expect(output).toMatch("success");
|
|
120
|
+
expect(output).not.toMatch("warning");
|
|
121
|
+
expect(output).toMatch(basename(tmpDir));
|
|
122
|
+
expect(output).not.toMatch("Routes");
|
|
123
|
+
expect(output).toMatch(/Language:\s*TypeScript/);
|
|
124
|
+
expect(output).toMatch("Help");
|
|
125
|
+
expect(output).toMatch("Next steps");
|
|
126
|
+
expect(output).toMatch(
|
|
127
|
+
/Run `cd .*? &&[^\w]*?npm[^\w]*?install[^\w]*?&&[^\w]*?npm[^\w]*?run[^\w]*?dev`/ims
|
|
62
128
|
);
|
|
63
129
|
});
|
|
64
130
|
});
|
|
65
|
-
it(
|
|
131
|
+
it("creates projects with route files", async () => {
|
|
66
132
|
await temporaryDirectoryTask(async (tmpDir) => {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
133
|
+
await runInit({ path: tmpDir, git: false, routes: true, language: "ts" });
|
|
134
|
+
const skeletonFiles = await glob("**/*", {
|
|
135
|
+
cwd: getSkeletonSourceDir(),
|
|
136
|
+
ignore: ["**/node_modules/**", "**/dist/**"]
|
|
70
137
|
});
|
|
71
|
-
await
|
|
72
|
-
expect(
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
})
|
|
138
|
+
const projectFiles = await glob("**/*", { cwd: tmpDir });
|
|
139
|
+
expect(projectFiles).toEqual(expect.arrayContaining(skeletonFiles));
|
|
140
|
+
expect(projectFiles).toContain("app/routes/_index.tsx");
|
|
141
|
+
await expect(readFile(`${tmpDir}/server.ts`)).resolves.toEqual(
|
|
142
|
+
await readFile(`${getSkeletonSourceDir()}/server.ts`)
|
|
76
143
|
);
|
|
144
|
+
const output = outputMock.info();
|
|
145
|
+
expect(output).toMatch("success");
|
|
146
|
+
expect(output).not.toMatch("warning");
|
|
147
|
+
expect(output).toMatch(basename(tmpDir));
|
|
148
|
+
expect(output).toMatch(/Language:\s*TypeScript/);
|
|
149
|
+
expect(output).toMatch("Routes");
|
|
150
|
+
expect(output).toMatch("Home (/ & /:catchAll)");
|
|
151
|
+
expect(output).toMatch("Account (/account/*)");
|
|
77
152
|
});
|
|
78
153
|
});
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
154
|
+
it("transpiles projects to JS", async () => {
|
|
155
|
+
await temporaryDirectoryTask(async (tmpDir) => {
|
|
156
|
+
await runInit({ path: tmpDir, git: false, routes: true, language: "js" });
|
|
157
|
+
const skeletonFiles = await glob("**/*", {
|
|
158
|
+
cwd: getSkeletonSourceDir(),
|
|
159
|
+
ignore: ["**/node_modules/**", "**/dist/**"]
|
|
160
|
+
});
|
|
161
|
+
const projectFiles = await glob("**/*", { cwd: tmpDir });
|
|
162
|
+
expect(projectFiles).toEqual(
|
|
163
|
+
expect.arrayContaining(
|
|
164
|
+
skeletonFiles.filter((item) => !item.endsWith(".d.ts")).map(
|
|
165
|
+
(item) => item.replace(/\.ts(x)?$/, ".js$1").replace(/tsconfig\.json$/, "jsconfig.json")
|
|
166
|
+
)
|
|
167
|
+
)
|
|
168
|
+
);
|
|
169
|
+
expect(projectFiles).toContain("app/routes/_index.jsx");
|
|
170
|
+
await expect(readFile(`${tmpDir}/server.js`)).resolves.toMatch(
|
|
171
|
+
/export default {\n\s+async fetch\(\s*request,\s*env,\s*executionContext,?\s*\)/
|
|
172
|
+
);
|
|
173
|
+
const output = outputMock.info();
|
|
174
|
+
expect(output).toMatch("success");
|
|
175
|
+
expect(output).not.toMatch("warning");
|
|
176
|
+
expect(output).toMatch(basename(tmpDir));
|
|
177
|
+
expect(output).toMatch(/Language:\s*JavaScript/);
|
|
178
|
+
expect(output).toMatch("Routes");
|
|
179
|
+
expect(output).toMatch("Home (/ & /:catchAll)");
|
|
180
|
+
expect(output).toMatch("Account (/account/*)");
|
|
181
|
+
});
|
|
85
182
|
});
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
183
|
+
describe("styling libraries", () => {
|
|
184
|
+
it("scaffolds Tailwind CSS", async () => {
|
|
185
|
+
await temporaryDirectoryTask(async (tmpDir) => {
|
|
186
|
+
await runInit({
|
|
187
|
+
path: tmpDir,
|
|
188
|
+
git: false,
|
|
189
|
+
language: "ts",
|
|
190
|
+
styling: "tailwind"
|
|
191
|
+
});
|
|
192
|
+
await expect(readFile(`${tmpDir}/remix.config.js`)).resolves.toMatch(
|
|
193
|
+
/tailwind: true,\n\s*postcss: true,\n\s*future:/
|
|
194
|
+
);
|
|
195
|
+
await expect(
|
|
196
|
+
readFile(`${tmpDir}/app/styles/tailwind.css`)
|
|
197
|
+
).resolves.toMatch(/@tailwind base;/);
|
|
198
|
+
const rootFile = await readFile(`${tmpDir}/app/root.tsx`);
|
|
199
|
+
await expect(rootFile).toMatch(/import tailwindCss from/);
|
|
200
|
+
await expect(rootFile).toMatch(
|
|
201
|
+
/export function links\(\) \{.*?return \[.*\{rel: 'stylesheet', href: tailwindCss\}/ims
|
|
202
|
+
);
|
|
203
|
+
const output = outputMock.info();
|
|
204
|
+
expect(output).toMatch("success");
|
|
205
|
+
expect(output).not.toMatch("warning");
|
|
206
|
+
expect(output).toMatch(/Styling:\s*Tailwind/);
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
it("scaffolds CSS Modules", async () => {
|
|
210
|
+
await temporaryDirectoryTask(async (tmpDir) => {
|
|
211
|
+
await runInit({
|
|
212
|
+
path: tmpDir,
|
|
213
|
+
git: false,
|
|
214
|
+
language: "ts",
|
|
215
|
+
styling: "css-modules"
|
|
216
|
+
});
|
|
217
|
+
await expect(readFile(`${tmpDir}/package.json`)).resolves.toMatch(
|
|
218
|
+
`"@remix-run/css-bundle": "`
|
|
219
|
+
);
|
|
220
|
+
const rootFile = await readFile(`${tmpDir}/app/root.tsx`);
|
|
221
|
+
await expect(rootFile).toMatch(/import {cssBundleHref} from/);
|
|
222
|
+
await expect(rootFile).toMatch(
|
|
223
|
+
/export function links\(\) \{.*?return \[.*\{rel: 'stylesheet', href: cssBundleHref\}/ims
|
|
224
|
+
);
|
|
225
|
+
const output = outputMock.info();
|
|
226
|
+
expect(output).toMatch("success");
|
|
227
|
+
expect(output).not.toMatch("warning");
|
|
228
|
+
expect(output).toMatch(/Styling:\s*CSS Modules/);
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
it("scaffolds Vanilla Extract", async () => {
|
|
232
|
+
await temporaryDirectoryTask(async (tmpDir) => {
|
|
233
|
+
await runInit({
|
|
234
|
+
path: tmpDir,
|
|
235
|
+
git: false,
|
|
236
|
+
language: "ts",
|
|
237
|
+
styling: "vanilla-extract"
|
|
238
|
+
});
|
|
239
|
+
const packageJson = await readFile(`${tmpDir}/package.json`);
|
|
240
|
+
expect(packageJson).toMatch(/"@remix-run\/css-bundle": "/);
|
|
241
|
+
expect(packageJson).toMatch(/"@vanilla-extract\/css": "/);
|
|
242
|
+
const rootFile = await readFile(`${tmpDir}/app/root.tsx`);
|
|
243
|
+
await expect(rootFile).toMatch(/import {cssBundleHref} from/);
|
|
244
|
+
await expect(rootFile).toMatch(
|
|
245
|
+
/export function links\(\) \{.*?return \[.*\{rel: 'stylesheet', href: cssBundleHref\}/ims
|
|
246
|
+
);
|
|
247
|
+
const output = outputMock.info();
|
|
248
|
+
expect(output).toMatch("success");
|
|
249
|
+
expect(output).not.toMatch("warning");
|
|
250
|
+
expect(output).toMatch(/Styling:\s*Vanilla Extract/);
|
|
251
|
+
});
|
|
252
|
+
});
|
|
92
253
|
});
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
254
|
+
describe("i18n strategies", () => {
|
|
255
|
+
it("scaffolds i18n with domains strategy", async () => {
|
|
256
|
+
await temporaryDirectoryTask(async (tmpDir) => {
|
|
257
|
+
await runInit({
|
|
258
|
+
path: tmpDir,
|
|
259
|
+
git: false,
|
|
260
|
+
language: "ts",
|
|
261
|
+
i18n: "domains",
|
|
262
|
+
routes: true
|
|
263
|
+
});
|
|
264
|
+
const projectFiles = await glob("**/*", { cwd: tmpDir });
|
|
265
|
+
expect(projectFiles).toContain("app/routes/_index.tsx");
|
|
266
|
+
const serverFile = await readFile(`${tmpDir}/server.ts`);
|
|
267
|
+
expect(serverFile).toMatch(/i18n: getLocaleFromRequest\(request\),/);
|
|
268
|
+
expect(serverFile).toMatch(/domain = url.hostname/);
|
|
269
|
+
const output = outputMock.info();
|
|
270
|
+
expect(output).toMatch("success");
|
|
271
|
+
expect(output).not.toMatch("warning");
|
|
272
|
+
expect(output).toMatch(/Markets:\s*Top-level domains/);
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
it("scaffolds i18n with subdomains strategy", async () => {
|
|
276
|
+
await temporaryDirectoryTask(async (tmpDir) => {
|
|
277
|
+
await runInit({
|
|
278
|
+
path: tmpDir,
|
|
279
|
+
git: false,
|
|
280
|
+
language: "ts",
|
|
281
|
+
i18n: "subdomains",
|
|
282
|
+
routes: true
|
|
283
|
+
});
|
|
284
|
+
const projectFiles = await glob("**/*", { cwd: tmpDir });
|
|
285
|
+
expect(projectFiles).toContain("app/routes/_index.tsx");
|
|
286
|
+
const serverFile = await readFile(`${tmpDir}/server.ts`);
|
|
287
|
+
expect(serverFile).toMatch(/i18n: getLocaleFromRequest\(request\),/);
|
|
288
|
+
expect(serverFile).toMatch(/firstSubdomain = url.hostname/);
|
|
289
|
+
const output = outputMock.info();
|
|
290
|
+
expect(output).toMatch("success");
|
|
291
|
+
expect(output).not.toMatch("warning");
|
|
292
|
+
expect(output).toMatch(/Markets:\s*Subdomains/);
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
it("scaffolds i18n with subfolders strategy", async () => {
|
|
296
|
+
await temporaryDirectoryTask(async (tmpDir) => {
|
|
297
|
+
await runInit({
|
|
298
|
+
path: tmpDir,
|
|
299
|
+
git: false,
|
|
300
|
+
language: "ts",
|
|
301
|
+
i18n: "subfolders",
|
|
302
|
+
routes: true
|
|
303
|
+
});
|
|
304
|
+
const projectFiles = await glob("**/*", { cwd: tmpDir });
|
|
305
|
+
expect(projectFiles).toContain("app/routes/($locale)._index.tsx");
|
|
306
|
+
const serverFile = await readFile(`${tmpDir}/server.ts`);
|
|
307
|
+
expect(serverFile).toMatch(/i18n: getLocaleFromRequest\(request\),/);
|
|
308
|
+
expect(serverFile).toMatch(/url.pathname/);
|
|
309
|
+
const output = outputMock.info();
|
|
310
|
+
expect(output).toMatch("success");
|
|
311
|
+
expect(output).not.toMatch("warning");
|
|
312
|
+
expect(output).toMatch(/Markets:\s*Subfolders/);
|
|
313
|
+
});
|
|
100
314
|
});
|
|
101
|
-
await runInit(options);
|
|
102
|
-
expect(renderInfo).toHaveBeenCalledTimes(1);
|
|
103
|
-
expect(renderInfo).toHaveBeenCalledWith(
|
|
104
|
-
expect.objectContaining({
|
|
105
|
-
body: expect.stringContaining(
|
|
106
|
-
"To connect this project to your Shopify store\u2019s inventory"
|
|
107
|
-
),
|
|
108
|
-
headline: expect.stringContaining(
|
|
109
|
-
"Your project will display inventory from the Hydrogen Demo Store"
|
|
110
|
-
)
|
|
111
|
-
})
|
|
112
|
-
);
|
|
113
315
|
});
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
316
|
+
describe("git", () => {
|
|
317
|
+
it("initializes a git repository and creates initial commits", async () => {
|
|
318
|
+
await temporaryDirectoryTask(async (tmpDir) => {
|
|
319
|
+
renderTasksHook.mockImplementationOnce(async () => {
|
|
320
|
+
await writeFile(`${tmpDir}/package-lock.json`, "{}");
|
|
321
|
+
});
|
|
322
|
+
await runInit({
|
|
323
|
+
path: tmpDir,
|
|
324
|
+
git: true,
|
|
325
|
+
language: "js",
|
|
326
|
+
styling: "tailwind",
|
|
327
|
+
i18n: "domains",
|
|
328
|
+
routes: true,
|
|
329
|
+
installDeps: true
|
|
330
|
+
});
|
|
331
|
+
expect(isDirectory(`${tmpDir}/.git`)).resolves.toBeTruthy();
|
|
332
|
+
const { stdout: gitLog } = await execAsync(`git log --oneline`, {
|
|
333
|
+
cwd: tmpDir
|
|
334
|
+
});
|
|
335
|
+
expect(gitLog.split("\n")).toEqual(
|
|
336
|
+
expect.arrayContaining([
|
|
337
|
+
expect.stringContaining("Lockfile"),
|
|
338
|
+
expect.stringContaining("Generate routes for core functionality"),
|
|
339
|
+
expect.stringContaining("Setup Tailwind"),
|
|
340
|
+
expect.stringContaining("Scaffold Storefront")
|
|
341
|
+
])
|
|
342
|
+
);
|
|
343
|
+
});
|
|
344
|
+
});
|
|
345
|
+
});
|
|
346
|
+
describe("project validity", () => {
|
|
347
|
+
it("typechecks the project", async () => {
|
|
348
|
+
await temporaryDirectoryTask(async (tmpDir) => {
|
|
349
|
+
renderTasksHook.mockImplementationOnce(async () => {
|
|
350
|
+
await writeFile(`${tmpDir}/package-lock.json`, "{}");
|
|
351
|
+
});
|
|
352
|
+
await runInit({
|
|
353
|
+
path: tmpDir,
|
|
354
|
+
git: true,
|
|
355
|
+
language: "ts",
|
|
356
|
+
styling: "tailwind",
|
|
357
|
+
i18n: "subfolders",
|
|
358
|
+
routes: true,
|
|
359
|
+
installDeps: true
|
|
360
|
+
});
|
|
361
|
+
await rmdir(joinPath(tmpDir, "node_modules")).catch(() => {
|
|
362
|
+
});
|
|
363
|
+
await symlink(
|
|
364
|
+
fileURLToPath(
|
|
365
|
+
new URL("../../../../../node_modules", import.meta.url)
|
|
366
|
+
),
|
|
367
|
+
joinPath(tmpDir, "node_modules")
|
|
368
|
+
);
|
|
369
|
+
await expect(
|
|
370
|
+
exec("npm", ["run", "typecheck"], {
|
|
371
|
+
cwd: tmpDir
|
|
372
|
+
})
|
|
373
|
+
).resolves.not.toThrow();
|
|
374
|
+
});
|
|
121
375
|
});
|
|
122
|
-
await runInit(options);
|
|
123
|
-
expect(renderInfo).toHaveBeenCalledTimes(0);
|
|
124
376
|
});
|
|
125
377
|
});
|
|
126
378
|
});
|
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
import { Flags } from '@oclif/core';
|
|
2
2
|
import Command from '@shopify/cli-kit/node/base-command';
|
|
3
|
-
import {
|
|
3
|
+
import { basename } from '@shopify/cli-kit/node/path';
|
|
4
|
+
import { renderSuccess, renderConfirmationPrompt, renderWarning, renderSelectPrompt, renderTextPrompt, renderTasks } from '@shopify/cli-kit/node/ui';
|
|
5
|
+
import { AbortError } from '@shopify/cli-kit/node/error';
|
|
4
6
|
import { commonFlags } from '../../lib/flags.js';
|
|
5
|
-
import { getHydrogenShop } from '../../lib/shop.js';
|
|
6
7
|
import { getStorefronts } from '../../lib/graphql/admin/link-storefront.js';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
8
|
+
import { setStorefront } from '../../lib/shopify-config.js';
|
|
9
|
+
import { createStorefront } from '../../lib/graphql/admin/create-storefront.js';
|
|
10
|
+
import { waitForJob } from '../../lib/graphql/admin/fetch-job.js';
|
|
11
|
+
import { titleize } from '../../lib/string.js';
|
|
9
12
|
import { getCliCommand } from '../../lib/shell.js';
|
|
13
|
+
import { login } from '../../lib/auth.js';
|
|
10
14
|
|
|
11
15
|
class Link extends Command {
|
|
12
16
|
static description = "Link a local project to one of your shop's Hydrogen storefronts.";
|
|
13
17
|
static flags = {
|
|
14
18
|
force: commonFlags.force,
|
|
15
19
|
path: commonFlags.path,
|
|
16
|
-
shop: commonFlags.shop,
|
|
17
20
|
storefront: Flags.string({
|
|
18
21
|
description: `The name of a Hydrogen Storefront (e.g. "Jane's Apparel")`,
|
|
19
22
|
env: "SHOPIFY_HYDROGEN_STOREFRONT"
|
|
@@ -21,33 +24,54 @@ class Link extends Command {
|
|
|
21
24
|
};
|
|
22
25
|
async run() {
|
|
23
26
|
const { flags } = await this.parse(Link);
|
|
24
|
-
await
|
|
27
|
+
await runLink(flags);
|
|
25
28
|
}
|
|
26
29
|
}
|
|
27
|
-
async function
|
|
30
|
+
async function runLink({
|
|
28
31
|
force,
|
|
29
|
-
path,
|
|
30
|
-
|
|
31
|
-
storefront: flagStorefront,
|
|
32
|
-
silent = false
|
|
32
|
+
path: root = process.cwd(),
|
|
33
|
+
storefront: flagStorefront
|
|
33
34
|
}) {
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
const [{ session, config }, cliCommand] = await Promise.all([
|
|
36
|
+
login(root),
|
|
37
|
+
getCliCommand()
|
|
38
|
+
]);
|
|
39
|
+
const linkedStore = await linkStorefront(root, session, config, {
|
|
40
|
+
force,
|
|
41
|
+
flagStorefront,
|
|
42
|
+
cliCommand
|
|
43
|
+
});
|
|
44
|
+
if (!linkedStore)
|
|
45
|
+
return;
|
|
46
|
+
renderSuccess({
|
|
47
|
+
body: [{ userInput: linkedStore.title }, "is now linked"],
|
|
48
|
+
nextSteps: [
|
|
49
|
+
[
|
|
50
|
+
"Run",
|
|
51
|
+
{ command: `${cliCommand} dev` },
|
|
52
|
+
"to start your local development server and start building"
|
|
53
|
+
]
|
|
54
|
+
]
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
async function linkStorefront(root, session, config, {
|
|
58
|
+
force = false,
|
|
59
|
+
flagStorefront,
|
|
60
|
+
cliCommand
|
|
61
|
+
}) {
|
|
62
|
+
if (!config.shop) {
|
|
63
|
+
throw new AbortError("No shop found in local config, login first.");
|
|
64
|
+
}
|
|
65
|
+
if (config.storefront?.id && !force) {
|
|
37
66
|
const overwriteLink = await renderConfirmationPrompt({
|
|
38
|
-
message: `Your project is currently linked to ${
|
|
67
|
+
message: `Your project is currently linked to ${config.storefront.title}. Do you want to link to a different Hydrogen storefront on Shopify?`
|
|
39
68
|
});
|
|
40
69
|
if (!overwriteLink) {
|
|
41
70
|
return;
|
|
42
71
|
}
|
|
43
72
|
}
|
|
44
|
-
const
|
|
45
|
-
if (storefronts.length === 0) {
|
|
46
|
-
logMissingStorefronts(adminSession);
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
73
|
+
const storefronts = await getStorefronts(session);
|
|
49
74
|
let selectedStorefront;
|
|
50
|
-
const cliCommand = await getCliCommand();
|
|
51
75
|
if (flagStorefront) {
|
|
52
76
|
selectedStorefront = storefronts.find(
|
|
53
77
|
({ title }) => title === flagStorefront
|
|
@@ -59,7 +83,7 @@ async function linkStorefront({
|
|
|
59
83
|
"There's no storefront matching",
|
|
60
84
|
{ userInput: flagStorefront },
|
|
61
85
|
"on your",
|
|
62
|
-
{ userInput: shop },
|
|
86
|
+
{ userInput: config.shop },
|
|
63
87
|
"shop. To see all available Hydrogen storefronts, run",
|
|
64
88
|
{
|
|
65
89
|
command: `${cliCommand} list`
|
|
@@ -69,32 +93,66 @@ async function linkStorefront({
|
|
|
69
93
|
return;
|
|
70
94
|
}
|
|
71
95
|
} else {
|
|
72
|
-
const choices =
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
96
|
+
const choices = [
|
|
97
|
+
{
|
|
98
|
+
label: "Create a new storefront",
|
|
99
|
+
value: null
|
|
100
|
+
},
|
|
101
|
+
...storefronts.map(({ id, title, productionUrl }) => ({
|
|
102
|
+
label: `${title} (${productionUrl})`,
|
|
103
|
+
value: id
|
|
104
|
+
}))
|
|
105
|
+
];
|
|
76
106
|
const storefrontId = await renderSelectPrompt({
|
|
77
|
-
message: "
|
|
107
|
+
message: "Select a Hydrogen storefront to link",
|
|
78
108
|
choices
|
|
79
109
|
});
|
|
80
|
-
|
|
110
|
+
if (storefrontId) {
|
|
111
|
+
selectedStorefront = storefronts.find(({ id }) => id === storefrontId);
|
|
112
|
+
} else {
|
|
113
|
+
selectedStorefront = await createNewStorefront(root, session);
|
|
114
|
+
}
|
|
81
115
|
}
|
|
82
|
-
if (
|
|
83
|
-
|
|
116
|
+
if (selectedStorefront) {
|
|
117
|
+
await setStorefront(root, selectedStorefront);
|
|
84
118
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
119
|
+
return selectedStorefront;
|
|
120
|
+
}
|
|
121
|
+
async function createNewStorefront(root, session) {
|
|
122
|
+
const projectDirectory = basename(root);
|
|
123
|
+
const projectName = await renderTextPrompt({
|
|
124
|
+
message: "New storefront name",
|
|
125
|
+
defaultValue: titleize(projectDirectory)
|
|
126
|
+
});
|
|
127
|
+
let storefront;
|
|
128
|
+
let jobId;
|
|
129
|
+
await renderTasks([
|
|
130
|
+
{
|
|
131
|
+
title: "Creating storefront",
|
|
132
|
+
task: async () => {
|
|
133
|
+
const result = await createStorefront(session, projectName);
|
|
134
|
+
storefront = result.storefront;
|
|
135
|
+
jobId = result.jobId;
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
title: "Creating API tokens",
|
|
140
|
+
task: async () => {
|
|
141
|
+
try {
|
|
142
|
+
await waitForJob(session, jobId);
|
|
143
|
+
} catch (_err) {
|
|
144
|
+
storefront = void 0;
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
skip: () => !jobId
|
|
148
|
+
}
|
|
149
|
+
]);
|
|
150
|
+
if (!storefront) {
|
|
151
|
+
throw new AbortError(
|
|
152
|
+
"Unknown error ocurred. Please try again or contact support if the error persists."
|
|
153
|
+
);
|
|
97
154
|
}
|
|
155
|
+
return storefront;
|
|
98
156
|
}
|
|
99
157
|
|
|
100
|
-
export { Link as default, linkStorefront };
|
|
158
|
+
export { Link as default, linkStorefront, runLink };
|