@shopify/cli-hydrogen 6.0.2 → 7.0.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 +40 -78
- package/dist/commands/hydrogen/codegen.js +8 -3
- package/dist/commands/hydrogen/deploy.js +173 -37
- package/dist/commands/hydrogen/deploy.test.js +192 -20
- package/dist/commands/hydrogen/dev.js +56 -31
- package/dist/commands/hydrogen/init.js +1 -1
- package/dist/commands/hydrogen/init.test.js +155 -53
- package/dist/commands/hydrogen/link.js +5 -21
- package/dist/commands/hydrogen/link.test.js +10 -10
- package/dist/commands/hydrogen/preview.js +22 -11
- package/dist/commands/hydrogen/setup.js +0 -4
- package/dist/commands/hydrogen/setup.test.js +0 -1
- package/dist/commands/hydrogen/shortcut.js +1 -0
- package/dist/commands/hydrogen/upgrade.js +720 -0
- package/dist/commands/hydrogen/upgrade.test.js +786 -0
- package/dist/generator-templates/starter/.graphqlrc.yml +12 -1
- package/dist/generator-templates/starter/CHANGELOG.md +126 -0
- package/dist/generator-templates/starter/README.md +23 -0
- package/dist/generator-templates/starter/app/components/Cart.tsx +1 -1
- package/dist/generator-templates/starter/app/components/Footer.tsx +3 -1
- package/dist/generator-templates/starter/app/components/Header.tsx +5 -1
- package/dist/generator-templates/starter/app/components/Layout.tsx +14 -11
- package/dist/generator-templates/starter/app/components/Search.tsx +1 -1
- package/dist/generator-templates/starter/app/graphql/customer-account/CustomerAddressMutations.ts +61 -0
- package/dist/generator-templates/starter/app/graphql/customer-account/CustomerDetailsQuery.ts +39 -0
- package/dist/generator-templates/starter/app/graphql/customer-account/CustomerOrderQuery.ts +87 -0
- package/dist/generator-templates/starter/app/graphql/customer-account/CustomerOrdersQuery.ts +58 -0
- package/dist/generator-templates/starter/app/graphql/customer-account/CustomerUpdateMutation.ts +24 -0
- package/dist/generator-templates/starter/app/lib/fragments.ts +102 -0
- package/dist/generator-templates/starter/app/lib/session.ts +67 -0
- package/dist/generator-templates/starter/app/root.tsx +11 -45
- package/dist/generator-templates/starter/app/routes/[robots.txt].tsx +0 -27
- package/dist/generator-templates/starter/app/routes/account.$.tsx +8 -4
- package/dist/generator-templates/starter/app/routes/account._index.tsx +5 -0
- package/dist/generator-templates/starter/app/routes/account.addresses.tsx +215 -206
- package/dist/generator-templates/starter/app/routes/account.orders.$id.tsx +56 -163
- package/dist/generator-templates/starter/app/routes/account.orders._index.tsx +32 -109
- package/dist/generator-templates/starter/app/routes/account.profile.tsx +40 -180
- package/dist/generator-templates/starter/app/routes/account.tsx +20 -135
- package/dist/generator-templates/starter/app/routes/account_.authorize.tsx +5 -0
- package/dist/generator-templates/starter/app/routes/account_.login.tsx +3 -140
- package/dist/generator-templates/starter/app/routes/account_.logout.tsx +5 -24
- package/dist/generator-templates/starter/app/routes/cart.tsx +7 -5
- package/dist/generator-templates/starter/app/routes/collections.$handle.tsx +1 -1
- package/dist/generator-templates/starter/app/routes/products.$handle.tsx +2 -2
- package/dist/generator-templates/starter/app/routes/search.tsx +1 -1
- package/dist/generator-templates/starter/customer-accountapi.generated.d.ts +506 -0
- package/dist/generator-templates/starter/package.json +11 -10
- package/dist/generator-templates/starter/remix.config.js +4 -0
- package/dist/generator-templates/starter/remix.env.d.ts +6 -11
- package/dist/generator-templates/starter/server.ts +24 -167
- package/dist/generator-templates/starter/storefrontapi.generated.d.ts +104 -881
- package/dist/hooks/init.js +4 -4
- package/dist/lib/auth.js +5 -10
- package/dist/lib/build.js +6 -1
- package/dist/lib/bundle/analyzer.js +36 -26
- package/dist/lib/check-lockfile.js +1 -0
- package/dist/lib/codegen.js +59 -18
- package/dist/lib/defer.js +12 -0
- package/dist/lib/file.js +52 -3
- package/dist/lib/flags.js +27 -9
- package/dist/lib/get-oxygen-deployment-data.test.js +4 -2
- package/dist/lib/graphql/admin/client.test.js +2 -2
- package/dist/lib/graphql/admin/get-oxygen-data.js +1 -0
- package/dist/lib/log.js +32 -14
- package/dist/lib/mini-oxygen/assets.js +118 -0
- package/dist/lib/mini-oxygen/common.js +2 -1
- package/dist/lib/mini-oxygen/index.js +7 -5
- package/dist/lib/mini-oxygen/mini-oxygen.test.js +214 -0
- package/dist/lib/mini-oxygen/node.js +19 -5
- package/dist/lib/mini-oxygen/workerd-inspector-logs.js +227 -0
- package/dist/lib/mini-oxygen/workerd-inspector-proxy.js +200 -0
- package/dist/lib/mini-oxygen/workerd-inspector.js +62 -235
- package/dist/lib/mini-oxygen/workerd.js +74 -50
- package/dist/lib/missing-routes.js +6 -3
- package/dist/lib/onboarding/common.js +40 -9
- package/dist/lib/onboarding/local.js +19 -11
- package/dist/lib/onboarding/remote.js +48 -28
- package/dist/lib/render-errors.js +2 -0
- package/dist/lib/request-events.js +65 -31
- package/dist/lib/setups/css/assets.js +1 -46
- package/dist/lib/setups/css/css-modules.js +3 -2
- package/dist/lib/setups/css/postcss.js +4 -2
- package/dist/lib/setups/css/tailwind.js +4 -2
- package/dist/lib/setups/css/vanilla-extract.js +3 -2
- package/dist/lib/setups/i18n/replacers.test.js +56 -38
- package/dist/lib/shell.js +1 -1
- package/dist/lib/template-diff.js +89 -0
- package/dist/lib/template-downloader.js +3 -2
- package/dist/lib/transpile/project.js +1 -1
- package/dist/virtual-routes/assets/debug-network.css +592 -0
- package/dist/virtual-routes/assets/favicon-dark.svg +20 -0
- package/dist/virtual-routes/components/FlameChartWrapper.jsx +8 -10
- package/dist/virtual-routes/components/IconClose.jsx +38 -0
- package/dist/virtual-routes/components/IconDiscard.jsx +44 -0
- package/dist/virtual-routes/components/RequestDetails.jsx +179 -0
- package/dist/virtual-routes/components/RequestTable.jsx +92 -0
- package/dist/virtual-routes/components/RequestWaterfall.jsx +151 -0
- package/dist/virtual-routes/lib/useDebugNetworkServer.jsx +176 -0
- package/dist/virtual-routes/routes/subrequest-profiler.jsx +243 -0
- package/oclif.manifest.json +134 -59
- package/package.json +18 -26
- package/dist/generator-templates/starter/app/routes/account_.activate.$id.$activationToken.tsx +0 -161
- package/dist/generator-templates/starter/app/routes/account_.recover.tsx +0 -129
- package/dist/generator-templates/starter/app/routes/account_.register.tsx +0 -207
- package/dist/generator-templates/starter/app/routes/account_.reset.$id.$resetToken.tsx +0 -136
- package/dist/virtual-routes/routes/debug-network.jsx +0 -289
- /package/dist/generator-templates/starter/app/{utils.ts → lib/variants.ts} +0 -0
|
@@ -0,0 +1,786 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { execa } from 'execa';
|
|
4
|
+
import { vi, beforeEach, beforeAll, afterAll, describe, it, expect } from 'vitest';
|
|
5
|
+
import { inTemporaryDirectory, writeFile, fileExists } from '@shopify/cli-kit/node/fs';
|
|
6
|
+
import { joinPath } from '@shopify/cli-kit/node/path';
|
|
7
|
+
import { renderSelectPrompt, renderConfirmationPrompt, renderTasks } from '@shopify/cli-kit/node/ui';
|
|
8
|
+
import { mockAndCaptureOutput } from '@shopify/cli-kit/node/testing/output';
|
|
9
|
+
import { runUpgrade, getChangelog, getHydrogenVersion, getAvailableUpgrades, buildUpgradeCommandArgs, getAbsoluteVersion, getSelectedRelease, getCummulativeRelease, displayConfirmation, upgradeNodeModules } from './upgrade.js';
|
|
10
|
+
|
|
11
|
+
vi.mock("../../lib/shell.js");
|
|
12
|
+
vi.mock("@shopify/cli-kit/node/session");
|
|
13
|
+
vi.mock("@shopify/cli-kit/node/ui", async () => {
|
|
14
|
+
const original = await vi.importActual("@shopify/cli-kit/node/ui");
|
|
15
|
+
return {
|
|
16
|
+
...original,
|
|
17
|
+
renderTasks: vi.fn(() => Promise.resolve()),
|
|
18
|
+
renderSelectPrompt: vi.fn(() => Promise.resolve()),
|
|
19
|
+
renderConfirmationPrompt: vi.fn(() => Promise.resolve(false))
|
|
20
|
+
};
|
|
21
|
+
});
|
|
22
|
+
const outputMock = mockAndCaptureOutput();
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
vi.restoreAllMocks();
|
|
25
|
+
vi.resetModules();
|
|
26
|
+
vi.clearAllMocks();
|
|
27
|
+
outputMock.clear();
|
|
28
|
+
});
|
|
29
|
+
beforeAll(() => {
|
|
30
|
+
process.env.FORCE_CHANGELOG_SOURCE = "local";
|
|
31
|
+
});
|
|
32
|
+
afterAll(() => {
|
|
33
|
+
delete process.env.FORCE_CHANGELOG_SOURCE;
|
|
34
|
+
});
|
|
35
|
+
function createOutdatedSkeletonPackageJson() {
|
|
36
|
+
const require2 = createRequire(import.meta.url);
|
|
37
|
+
const packageJson = require2(fileURLToPath(
|
|
38
|
+
new URL("../../../../../templates/skeleton/package.json", import.meta.url)
|
|
39
|
+
));
|
|
40
|
+
if (!packageJson)
|
|
41
|
+
throw new Error("Could not parse package.json");
|
|
42
|
+
if (!packageJson?.dependencies)
|
|
43
|
+
throw new Error("Could not parse package.json dependencies");
|
|
44
|
+
if (!packageJson?.devDependencies)
|
|
45
|
+
throw new Error("Could not parse package.json devDependencies");
|
|
46
|
+
packageJson.dependencies["@shopify/hydrogen"] = "^2023.1.6";
|
|
47
|
+
packageJson.dependencies["@remix-run/react"] = "1.12.0";
|
|
48
|
+
packageJson.devDependencies["@shopify/cli-hydrogen"] = "^4.0.8";
|
|
49
|
+
packageJson.devDependencies["@shopify/remix-oxygen"] = "^1.0.3";
|
|
50
|
+
packageJson.devDependencies["@remix-run/dev"] = "1.12.0";
|
|
51
|
+
packageJson.devDependencies["typescript"] = "^4.9.5";
|
|
52
|
+
return packageJson;
|
|
53
|
+
}
|
|
54
|
+
async function inTemporaryHydrogenRepo(cb, {
|
|
55
|
+
cleanGitRepo,
|
|
56
|
+
packageJson
|
|
57
|
+
} = {
|
|
58
|
+
cleanGitRepo: true,
|
|
59
|
+
packageJson: null
|
|
60
|
+
}) {
|
|
61
|
+
return inTemporaryDirectory(async (tmpDir) => {
|
|
62
|
+
await execa("git", ["init"], { cwd: tmpDir });
|
|
63
|
+
if (packageJson) {
|
|
64
|
+
const packageJsonPath = joinPath(tmpDir, "package.json");
|
|
65
|
+
await writeFile(packageJsonPath, JSON.stringify(packageJson));
|
|
66
|
+
expect(await fileExists(packageJsonPath)).toBeTruthy();
|
|
67
|
+
}
|
|
68
|
+
expect(await fileExists(joinPath(tmpDir, "/.git/config"))).toBeTruthy();
|
|
69
|
+
if (cleanGitRepo) {
|
|
70
|
+
await execa("git", ["add", "package.json"], { cwd: tmpDir });
|
|
71
|
+
if (process.env.NODE_ENV === "test" && process.env.CI) {
|
|
72
|
+
await execa("git", ["config", "user.email", "test@hydrogen.shop"], {
|
|
73
|
+
cwd: tmpDir
|
|
74
|
+
});
|
|
75
|
+
await execa("git", ["config", "user.name", "Hydrogen Test"], {
|
|
76
|
+
cwd: tmpDir
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
await execa("git", ["commit", "-m", "initial commit"], { cwd: tmpDir });
|
|
80
|
+
}
|
|
81
|
+
await cb(tmpDir);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
describe("upgrade", async () => {
|
|
85
|
+
const OUTDATED_HYDROGEN_PACKAGE_JSON = createOutdatedSkeletonPackageJson();
|
|
86
|
+
describe("checkIsGitRepo", () => {
|
|
87
|
+
it("renders an error message when not in a git repo", async () => {
|
|
88
|
+
await inTemporaryDirectory(async (appPath) => {
|
|
89
|
+
await expect(runUpgrade({ appPath })).rejects.toThrowError(
|
|
90
|
+
"git repository"
|
|
91
|
+
);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
describe("checkDirtyGitBranch", () => {
|
|
96
|
+
it("renders error message if the target git repo is dirty", async () => {
|
|
97
|
+
await inTemporaryHydrogenRepo(
|
|
98
|
+
async (appPath) => {
|
|
99
|
+
await expect(runUpgrade({ appPath })).rejects.toThrowError("clean git");
|
|
100
|
+
},
|
|
101
|
+
{ cleanGitRepo: false, packageJson: OUTDATED_HYDROGEN_PACKAGE_JSON }
|
|
102
|
+
);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
describe("getHydrogenVersion", () => {
|
|
106
|
+
it("throws if no package.json is found", async () => {
|
|
107
|
+
await inTemporaryHydrogenRepo(
|
|
108
|
+
async (appPath) => {
|
|
109
|
+
await expect(runUpgrade({ appPath })).rejects.toThrowError(
|
|
110
|
+
"valid package.json"
|
|
111
|
+
);
|
|
112
|
+
},
|
|
113
|
+
{ packageJson: null }
|
|
114
|
+
);
|
|
115
|
+
});
|
|
116
|
+
it("throws if no hydrogen version is found in package.json", async () => {
|
|
117
|
+
await inTemporaryHydrogenRepo(
|
|
118
|
+
async (appPath) => {
|
|
119
|
+
await expect(runUpgrade({ appPath })).rejects.toThrowError(
|
|
120
|
+
"version in package.json"
|
|
121
|
+
);
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
cleanGitRepo: true,
|
|
125
|
+
packageJson: {
|
|
126
|
+
name: "hello-world",
|
|
127
|
+
dependencies: {}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
);
|
|
131
|
+
});
|
|
132
|
+
it("returns the current hydrogen version from the package.json", async () => {
|
|
133
|
+
await inTemporaryHydrogenRepo(
|
|
134
|
+
async (appPath) => {
|
|
135
|
+
const hydrogen = await getHydrogenVersion({ appPath });
|
|
136
|
+
expect(hydrogen).toBeDefined();
|
|
137
|
+
expect(hydrogen.currentVersion).toMatch("^2023.1.6");
|
|
138
|
+
expect(hydrogen.currentDependencies).toMatchObject({
|
|
139
|
+
...OUTDATED_HYDROGEN_PACKAGE_JSON.dependencies,
|
|
140
|
+
...OUTDATED_HYDROGEN_PACKAGE_JSON.devDependencies
|
|
141
|
+
});
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
cleanGitRepo: true,
|
|
145
|
+
packageJson: OUTDATED_HYDROGEN_PACKAGE_JSON
|
|
146
|
+
}
|
|
147
|
+
);
|
|
148
|
+
});
|
|
149
|
+
it('exists when run over a prerelease "next" version', async () => {
|
|
150
|
+
await inTemporaryHydrogenRepo(
|
|
151
|
+
async (appPath) => {
|
|
152
|
+
await expect(runUpgrade({ appPath })).rejects.toThrowError(
|
|
153
|
+
"prerelease"
|
|
154
|
+
);
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
cleanGitRepo: true,
|
|
158
|
+
packageJson: {
|
|
159
|
+
dependencies: {
|
|
160
|
+
"@shopify/hydrogen": "0.0.0-next-74ea1db-20231120210149"
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
);
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
describe.skip("fetchChangelog", () => {
|
|
168
|
+
it("fetches the latest changelog from the hydrogen repo", async () => {
|
|
169
|
+
});
|
|
170
|
+
it("renders an error message if the changelog could not be fetched", async () => {
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
describe("getAvailableUpgrades", async () => {
|
|
174
|
+
it('renders "already in the latest version" success message if no upgrades are available', async () => {
|
|
175
|
+
const { releases } = await getChangelog();
|
|
176
|
+
await inTemporaryHydrogenRepo(
|
|
177
|
+
async (appPath) => {
|
|
178
|
+
await runUpgrade({ appPath });
|
|
179
|
+
expect(outputMock.info()).toMatch(
|
|
180
|
+
/ success.+ latest Hydrogen version/is
|
|
181
|
+
);
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
cleanGitRepo: true,
|
|
185
|
+
packageJson: {
|
|
186
|
+
dependencies: {
|
|
187
|
+
// @ts-expect-error - we know this release version exists
|
|
188
|
+
"@shopify/hydrogen": releases[0].version
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
);
|
|
193
|
+
});
|
|
194
|
+
it("returns available upgrades and uniqueAvailableUpgrades if they exist", async () => {
|
|
195
|
+
const { releases } = await getChangelog();
|
|
196
|
+
await inTemporaryHydrogenRepo(
|
|
197
|
+
async (appPath) => {
|
|
198
|
+
const current = await getHydrogenVersion({ appPath });
|
|
199
|
+
const availableUpgrades = getAvailableUpgrades({
|
|
200
|
+
releases,
|
|
201
|
+
...current
|
|
202
|
+
});
|
|
203
|
+
const uniqueAvailableUpgrades = releases.slice(0, 2).reduce((acc, release) => {
|
|
204
|
+
if (acc[release.version])
|
|
205
|
+
return acc;
|
|
206
|
+
return {
|
|
207
|
+
...acc,
|
|
208
|
+
[release.version]: release
|
|
209
|
+
};
|
|
210
|
+
}, {});
|
|
211
|
+
expect(availableUpgrades).toMatchObject({
|
|
212
|
+
availableUpgrades: releases.slice(0, 2),
|
|
213
|
+
uniqueAvailableUpgrades
|
|
214
|
+
});
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
cleanGitRepo: true,
|
|
218
|
+
packageJson: {
|
|
219
|
+
dependencies: {
|
|
220
|
+
// @ts-ignore
|
|
221
|
+
"@shopify/hydrogen": releases[2].version
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
);
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
describe("getSelectedRelease", () => {
|
|
229
|
+
it("prioritizes a passed target --version over a select prompt if available", async () => {
|
|
230
|
+
await inTemporaryHydrogenRepo(
|
|
231
|
+
async (appPath) => {
|
|
232
|
+
const { releases } = await getChangelog();
|
|
233
|
+
const current = await getHydrogenVersion({ appPath });
|
|
234
|
+
expect(current?.currentVersion).toBeDefined();
|
|
235
|
+
const { availableUpgrades } = getAvailableUpgrades({
|
|
236
|
+
...current,
|
|
237
|
+
releases
|
|
238
|
+
});
|
|
239
|
+
await expect(
|
|
240
|
+
getSelectedRelease({
|
|
241
|
+
availableUpgrades,
|
|
242
|
+
// @ts-ignore - we know this release version exists
|
|
243
|
+
currentVersion: current.currentVersion,
|
|
244
|
+
// OUTDATED_HYDROGEN_PACKAGE_JSON.dependencies['@shopify/hydrogen'],
|
|
245
|
+
targetVersion: "2023.7.10"
|
|
246
|
+
})
|
|
247
|
+
).resolves.toMatchObject({
|
|
248
|
+
version: "2023.7.10"
|
|
249
|
+
});
|
|
250
|
+
expect(renderSelectPrompt).not.toHaveBeenCalled();
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
cleanGitRepo: true,
|
|
254
|
+
packageJson: OUTDATED_HYDROGEN_PACKAGE_JSON
|
|
255
|
+
}
|
|
256
|
+
);
|
|
257
|
+
});
|
|
258
|
+
it("prompts if a passed target --version is not a valid upgradable version", async () => {
|
|
259
|
+
await inTemporaryHydrogenRepo(
|
|
260
|
+
async (appPath) => {
|
|
261
|
+
const { releases } = await getChangelog();
|
|
262
|
+
const current = await getHydrogenVersion({ appPath });
|
|
263
|
+
expect(current?.currentVersion).toBeDefined();
|
|
264
|
+
const { availableUpgrades } = getAvailableUpgrades({
|
|
265
|
+
...current,
|
|
266
|
+
releases
|
|
267
|
+
});
|
|
268
|
+
vi.mocked(renderSelectPrompt).mockImplementationOnce(
|
|
269
|
+
({ choices }) => Promise.resolve(choices[0]?.value)
|
|
270
|
+
);
|
|
271
|
+
await expect(
|
|
272
|
+
getSelectedRelease({
|
|
273
|
+
availableUpgrades,
|
|
274
|
+
currentVersion: current.currentVersion,
|
|
275
|
+
targetVersion: "2023.1.5"
|
|
276
|
+
// fails because this version is in the past
|
|
277
|
+
})
|
|
278
|
+
).resolves.toMatchObject(availableUpgrades[0]);
|
|
279
|
+
expect(renderSelectPrompt).toHaveBeenCalled();
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
cleanGitRepo: true,
|
|
283
|
+
packageJson: OUTDATED_HYDROGEN_PACKAGE_JSON
|
|
284
|
+
}
|
|
285
|
+
);
|
|
286
|
+
});
|
|
287
|
+
it("prompts to select a release if no target --version is passed", async () => {
|
|
288
|
+
await inTemporaryHydrogenRepo(
|
|
289
|
+
async (appPath) => {
|
|
290
|
+
const { releases } = await getChangelog();
|
|
291
|
+
const previousRelease = releases[1];
|
|
292
|
+
const latestRelease = releases[0];
|
|
293
|
+
const current = await getHydrogenVersion({ appPath });
|
|
294
|
+
expect(current?.currentVersion).toBeDefined();
|
|
295
|
+
const { availableUpgrades } = getAvailableUpgrades({
|
|
296
|
+
...current,
|
|
297
|
+
releases
|
|
298
|
+
});
|
|
299
|
+
vi.mocked(renderSelectPrompt).mockImplementationOnce(
|
|
300
|
+
({ choices }) => Promise.resolve(choices[0]?.value)
|
|
301
|
+
);
|
|
302
|
+
await expect(
|
|
303
|
+
getSelectedRelease({
|
|
304
|
+
availableUpgrades,
|
|
305
|
+
currentVersion: previousRelease.version
|
|
306
|
+
})
|
|
307
|
+
).resolves.toMatchObject(availableUpgrades[0]);
|
|
308
|
+
expect(renderSelectPrompt).toHaveBeenCalledWith({
|
|
309
|
+
message: expect.stringContaining(previousRelease.version),
|
|
310
|
+
choices: expect.arrayContaining([
|
|
311
|
+
{
|
|
312
|
+
label: expect.stringContaining(latestRelease.version),
|
|
313
|
+
value: latestRelease
|
|
314
|
+
}
|
|
315
|
+
]),
|
|
316
|
+
defaultValue: latestRelease
|
|
317
|
+
});
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
cleanGitRepo: true,
|
|
321
|
+
packageJson: OUTDATED_HYDROGEN_PACKAGE_JSON
|
|
322
|
+
}
|
|
323
|
+
);
|
|
324
|
+
});
|
|
325
|
+
});
|
|
326
|
+
describe("getCummulativeRelease", () => {
|
|
327
|
+
it("returns the correct fixes and features for a release range thats outdated", async () => {
|
|
328
|
+
await inTemporaryHydrogenRepo(
|
|
329
|
+
async (appPath) => {
|
|
330
|
+
const { releases } = await getChangelog();
|
|
331
|
+
const current = await getHydrogenVersion({ appPath });
|
|
332
|
+
expect(current?.currentVersion).toBeDefined();
|
|
333
|
+
const { availableUpgrades } = getAvailableUpgrades({
|
|
334
|
+
...current,
|
|
335
|
+
releases
|
|
336
|
+
});
|
|
337
|
+
const selectedRelease = releases.find(
|
|
338
|
+
(release) => release.version === "2023.4.1"
|
|
339
|
+
);
|
|
340
|
+
const { features, fixes } = getCummulativeRelease({
|
|
341
|
+
availableUpgrades,
|
|
342
|
+
...current,
|
|
343
|
+
// @ts-ignore - we know this release version exists
|
|
344
|
+
selectedRelease
|
|
345
|
+
});
|
|
346
|
+
expect(features).toMatchObject(CUMMLATIVE_RELEASE.features);
|
|
347
|
+
expect(fixes).toMatchObject(CUMMLATIVE_RELEASE.fixes);
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
cleanGitRepo: true,
|
|
351
|
+
packageJson: OUTDATED_HYDROGEN_PACKAGE_JSON
|
|
352
|
+
}
|
|
353
|
+
);
|
|
354
|
+
});
|
|
355
|
+
});
|
|
356
|
+
describe("displayConfirmation", () => {
|
|
357
|
+
it("renders a confirmation prompt to continue or return to the previous menu", async () => {
|
|
358
|
+
await inTemporaryHydrogenRepo(
|
|
359
|
+
async () => {
|
|
360
|
+
const { releases } = await getChangelog();
|
|
361
|
+
const selectedRelease = releases.find(
|
|
362
|
+
(release) => release.version === "2023.10.0"
|
|
363
|
+
);
|
|
364
|
+
await expect(
|
|
365
|
+
displayConfirmation({
|
|
366
|
+
cumulativeRelease: CUMMLATIVE_RELEASE,
|
|
367
|
+
selectedRelease
|
|
368
|
+
})
|
|
369
|
+
).resolves.toEqual(false);
|
|
370
|
+
const info = outputMock.info();
|
|
371
|
+
expect(info).toMatch("Included in this upgrade");
|
|
372
|
+
[...CUMMLATIVE_RELEASE.features, ...CUMMLATIVE_RELEASE.fixes].forEach(
|
|
373
|
+
(feat) => (
|
|
374
|
+
// Cut the string to avoid matching the banner
|
|
375
|
+
expect(info).toMatch(feat.title.slice(0, 15))
|
|
376
|
+
)
|
|
377
|
+
);
|
|
378
|
+
expect(renderConfirmationPrompt).toHaveBeenCalledWith({
|
|
379
|
+
message: `Are you sure you want to upgrade to ${selectedRelease.version}?`,
|
|
380
|
+
cancellationMessage: `No, choose another version`,
|
|
381
|
+
defaultValue: true
|
|
382
|
+
});
|
|
383
|
+
},
|
|
384
|
+
{
|
|
385
|
+
cleanGitRepo: true,
|
|
386
|
+
packageJson: OUTDATED_HYDROGEN_PACKAGE_JSON
|
|
387
|
+
}
|
|
388
|
+
);
|
|
389
|
+
});
|
|
390
|
+
});
|
|
391
|
+
describe("upgradeNodeModules", () => {
|
|
392
|
+
it("runs the upgrade command task", async () => {
|
|
393
|
+
await inTemporaryHydrogenRepo(
|
|
394
|
+
async (appPath) => {
|
|
395
|
+
const { releases } = await getChangelog();
|
|
396
|
+
const selectedRelease = releases.find(
|
|
397
|
+
(release) => release.version === "2023.10.0"
|
|
398
|
+
);
|
|
399
|
+
const currentDependencies = {
|
|
400
|
+
...OUTDATED_HYDROGEN_PACKAGE_JSON.dependencies,
|
|
401
|
+
...OUTDATED_HYDROGEN_PACKAGE_JSON.devDependencies
|
|
402
|
+
};
|
|
403
|
+
await upgradeNodeModules({
|
|
404
|
+
appPath,
|
|
405
|
+
selectedRelease,
|
|
406
|
+
currentDependencies
|
|
407
|
+
});
|
|
408
|
+
expect(renderTasks).toHaveBeenCalled();
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
cleanGitRepo: true,
|
|
412
|
+
packageJson: OUTDATED_HYDROGEN_PACKAGE_JSON
|
|
413
|
+
}
|
|
414
|
+
);
|
|
415
|
+
});
|
|
416
|
+
it("builds the upgrade command args", async () => {
|
|
417
|
+
const { releases } = await getChangelog();
|
|
418
|
+
const selectedRelease = releases.find(
|
|
419
|
+
(release) => release.version === "2023.10.0"
|
|
420
|
+
);
|
|
421
|
+
const currentDependencies = {
|
|
422
|
+
...OUTDATED_HYDROGEN_PACKAGE_JSON.dependencies,
|
|
423
|
+
...OUTDATED_HYDROGEN_PACKAGE_JSON.devDependencies
|
|
424
|
+
};
|
|
425
|
+
const result = [
|
|
426
|
+
"@shopify/hydrogen@2023.10.0",
|
|
427
|
+
"@shopify/cli-hydrogen@6.0.0",
|
|
428
|
+
"@shopify/remix-oxygen@2.0.0",
|
|
429
|
+
"@remix-run/react@2.1.0",
|
|
430
|
+
"@remix-run/dev@2.1.0",
|
|
431
|
+
"typescript@5.2.2"
|
|
432
|
+
];
|
|
433
|
+
const args = buildUpgradeCommandArgs({
|
|
434
|
+
selectedRelease,
|
|
435
|
+
currentDependencies
|
|
436
|
+
});
|
|
437
|
+
expect(args).toEqual(expect.arrayContaining(result));
|
|
438
|
+
});
|
|
439
|
+
it("upgrades and syncs up all available Remix deps if they are out-of-date", async () => {
|
|
440
|
+
const { releases } = await getChangelog();
|
|
441
|
+
const selectedRelease = releases.find(
|
|
442
|
+
(release) => release.version === "2023.10.0"
|
|
443
|
+
);
|
|
444
|
+
const currentDependencies = {
|
|
445
|
+
...OUTDATED_HYDROGEN_PACKAGE_JSON.dependencies,
|
|
446
|
+
"@remix-run/react": "1.3.0",
|
|
447
|
+
...OUTDATED_HYDROGEN_PACKAGE_JSON.devDependencies,
|
|
448
|
+
"@remix-run/dev": "1.2.0",
|
|
449
|
+
"@remix-run/css-bundle": "1.7.0"
|
|
450
|
+
};
|
|
451
|
+
const result = [
|
|
452
|
+
"@shopify/cli-hydrogen@6.0.0",
|
|
453
|
+
"@shopify/hydrogen@2023.10.0",
|
|
454
|
+
"@shopify/remix-oxygen@2.0.0",
|
|
455
|
+
"typescript@5.2.2",
|
|
456
|
+
"@remix-run/react@2.1.0",
|
|
457
|
+
"@remix-run/server-runtime@2.1.0",
|
|
458
|
+
"@remix-run/dev@2.1.0",
|
|
459
|
+
"@remix-run/eslint-config@2.1.0",
|
|
460
|
+
"@remix-run/css-bundle@2.1.0"
|
|
461
|
+
];
|
|
462
|
+
const args = buildUpgradeCommandArgs({
|
|
463
|
+
selectedRelease,
|
|
464
|
+
currentDependencies
|
|
465
|
+
});
|
|
466
|
+
expect(args).toEqual(result);
|
|
467
|
+
});
|
|
468
|
+
it("upgrades all available Remix deps if they are out-of-date", async () => {
|
|
469
|
+
const { releases } = await getChangelog();
|
|
470
|
+
const selectedRelease = releases.find(
|
|
471
|
+
(release) => release.version === "2023.10.0"
|
|
472
|
+
);
|
|
473
|
+
const currentDependencies = {
|
|
474
|
+
...OUTDATED_HYDROGEN_PACKAGE_JSON.dependencies,
|
|
475
|
+
"@remix-run/react": "1.8.0",
|
|
476
|
+
...OUTDATED_HYDROGEN_PACKAGE_JSON.devDependencies,
|
|
477
|
+
"@remix-run/dev": "1.8.0",
|
|
478
|
+
"@remix-run/css-bundle": "1.8.0"
|
|
479
|
+
};
|
|
480
|
+
const result = [
|
|
481
|
+
"@shopify/cli-hydrogen@6.0.0",
|
|
482
|
+
"@shopify/hydrogen@2023.10.0",
|
|
483
|
+
"@shopify/remix-oxygen@2.0.0",
|
|
484
|
+
"typescript@5.2.2",
|
|
485
|
+
"@remix-run/react@2.1.0",
|
|
486
|
+
"@remix-run/server-runtime@2.1.0",
|
|
487
|
+
"@remix-run/dev@2.1.0",
|
|
488
|
+
"@remix-run/eslint-config@2.1.0",
|
|
489
|
+
"@remix-run/css-bundle@2.1.0"
|
|
490
|
+
];
|
|
491
|
+
const args = buildUpgradeCommandArgs({
|
|
492
|
+
selectedRelease,
|
|
493
|
+
currentDependencies
|
|
494
|
+
});
|
|
495
|
+
expect(args).toEqual(result);
|
|
496
|
+
});
|
|
497
|
+
it("does not upgrade Remix deps if they are more up-to-date", async () => {
|
|
498
|
+
const { releases } = await getChangelog();
|
|
499
|
+
const selectedRelease = releases.find(
|
|
500
|
+
(release) => release.version === "2023.10.0"
|
|
501
|
+
);
|
|
502
|
+
const currentDependencies = {
|
|
503
|
+
...OUTDATED_HYDROGEN_PACKAGE_JSON.dependencies,
|
|
504
|
+
"@remix-run/react": "2.2.0",
|
|
505
|
+
...OUTDATED_HYDROGEN_PACKAGE_JSON.devDependencies,
|
|
506
|
+
"@remix-run/dev": "2.2.0"
|
|
507
|
+
};
|
|
508
|
+
const result = [
|
|
509
|
+
"@shopify/cli-hydrogen@6.0.0",
|
|
510
|
+
"@shopify/hydrogen@2023.10.0",
|
|
511
|
+
"@shopify/remix-oxygen@2.0.0",
|
|
512
|
+
"typescript@5.2.2"
|
|
513
|
+
];
|
|
514
|
+
const args = buildUpgradeCommandArgs({
|
|
515
|
+
selectedRelease,
|
|
516
|
+
currentDependencies
|
|
517
|
+
});
|
|
518
|
+
expect(args).toEqual(result);
|
|
519
|
+
});
|
|
520
|
+
it("does not install an optional dependency that was not installed", async () => {
|
|
521
|
+
const { releases } = await getChangelog();
|
|
522
|
+
const selectedRelease = Object.create(
|
|
523
|
+
// @ts-ignore - we know this release version exists
|
|
524
|
+
releases.find((release) => release.version === "2023.10.0")
|
|
525
|
+
);
|
|
526
|
+
selectedRelease.dependenciesMeta = {
|
|
527
|
+
typescript: {
|
|
528
|
+
required: false
|
|
529
|
+
}
|
|
530
|
+
};
|
|
531
|
+
const currentDependencies = {
|
|
532
|
+
...OUTDATED_HYDROGEN_PACKAGE_JSON.dependencies,
|
|
533
|
+
"@remix-run/react": "2.1.0",
|
|
534
|
+
...OUTDATED_HYDROGEN_PACKAGE_JSON.devDependencies,
|
|
535
|
+
"@remix-run/dev": "2.1.0"
|
|
536
|
+
};
|
|
537
|
+
delete currentDependencies["typescript"];
|
|
538
|
+
const result = [
|
|
539
|
+
"@shopify/cli-hydrogen@6.0.0",
|
|
540
|
+
"@shopify/hydrogen@2023.10.0",
|
|
541
|
+
"@shopify/remix-oxygen@2.0.0"
|
|
542
|
+
];
|
|
543
|
+
const args = buildUpgradeCommandArgs({
|
|
544
|
+
selectedRelease,
|
|
545
|
+
currentDependencies
|
|
546
|
+
});
|
|
547
|
+
expect(args).toEqual(result);
|
|
548
|
+
});
|
|
549
|
+
it("adds a required dependency that was not installed", async () => {
|
|
550
|
+
const { releases } = await getChangelog();
|
|
551
|
+
const selectedRelease = releases.find(
|
|
552
|
+
(release) => release.version === "2023.10.0"
|
|
553
|
+
);
|
|
554
|
+
const currentDependencies = {
|
|
555
|
+
...OUTDATED_HYDROGEN_PACKAGE_JSON.dependencies,
|
|
556
|
+
"@remix-run/react": "2.1.0",
|
|
557
|
+
...OUTDATED_HYDROGEN_PACKAGE_JSON.devDependencies,
|
|
558
|
+
"@remix-run/dev": "2.1.0"
|
|
559
|
+
};
|
|
560
|
+
delete currentDependencies["typescript"];
|
|
561
|
+
const result = [
|
|
562
|
+
"@shopify/cli-hydrogen@6.0.0",
|
|
563
|
+
"@shopify/hydrogen@2023.10.0",
|
|
564
|
+
"@shopify/remix-oxygen@2.0.0",
|
|
565
|
+
`typescript@${getAbsoluteVersion(
|
|
566
|
+
// @ts-ignore - we know this release version exists
|
|
567
|
+
selectedRelease.devDependencies.typescript
|
|
568
|
+
)}`
|
|
569
|
+
];
|
|
570
|
+
const args = buildUpgradeCommandArgs({
|
|
571
|
+
selectedRelease,
|
|
572
|
+
currentDependencies
|
|
573
|
+
});
|
|
574
|
+
expect(args).toEqual(expect.arrayContaining(result));
|
|
575
|
+
});
|
|
576
|
+
it("does not upgrade a required dependency that is further up-to-date", async () => {
|
|
577
|
+
const { releases } = await getChangelog();
|
|
578
|
+
const selectedRelease = releases.find(
|
|
579
|
+
(release) => release.version === "2023.10.0"
|
|
580
|
+
);
|
|
581
|
+
const currentDependencies = {
|
|
582
|
+
...OUTDATED_HYDROGEN_PACKAGE_JSON.dependencies,
|
|
583
|
+
"@remix-run/react": "2.1.0",
|
|
584
|
+
...OUTDATED_HYDROGEN_PACKAGE_JSON.devDependencies,
|
|
585
|
+
"@remix-run/dev": "2.1.0",
|
|
586
|
+
typescript: "5.3.0"
|
|
587
|
+
// more up-to-date than that of 2023.10.0
|
|
588
|
+
};
|
|
589
|
+
const result = [
|
|
590
|
+
"@shopify/cli-hydrogen@6.0.0",
|
|
591
|
+
"@shopify/hydrogen@2023.10.0",
|
|
592
|
+
"@shopify/remix-oxygen@2.0.0"
|
|
593
|
+
];
|
|
594
|
+
const args = buildUpgradeCommandArgs({
|
|
595
|
+
selectedRelease,
|
|
596
|
+
currentDependencies
|
|
597
|
+
});
|
|
598
|
+
expect(args).toEqual(expect.arrayContaining(result));
|
|
599
|
+
});
|
|
600
|
+
it("does not upgrade @next dependencies", async () => {
|
|
601
|
+
const { releases } = await getChangelog();
|
|
602
|
+
const selectedRelease = releases.find(
|
|
603
|
+
(release) => release.version === "2023.10.0"
|
|
604
|
+
);
|
|
605
|
+
const currentDependencies = {
|
|
606
|
+
...OUTDATED_HYDROGEN_PACKAGE_JSON.dependencies,
|
|
607
|
+
"@remix-run/react": "2.1.0",
|
|
608
|
+
...OUTDATED_HYDROGEN_PACKAGE_JSON.devDependencies,
|
|
609
|
+
"@remix-run/dev": "2.1.0",
|
|
610
|
+
"@shopify/hydrogen": "next"
|
|
611
|
+
};
|
|
612
|
+
const result = [
|
|
613
|
+
"@shopify/cli-hydrogen@6.0.0",
|
|
614
|
+
"@shopify/remix-oxygen@2.0.0",
|
|
615
|
+
`typescript@${getAbsoluteVersion(
|
|
616
|
+
// @ts-ignore - we know this release version exists
|
|
617
|
+
selectedRelease.devDependencies.typescript
|
|
618
|
+
)}`
|
|
619
|
+
];
|
|
620
|
+
const args = buildUpgradeCommandArgs({
|
|
621
|
+
selectedRelease,
|
|
622
|
+
currentDependencies
|
|
623
|
+
});
|
|
624
|
+
expect(args).toEqual(result);
|
|
625
|
+
});
|
|
626
|
+
});
|
|
627
|
+
});
|
|
628
|
+
const CUMMLATIVE_RELEASE = {
|
|
629
|
+
fixes: [
|
|
630
|
+
{
|
|
631
|
+
title: "Add a default Powered-By: Shopify-Hydrogen header",
|
|
632
|
+
pr: "https://github.com/Shopify/hydrogen/pull/872",
|
|
633
|
+
id: "872",
|
|
634
|
+
steps: [
|
|
635
|
+
{
|
|
636
|
+
title: " It can be disabled by passing poweredByHeader: false in the configuration object of createRequestHandler",
|
|
637
|
+
code: "YGBgdHMKaW1wb3J0IHtjcmVhdGVSZXF1ZXN0SGFuZGxlcn0gZnJvbSAnQHNob3BpZnkvcmVtaXgtb3h5Z2VuJzsKCmV4cG9ydCBkZWZhdWx0IHsKICBhc3luYyBmZXRjaChyZXF1ZXN0KSB7CiAgICAvLyAuLi4KICAgIGNvbnN0IGhhbmRsZVJlcXVlc3QgPSBjcmVhdGVSZXF1ZXN0SGFuZGxlcih7CiAgICAgIC8vIC4uLiBvdGhlciBwcm9wZXJ0aWVzIGluY2x1ZGVkCiAgICAgIHBvd2VyZWRCeUhlYWRlcjogZmFsc2UsCiAgICB9KTsKICAgIC8vIC4uLgogIH0sCn07CmBgYA",
|
|
638
|
+
file: "server.ts"
|
|
639
|
+
}
|
|
640
|
+
]
|
|
641
|
+
},
|
|
642
|
+
{
|
|
643
|
+
title: "Updated CLI prompts",
|
|
644
|
+
pr: "https://github.com/Shopify/hydrogen/pull/733",
|
|
645
|
+
id: "733",
|
|
646
|
+
steps: [
|
|
647
|
+
{
|
|
648
|
+
title: "Update package.json",
|
|
649
|
+
code: "YGBgZGlmZgoiZGVwZW5kZW5jaWVzIjogewotICAiQHNob3BpZnkvY2xpIjogIjMueC54IiwKKyAgIkBzaG9waWZ5L2NsaSI6ICIzLjQ1LjAiLAp9CmBgYA==",
|
|
650
|
+
file: "package.json"
|
|
651
|
+
}
|
|
652
|
+
]
|
|
653
|
+
},
|
|
654
|
+
{
|
|
655
|
+
title: "Added support for the Remix future flags v2_meta, v2_errorBoundary and v2_routeConvention to the generate command",
|
|
656
|
+
pr: "https://github.com/Shopify/hydrogen/pull/756",
|
|
657
|
+
id: "756"
|
|
658
|
+
},
|
|
659
|
+
{
|
|
660
|
+
title: "Update virtual route to use Remix V2 route name conventions",
|
|
661
|
+
pr: "https://github.com/Shopify/hydrogen/pull/792",
|
|
662
|
+
id: "792"
|
|
663
|
+
},
|
|
664
|
+
{
|
|
665
|
+
title: "Update internal Remix dependencies to 1.15.0",
|
|
666
|
+
pr: "https://github.com/Shopify/hydrogen/pull/728",
|
|
667
|
+
id: "728",
|
|
668
|
+
docs: "https://github.com/remix-run/remix/releases/tag/remix%401.15.0"
|
|
669
|
+
},
|
|
670
|
+
{
|
|
671
|
+
title: "Improve type safety in SEO data generators",
|
|
672
|
+
pr: "https://github.com/Shopify/hydrogen/pull/763",
|
|
673
|
+
id: "763"
|
|
674
|
+
},
|
|
675
|
+
{
|
|
676
|
+
title: "Stop hydrating with requestIdleCallback",
|
|
677
|
+
pr: "https://github.com/Shopify/hydrogen/pull/667",
|
|
678
|
+
id: "667"
|
|
679
|
+
},
|
|
680
|
+
{
|
|
681
|
+
title: "Fix active cart session event in Live View",
|
|
682
|
+
pr: "https://github.com/Shopify/hydrogen/pull/614",
|
|
683
|
+
id: "614",
|
|
684
|
+
steps: [
|
|
685
|
+
{
|
|
686
|
+
title: "Introducing getStorefrontHeaders that collects the required Shopify headers for making a Storefront API call.",
|
|
687
|
+
code: "YGBgdHMKKyBpbXBvcnQge2dldFN0b3JlZnJvbnRIZWFkZXJzfSBmcm9tICdAc2hvcGlmeS9yZW1peC1veHlnZW4nOwppbXBvcnQge2NyZWF0ZVN0b3JlZnJvbnRDbGllbnQsIHN0b3JlZnJvbnRSZWRpcmVjdH0gZnJvbSAnQHNob3BpZnkvaHlkcm9nZW4nOwoKZXhwb3J0IGRlZmF1bHQgewogIGFzeW5jIGZldGNoKAogICAgcmVxdWVzdDogUmVxdWVzdCwKICAgIGVudjogRW52LAogICAgZXhlY3V0aW9uQ29udGV4dDogRXhlY3V0aW9uQ29udGV4dCwKICApOiBQcm9taXNlPFJlc3BvbnNlPiB7CgogICAgY29uc3Qge3N0b3JlZnJvbnR9ID0gY3JlYXRlU3RvcmVmcm9udENsaWVudCh7CiAgICAgIGNhY2hlLAogICAgICB3YWl0VW50aWwsCi0gICAgIGJ1eWVySXA6IGdldEJ1eWVySXAocmVxdWVzdCksCiAgICAgIGkxOG46IHtsYW5ndWFnZTogJ0VOJywgY291bnRyeTogJ1VTJ30sCiAgICAgIHB1YmxpY1N0b3JlZnJvbnRUb2tlbjogZW52LlBVQkxJQ19TVE9SRUZST05UX0FQSV9UT0tFTiwKICAgICAgcHJpdmF0ZVN0b3JlZnJvbnRUb2tlbjogZW52LlBSSVZBVEVfU1RPUkVGUk9OVF9BUElfVE9LRU4sCiAgICAgIHN0b3JlRG9tYWluOiBgaHR0cHM6Ly8ke2Vudi5QVUJMSUNfU1RPUkVfRE9NQUlOfWAsCiAgICAgIHN0b3JlZnJvbnRBcGlWZXJzaW9uOiBlbnYuUFVCTElDX1NUT1JFRlJPTlRfQVBJX1ZFUlNJT04gfHwgJzIwMjMtMDEnLAogICAgICBzdG9yZWZyb250SWQ6IGVudi5QVUJMSUNfU1RPUkVGUk9OVF9JRCwKLSAgICAgcmVxdWVzdEdyb3VwSWQ6IHJlcXVlc3QuaGVhZGVycy5nZXQoJ3JlcXVlc3QtaWQnKSwKKyAgICAgc3RvcmVmcm9udEhlYWRlcnM6IGdldFN0b3JlZnJvbnRIZWFkZXJzKHJlcXVlc3QpLAogICAgfSk7CmBgYA==",
|
|
688
|
+
file: "server.ts"
|
|
689
|
+
}
|
|
690
|
+
]
|
|
691
|
+
}
|
|
692
|
+
],
|
|
693
|
+
features: [
|
|
694
|
+
{
|
|
695
|
+
title: "Add command to pull environment variables from a Hydrogen storefront",
|
|
696
|
+
pr: "https://github.com/Shopify/hydrogen/pull/809",
|
|
697
|
+
id: "809"
|
|
698
|
+
},
|
|
699
|
+
{
|
|
700
|
+
title: "New --debug flag for the dev command that attaches a Node inspector to the development server",
|
|
701
|
+
pr: "https://github.com/Shopify/hydrogen/pull/869",
|
|
702
|
+
id: "869"
|
|
703
|
+
},
|
|
704
|
+
{
|
|
705
|
+
title: "Add new commands for merchants to be able to list and link Hydrogen storefronts",
|
|
706
|
+
pr: "https://github.com/Shopify/hydrogen/pull/784",
|
|
707
|
+
id: "784"
|
|
708
|
+
},
|
|
709
|
+
{
|
|
710
|
+
title: "Added parseGid() utility",
|
|
711
|
+
pr: "https://github.com/Shopify/hydrogen/pull/845",
|
|
712
|
+
id: "845",
|
|
713
|
+
steps: [
|
|
714
|
+
{
|
|
715
|
+
title: "Example usage",
|
|
716
|
+
code: "YGBgdHMKaW1wb3J0IHtwYXJzZUdpZH0gZnJvbSAnQHNob3BpZnkvaHlkcm9nZW4tcmVhY3QnOwoKY29uc3Qge2lkLCByZXNvdXJjZX0gPSBwYXJzZUdpZCgnZ2lkOi8vc2hvcGlmeS9PcmRlci8xMjMnKTsKCmNvbnNvbGUubG9nKGlkKTsgLy8gMTIzCmNvbnNvbGUubG9nKHJlc291cmNlKTsgLy8gT3JkZXIKYGBg"
|
|
717
|
+
}
|
|
718
|
+
]
|
|
719
|
+
},
|
|
720
|
+
{
|
|
721
|
+
title: "Added a new shortcut command that creates a global h2 alias for the Hydrogen CLI",
|
|
722
|
+
pr: "https://github.com/Shopify/hydrogen/pull/679",
|
|
723
|
+
id: "679",
|
|
724
|
+
steps: [
|
|
725
|
+
{
|
|
726
|
+
title: "Create the h2 alias",
|
|
727
|
+
code: "YGBgYmFzaApucHggc2hvcGlmeSBoeWRyb2dlbiBzaG9ydGN1dApgYGA="
|
|
728
|
+
},
|
|
729
|
+
{
|
|
730
|
+
title: "After that, you can run commands using the new alias:",
|
|
731
|
+
code: "YGBgYmFzaApoMiBnZW5lcmF0ZSByb3V0ZSBob21lCmgyIGcgciBob21lICMgU2FtZSBhcyB0aGUgYWJvdmUKaDIgY2hlY2sgcm91dGVzCmBgYA=="
|
|
732
|
+
}
|
|
733
|
+
]
|
|
734
|
+
},
|
|
735
|
+
{
|
|
736
|
+
title: "Add an experimental createWithCache_unstable",
|
|
737
|
+
info: "This utility creates a function similar to useQuery from Hydrogen v1. Use this utility to query third-party APIs and apply custom cache options",
|
|
738
|
+
pr: "https://github.com/Shopify/hydrogen/pull/600",
|
|
739
|
+
id: "600",
|
|
740
|
+
steps: [
|
|
741
|
+
{
|
|
742
|
+
title: "To setup the utility, update your server.ts",
|
|
743
|
+
file: "server.ts",
|
|
744
|
+
code: "YGBgdHMKaW1wb3J0IHsKICBjcmVhdGVTdG9yZWZyb250Q2xpZW50LAogIGNyZWF0ZVdpdGhDYWNoZV91bnN0YWJsZSwKICBDYWNoZUxvbmcsCn0gZnJvbSAnQHNob3BpZnkvaHlkcm9nZW4nOwoKLy8gLi4uCgogIGNvbnN0IGNhY2hlID0gYXdhaXQgY2FjaGVzLm9wZW4oJ2h5ZHJvZ2VuJyk7CiAgY29uc3Qgd2l0aENhY2hlID0gY3JlYXRlV2l0aENhY2hlX3Vuc3RhYmxlKHtjYWNoZSwgd2FpdFVudGlsfSk7CgogIC8vIENyZWF0ZSBjdXN0b20gdXRpbGl0aWVzIHRvIHF1ZXJ5IHRoaXJkLXBhcnR5IEFQSXM6CiAgY29uc3QgZmV0Y2hNeUNNUyA9IChxdWVyeSkgPT4gewogICAgLy8gUHJlZml4IHRoZSBjYWNoZSBrZXkgYW5kIG1ha2UgaXQgdW5pcXVlIGJhc2VkIG9uIGFyZ3VtZW50cy4KICAgIHJldHVybiB3aXRoQ2FjaGUoWydteS1jbXMnLCBxdWVyeV0sIENhY2hlTG9uZygpLCAoKSA9PiB7CiAgICAgIGNvbnN0IGNtc0RhdGEgPSBhd2FpdCAoYXdhaXQgZmV0Y2goJ215LWNtcy5jb20vYXBpJywgewogICAgICAgIG1ldGhvZDogJ1BPU1QnLAogICAgICAgIGJvZHk6IHF1ZXJ5CiAgICAgIH0pKS5qc29uKCk7CgogICAgICBjb25zdCBuZXh0UGFnZSA9IChhd2FpdCBmZXRjaCgnbXktY21zLmNvbS9hcGknLCB7CiAgICAgICAgbWV0aG9kOiAnUE9TVCcsCiAgICAgICAgYm9keTogY21zRGF0YTEubmV4dFBhZ2VRdWVyeSwKICAgICAgfSkpLmpzb24oKTsKCiAgICAgIHJldHVybiB7Li4uY21zRGF0YSwgbmV4dFBhZ2V9CiAgICB9KTsKICB9OwoKICBjb25zdCBoYW5kbGVSZXF1ZXN0ID0gY3JlYXRlUmVxdWVzdEhhbmRsZXIoewogICAgYnVpbGQ6IHJlbWl4QnVpbGQsCiAgICBtb2RlOiBwcm9jZXNzLmVudi5OT0RFX0VOViwKICAgIGdldExvYWRDb250ZXh0OiAoKSA9PiAoewogICAgICBzZXNzaW9uLAogICAgICB3YWl0VW50aWwsCiAgICAgIHN0b3JlZnJvbnQsCiAgICAgIGVudiwKICAgICAgZmV0Y2hNeUNNUywKICAgIH0pLAogIH0pOwpgYGA="
|
|
745
|
+
}
|
|
746
|
+
]
|
|
747
|
+
},
|
|
748
|
+
{
|
|
749
|
+
title: "Update Remix to 1.14.0",
|
|
750
|
+
pr: "https://github.com/Shopify/hydrogen/pull/599",
|
|
751
|
+
id: "599"
|
|
752
|
+
},
|
|
753
|
+
{
|
|
754
|
+
title: "Added Cache-Control defaults to all the demo store routes",
|
|
755
|
+
pr: "https://github.com/Shopify/hydrogen/pull/599",
|
|
756
|
+
id: "599"
|
|
757
|
+
},
|
|
758
|
+
{
|
|
759
|
+
title: "Added new loader API for setting SEO tags within route module",
|
|
760
|
+
pr: "https://github.com/Shopify/hydrogen/pull/591",
|
|
761
|
+
id: "591"
|
|
762
|
+
},
|
|
763
|
+
{
|
|
764
|
+
title: "ShopPayButton component now can receive a storeDomain",
|
|
765
|
+
pr: "https://github.com/Shopify/hydrogen/pull/645",
|
|
766
|
+
id: "645"
|
|
767
|
+
},
|
|
768
|
+
{
|
|
769
|
+
title: "Added robots option to SEO config that allows users granular control over the robots meta tag.",
|
|
770
|
+
pr: "https://github.com/Shopify/hydrogen/pull/572",
|
|
771
|
+
id: "572",
|
|
772
|
+
steps: [
|
|
773
|
+
{
|
|
774
|
+
title: "Example usage",
|
|
775
|
+
code: "YGBgdHMKZXhwb3J0IGhhbmRsZSA9IHsKICBzZW86IHsKICAgIHJvYm90czogewogICAgICBub0luZGV4OiBmYWxzZSwKICAgICAgbm9Gb2xsb3c6IGZhbHNlLAogICAgfQogIH0KfQpgYGA=",
|
|
776
|
+
file: "All files that use SEO config"
|
|
777
|
+
}
|
|
778
|
+
]
|
|
779
|
+
},
|
|
780
|
+
{
|
|
781
|
+
title: "Added decoding prop to the SpreadMedia component",
|
|
782
|
+
pr: "https://github.com/Shopify/hydrogen/pull/642",
|
|
783
|
+
id: "642"
|
|
784
|
+
}
|
|
785
|
+
]
|
|
786
|
+
};
|