@shopify/cli-hydrogen 4.0.8 → 4.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/README.md +9 -0
- package/dist/commands/hydrogen/build.d.ts +4 -1
- package/dist/commands/hydrogen/build.js +21 -17
- package/dist/commands/hydrogen/check.d.ts +3 -6
- package/dist/commands/hydrogen/check.js +10 -9
- package/dist/commands/hydrogen/dev.d.ts +3 -2
- package/dist/commands/hydrogen/dev.js +24 -22
- package/dist/commands/hydrogen/g.d.ts +10 -0
- package/dist/commands/hydrogen/g.js +17 -0
- package/dist/commands/hydrogen/generate/route.d.ts +7 -9
- package/dist/commands/hydrogen/generate/route.js +49 -47
- package/dist/commands/hydrogen/generate/route.test.js +48 -40
- package/dist/commands/hydrogen/generate/routes.d.ts +2 -2
- package/dist/commands/hydrogen/init.d.ts +3 -3
- package/dist/commands/hydrogen/init.js +76 -95
- package/dist/commands/hydrogen/init.test.js +126 -0
- package/dist/commands/hydrogen/preview.d.ts +2 -2
- package/dist/commands/hydrogen/preview.js +4 -4
- package/dist/commands/hydrogen/shortcut.d.ts +9 -0
- package/dist/commands/hydrogen/shortcut.js +74 -0
- package/dist/commands/hydrogen/shortcut.test.js +58 -0
- package/dist/generator-templates/routes/[robots.txt].tsx +35 -1
- package/dist/generator-templates/routes/[sitemap.xml].tsx +45 -10
- package/dist/generator-templates/routes/account/login.tsx +42 -13
- package/dist/generator-templates/routes/account/register.tsx +42 -13
- package/dist/generator-templates/routes/cart.tsx +42 -2
- package/dist/generator-templates/routes/collections/$collectionHandle.tsx +44 -5
- package/dist/generator-templates/routes/index.tsx +33 -0
- package/dist/generator-templates/routes/pages/$pageHandle.tsx +48 -10
- package/dist/generator-templates/routes/policies/$policyHandle.tsx +67 -14
- package/dist/generator-templates/routes/policies/index.tsx +54 -4
- package/dist/generator-templates/routes/products/$productHandle.tsx +44 -9
- package/dist/hooks/init.js +2 -2
- package/dist/{utils → lib}/check-lockfile.js +7 -4
- package/dist/{utils → lib}/check-lockfile.test.js +19 -28
- package/dist/{utils → lib}/check-version.test.js +3 -2
- package/dist/lib/colors.d.ts +8 -0
- package/dist/lib/colors.js +8 -0
- package/dist/{utils → lib}/config.js +10 -19
- package/dist/{utils → lib}/flags.d.ts +9 -3
- package/dist/{utils → lib}/flags.js +19 -4
- package/dist/lib/flags.test.d.ts +1 -0
- package/dist/{utils → lib}/mini-oxygen.js +14 -12
- package/dist/{utils → lib}/missing-routes.js +1 -1
- package/dist/lib/remix-version-interop.d.ts +11 -0
- package/dist/lib/remix-version-interop.js +54 -0
- package/dist/lib/remix-version-interop.test.d.ts +1 -0
- package/dist/lib/remix-version-interop.test.js +93 -0
- package/dist/lib/shell.d.ts +12 -0
- package/dist/lib/shell.js +73 -0
- package/dist/lib/template-downloader.d.ts +6 -0
- package/dist/{utils → lib}/template-downloader.js +21 -16
- package/dist/{utils → lib}/transpile-ts.js +5 -5
- package/dist/lib/virtual-routes.test.d.ts +1 -0
- package/dist/virtual-routes/routes/index.jsx +2 -15
- package/dist/virtual-routes/virtual-root.jsx +5 -6
- package/oclif.manifest.json +1 -1
- package/package.json +11 -10
- package/dist/utils/template-downloader.d.ts +0 -11
- /package/dist/{utils/check-lockfile.test.d.ts → commands/hydrogen/init.test.d.ts} +0 -0
- /package/dist/{utils/check-version.test.d.ts → commands/hydrogen/shortcut.test.d.ts} +0 -0
- /package/dist/{utils → lib}/check-lockfile.d.ts +0 -0
- /package/dist/{utils/flags.test.d.ts → lib/check-lockfile.test.d.ts} +0 -0
- /package/dist/{utils → lib}/check-version.d.ts +0 -0
- /package/dist/{utils → lib}/check-version.js +0 -0
- /package/dist/{utils/virtual-routes.test.d.ts → lib/check-version.test.d.ts} +0 -0
- /package/dist/{utils → lib}/config.d.ts +0 -0
- /package/dist/{utils → lib}/flags.test.js +0 -0
- /package/dist/{utils → lib}/log.d.ts +0 -0
- /package/dist/{utils → lib}/log.js +0 -0
- /package/dist/{utils → lib}/mini-oxygen.d.ts +0 -0
- /package/dist/{utils → lib}/missing-routes.d.ts +0 -0
- /package/dist/{utils → lib}/transpile-ts.d.ts +0 -0
- /package/dist/{utils → lib}/virtual-routes.d.ts +0 -0
- /package/dist/{utils → lib}/virtual-routes.js +0 -0
- /package/dist/{utils → lib}/virtual-routes.test.js +0 -0
package/README.md
CHANGED
|
@@ -3,3 +3,12 @@
|
|
|
3
3
|
The Hydrogen extension for the [Shopify CLI](https://shopify.dev/apps/tools/cli). Hydrogen is a set of tools, utilities, and best-in-class examples for building a commerce application with [Remix](https://wwww.remix.run).
|
|
4
4
|
|
|
5
5
|
[Check out the docs](https://shopify.dev/custom-storefronts/hydrogen)
|
|
6
|
+
|
|
7
|
+
## Contributing
|
|
8
|
+
|
|
9
|
+
The most common way to test the cli changes locally is to do the following:
|
|
10
|
+
|
|
11
|
+
- Run `npm run build` in this directory (`packages/cli` from the root of the repo).
|
|
12
|
+
- Run `npx shopify hydrogen` anywhere else in the monorepo, for example `npx shopify hydrogen init`.
|
|
13
|
+
- If you want to test a command inside of a template, run the command from within that template or use the `--path` flag to point to another template or any Hydrogen app.
|
|
14
|
+
- If you want to make changes to a file that is generated when running `npx shopify hydrogen generate`, make changes to that file from inside of the `templates/skeleton` directory.
|
|
@@ -4,9 +4,12 @@ import Command from '@shopify/cli-kit/node/base-command';
|
|
|
4
4
|
declare class Build extends Command {
|
|
5
5
|
static description: string;
|
|
6
6
|
static flags: {
|
|
7
|
-
path: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined>;
|
|
7
|
+
path: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
|
8
8
|
sourcemap: _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
|
|
9
9
|
"disable-route-warning": _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
|
|
10
|
+
base: _oclif_core_lib_interfaces_parser_js.OptionFlag<unknown, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
|
11
|
+
entry: _oclif_core_lib_interfaces_parser_js.OptionFlag<unknown, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
|
12
|
+
target: _oclif_core_lib_interfaces_parser_js.OptionFlag<unknown, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
|
10
13
|
};
|
|
11
14
|
run(): Promise<void>;
|
|
12
15
|
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import { getProjectPaths, getRemixConfig } from '../../
|
|
5
|
-
import { commonFlags, flagsToCamelObject } from '../../
|
|
2
|
+
import { outputInfo, outputContent, outputToken, outputWarn } from '@shopify/cli-kit/node/output';
|
|
3
|
+
import { rmdir, fileSize, copyFile } from '@shopify/cli-kit/node/fs';
|
|
4
|
+
import { getProjectPaths, getRemixConfig } from '../../lib/config.js';
|
|
5
|
+
import { commonFlags, deprecated, flagsToCamelObject } from '../../lib/flags.js';
|
|
6
6
|
import Command from '@shopify/cli-kit/node/base-command';
|
|
7
|
-
import Flags from '@oclif/core
|
|
8
|
-
import { checkLockfileStatus } from '../../
|
|
9
|
-
import { findMissingRoutes } from '../../
|
|
7
|
+
import { Flags } from '@oclif/core';
|
|
8
|
+
import { checkLockfileStatus } from '../../lib/check-lockfile.js';
|
|
9
|
+
import { findMissingRoutes } from '../../lib/missing-routes.js';
|
|
10
10
|
import { getPackageManager } from '@shopify/cli-kit/node/node-package-manager';
|
|
11
|
+
import { colors } from '../../lib/colors.js';
|
|
11
12
|
|
|
12
13
|
const LOG_WORKER_BUILT = "\u{1F4E6} Worker built";
|
|
13
14
|
class Build extends Command {
|
|
@@ -22,7 +23,10 @@ class Build extends Command {
|
|
|
22
23
|
["disable-route-warning"]: Flags.boolean({
|
|
23
24
|
description: "Disable warning about missing standard routes.",
|
|
24
25
|
env: "SHOPIFY_HYDROGEN_FLAG_DISABLE_ROUTE_WARNING"
|
|
25
|
-
})
|
|
26
|
+
}),
|
|
27
|
+
base: deprecated("--base")(),
|
|
28
|
+
entry: deprecated("--entry")(),
|
|
29
|
+
target: deprecated("--target")()
|
|
26
30
|
};
|
|
27
31
|
async run() {
|
|
28
32
|
const { flags } = await this.parse(Build);
|
|
@@ -43,9 +47,9 @@ async function runBuild({
|
|
|
43
47
|
console.time(LOG_WORKER_BUILT);
|
|
44
48
|
const [remixConfig] = await Promise.all([
|
|
45
49
|
getRemixConfig(root),
|
|
46
|
-
|
|
50
|
+
rmdir(buildPath, { force: true })
|
|
47
51
|
]);
|
|
48
|
-
|
|
52
|
+
outputInfo(`
|
|
49
53
|
\u{1F3D7}\uFE0F Building in ${process.env.NODE_ENV} mode...`);
|
|
50
54
|
const { build } = await import('@remix-run/dev/dist/compiler/build.js');
|
|
51
55
|
const { logCompileFailure } = await import('@remix-run/dev/dist/compiler/onCompileFailure.js');
|
|
@@ -62,14 +66,14 @@ async function runBuild({
|
|
|
62
66
|
]);
|
|
63
67
|
if (process.env.NODE_ENV !== "development") {
|
|
64
68
|
console.timeEnd(LOG_WORKER_BUILT);
|
|
65
|
-
const sizeMB = await
|
|
66
|
-
|
|
67
|
-
|
|
69
|
+
const sizeMB = await fileSize(buildPathWorkerFile) / (1024 * 1024);
|
|
70
|
+
outputInfo(
|
|
71
|
+
outputContent` ${colors.dim(
|
|
68
72
|
path.relative(root, buildPathWorkerFile)
|
|
69
|
-
)} ${
|
|
73
|
+
)} ${outputToken.yellow(sizeMB.toFixed(2))} MB\n`
|
|
70
74
|
);
|
|
71
75
|
if (sizeMB >= 1) {
|
|
72
|
-
|
|
76
|
+
outputWarn(
|
|
73
77
|
`\u{1F6A8} Worker bundle exceeds 1 MB! This can delay your worker response.${remixConfig.serverMinify ? "" : " Minify your bundle by adding `serverMinify: true` to remix.config.js."}
|
|
74
78
|
`
|
|
75
79
|
);
|
|
@@ -80,7 +84,7 @@ async function runBuild({
|
|
|
80
84
|
if (missingRoutes.length) {
|
|
81
85
|
const packageManager = await getPackageManager(root);
|
|
82
86
|
const exec = packageManager === "npm" ? "npx" : packageManager;
|
|
83
|
-
|
|
87
|
+
outputWarn(
|
|
84
88
|
`Heads up: Shopify stores have a number of standard routes that aren\u2019t set up yet.
|
|
85
89
|
Some functionality and backlinks might not work as expected until these are created or redirects are set up.
|
|
86
90
|
This build is missing ${missingRoutes.length} route${missingRoutes.length > 1 ? "s" : ""}. For more details, run \`${exec} shopify hydrogen check routes\`.
|
|
@@ -91,7 +95,7 @@ This build is missing ${missingRoutes.length} route${missingRoutes.length > 1 ?
|
|
|
91
95
|
process.exit(0);
|
|
92
96
|
}
|
|
93
97
|
async function copyPublicFiles(publicPath, buildPathClient) {
|
|
94
|
-
return
|
|
98
|
+
return copyFile(publicPath, buildPathClient);
|
|
95
99
|
}
|
|
96
100
|
|
|
97
101
|
export { copyPublicFiles, Build as default, runBuild };
|
|
@@ -4,14 +4,11 @@ import Command from '@shopify/cli-kit/node/base-command';
|
|
|
4
4
|
declare class GenerateRoute extends Command {
|
|
5
5
|
static description: string;
|
|
6
6
|
static flags: {
|
|
7
|
-
path: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined>;
|
|
7
|
+
path: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
|
8
8
|
};
|
|
9
9
|
static args: {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
required: boolean;
|
|
13
|
-
options: string[];
|
|
14
|
-
}[];
|
|
10
|
+
resource: _oclif_core_lib_interfaces_parser_js.Arg<string, Record<string, unknown>>;
|
|
11
|
+
};
|
|
15
12
|
run(): Promise<void>;
|
|
16
13
|
}
|
|
17
14
|
|
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
import Command from '@shopify/cli-kit/node/base-command';
|
|
2
|
-
import {
|
|
3
|
-
import { commonFlags } from '../../
|
|
4
|
-
import { getRemixConfig } from '../../
|
|
5
|
-
import { logMissingRoutes, findMissingRoutes } from '../../
|
|
2
|
+
import { resolvePath } from '@shopify/cli-kit/node/path';
|
|
3
|
+
import { commonFlags } from '../../lib/flags.js';
|
|
4
|
+
import { getRemixConfig } from '../../lib/config.js';
|
|
5
|
+
import { logMissingRoutes, findMissingRoutes } from '../../lib/missing-routes.js';
|
|
6
|
+
import { Args } from '@oclif/core';
|
|
6
7
|
|
|
7
8
|
class GenerateRoute extends Command {
|
|
8
9
|
static description = "Returns diagnostic information about a Hydrogen storefront.";
|
|
9
10
|
static flags = {
|
|
10
11
|
path: commonFlags.path
|
|
11
12
|
};
|
|
12
|
-
static args =
|
|
13
|
-
{
|
|
13
|
+
static args = {
|
|
14
|
+
resource: Args.string({
|
|
14
15
|
name: "resource",
|
|
15
16
|
description: `The resource to check. Currently only 'routes' is supported.`,
|
|
16
17
|
required: true,
|
|
17
18
|
options: ["routes"]
|
|
18
|
-
}
|
|
19
|
-
|
|
19
|
+
})
|
|
20
|
+
};
|
|
20
21
|
async run() {
|
|
21
22
|
const { flags, args } = await this.parse(GenerateRoute);
|
|
22
|
-
const directory = flags.path ?
|
|
23
|
+
const directory = flags.path ? resolvePath(flags.path) : process.cwd();
|
|
23
24
|
if (args.resource === "routes") {
|
|
24
25
|
await runCheckRoutes({ directory });
|
|
25
26
|
} else {
|
|
@@ -4,9 +4,10 @@ import Command from '@shopify/cli-kit/node/base-command';
|
|
|
4
4
|
declare class Dev extends Command {
|
|
5
5
|
static description: string;
|
|
6
6
|
static flags: {
|
|
7
|
-
path: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined>;
|
|
8
|
-
port: _oclif_core_lib_interfaces_parser_js.OptionFlag<number>;
|
|
7
|
+
path: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
|
8
|
+
port: _oclif_core_lib_interfaces_parser_js.OptionFlag<number, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
|
9
9
|
"disable-virtual-routes": _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
|
|
10
|
+
host: _oclif_core_lib_interfaces_parser_js.OptionFlag<unknown, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
|
10
11
|
};
|
|
11
12
|
run(): Promise<void>;
|
|
12
13
|
}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
import fs from 'fs/promises';
|
|
3
|
-
import {
|
|
3
|
+
import { outputInfo } from '@shopify/cli-kit/node/output';
|
|
4
|
+
import { fileExists } from '@shopify/cli-kit/node/fs';
|
|
4
5
|
import { copyPublicFiles } from './build.js';
|
|
5
|
-
import { getProjectPaths, getRemixConfig } from '../../
|
|
6
|
-
import { muteDevLogs } from '../../
|
|
7
|
-
import { commonFlags, flagsToCamelObject } from '../../
|
|
6
|
+
import { getProjectPaths, getRemixConfig } from '../../lib/config.js';
|
|
7
|
+
import { muteDevLogs } from '../../lib/log.js';
|
|
8
|
+
import { commonFlags, deprecated, flagsToCamelObject } from '../../lib/flags.js';
|
|
8
9
|
import Command from '@shopify/cli-kit/node/base-command';
|
|
9
|
-
import Flags from '@oclif/core
|
|
10
|
-
import { startMiniOxygen } from '../../
|
|
11
|
-
import { checkHydrogenVersion } from '../../
|
|
12
|
-
import { addVirtualRoutes } from '../../
|
|
10
|
+
import { Flags } from '@oclif/core';
|
|
11
|
+
import { startMiniOxygen } from '../../lib/mini-oxygen.js';
|
|
12
|
+
import { checkHydrogenVersion } from '../../lib/check-version.js';
|
|
13
|
+
import { addVirtualRoutes } from '../../lib/virtual-routes.js';
|
|
13
14
|
|
|
14
15
|
const LOG_INITIAL_BUILD = "\n\u{1F3C1} Initial build";
|
|
15
16
|
const LOG_REBUILDING = "\u{1F9F1} Rebuilding...";
|
|
@@ -23,7 +24,8 @@ class Dev extends Command {
|
|
|
23
24
|
description: "Disable rendering fallback routes when a route file doesn't exist",
|
|
24
25
|
env: "SHOPIFY_HYDROGEN_FLAG_DISABLE_VIRTUAL_ROUTES",
|
|
25
26
|
default: false
|
|
26
|
-
})
|
|
27
|
+
}),
|
|
28
|
+
host: deprecated("--host")()
|
|
27
29
|
};
|
|
28
30
|
async run() {
|
|
29
31
|
const { flags } = await this.parse(Dev);
|
|
@@ -47,11 +49,11 @@ async function runDev({
|
|
|
47
49
|
const config = await getRemixConfig(root);
|
|
48
50
|
return disableVirtualRoutes ? config : addVirtualRoutes(config);
|
|
49
51
|
};
|
|
50
|
-
const getFilePaths = (
|
|
51
|
-
const fileRelative = path.relative(root,
|
|
52
|
+
const getFilePaths = (file) => {
|
|
53
|
+
const fileRelative = path.relative(root, file);
|
|
52
54
|
return [fileRelative, path.resolve(root, fileRelative)];
|
|
53
55
|
};
|
|
54
|
-
const serverBundleExists = () =>
|
|
56
|
+
const serverBundleExists = () => fileExists(buildPathWorkerFile);
|
|
55
57
|
let miniOxygenStarted = false;
|
|
56
58
|
async function safeStartMiniOxygen() {
|
|
57
59
|
if (miniOxygenStarted)
|
|
@@ -86,9 +88,9 @@ async function runDev({
|
|
|
86
88
|
console.timeEnd(LOG_INITIAL_BUILD);
|
|
87
89
|
await safeStartMiniOxygen();
|
|
88
90
|
},
|
|
89
|
-
async onFileCreated(
|
|
90
|
-
const [relative, absolute] = getFilePaths(
|
|
91
|
-
|
|
91
|
+
async onFileCreated(file) {
|
|
92
|
+
const [relative, absolute] = getFilePaths(file);
|
|
93
|
+
outputInfo(`
|
|
92
94
|
\u{1F4C4} File created: ${relative}`);
|
|
93
95
|
if (absolute.startsWith(publicPath)) {
|
|
94
96
|
await copyPublicFiles(
|
|
@@ -97,9 +99,9 @@ async function runDev({
|
|
|
97
99
|
);
|
|
98
100
|
}
|
|
99
101
|
},
|
|
100
|
-
async onFileChanged(
|
|
101
|
-
const [relative, absolute] = getFilePaths(
|
|
102
|
-
|
|
102
|
+
async onFileChanged(file) {
|
|
103
|
+
const [relative, absolute] = getFilePaths(file);
|
|
104
|
+
outputInfo(`
|
|
103
105
|
\u{1F4C4} File changed: ${relative}`);
|
|
104
106
|
if (absolute.startsWith(publicPath)) {
|
|
105
107
|
await copyPublicFiles(
|
|
@@ -108,16 +110,16 @@ async function runDev({
|
|
|
108
110
|
);
|
|
109
111
|
}
|
|
110
112
|
},
|
|
111
|
-
async onFileDeleted(
|
|
112
|
-
const [relative, absolute] = getFilePaths(
|
|
113
|
-
|
|
113
|
+
async onFileDeleted(file) {
|
|
114
|
+
const [relative, absolute] = getFilePaths(file);
|
|
115
|
+
outputInfo(`
|
|
114
116
|
\u{1F4C4} File deleted: ${relative}`);
|
|
115
117
|
if (absolute.startsWith(publicPath)) {
|
|
116
118
|
await fs.unlink(absolute.replace(publicPath, buildPathClient));
|
|
117
119
|
}
|
|
118
120
|
},
|
|
119
121
|
onRebuildStart() {
|
|
120
|
-
|
|
122
|
+
outputInfo(LOG_REBUILDING);
|
|
121
123
|
console.time(LOG_REBUILT);
|
|
122
124
|
},
|
|
123
125
|
async onRebuildFinish() {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import Command from '@shopify/cli-kit/node/base-command';
|
|
2
|
+
|
|
3
|
+
declare class GenerateRouteShortcut extends Command {
|
|
4
|
+
static description: string;
|
|
5
|
+
static strict: boolean;
|
|
6
|
+
static hidden: boolean;
|
|
7
|
+
run(): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export { GenerateRouteShortcut as default };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import Command from '@shopify/cli-kit/node/base-command';
|
|
2
|
+
import GenerateRoute from './generate/route.js';
|
|
3
|
+
|
|
4
|
+
class GenerateRouteShortcut extends Command {
|
|
5
|
+
static description = "Shortcut for `hydrogen generate`. See `hydrogen generate --help` for more information.";
|
|
6
|
+
static strict = false;
|
|
7
|
+
static hidden = true;
|
|
8
|
+
async run() {
|
|
9
|
+
const [command, ...args] = this.argv;
|
|
10
|
+
if (command === "r" || command === "route") {
|
|
11
|
+
return new GenerateRoute(args, this.config).run();
|
|
12
|
+
}
|
|
13
|
+
throw new Error(`Invalid command argument "${command}".`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export { GenerateRouteShortcut as default };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as _oclif_core_lib_interfaces_parser_js from '@oclif/core/lib/interfaces/parser.js';
|
|
2
2
|
import Command from '@shopify/cli-kit/node/base-command';
|
|
3
|
+
import { RemixV2Flags } from '../../../lib/remix-version-interop.js';
|
|
3
4
|
|
|
4
5
|
declare const GENERATOR_TEMPLATES_DIR = "generator-templates";
|
|
5
6
|
interface Result {
|
|
@@ -8,27 +9,24 @@ interface Result {
|
|
|
8
9
|
declare class GenerateRoute extends Command {
|
|
9
10
|
static description: string;
|
|
10
11
|
static flags: {
|
|
11
|
-
adapter: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined>;
|
|
12
|
+
adapter: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
|
12
13
|
typescript: _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
|
|
13
14
|
force: _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
|
|
14
|
-
path: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined>;
|
|
15
|
+
path: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
|
15
16
|
};
|
|
16
17
|
static hidden: true;
|
|
17
18
|
static args: {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
required: boolean;
|
|
21
|
-
options: string[];
|
|
22
|
-
env: string;
|
|
23
|
-
}[];
|
|
19
|
+
route: _oclif_core_lib_interfaces_parser_js.Arg<string, Record<string, unknown>>;
|
|
20
|
+
};
|
|
24
21
|
run(): Promise<void>;
|
|
25
22
|
}
|
|
26
|
-
declare function runGenerate(
|
|
23
|
+
declare function runGenerate(routeFrom: string, routeTo: string, { directory, typescript, force, adapter, templatesRoot, v2Flags, }: {
|
|
27
24
|
directory: string;
|
|
28
25
|
typescript?: boolean;
|
|
29
26
|
force?: boolean;
|
|
30
27
|
adapter?: string;
|
|
31
28
|
templatesRoot?: string;
|
|
29
|
+
v2Flags?: RemixV2Flags;
|
|
32
30
|
}): Promise<Result>;
|
|
33
31
|
|
|
34
32
|
export { GENERATOR_TEMPLATES_DIR, GenerateRoute as default, runGenerate };
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { fileURLToPath } from 'url';
|
|
2
2
|
import Command from '@shopify/cli-kit/node/base-command';
|
|
3
|
-
import {
|
|
3
|
+
import { fileExists, readFile, mkdir, writeFile } from '@shopify/cli-kit/node/fs';
|
|
4
|
+
import { resolvePath, joinPath, relativePath, relativizePath, dirname } from '@shopify/cli-kit/node/path';
|
|
4
5
|
import { AbortError } from '@shopify/cli-kit/node/error';
|
|
5
|
-
import { renderSuccess } from '@shopify/cli-kit/node/ui';
|
|
6
|
-
import { commonFlags } from '../../../
|
|
7
|
-
import Flags from '@oclif/core
|
|
8
|
-
import { transpileFile, format, resolveFormatConfig } from '../../../
|
|
6
|
+
import { renderSuccess, renderConfirmationPrompt } from '@shopify/cli-kit/node/ui';
|
|
7
|
+
import { commonFlags } from '../../../lib/flags.js';
|
|
8
|
+
import { Flags, Args } from '@oclif/core';
|
|
9
|
+
import { transpileFile, format, resolveFormatConfig } from '../../../lib/transpile-ts.js';
|
|
10
|
+
import { getV2Flags, convertRouteToV2, convertTemplateToRemixVersion } from '../../../lib/remix-version-interop.js';
|
|
9
11
|
|
|
10
12
|
const GENERATOR_TEMPLATES_DIR = "generator-templates";
|
|
11
13
|
const ROUTE_MAP = {
|
|
@@ -35,37 +37,43 @@ class GenerateRoute extends Command {
|
|
|
35
37
|
path: commonFlags.path
|
|
36
38
|
};
|
|
37
39
|
static hidden;
|
|
38
|
-
static args =
|
|
39
|
-
{
|
|
40
|
+
static args = {
|
|
41
|
+
route: Args.string({
|
|
40
42
|
name: "route",
|
|
41
43
|
description: `The route to generate. One of ${ROUTES.join()}.`,
|
|
42
44
|
required: true,
|
|
43
45
|
options: ROUTES,
|
|
44
46
|
env: "SHOPIFY_HYDROGEN_ARG_ROUTE"
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
+
})
|
|
48
|
+
};
|
|
47
49
|
async run() {
|
|
48
50
|
const result = /* @__PURE__ */ new Map();
|
|
49
|
-
const {
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
const {
|
|
52
|
+
flags,
|
|
53
|
+
args: { route }
|
|
54
|
+
} = await this.parse(GenerateRoute);
|
|
52
55
|
const routePath = route === "all" ? Object.values(ROUTE_MAP).flat() : ROUTE_MAP[route];
|
|
53
56
|
if (!routePath) {
|
|
54
57
|
throw new AbortError(
|
|
55
58
|
`No route found for ${route}. Try one of ${ROUTES.join()}.`
|
|
56
59
|
);
|
|
57
60
|
}
|
|
58
|
-
const
|
|
61
|
+
const directory = flags.path ? resolvePath(flags.path) : process.cwd();
|
|
62
|
+
const isTypescript = flags.typescript || await fileExists(joinPath(directory, "tsconfig.json"));
|
|
59
63
|
const routesArray = Array.isArray(routePath) ? routePath : [routePath];
|
|
60
64
|
try {
|
|
65
|
+
const { isV2RouteConvention, ...v2Flags } = await getV2Flags(directory);
|
|
61
66
|
for (const item of routesArray) {
|
|
67
|
+
const routeFrom = item;
|
|
68
|
+
const routeTo = isV2RouteConvention ? convertRouteToV2(item) : item;
|
|
62
69
|
result.set(
|
|
63
|
-
|
|
64
|
-
await runGenerate(
|
|
70
|
+
routeTo,
|
|
71
|
+
await runGenerate(routeFrom, routeTo, {
|
|
65
72
|
directory,
|
|
66
73
|
typescript: isTypescript,
|
|
67
74
|
force: flags.force,
|
|
68
|
-
adapter: flags.adapter
|
|
75
|
+
adapter: flags.adapter,
|
|
76
|
+
v2Flags
|
|
69
77
|
})
|
|
70
78
|
);
|
|
71
79
|
}
|
|
@@ -81,62 +89,56 @@ class GenerateRoute extends Command {
|
|
|
81
89
|
body: {
|
|
82
90
|
list: {
|
|
83
91
|
items: Array.from(result.entries()).map(
|
|
84
|
-
([
|
|
92
|
+
([path, { operation }]) => `[${operation}] app/routes${path}${extension}`
|
|
85
93
|
)
|
|
86
94
|
}
|
|
87
95
|
}
|
|
88
96
|
});
|
|
89
97
|
}
|
|
90
98
|
}
|
|
91
|
-
async function runGenerate(
|
|
99
|
+
async function runGenerate(routeFrom, routeTo, {
|
|
92
100
|
directory,
|
|
93
101
|
typescript,
|
|
94
102
|
force,
|
|
95
103
|
adapter,
|
|
96
|
-
templatesRoot = fileURLToPath(new URL("../../../", import.meta.url))
|
|
104
|
+
templatesRoot = fileURLToPath(new URL("../../../", import.meta.url)),
|
|
105
|
+
v2Flags = {}
|
|
97
106
|
}) {
|
|
98
107
|
let operation;
|
|
99
108
|
const extension = typescript ? ".tsx" : ".jsx";
|
|
100
|
-
const templatePath =
|
|
109
|
+
const templatePath = joinPath(
|
|
101
110
|
templatesRoot,
|
|
102
111
|
GENERATOR_TEMPLATES_DIR,
|
|
103
112
|
"routes",
|
|
104
|
-
`${
|
|
113
|
+
`${routeFrom}.tsx`
|
|
105
114
|
);
|
|
106
|
-
const destinationPath =
|
|
115
|
+
const destinationPath = joinPath(
|
|
107
116
|
directory,
|
|
108
117
|
"app",
|
|
109
118
|
"routes",
|
|
110
|
-
`${
|
|
119
|
+
`${routeTo}${extension}`
|
|
111
120
|
);
|
|
112
|
-
const relativeDestinationPath =
|
|
113
|
-
if (!force && await
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
name: "value",
|
|
122
|
-
message: `The file ${path.relativize(
|
|
123
|
-
relativeDestinationPath
|
|
124
|
-
)} already exists. Do you want to overwrite it?`,
|
|
125
|
-
choices: options
|
|
126
|
-
}
|
|
127
|
-
]);
|
|
128
|
-
operation = choice.value === "skip" ? "skipped" : "overwritten";
|
|
121
|
+
const relativeDestinationPath = relativePath(directory, destinationPath);
|
|
122
|
+
if (!force && await fileExists(destinationPath)) {
|
|
123
|
+
const shouldOverwrite = await renderConfirmationPrompt({
|
|
124
|
+
message: `The file ${relativizePath(
|
|
125
|
+
relativeDestinationPath
|
|
126
|
+
)} already exists. Do you want to overwrite it?`,
|
|
127
|
+
defaultValue: false
|
|
128
|
+
});
|
|
129
|
+
operation = shouldOverwrite ? "overwritten" : "skipped";
|
|
129
130
|
if (operation === "skipped") {
|
|
130
131
|
return { operation };
|
|
131
132
|
}
|
|
132
133
|
} else {
|
|
133
134
|
operation = "generated";
|
|
134
135
|
}
|
|
135
|
-
let templateContent = await
|
|
136
|
+
let templateContent = await readFile(templatePath);
|
|
137
|
+
templateContent = convertTemplateToRemixVersion(templateContent, v2Flags);
|
|
136
138
|
if (!typescript) {
|
|
137
|
-
const jsConfigPath =
|
|
138
|
-
const config = await
|
|
139
|
-
(await
|
|
139
|
+
const jsConfigPath = joinPath(directory, "jsconfig.json");
|
|
140
|
+
const config = await fileExists(jsConfigPath) ? JSON.parse(
|
|
141
|
+
(await readFile(jsConfigPath, { encoding: "utf8" })).replace(
|
|
140
142
|
/^\s*\/\/.*$/gm,
|
|
141
143
|
""
|
|
142
144
|
)
|
|
@@ -154,10 +156,10 @@ async function runGenerate(route, {
|
|
|
154
156
|
await resolveFormatConfig(destinationPath),
|
|
155
157
|
destinationPath
|
|
156
158
|
);
|
|
157
|
-
if (!await
|
|
158
|
-
await
|
|
159
|
+
if (!await fileExists(dirname(destinationPath))) {
|
|
160
|
+
await mkdir(dirname(destinationPath));
|
|
159
161
|
}
|
|
160
|
-
await
|
|
162
|
+
await writeFile(destinationPath, templateContent);
|
|
161
163
|
return {
|
|
162
164
|
operation
|
|
163
165
|
};
|