@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
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { vi, describe, beforeEach, afterEach, it, expect } from 'vitest';
|
|
2
|
+
import { inTemporaryDirectory, writeFile } from '@shopify/cli-kit/node/fs';
|
|
3
|
+
import { joinPath } from '@shopify/cli-kit/node/path';
|
|
4
|
+
import { mockAndCaptureOutput } from '@shopify/cli-kit/node/testing/output';
|
|
5
|
+
import { getAllEnvironmentVariables } from './environment-variables.js';
|
|
6
|
+
import { getStorefrontEnvVariables } from './graphql/admin/pull-variables.js';
|
|
7
|
+
import { login } from './auth.js';
|
|
8
|
+
|
|
9
|
+
vi.mock("./auth.js");
|
|
10
|
+
vi.mock("./graphql/admin/pull-variables.js");
|
|
11
|
+
describe("getAllEnvironmentVariables()", () => {
|
|
12
|
+
const ADMIN_SESSION = {
|
|
13
|
+
token: "abc123",
|
|
14
|
+
storeFqdn: "my-shop"
|
|
15
|
+
};
|
|
16
|
+
const SHOPIFY_CONFIG = {
|
|
17
|
+
shop: "my-shop",
|
|
18
|
+
shopName: "My Shop",
|
|
19
|
+
email: "email",
|
|
20
|
+
storefront: {
|
|
21
|
+
id: "gid://shopify/HydrogenStorefront/1",
|
|
22
|
+
title: "Hydrogen"
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
vi.mocked(login).mockResolvedValue({
|
|
27
|
+
session: ADMIN_SESSION,
|
|
28
|
+
config: SHOPIFY_CONFIG
|
|
29
|
+
});
|
|
30
|
+
vi.mocked(getStorefrontEnvVariables).mockResolvedValue({
|
|
31
|
+
id: SHOPIFY_CONFIG.storefront.id,
|
|
32
|
+
environmentVariables: [
|
|
33
|
+
{
|
|
34
|
+
id: "gid://shopify/HydrogenStorefrontEnvironmentVariable/1",
|
|
35
|
+
key: "PUBLIC_API_TOKEN",
|
|
36
|
+
value: "abc123",
|
|
37
|
+
isSecret: false
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
afterEach(() => {
|
|
43
|
+
vi.resetAllMocks();
|
|
44
|
+
mockAndCaptureOutput().clear();
|
|
45
|
+
});
|
|
46
|
+
it("calls pullRemoteEnvironmentVariables", async () => {
|
|
47
|
+
await inTemporaryDirectory(async (tmpDir) => {
|
|
48
|
+
await getAllEnvironmentVariables({
|
|
49
|
+
envBranch: "main",
|
|
50
|
+
root: tmpDir
|
|
51
|
+
});
|
|
52
|
+
expect(getStorefrontEnvVariables).toHaveBeenCalledWith(
|
|
53
|
+
ADMIN_SESSION,
|
|
54
|
+
SHOPIFY_CONFIG.storefront.id,
|
|
55
|
+
"main"
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
it("does not call pullRemoteEnvironmentVariables when indicated", async () => {
|
|
60
|
+
await inTemporaryDirectory(async (tmpDir) => {
|
|
61
|
+
await getAllEnvironmentVariables({
|
|
62
|
+
envBranch: "main",
|
|
63
|
+
root: tmpDir,
|
|
64
|
+
fetchRemote: false
|
|
65
|
+
});
|
|
66
|
+
expect(getStorefrontEnvVariables).not.toHaveBeenCalled();
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
it("renders a message about injection", async () => {
|
|
70
|
+
await inTemporaryDirectory(async (tmpDir) => {
|
|
71
|
+
const outputMock = mockAndCaptureOutput();
|
|
72
|
+
await getAllEnvironmentVariables({ root: tmpDir });
|
|
73
|
+
expect(outputMock.info()).toMatch(
|
|
74
|
+
/Environment variables injected into MiniOxygen:/
|
|
75
|
+
);
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
it("lists all of the variables being used", async () => {
|
|
79
|
+
await inTemporaryDirectory(async (tmpDir) => {
|
|
80
|
+
const outputMock = mockAndCaptureOutput();
|
|
81
|
+
await getAllEnvironmentVariables({ root: tmpDir });
|
|
82
|
+
expect(outputMock.info()).toMatch(/PUBLIC_API_TOKEN\s+from Oxygen/);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
it("doest not fail on network errors", async () => {
|
|
86
|
+
await inTemporaryDirectory(async (tmpDir) => {
|
|
87
|
+
vi.mocked(getStorefrontEnvVariables).mockRejectedValue(
|
|
88
|
+
new Error("Network error")
|
|
89
|
+
);
|
|
90
|
+
const outputMock = mockAndCaptureOutput();
|
|
91
|
+
await getAllEnvironmentVariables({ root: tmpDir });
|
|
92
|
+
expect(outputMock.info()).not.toMatch(/PUBLIC_API_TOKEN\s+from Oxygen/);
|
|
93
|
+
expect(outputMock.warn()).toMatch(/failed to load/i);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
describe("when one of the variables is a secret", () => {
|
|
97
|
+
beforeEach(() => {
|
|
98
|
+
vi.mocked(getStorefrontEnvVariables).mockResolvedValue({
|
|
99
|
+
id: SHOPIFY_CONFIG.storefront.id,
|
|
100
|
+
environmentVariables: [
|
|
101
|
+
{
|
|
102
|
+
id: "gid://shopify/HydrogenStorefrontEnvironmentVariable/1",
|
|
103
|
+
key: "PUBLIC_API_TOKEN",
|
|
104
|
+
value: "",
|
|
105
|
+
isSecret: true
|
|
106
|
+
}
|
|
107
|
+
]
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
it("uses special messaging to alert the user", async () => {
|
|
111
|
+
await inTemporaryDirectory(async (tmpDir) => {
|
|
112
|
+
const outputMock = mockAndCaptureOutput();
|
|
113
|
+
await getAllEnvironmentVariables({ root: tmpDir });
|
|
114
|
+
expect(outputMock.info()).toMatch(
|
|
115
|
+
/PUBLIC_API_TOKEN\s+from Oxygen \(Marked as secret\)/
|
|
116
|
+
);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
describe("when there are local variables", () => {
|
|
121
|
+
it("includes local variables in the list", async () => {
|
|
122
|
+
await inTemporaryDirectory(async (tmpDir) => {
|
|
123
|
+
const filePath = joinPath(tmpDir, ".env");
|
|
124
|
+
await writeFile(filePath, "LOCAL_TOKEN=1");
|
|
125
|
+
const outputMock = mockAndCaptureOutput();
|
|
126
|
+
await getAllEnvironmentVariables({ root: tmpDir });
|
|
127
|
+
expect(outputMock.info()).toMatch(/LOCAL_TOKEN\s+from local \.env/);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
describe("and they overwrite remote variables", () => {
|
|
131
|
+
it("uses special messaging to alert the user", async () => {
|
|
132
|
+
await inTemporaryDirectory(async (tmpDir) => {
|
|
133
|
+
const filePath = joinPath(tmpDir, ".env");
|
|
134
|
+
await writeFile(filePath, "PUBLIC_API_TOKEN=abc");
|
|
135
|
+
const outputMock = mockAndCaptureOutput();
|
|
136
|
+
await getAllEnvironmentVariables({ root: tmpDir });
|
|
137
|
+
expect(outputMock.info()).not.toMatch(
|
|
138
|
+
/PUBLIC_API_TOKEN\s+from Oxygen/
|
|
139
|
+
);
|
|
140
|
+
expect(outputMock.info()).toMatch(
|
|
141
|
+
/PUBLIC_API_TOKEN\s+from local \.env/
|
|
142
|
+
);
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
});
|
package/dist/lib/file.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { resolvePath } from '@shopify/cli-kit/node/path';
|
|
2
|
+
import { readFile, writeFile, isDirectory, fileExists } from '@shopify/cli-kit/node/fs';
|
|
3
|
+
import { readdir } from 'fs/promises';
|
|
4
|
+
import { formatCode } from './format-code.js';
|
|
5
|
+
|
|
6
|
+
async function replaceFileContent(filepath, formatConfig, replacer) {
|
|
7
|
+
let content = await replacer(await readFile(filepath));
|
|
8
|
+
if (typeof content !== "string")
|
|
9
|
+
return;
|
|
10
|
+
if (formatConfig) {
|
|
11
|
+
content = formatCode(content, formatConfig, filepath);
|
|
12
|
+
}
|
|
13
|
+
return writeFile(filepath, content);
|
|
14
|
+
}
|
|
15
|
+
const DEFAULT_EXTENSIONS = ["tsx", "ts", "jsx", "js", "mjs", "cjs"];
|
|
16
|
+
async function findFileWithExtension(directory, fileBase, extensions = DEFAULT_EXTENSIONS) {
|
|
17
|
+
const dirFiles = await readdir(directory);
|
|
18
|
+
if (dirFiles.includes(fileBase)) {
|
|
19
|
+
const filepath = resolvePath(directory, fileBase);
|
|
20
|
+
if (!await isDirectory(filepath)) {
|
|
21
|
+
return { filepath };
|
|
22
|
+
}
|
|
23
|
+
for (const extension of ["ts", "js"]) {
|
|
24
|
+
const filepath2 = resolvePath(directory, `${fileBase}/index.${extension}`);
|
|
25
|
+
if (await fileExists(resolvePath(directory, filepath2))) {
|
|
26
|
+
return { filepath: filepath2, extension, astType: extension };
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
} else {
|
|
30
|
+
for (const extension of extensions) {
|
|
31
|
+
const filename = `${fileBase}.${extension}`;
|
|
32
|
+
if (dirFiles.includes(filename)) {
|
|
33
|
+
const astType = extension === "mjs" || extension === "cjs" ? "js" : extension;
|
|
34
|
+
return { filepath: resolvePath(directory, filename), extension, astType };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return {};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export { findFileWithExtension, replaceFileContent };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { temporaryDirectoryTask } from 'tempy';
|
|
2
|
+
import { describe, it, expect } from 'vitest';
|
|
3
|
+
import { replaceFileContent, findFileWithExtension } from './file.js';
|
|
4
|
+
import { resolvePath } from '@shopify/cli-kit/node/path';
|
|
5
|
+
import { writeFile, readFile, mkdir } from '@shopify/cli-kit/node/fs';
|
|
6
|
+
|
|
7
|
+
describe("File utils", () => {
|
|
8
|
+
describe("replaceFileContent", () => {
|
|
9
|
+
it("replaces the content of a file and formats it", async () => {
|
|
10
|
+
await temporaryDirectoryTask(async (tmpDir) => {
|
|
11
|
+
const filepath = resolvePath(tmpDir, "index.js");
|
|
12
|
+
await writeFile(
|
|
13
|
+
filepath,
|
|
14
|
+
'function foo() { console.log("foo"); return null}'
|
|
15
|
+
);
|
|
16
|
+
await replaceFileContent(filepath, {}, async (content) => {
|
|
17
|
+
return content.replaceAll("foo", "bar");
|
|
18
|
+
});
|
|
19
|
+
expect(await readFile(filepath)).toBe(
|
|
20
|
+
'function bar() {\n console.log("bar");\n return null;\n}\n'
|
|
21
|
+
);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
describe("findFileWithExtension", () => {
|
|
26
|
+
it("ignores missing files", async () => {
|
|
27
|
+
await temporaryDirectoryTask(async (tmpDir) => {
|
|
28
|
+
expect(findFileWithExtension(tmpDir, "nope")).resolves.toEqual({
|
|
29
|
+
filepath: void 0,
|
|
30
|
+
extension: void 0,
|
|
31
|
+
astType: void 0
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
it("finds the file with its corresponding extension and astType", async () => {
|
|
36
|
+
await temporaryDirectoryTask(async (tmpDir) => {
|
|
37
|
+
await writeFile(resolvePath(tmpDir, "first.js"), "content");
|
|
38
|
+
await writeFile(resolvePath(tmpDir, "second.tsx"), "content");
|
|
39
|
+
await writeFile(resolvePath(tmpDir, "third.mjs"), "content");
|
|
40
|
+
await writeFile(resolvePath(tmpDir, "fourth"), "content");
|
|
41
|
+
await mkdir(resolvePath(tmpDir, "fifth"));
|
|
42
|
+
await writeFile(resolvePath(tmpDir, "fifth", "index.ts"), "content");
|
|
43
|
+
expect(findFileWithExtension(tmpDir, "first")).resolves.toEqual({
|
|
44
|
+
filepath: expect.stringMatching(/first\.js$/),
|
|
45
|
+
extension: "js",
|
|
46
|
+
astType: "js"
|
|
47
|
+
});
|
|
48
|
+
expect(findFileWithExtension(tmpDir, "second")).resolves.toEqual({
|
|
49
|
+
filepath: expect.stringMatching(/second\.tsx$/),
|
|
50
|
+
extension: "tsx",
|
|
51
|
+
astType: "tsx"
|
|
52
|
+
});
|
|
53
|
+
expect(findFileWithExtension(tmpDir, "third")).resolves.toEqual({
|
|
54
|
+
filepath: expect.stringMatching(/third\.mjs$/),
|
|
55
|
+
extension: "mjs",
|
|
56
|
+
astType: "js"
|
|
57
|
+
});
|
|
58
|
+
expect(findFileWithExtension(tmpDir, "fourth")).resolves.toEqual({
|
|
59
|
+
filepath: expect.stringMatching(/fourth$/)
|
|
60
|
+
});
|
|
61
|
+
expect(findFileWithExtension(tmpDir, "fifth")).resolves.toEqual({
|
|
62
|
+
filepath: expect.stringMatching(/fifth\/index\.ts$/),
|
|
63
|
+
extension: "ts",
|
|
64
|
+
astType: "ts"
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
});
|
package/dist/lib/flags.js
CHANGED
|
@@ -3,6 +3,8 @@ import { camelize } from '@shopify/cli-kit/common/string';
|
|
|
3
3
|
import { renderInfo } from '@shopify/cli-kit/node/ui';
|
|
4
4
|
import { normalizeStoreFqdn } from '@shopify/cli-kit/node/context/fqdn';
|
|
5
5
|
import colors from '@shopify/cli-kit/node/colors';
|
|
6
|
+
import { SETUP_CSS_STRATEGIES } from './setups/css/index.js';
|
|
7
|
+
import { I18N_CHOICES } from './setups/i18n/index.js';
|
|
6
8
|
|
|
7
9
|
const commonFlags = {
|
|
8
10
|
path: Flags.string({
|
|
@@ -25,7 +27,12 @@ const commonFlags = {
|
|
|
25
27
|
env: "SHOPIFY_SHOP",
|
|
26
28
|
parse: async (input) => normalizeStoreFqdn(input)
|
|
27
29
|
}),
|
|
28
|
-
|
|
30
|
+
installDeps: Flags.boolean({
|
|
31
|
+
description: "Auto install dependencies using the active package manager",
|
|
32
|
+
env: "SHOPIFY_HYDROGEN_FLAG_INSTALL_DEPS",
|
|
33
|
+
allowNo: true
|
|
34
|
+
}),
|
|
35
|
+
envBranch: Flags.string({
|
|
29
36
|
description: "Specify an environment's branch name when using remote environment variables.",
|
|
30
37
|
env: "SHOPIFY_HYDROGEN_ENVIRONMENT_BRANCH",
|
|
31
38
|
char: "e"
|
|
@@ -35,6 +42,30 @@ const commonFlags = {
|
|
|
35
42
|
env: "SHOPIFY_HYDROGEN_FLAG_SOURCEMAP",
|
|
36
43
|
default: true,
|
|
37
44
|
allowNo: true
|
|
45
|
+
}),
|
|
46
|
+
codegenConfigPath: Flags.string({
|
|
47
|
+
description: "Specify a path to a codegen configuration file. Defaults to `<root>/codegen.ts` if it exists.",
|
|
48
|
+
required: false,
|
|
49
|
+
dependsOn: ["codegen-unstable"]
|
|
50
|
+
}),
|
|
51
|
+
styling: Flags.string({
|
|
52
|
+
description: `Sets the styling strategy to use. One of ${SETUP_CSS_STRATEGIES.map(
|
|
53
|
+
(item) => `\`${item}\``
|
|
54
|
+
).join(", ")}.`,
|
|
55
|
+
choices: SETUP_CSS_STRATEGIES,
|
|
56
|
+
env: "SHOPIFY_HYDROGEN_FLAG_STYLING"
|
|
57
|
+
}),
|
|
58
|
+
markets: Flags.string({
|
|
59
|
+
description: `Sets the URL structure to support multiple markets. One of ${I18N_CHOICES.map(
|
|
60
|
+
(item) => `\`${item}\``
|
|
61
|
+
).join(", ")}.`,
|
|
62
|
+
choices: I18N_CHOICES,
|
|
63
|
+
env: "SHOPIFY_HYDROGEN_FLAG_I18N"
|
|
64
|
+
}),
|
|
65
|
+
shortcut: Flags.boolean({
|
|
66
|
+
description: "Create a shortcut to the Shopify Hydrogen CLI.",
|
|
67
|
+
env: "SHOPIFY_HYDROGEN_FLAG_SHORTCUT",
|
|
68
|
+
allowNo: true
|
|
38
69
|
})
|
|
39
70
|
};
|
|
40
71
|
function flagsToCamelObject(obj) {
|
|
@@ -74,5 +105,11 @@ function deprecated(name) {
|
|
|
74
105
|
hidden: true
|
|
75
106
|
});
|
|
76
107
|
}
|
|
108
|
+
function overrideFlag(flag, extra) {
|
|
109
|
+
return {
|
|
110
|
+
...flag,
|
|
111
|
+
...extra
|
|
112
|
+
};
|
|
113
|
+
}
|
|
77
114
|
|
|
78
|
-
export { commonFlags, deprecated, flagsToCamelObject, parseProcessFlags };
|
|
115
|
+
export { commonFlags, deprecated, flagsToCamelObject, overrideFlag, parseProcessFlags };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import prettier from 'prettier';
|
|
2
|
+
import { extname } from '@shopify/cli-kit/node/path';
|
|
3
|
+
|
|
4
|
+
const DEFAULT_PRETTIER_CONFIG = {
|
|
5
|
+
arrowParens: "always",
|
|
6
|
+
singleQuote: true,
|
|
7
|
+
bracketSpacing: false,
|
|
8
|
+
trailingComma: "all"
|
|
9
|
+
};
|
|
10
|
+
async function getCodeFormatOptions(filePath = process.cwd()) {
|
|
11
|
+
try {
|
|
12
|
+
return await prettier.resolveConfig(filePath) || DEFAULT_PRETTIER_CONFIG;
|
|
13
|
+
} catch {
|
|
14
|
+
return DEFAULT_PRETTIER_CONFIG;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function formatCode(content, config = DEFAULT_PRETTIER_CONFIG, filePath = "") {
|
|
18
|
+
const ext = extname(filePath);
|
|
19
|
+
const formattedContent = prettier.format(content, {
|
|
20
|
+
parser: ext === ".tsx" || ext === ".ts" ? "typescript" : "babel",
|
|
21
|
+
...config
|
|
22
|
+
});
|
|
23
|
+
return formattedContent;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export { formatCode, getCodeFormatOptions };
|
package/dist/lib/gid.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { AbortError } from '@shopify/cli-kit/node/error';
|
|
2
|
+
|
|
3
|
+
const GID_REGEXP = /gid:\/\/shopify\/\w*\/(\d+)/;
|
|
4
|
+
function parseGid(gid) {
|
|
5
|
+
const matches = GID_REGEXP.exec(gid);
|
|
6
|
+
if (matches && matches[1] !== void 0) {
|
|
7
|
+
return matches[1];
|
|
8
|
+
}
|
|
9
|
+
throw new AbortError(`Invalid Global ID: ${gid}`);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export { parseGid };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { AbortError } from '@shopify/cli-kit/node/error';
|
|
2
|
+
import { graphqlRequest } from '@shopify/cli-kit/node/api/graphql';
|
|
3
|
+
|
|
4
|
+
async function adminRequest(query, session, variables) {
|
|
5
|
+
const api = "Admin";
|
|
6
|
+
const url = `https://${session.storeFqdn}/admin/api/unstable/graphql.json`;
|
|
7
|
+
try {
|
|
8
|
+
return await graphqlRequest({
|
|
9
|
+
query,
|
|
10
|
+
api,
|
|
11
|
+
url,
|
|
12
|
+
token: session.token,
|
|
13
|
+
variables
|
|
14
|
+
});
|
|
15
|
+
} catch (error) {
|
|
16
|
+
const errors = error.errors;
|
|
17
|
+
if (errors?.some?.((error2) => error2.message.includes("app is not installed"))) {
|
|
18
|
+
throw new AbortError(
|
|
19
|
+
"Hydrogen sales channel isn't installed",
|
|
20
|
+
"Install the Hydrogen sales channel on your store to start creating and linking Hydrogen storefronts: https://apps.shopify.com/hydrogen"
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
throw error;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export { adminRequest };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { AbortError } from '@shopify/cli-kit/node/error';
|
|
2
|
+
import { vi, describe, it, expect } from 'vitest';
|
|
3
|
+
import { adminRequest } from './client.js';
|
|
4
|
+
import { graphqlRequest } from '@shopify/cli-kit/node/api/graphql';
|
|
5
|
+
|
|
6
|
+
vi.mock("@shopify/cli-kit/node/api/graphql");
|
|
7
|
+
describe("adminRequest", () => {
|
|
8
|
+
it("sends a query to the Admin API and returns the successful response", async () => {
|
|
9
|
+
const fakeResponse = {
|
|
10
|
+
test: "test"
|
|
11
|
+
};
|
|
12
|
+
vi.mocked(graphqlRequest).mockResolvedValue(fakeResponse);
|
|
13
|
+
const response = await adminRequest("", {
|
|
14
|
+
token: "",
|
|
15
|
+
storeFqdn: ""
|
|
16
|
+
});
|
|
17
|
+
expect(response).toContain(fakeResponse);
|
|
18
|
+
});
|
|
19
|
+
describe("error response", () => {
|
|
20
|
+
it("sends a query to the Admin API and returns an unknown error response", async () => {
|
|
21
|
+
const fakeGraphqlError = {
|
|
22
|
+
errors: [
|
|
23
|
+
{
|
|
24
|
+
message: "test error"
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
};
|
|
28
|
+
vi.mocked(graphqlRequest).mockRejectedValue(fakeGraphqlError);
|
|
29
|
+
const response = adminRequest("", {
|
|
30
|
+
token: "",
|
|
31
|
+
storeFqdn: ""
|
|
32
|
+
});
|
|
33
|
+
await expect(response).rejects.toContain(fakeGraphqlError);
|
|
34
|
+
});
|
|
35
|
+
it("sends a query to the Admin API and returns an error where app isn't installed", async () => {
|
|
36
|
+
const fakeGraphqlError = {
|
|
37
|
+
errors: [
|
|
38
|
+
{
|
|
39
|
+
message: "app is not installed"
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
};
|
|
43
|
+
vi.mocked(graphqlRequest).mockRejectedValue(fakeGraphqlError);
|
|
44
|
+
const response = adminRequest("", {
|
|
45
|
+
token: "",
|
|
46
|
+
storeFqdn: ""
|
|
47
|
+
});
|
|
48
|
+
await expect(response).rejects.toThrowError(AbortError);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { AbortError } from '@shopify/cli-kit/node/error';
|
|
2
|
+
import { adminRequest } from './client.js';
|
|
3
3
|
|
|
4
4
|
const CreateStorefrontMutation = `#graphql
|
|
5
5
|
mutation CreateStorefront($title: String!) {
|
|
@@ -18,21 +18,19 @@ const CreateStorefrontMutation = `#graphql
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
`;
|
|
21
|
-
async function createStorefront(
|
|
22
|
-
const
|
|
23
|
-
|
|
21
|
+
async function createStorefront(adminSession, title) {
|
|
22
|
+
const {
|
|
23
|
+
hydrogenStorefrontCreate: { hydrogenStorefront, userErrors, jobId }
|
|
24
|
+
} = await adminRequest(
|
|
24
25
|
CreateStorefrontMutation,
|
|
25
26
|
adminSession,
|
|
26
|
-
{
|
|
27
|
-
title
|
|
28
|
-
}
|
|
27
|
+
{ title }
|
|
29
28
|
);
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
storefront
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
};
|
|
29
|
+
if (!hydrogenStorefront || !jobId || userErrors.length > 0) {
|
|
30
|
+
const errorMessages = userErrors.map(({ message }) => message).join(", ");
|
|
31
|
+
throw new AbortError("Could not create storefront. " + errorMessages);
|
|
32
|
+
}
|
|
33
|
+
return { jobId, storefront: hydrogenStorefront };
|
|
36
34
|
}
|
|
37
35
|
|
|
38
|
-
export {
|
|
36
|
+
export { createStorefront };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { vi, describe, afterEach, it, expect } from 'vitest';
|
|
2
|
+
import { adminRequest } from './client.js';
|
|
3
|
+
import { createStorefront } from './create-storefront.js';
|
|
4
|
+
|
|
5
|
+
vi.mock("./client.js");
|
|
6
|
+
describe("createStorefront", () => {
|
|
7
|
+
const ADMIN_SESSION = {
|
|
8
|
+
token: "abc123",
|
|
9
|
+
storeFqdn: "my-shop.myshopify.com"
|
|
10
|
+
};
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
vi.resetAllMocks();
|
|
13
|
+
});
|
|
14
|
+
it("sends a mutation to create a new storefront and returns it", async () => {
|
|
15
|
+
vi.mocked(adminRequest).mockImplementation(
|
|
16
|
+
(_, __, variables) => Promise.resolve({
|
|
17
|
+
hydrogenStorefrontCreate: {
|
|
18
|
+
hydrogenStorefront: {
|
|
19
|
+
id: "gid://shopify/HydrogenStorefront/123",
|
|
20
|
+
title: variables?.title,
|
|
21
|
+
productionUrl: "https://..."
|
|
22
|
+
},
|
|
23
|
+
userErrors: [],
|
|
24
|
+
jobId: "123"
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
);
|
|
28
|
+
const TITLE = "title";
|
|
29
|
+
await expect(createStorefront(ADMIN_SESSION, TITLE)).resolves.toStrictEqual(
|
|
30
|
+
{
|
|
31
|
+
jobId: "123",
|
|
32
|
+
storefront: {
|
|
33
|
+
id: "gid://shopify/HydrogenStorefront/123",
|
|
34
|
+
title: TITLE,
|
|
35
|
+
productionUrl: "https://..."
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
expect(adminRequest).toHaveBeenCalledWith(
|
|
40
|
+
expect.stringMatching(/^#graphql.+mutation.+hydrogenStorefrontCreate\(/s),
|
|
41
|
+
ADMIN_SESSION,
|
|
42
|
+
{ title: TITLE }
|
|
43
|
+
);
|
|
44
|
+
});
|
|
45
|
+
it("throws formatted GraphQL errors", async () => {
|
|
46
|
+
const error = "Title is invalid";
|
|
47
|
+
vi.mocked(adminRequest).mockResolvedValue({
|
|
48
|
+
hydrogenStorefrontCreate: {
|
|
49
|
+
jobId: void 0,
|
|
50
|
+
hydrogenStorefront: void 0,
|
|
51
|
+
userErrors: [
|
|
52
|
+
{
|
|
53
|
+
code: "INVALID",
|
|
54
|
+
field: ["title"],
|
|
55
|
+
message: error
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
await expect(createStorefront(ADMIN_SESSION, "title")).rejects.toThrow(
|
|
61
|
+
error
|
|
62
|
+
);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { adminRequest } from '
|
|
2
|
-
import { getAdminSession } from '../../admin-session.js';
|
|
1
|
+
import { adminRequest } from './client.js';
|
|
3
2
|
|
|
4
3
|
const FetchJobQuery = `#graphql
|
|
5
4
|
query FetchJob($id: ID!) {
|
|
@@ -13,26 +12,18 @@ const FetchJobQuery = `#graphql
|
|
|
13
12
|
}
|
|
14
13
|
}
|
|
15
14
|
`;
|
|
16
|
-
async function fetchJob(
|
|
17
|
-
const adminSession = await getAdminSession(shop);
|
|
15
|
+
async function fetchJob(adminSession, jobId) {
|
|
18
16
|
const { hydrogenStorefrontJob } = await adminRequest(
|
|
19
17
|
FetchJobQuery,
|
|
20
18
|
adminSession,
|
|
21
|
-
{
|
|
22
|
-
id: jobId
|
|
23
|
-
}
|
|
19
|
+
{ id: jobId }
|
|
24
20
|
);
|
|
25
|
-
return
|
|
26
|
-
adminSession,
|
|
27
|
-
id: hydrogenStorefrontJob.id,
|
|
28
|
-
done: hydrogenStorefrontJob.done,
|
|
29
|
-
errors: hydrogenStorefrontJob.errors
|
|
30
|
-
};
|
|
21
|
+
return hydrogenStorefrontJob;
|
|
31
22
|
}
|
|
32
|
-
function waitForJob(
|
|
23
|
+
function waitForJob(adminSession, jobId) {
|
|
33
24
|
return new Promise((resolve, reject) => {
|
|
34
25
|
const interval = setInterval(async () => {
|
|
35
|
-
const job = await fetchJob(
|
|
26
|
+
const job = await fetchJob(adminSession, jobId);
|
|
36
27
|
if (job.errors.length > 0) {
|
|
37
28
|
clearInterval(interval);
|
|
38
29
|
return reject();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { adminRequest
|
|
2
|
-
import {
|
|
1
|
+
import { adminRequest } from './client.js';
|
|
2
|
+
import { parseGid } from '../../gid.js';
|
|
3
3
|
|
|
4
4
|
const LinkStorefrontQuery = `#graphql
|
|
5
5
|
query LinkStorefront {
|
|
@@ -10,19 +10,15 @@ const LinkStorefrontQuery = `#graphql
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
`;
|
|
13
|
-
async function getStorefronts(
|
|
14
|
-
const adminSession = await getAdminSession(shop);
|
|
13
|
+
async function getStorefronts(adminSession) {
|
|
15
14
|
const { hydrogenStorefronts } = await adminRequest(
|
|
16
15
|
LinkStorefrontQuery,
|
|
17
16
|
adminSession
|
|
18
17
|
);
|
|
19
|
-
return {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
parsedId: parseGid(storefront.id)
|
|
24
|
-
}))
|
|
25
|
-
};
|
|
18
|
+
return hydrogenStorefronts.map((storefront) => ({
|
|
19
|
+
...storefront,
|
|
20
|
+
parsedId: parseGid(storefront.id)
|
|
21
|
+
}));
|
|
26
22
|
}
|
|
27
23
|
|
|
28
24
|
export { LinkStorefrontQuery, getStorefronts };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { vi, describe, afterEach, it, expect } from 'vitest';
|
|
2
|
+
import { adminRequest } from './client.js';
|
|
3
|
+
import { getStorefronts } from './link-storefront.js';
|
|
4
|
+
|
|
5
|
+
vi.mock("./client.js");
|
|
6
|
+
describe("getStorefrontsWithDeployment", () => {
|
|
7
|
+
const ADMIN_SESSION = {
|
|
8
|
+
token: "abc123",
|
|
9
|
+
storeFqdn: "my-shop.myshopify.com"
|
|
10
|
+
};
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
vi.resetAllMocks();
|
|
13
|
+
});
|
|
14
|
+
it("calls the graphql client and returns Hydrogen storefronts", async () => {
|
|
15
|
+
const mockedResponse = {
|
|
16
|
+
hydrogenStorefronts: [
|
|
17
|
+
{
|
|
18
|
+
id: "gid://shopify/HydrogenStorefront/123",
|
|
19
|
+
title: "title",
|
|
20
|
+
productionUrl: "https://..."
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
};
|
|
24
|
+
vi.mocked(adminRequest).mockResolvedValue(
|
|
25
|
+
mockedResponse
|
|
26
|
+
);
|
|
27
|
+
await expect(getStorefronts(ADMIN_SESSION)).resolves.toStrictEqual([
|
|
28
|
+
{
|
|
29
|
+
...mockedResponse.hydrogenStorefronts[0],
|
|
30
|
+
parsedId: "123"
|
|
31
|
+
}
|
|
32
|
+
]);
|
|
33
|
+
expect(adminRequest).toHaveBeenCalledWith(
|
|
34
|
+
expect.stringMatching(/^#graphql.+query.+hydrogenStorefronts\s*{/s),
|
|
35
|
+
ADMIN_SESSION
|
|
36
|
+
);
|
|
37
|
+
});
|
|
38
|
+
});
|