@shopify/cli-hydrogen 7.1.2 → 8.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-vite.js +19 -10
- package/dist/commands/hydrogen/build.js +10 -2
- package/dist/commands/hydrogen/check.js +1 -0
- package/dist/commands/hydrogen/codegen.js +1 -0
- package/dist/commands/hydrogen/customer-account/push.js +170 -0
- package/dist/commands/hydrogen/debug/cpu.js +3 -0
- package/dist/commands/hydrogen/deploy.js +121 -36
- package/dist/commands/hydrogen/dev-vite.js +128 -59
- package/dist/commands/hydrogen/dev.js +108 -51
- package/dist/commands/hydrogen/env/list.js +7 -8
- package/dist/commands/hydrogen/env/pull.js +17 -1
- package/dist/commands/hydrogen/env/{push__unstable.js → push.js} +23 -50
- package/dist/commands/hydrogen/generate/route.js +1 -0
- package/dist/commands/hydrogen/init.js +45 -17
- package/dist/commands/hydrogen/link.js +20 -4
- package/dist/commands/hydrogen/list.js +1 -0
- package/dist/commands/hydrogen/login.js +1 -0
- package/dist/commands/hydrogen/logout.js +1 -0
- package/dist/commands/hydrogen/preview.js +31 -16
- package/dist/commands/hydrogen/setup/css.js +8 -1
- package/dist/commands/hydrogen/setup/markets.js +1 -0
- package/dist/commands/hydrogen/setup/vite.js +244 -138
- package/dist/commands/hydrogen/setup.js +21 -22
- package/dist/commands/hydrogen/shortcut.js +10 -0
- package/dist/commands/hydrogen/unlink.js +1 -0
- package/dist/commands/hydrogen/upgrade.js +2 -1
- package/dist/generator-templates/assets/vite/package.json +3 -4
- package/dist/generator-templates/assets/vite/vite.config.js +10 -2
- package/dist/generator-templates/starter/CHANGELOG.md +89 -0
- package/dist/generator-templates/starter/README.md +3 -44
- package/dist/generator-templates/starter/app/graphql/customer-account/CustomerDetailsQuery.ts +1 -0
- package/dist/generator-templates/starter/app/lib/fragments.ts +2 -0
- package/dist/generator-templates/starter/app/root.tsx +2 -5
- package/dist/generator-templates/starter/app/routes/account.orders._index.tsx +1 -1
- package/dist/generator-templates/starter/app/routes/account.tsx +1 -1
- package/dist/generator-templates/starter/app/routes/collections.all.tsx +160 -0
- package/dist/generator-templates/starter/app/routes/products.$handle.tsx +1 -2
- package/dist/generator-templates/starter/customer-accountapi.generated.d.ts +6 -3
- package/dist/generator-templates/starter/{remix.env.d.ts → env.d.ts} +8 -2
- package/dist/generator-templates/starter/package.json +14 -9
- package/dist/generator-templates/starter/server.ts +2 -1
- package/dist/generator-templates/starter/storefrontapi.generated.d.ts +59 -3
- package/dist/generator-templates/starter/vite.config.ts +21 -0
- package/dist/{commands/hydrogen/init.d.ts → init.d.ts} +11 -3
- package/dist/lib/check-lockfile.js +12 -18
- package/dist/lib/codegen.js +37 -13
- package/dist/lib/common.js +50 -0
- package/dist/lib/cpu-profiler.js +4 -1
- package/dist/lib/dev-shared.js +97 -0
- package/dist/lib/environment-variables.js +51 -30
- package/dist/lib/file.js +8 -1
- package/dist/lib/flags.js +37 -16
- package/dist/lib/graphql/admin/customer-application-update.js +29 -0
- package/dist/lib/graphql/admin/get-oxygen-data.js +1 -0
- package/dist/lib/graphql/admin/list-environments.js +1 -0
- package/dist/lib/graphql/admin/pull-variables.js +4 -4
- package/dist/lib/graphql/admin/test-helper.js +37 -0
- package/dist/lib/log.js +86 -13
- package/dist/lib/mini-oxygen/common.js +19 -33
- package/dist/lib/mini-oxygen/index.js +6 -2
- package/dist/lib/mini-oxygen/node.js +43 -31
- package/dist/lib/mini-oxygen/workerd.js +72 -165
- package/dist/lib/missing-routes.js +1 -1
- package/dist/lib/onboarding/common.js +82 -70
- package/dist/lib/onboarding/local.js +19 -9
- package/dist/lib/onboarding/remote.js +35 -30
- package/dist/lib/package-managers.js +24 -0
- package/dist/lib/remix-config.js +17 -1
- package/dist/lib/request-events.js +6 -1
- package/dist/lib/setups/i18n/replacers.js +9 -6
- package/dist/lib/setups/routes/generate.js +1 -0
- package/dist/lib/shell.js +2 -1
- package/dist/lib/shopify-config.js +19 -1
- package/dist/lib/template-diff.js +36 -15
- package/dist/lib/template-downloader.js +35 -5
- package/dist/lib/transpile/morph/typedefs.js +5 -2
- package/dist/lib/transpile/project.js +8 -4
- package/dist/lib/tunneling.js +44 -0
- package/dist/lib/virtual-routes.js +1 -1
- package/dist/lib/vite-config.js +39 -9
- package/oclif.manifest.json +711 -498
- package/package.json +32 -24
- package/dist/commands/hydrogen/deploy.test.js +0 -553
- package/dist/commands/hydrogen/env/list.test.js +0 -148
- package/dist/commands/hydrogen/env/pull.test.js +0 -207
- package/dist/commands/hydrogen/env/push__unstable.test.js +0 -383
- package/dist/commands/hydrogen/generate/route.test.js +0 -43
- package/dist/commands/hydrogen/init.test.js +0 -641
- package/dist/commands/hydrogen/link.test.js +0 -187
- package/dist/commands/hydrogen/list.test.js +0 -111
- package/dist/commands/hydrogen/setup.test.js +0 -61
- package/dist/commands/hydrogen/shortcut.test.js +0 -30
- package/dist/commands/hydrogen/unlink.test.js +0 -36
- package/dist/commands/hydrogen/upgrade.test.js +0 -786
- package/dist/generator-templates/starter/remix.config.js +0 -24
- package/dist/lib/auth.test.js +0 -157
- package/dist/lib/check-lockfile.test.js +0 -81
- package/dist/lib/check-version.test.js +0 -86
- package/dist/lib/environment-variables.test.js +0 -149
- package/dist/lib/file.test.js +0 -68
- package/dist/lib/flags.test.js +0 -43
- package/dist/lib/get-oxygen-deployment-data.test.js +0 -120
- package/dist/lib/gid.test.js +0 -15
- package/dist/lib/graphql/admin/client.test.js +0 -76
- package/dist/lib/graphql/admin/create-storefront.test.js +0 -64
- package/dist/lib/graphql/admin/link-storefront.test.js +0 -38
- package/dist/lib/graphql/admin/list-environments.test.js +0 -44
- package/dist/lib/graphql/admin/list-storefronts.test.js +0 -44
- package/dist/lib/graphql/admin/pull-variables.test.js +0 -43
- package/dist/lib/graphql/business-platform/user-account.test.js +0 -80
- package/dist/lib/log.test.js +0 -92
- package/dist/lib/mini-oxygen/assets.js +0 -134
- package/dist/lib/mini-oxygen/mini-oxygen.test.js +0 -214
- package/dist/lib/mini-oxygen/workerd-inspector-logs.js +0 -227
- package/dist/lib/mini-oxygen/workerd-inspector-proxy.js +0 -200
- package/dist/lib/mini-oxygen/workerd-inspector.js +0 -219
- package/dist/lib/missing-routes.test.js +0 -45
- package/dist/lib/remix-version-check.test.js +0 -39
- package/dist/lib/remix-version-interop.test.js +0 -13
- package/dist/lib/setups/i18n/domains.test.js +0 -39
- package/dist/lib/setups/i18n/replacers.test.js +0 -261
- package/dist/lib/setups/i18n/subdomains.test.js +0 -39
- package/dist/lib/setups/i18n/subfolders.test.js +0 -39
- package/dist/lib/setups/routes/generate.test.js +0 -296
- package/dist/lib/shell.test.js +0 -111
- package/dist/lib/shopify-config.test.js +0 -199
- package/dist/lib/string.test.js +0 -16
- package/dist/lib/virtual-routes.test.js +0 -49
- package/dist/lib/vite/hydrogen-middleware.js +0 -82
- package/dist/lib/vite/mini-oxygen.js +0 -152
- package/dist/lib/vite/plugins.d.ts +0 -27
- package/dist/lib/vite/plugins.js +0 -139
- package/dist/lib/vite/shared.js +0 -10
- package/dist/lib/vite/utils.js +0 -55
- package/dist/lib/vite/worker-entry.js +0 -1518
- /package/dist/generator-templates/starter/{.eslintrc.js → .eslintrc.cjs} +0 -0
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
import { resolvePath } from '@shopify/cli-kit/node/path';
|
|
1
|
+
import { resolvePath, joinPath } from '@shopify/cli-kit/node/path';
|
|
2
2
|
import Command from '@shopify/cli-kit/node/base-command';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { installNodeModules, getPackageManager } from '@shopify/cli-kit/node/node-package-manager';
|
|
3
|
+
import { renderTasks, renderSuccess } from '@shopify/cli-kit/node/ui';
|
|
4
|
+
import { removeFile, moveFile, readFile, writeFile, fileExists } from '@shopify/cli-kit/node/fs';
|
|
5
|
+
import { readAndParsePackageJson, installNodeModules, getPackageManager } from '@shopify/cli-kit/node/node-package-manager';
|
|
6
6
|
import { commonFlags, flagsToCamelObject } from '../../../lib/flags.js';
|
|
7
|
-
import {
|
|
7
|
+
import { getRawRemixConfig } from '../../../lib/remix-config.js';
|
|
8
8
|
import { replaceFileContent, mergePackageJson } from '../../../lib/file.js';
|
|
9
9
|
import { importLangAstGrep } from '../../../lib/ast.js';
|
|
10
10
|
import { getAssetDir } from '../../../lib/build.js';
|
|
11
|
-
import { getCodeFormatOptions } from '../../../lib/format-code.js';
|
|
11
|
+
import { getCodeFormatOptions, formatCode } from '../../../lib/format-code.js';
|
|
12
|
+
import { hasViteConfig } from '../../../lib/vite-config.js';
|
|
13
|
+
import { AbortError } from '@shopify/cli-kit/node/error';
|
|
14
|
+
import { outputNewline } from '@shopify/cli-kit/node/output';
|
|
12
15
|
|
|
13
16
|
class SetupVite extends Command {
|
|
14
17
|
static description = "EXPERIMENTAL: Upgrades the project to use Vite.";
|
|
@@ -24,16 +27,35 @@ class SetupVite extends Command {
|
|
|
24
27
|
});
|
|
25
28
|
}
|
|
26
29
|
}
|
|
30
|
+
const tailwindPostCSSConfig = `export default {
|
|
31
|
+
plugins: {
|
|
32
|
+
tailwindcss: {},
|
|
33
|
+
autoprefixer: {},
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
`;
|
|
27
37
|
async function runSetupVite({ directory }) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
|
|
38
|
+
outputNewline();
|
|
39
|
+
if (await hasViteConfig(directory)) {
|
|
40
|
+
throw new AbortError("This project already has a Vite config file.");
|
|
41
|
+
}
|
|
42
|
+
const [rawRemixConfig, pkgJson, formatOptions] = await Promise.all([
|
|
43
|
+
getRawRemixConfig(directory),
|
|
44
|
+
readAndParsePackageJson(joinPath(directory, "package.json")),
|
|
45
|
+
getCodeFormatOptions(directory)
|
|
46
|
+
]);
|
|
47
|
+
const serverEntry = rawRemixConfig.server || "server.js";
|
|
48
|
+
const isTS = serverEntry.endsWith(".ts");
|
|
49
|
+
const fileExt = isTS ? "tsx" : "jsx";
|
|
50
|
+
const viteAssets = getAssetDir("vite");
|
|
51
|
+
const usesTailwind = !!rawRemixConfig.tailwind;
|
|
52
|
+
const postCssConfigPath = resolvePath(directory, "postcss.config.js");
|
|
34
53
|
const handlePartialIssue = () => {
|
|
35
54
|
};
|
|
36
55
|
const backgroundWorkPromise = Promise.all([
|
|
56
|
+
removeFile(resolvePath(directory, "remix.config.js")).catch(
|
|
57
|
+
handlePartialIssue
|
|
58
|
+
),
|
|
37
59
|
moveFile(
|
|
38
60
|
resolvePath(directory, "remix.env.d.ts"),
|
|
39
61
|
resolvePath(directory, "env.d.ts")
|
|
@@ -48,137 +70,217 @@ async function runSetupVite({ directory }) {
|
|
|
48
70
|
resolvePath(directory, ".eslintrc.js"),
|
|
49
71
|
resolvePath(directory, ".eslintrc.cjs")
|
|
50
72
|
).catch(handlePartialIssue),
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
73
|
+
// Adjust PostCSS configuration:
|
|
74
|
+
readFile(resolvePath(directory, "postcss.config.js")).then(async (postCssContent) => {
|
|
75
|
+
const hasTailwindPlugin = postCssContent.includes("tailwindcss");
|
|
76
|
+
if (!hasTailwindPlugin && usesTailwind) {
|
|
77
|
+
postCssContent = await formatCode(
|
|
78
|
+
postCssContent.replace(
|
|
79
|
+
/(plugins:\s+{)/,
|
|
80
|
+
"$1\n tailwindcss: {},"
|
|
81
|
+
),
|
|
82
|
+
formatOptions
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
const isCJS = postCssContent.includes("module.exports") || postCssContent.includes("exports.") || postCssContent.includes("require(");
|
|
86
|
+
return writeFile(
|
|
87
|
+
isCJS ? postCssConfigPath.replace(".js", ".cjs") : postCssConfigPath,
|
|
88
|
+
postCssContent
|
|
89
|
+
);
|
|
90
|
+
}).catch(async () => {
|
|
91
|
+
if (usesTailwind && !await fileExists(postCssConfigPath) && !await fileExists(postCssConfigPath.replace(".js", ".cjs"))) {
|
|
92
|
+
return writeFile(postCssConfigPath, tailwindPostCSSConfig);
|
|
93
|
+
}
|
|
94
|
+
}).catch(handlePartialIssue),
|
|
95
|
+
// Adjust dependencies:
|
|
96
|
+
mergePackageJson(viteAssets, directory, {
|
|
97
|
+
onResult(pkgJson2) {
|
|
98
|
+
if (pkgJson2.dependencies) {
|
|
99
|
+
delete pkgJson2.dependencies["@remix-run/css-bundle"];
|
|
100
|
+
}
|
|
101
|
+
if (pkgJson2.devDependencies) {
|
|
102
|
+
if (pkgJson2.devDependencies["@vanilla-extract/css"]) {
|
|
103
|
+
pkgJson2.devDependencies["@vanilla-extract/vite-plugin"] = "^4.0.0";
|
|
104
|
+
pkgJson2.devDependencies = Object.keys(pkgJson2.devDependencies).sort().reduce((acc, key) => {
|
|
105
|
+
acc[key] = pkgJson2.devDependencies?.[key];
|
|
106
|
+
return acc;
|
|
107
|
+
}, {});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return pkgJson2;
|
|
111
|
+
}
|
|
112
|
+
}),
|
|
113
|
+
// Build `vite.config.js` for the project:
|
|
114
|
+
readFile(resolvePath(viteAssets, "vite.config.js")).then(
|
|
115
|
+
async (viteConfigContent) => {
|
|
116
|
+
const hasVanillaExtract = !!pkgJson.devDependencies?.["@vanilla-extract/css"];
|
|
117
|
+
if (hasVanillaExtract) {
|
|
118
|
+
viteConfigContent = viteConfigContent.replace(
|
|
119
|
+
/\n\n/g,
|
|
120
|
+
`
|
|
121
|
+
import {vanillaExtractPlugin} from '@vanilla-extract/vite-plugin';
|
|
122
|
+
|
|
123
|
+
`
|
|
124
|
+
).replace(/^(\s+)\],/m, "$1 vanillaExtractPlugin(),\n$1],");
|
|
125
|
+
}
|
|
126
|
+
const { future, appDirectory, ignoredRouteFiles, routes } = rawRemixConfig;
|
|
127
|
+
for (const flag of [
|
|
128
|
+
"v3_fetcherPersist",
|
|
129
|
+
"v3_throwAbortReason",
|
|
130
|
+
"v3_relativeSplatPath"
|
|
131
|
+
]) {
|
|
132
|
+
if (!future?.[flag]) {
|
|
133
|
+
viteConfigContent = viteConfigContent.replace(
|
|
134
|
+
`${flag}: true`,
|
|
135
|
+
`${flag}: false`
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (appDirectory && appDirectory !== "app") {
|
|
140
|
+
viteConfigContent = viteConfigContent.replace(
|
|
141
|
+
/^(\s+)(future:)/m,
|
|
142
|
+
`$1appDirectory: '${appDirectory}',
|
|
143
|
+
$1$2`
|
|
82
144
|
);
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
145
|
+
}
|
|
146
|
+
if (ignoredRouteFiles) {
|
|
147
|
+
viteConfigContent = viteConfigContent.replace(
|
|
148
|
+
/^(\s+)(future:)/m,
|
|
149
|
+
`$1ignoredRouteFiles: ${JSON.stringify(ignoredRouteFiles)},
|
|
150
|
+
$1$2`
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
if (routes) {
|
|
154
|
+
viteConfigContent = viteConfigContent.replace(
|
|
155
|
+
/^(\s+)(future:)/m,
|
|
156
|
+
`$1routes: ${routes.toString()},
|
|
157
|
+
$1$2`
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
const viteConfigPath = resolvePath(
|
|
161
|
+
directory,
|
|
162
|
+
"vite.config." + fileExt.slice(0, 2)
|
|
163
|
+
);
|
|
164
|
+
viteConfigContent = await formatCode(
|
|
165
|
+
viteConfigContent,
|
|
166
|
+
formatOptions,
|
|
167
|
+
viteConfigPath
|
|
168
|
+
);
|
|
169
|
+
return writeFile(viteConfigPath, viteConfigContent);
|
|
170
|
+
}
|
|
171
|
+
),
|
|
172
|
+
// Adjust server entry:
|
|
173
|
+
replaceFileContent(
|
|
174
|
+
resolvePath(directory, serverEntry),
|
|
175
|
+
false,
|
|
176
|
+
(content) => (isTS ? "// @ts-ignore\n" : "") + content.replace(
|
|
177
|
+
"@remix-run/dev/server-build",
|
|
178
|
+
"virtual:remix/server-build"
|
|
179
|
+
)
|
|
180
|
+
),
|
|
181
|
+
// Adjust CSS imports in the project routes:
|
|
182
|
+
importLangAstGrep(fileExt).then(async (astGrep) => {
|
|
183
|
+
const appDirectory = resolvePath(
|
|
184
|
+
directory,
|
|
185
|
+
rawRemixConfig.appDirectory ?? "app"
|
|
186
|
+
);
|
|
187
|
+
const rootFilepath = joinPath(appDirectory, "root." + fileExt);
|
|
188
|
+
await new Promise(async (resolve, reject) => {
|
|
189
|
+
const fileNumber = await astGrep.findInFiles(
|
|
190
|
+
{
|
|
191
|
+
paths: [rootFilepath, joinPath(appDirectory, "routes")],
|
|
192
|
+
matcher: {
|
|
193
|
+
rule: {
|
|
194
|
+
kind: "string_fragment",
|
|
195
|
+
regex: "\\.css$",
|
|
196
|
+
inside: {
|
|
197
|
+
kind: "import_statement",
|
|
198
|
+
stopBy: "end"
|
|
99
199
|
}
|
|
100
|
-
},
|
|
101
|
-
async (err, nodes) => {
|
|
102
|
-
if (err)
|
|
103
|
-
reject(err);
|
|
104
|
-
const nodeMap = {};
|
|
105
|
-
nodes.forEach((node) => {
|
|
106
|
-
const filename = node.getRoot().filename();
|
|
107
|
-
const content = node.getRoot().root().text();
|
|
108
|
-
const position = node.range().end.index;
|
|
109
|
-
const tmp = nodeMap[filename] || { content, positions: [] };
|
|
110
|
-
tmp.positions.push(position);
|
|
111
|
-
nodeMap[filename] = tmp;
|
|
112
|
-
});
|
|
113
|
-
await Promise.all(
|
|
114
|
-
Object.entries(nodeMap).flatMap(
|
|
115
|
-
([filename, { content, positions }]) => {
|
|
116
|
-
positions.reverse();
|
|
117
|
-
for (const position of positions) {
|
|
118
|
-
content = content.slice(0, position) + "?url" + content.slice(position);
|
|
119
|
-
}
|
|
120
|
-
return writeFile(filename, content);
|
|
121
|
-
}
|
|
122
|
-
)
|
|
123
|
-
);
|
|
124
|
-
resolve(null);
|
|
125
200
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
async (err, nodes) => {
|
|
204
|
+
if (err)
|
|
205
|
+
reject(err);
|
|
206
|
+
const nodeMap = {};
|
|
207
|
+
nodes.forEach((node) => {
|
|
208
|
+
if (node.text().endsWith(".module.css")) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
const filename = node.getRoot().filename();
|
|
212
|
+
const content = node.getRoot().root().text();
|
|
213
|
+
const position = node.range().end.index;
|
|
214
|
+
const tmp = nodeMap[filename] || { content, positions: [] };
|
|
215
|
+
tmp.positions.push(position);
|
|
216
|
+
nodeMap[filename] = tmp;
|
|
217
|
+
});
|
|
218
|
+
await Promise.all(
|
|
219
|
+
Object.entries(nodeMap).flatMap(
|
|
220
|
+
([filename, { content, positions }]) => {
|
|
221
|
+
positions.reverse();
|
|
222
|
+
for (const position of positions) {
|
|
223
|
+
content = content.slice(0, position) + "?url" + content.slice(position);
|
|
147
224
|
}
|
|
225
|
+
return writeFile(filename, content);
|
|
148
226
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
227
|
+
)
|
|
228
|
+
);
|
|
229
|
+
resolve(null);
|
|
230
|
+
}
|
|
231
|
+
);
|
|
232
|
+
if (fileNumber === 0)
|
|
233
|
+
resolve(null);
|
|
234
|
+
});
|
|
235
|
+
await replaceFileContent(rootFilepath, formatOptions, (content) => {
|
|
236
|
+
const root = astGrep.parse(content).root();
|
|
237
|
+
const liveReloadRegex = "LiveReload";
|
|
238
|
+
const hasLiveReloadRule = {
|
|
239
|
+
kind: "identifier",
|
|
240
|
+
regex: liveReloadRegex
|
|
241
|
+
};
|
|
242
|
+
const liveReloadImport = root.find({
|
|
243
|
+
rule: {
|
|
244
|
+
kind: "import_specifier",
|
|
245
|
+
regex: liveReloadRegex,
|
|
246
|
+
inside: {
|
|
247
|
+
kind: "import_statement",
|
|
248
|
+
stopBy: "end"
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
const liveReloadElements = root.findAll({
|
|
253
|
+
rule: {
|
|
254
|
+
any: [
|
|
255
|
+
{
|
|
256
|
+
kind: "jsx_self_closing_element",
|
|
257
|
+
has: hasLiveReloadRule
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
kind: "jsx_element",
|
|
261
|
+
has: {
|
|
262
|
+
kind: "jsx_opening_element",
|
|
263
|
+
has: hasLiveReloadRule
|
|
165
264
|
}
|
|
166
|
-
});
|
|
167
|
-
for (const node of [
|
|
168
|
-
// From bottom to top
|
|
169
|
-
...liveReloadElements.reverse(),
|
|
170
|
-
liveReloadImport
|
|
171
|
-
]) {
|
|
172
|
-
if (!node)
|
|
173
|
-
continue;
|
|
174
|
-
const { start, end } = node.range();
|
|
175
|
-
content = content.slice(0, start.index) + content.slice(end.index);
|
|
176
265
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
266
|
+
]
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
for (const node of [
|
|
270
|
+
// From bottom to top
|
|
271
|
+
...liveReloadElements.reverse(),
|
|
272
|
+
liveReloadImport
|
|
273
|
+
]) {
|
|
274
|
+
if (!node)
|
|
275
|
+
continue;
|
|
276
|
+
const { start, end } = node.range();
|
|
277
|
+
content = content.slice(0, start.index) + content.slice(end.index);
|
|
278
|
+
}
|
|
279
|
+
return content.replace(/,\s*,/g, ",").replace(
|
|
280
|
+
/import\s+{\s+cssBundleHref\s+}\s+from\s+['"]@remix-run\/css-bundle['"];?\n/,
|
|
281
|
+
""
|
|
282
|
+
).replace(/\.\.\.\(\s*cssBundleHref[^)]+\),?/, "");
|
|
283
|
+
});
|
|
182
284
|
})
|
|
183
285
|
]);
|
|
184
286
|
await renderTasks([
|
|
@@ -201,8 +303,12 @@ async function runSetupVite({ directory }) {
|
|
|
201
303
|
]);
|
|
202
304
|
renderSuccess({
|
|
203
305
|
headline: `Your Vite project is ready!`,
|
|
204
|
-
body: `We've modified your project to use Vite
|
|
205
|
-
Please use
|
|
306
|
+
body: `We've modified your project to use Vite.
|
|
307
|
+
Please use Git to review the changes.`,
|
|
308
|
+
nextSteps: [
|
|
309
|
+
rawRemixConfig.mdx ? "Setup MDX support in Vite: https://remix.run/docs/en/main/future/vite#add-mdx-plugin" : "",
|
|
310
|
+
`See more information about Vite in Remix at https://remix.run/docs/en/main/future/vite`
|
|
311
|
+
].filter(Boolean)
|
|
206
312
|
});
|
|
207
313
|
}
|
|
208
314
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import Command from '@shopify/cli-kit/node/base-command';
|
|
2
2
|
import { AbortController } from '@shopify/cli-kit/node/abort';
|
|
3
3
|
import { renderTasks } from '@shopify/cli-kit/node/ui';
|
|
4
|
-
import { resolvePath, basename } from '@shopify/cli-kit/node/path';
|
|
5
|
-
import { copyFile } from '@shopify/cli-kit/node/fs';
|
|
4
|
+
import { resolvePath, basename, joinPath } from '@shopify/cli-kit/node/path';
|
|
5
|
+
import { fileExists, glob, copyFile } from '@shopify/cli-kit/node/fs';
|
|
6
6
|
import { commonFlags, overrideFlag, flagsToCamelObject } from '../../lib/flags.js';
|
|
7
7
|
import { renderI18nPrompt, setupI18nStrategy } from '../../lib/setups/i18n/index.js';
|
|
8
8
|
import { getRemixConfig } from '../../lib/remix-config.js';
|
|
@@ -33,8 +33,10 @@ class Setup extends Command {
|
|
|
33
33
|
}
|
|
34
34
|
async function runSetup(options) {
|
|
35
35
|
const controller = new AbortController();
|
|
36
|
-
const
|
|
37
|
-
|
|
36
|
+
const { rootDirectory, appDirectory, serverEntryPoint } = await getRemixConfig(
|
|
37
|
+
options.directory
|
|
38
|
+
);
|
|
39
|
+
const location = basename(rootDirectory);
|
|
38
40
|
const cliCommandPromise = getCliCommand();
|
|
39
41
|
let backgroundWorkPromise = Promise.resolve();
|
|
40
42
|
const tasks = [
|
|
@@ -55,32 +57,29 @@ async function runSetup(options) {
|
|
|
55
57
|
);
|
|
56
58
|
let routes;
|
|
57
59
|
if (needsRouteGeneration) {
|
|
58
|
-
const
|
|
60
|
+
const templateRoot = getTemplateAppFile("..");
|
|
61
|
+
const [typescript, dtsFiles] = await Promise.all([
|
|
62
|
+
fileExists(joinPath(rootDirectory, "tsconfig.json")),
|
|
63
|
+
glob("*.d.ts", { cwd: templateRoot })
|
|
64
|
+
]);
|
|
59
65
|
backgroundWorkPromise = backgroundWorkPromise.then(
|
|
60
66
|
() => Promise.all([
|
|
61
|
-
...
|
|
62
|
-
copyFile(
|
|
63
|
-
|
|
64
|
-
resolvePath(
|
|
65
|
-
),
|
|
66
|
-
copyFile(
|
|
67
|
-
getTemplateAppFile("../storefrontapi.generated.d.ts"),
|
|
68
|
-
resolvePath(
|
|
69
|
-
remixConfig.rootDirectory,
|
|
70
|
-
"storefrontapi.generated.d.ts"
|
|
71
|
-
)
|
|
67
|
+
...dtsFiles.map(
|
|
68
|
+
(filename) => copyFile(
|
|
69
|
+
joinPath(templateRoot, filename),
|
|
70
|
+
resolvePath(rootDirectory, filename)
|
|
72
71
|
)
|
|
73
|
-
|
|
72
|
+
),
|
|
74
73
|
// Copy app entries
|
|
75
74
|
generateProjectEntries({
|
|
76
|
-
rootDirectory
|
|
77
|
-
appDirectory
|
|
75
|
+
rootDirectory,
|
|
76
|
+
appDirectory,
|
|
78
77
|
typescript
|
|
79
78
|
})
|
|
80
79
|
])
|
|
81
80
|
).then(async () => {
|
|
82
81
|
routes = await setupRoutes(
|
|
83
|
-
|
|
82
|
+
rootDirectory,
|
|
84
83
|
typescript ? "ts" : "js",
|
|
85
84
|
i18n
|
|
86
85
|
);
|
|
@@ -88,7 +87,7 @@ async function runSetup(options) {
|
|
|
88
87
|
}
|
|
89
88
|
if (i18n) {
|
|
90
89
|
backgroundWorkPromise = backgroundWorkPromise.then(
|
|
91
|
-
() => setupI18nStrategy(i18n,
|
|
90
|
+
() => setupI18nStrategy(i18n, { rootDirectory, serverEntryPoint })
|
|
92
91
|
);
|
|
93
92
|
}
|
|
94
93
|
let cliCommand = await Promise.resolve(cliCommandPromise);
|
|
@@ -112,7 +111,7 @@ async function runSetup(options) {
|
|
|
112
111
|
{
|
|
113
112
|
location,
|
|
114
113
|
name: location,
|
|
115
|
-
directory:
|
|
114
|
+
directory: rootDirectory
|
|
116
115
|
},
|
|
117
116
|
{
|
|
118
117
|
cliCommand,
|
|
@@ -3,6 +3,16 @@ import { renderSuccess, renderFatalError } from '@shopify/cli-kit/node/ui';
|
|
|
3
3
|
import { ALIAS_NAME, createPlatformShortcut } from '../../lib/shell.js';
|
|
4
4
|
|
|
5
5
|
class Shortcut extends Command {
|
|
6
|
+
static descriptionWithMarkdown = `Creates a global h2 shortcut for Shopify CLI using shell aliases.
|
|
7
|
+
|
|
8
|
+
The following shells are supported:
|
|
9
|
+
|
|
10
|
+
- Bash (using \`~/.bashrc\`)
|
|
11
|
+
- ZSH (using \`~/.zshrc\`)
|
|
12
|
+
- Fish (using \`~/.config/fish/functions\`)
|
|
13
|
+
- PowerShell (added to \`$PROFILE\`)
|
|
14
|
+
|
|
15
|
+
After the alias is created, you can call Shopify CLI from anywhere in your project using \`h2 <command>\`.`;
|
|
6
16
|
static description = `Creates a global \`${ALIAS_NAME}\` shortcut for the Hydrogen CLI`;
|
|
7
17
|
async run() {
|
|
8
18
|
await runCreateShortcut();
|
|
@@ -5,6 +5,7 @@ import { commonFlags } from '../../lib/flags.js';
|
|
|
5
5
|
import { getConfig, unsetStorefront } from '../../lib/shopify-config.js';
|
|
6
6
|
|
|
7
7
|
class Unlink extends Command {
|
|
8
|
+
static descriptionWithMarkdown = "Unlinks your local development environment from a remote Hydrogen storefront.";
|
|
8
9
|
static description = "Unlink a local project from a Hydrogen storefront.";
|
|
9
10
|
static flags = {
|
|
10
11
|
...commonFlags.path
|
|
@@ -16,6 +16,7 @@ import { getProjectPaths } from '../../lib/remix-config.js';
|
|
|
16
16
|
|
|
17
17
|
const INSTRUCTIONS_FOLDER = ".hydrogen";
|
|
18
18
|
class Upgrade extends Command {
|
|
19
|
+
static descriptionWithMarkdown = "Upgrade Hydrogen project dependencies, preview features, fixes and breaking changes. The command also generates an instruction file for each upgrade.";
|
|
19
20
|
static description = "Upgrade Remix and Hydrogen npm dependencies.";
|
|
20
21
|
static flags = {
|
|
21
22
|
...commonFlags.path,
|
|
@@ -655,7 +656,7 @@ async function displayDevUpgradeNotice({
|
|
|
655
656
|
const appPath = targetPath ? path.resolve(targetPath) : process.cwd();
|
|
656
657
|
const { currentVersion } = await getHydrogenVersion({ appPath });
|
|
657
658
|
const isPrerelease = semver.prerelease(currentVersion);
|
|
658
|
-
if (isPrerelease) {
|
|
659
|
+
if (isPrerelease || /^[a-z]+$/i.test(currentVersion)) {
|
|
659
660
|
return;
|
|
660
661
|
}
|
|
661
662
|
const changelog = await getChangelog();
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"scripts": {
|
|
4
|
-
"build": "shopify hydrogen build
|
|
5
|
-
"dev": "shopify hydrogen dev
|
|
4
|
+
"build": "shopify hydrogen build --codegen",
|
|
5
|
+
"dev": "shopify hydrogen dev --codegen"
|
|
6
6
|
},
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@remix-run/node": "^2.8.0",
|
|
9
8
|
"isbot": "^3.8.0"
|
|
10
9
|
},
|
|
11
10
|
"devDependencies": {
|
|
12
|
-
"vite": "
|
|
11
|
+
"vite": "^5.1.0",
|
|
13
12
|
"vite-tsconfig-paths": "^4.3.1"
|
|
14
13
|
}
|
|
15
14
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {defineConfig} from 'vite';
|
|
2
|
-
import {hydrogen
|
|
2
|
+
import {hydrogen} from '@shopify/hydrogen/vite';
|
|
3
|
+
import {oxygen} from '@shopify/mini-oxygen/vite';
|
|
3
4
|
import {vitePlugin as remix} from '@remix-run/dev';
|
|
4
5
|
import tsconfigPaths from 'vite-tsconfig-paths';
|
|
5
6
|
|
|
@@ -7,7 +8,14 @@ export default defineConfig({
|
|
|
7
8
|
plugins: [
|
|
8
9
|
hydrogen(),
|
|
9
10
|
oxygen(),
|
|
10
|
-
remix({
|
|
11
|
+
remix({
|
|
12
|
+
presets: [hydrogen.preset()],
|
|
13
|
+
future: {
|
|
14
|
+
v3_fetcherPersist: true,
|
|
15
|
+
v3_relativeSplatPath: true,
|
|
16
|
+
v3_throwAbortReason: true,
|
|
17
|
+
},
|
|
18
|
+
}),
|
|
11
19
|
tsconfigPaths(),
|
|
12
20
|
],
|
|
13
21
|
});
|