create-react-router 0.0.0-experimental-abd9fc79b → 0.0.0-experimental-2a01b6fd8
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/CHANGELOG.md +25 -0
- package/dist/cli.js +104 -61
- package/package.json +1 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# `create-react-router`
|
|
2
2
|
|
|
3
|
+
## v8.3.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- _No changes_
|
|
8
|
+
|
|
9
|
+
## v8.2.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- Detect `nub` as a supported package manager when creating new projects ([#15276](https://github.com/remix-run/react-router/pull/15276))
|
|
14
|
+
|
|
15
|
+
## v8.1.0
|
|
16
|
+
|
|
17
|
+
### Minor Changes
|
|
18
|
+
|
|
19
|
+
- Add a default-on CLI option to include the official React Router agent skill in generated projects ([#15213](https://github.com/remix-run/react-router/pull/15213))
|
|
20
|
+
- New projects include `.agents/skills/react-router` by default when running with `--yes` or in non-interactive shells
|
|
21
|
+
- Interactive runs prompt to include the skill, defaulting to yes
|
|
22
|
+
- Use `--no-agent-skills` to skip copying the skill
|
|
23
|
+
|
|
24
|
+
### Patch Changes
|
|
25
|
+
|
|
26
|
+
- Use Node's built-in utilities for CLI argument parsing, ANSI-stripping, and child process execution to remove the `arg`, `strip-ansi`, and `execa` dependencies ([#15231](https://github.com/remix-run/react-router/pull/15231))
|
|
27
|
+
|
|
3
28
|
## v8.0.1
|
|
4
29
|
|
|
5
30
|
### Patch Changes
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* create-react-router v0.0.0-experimental-
|
|
3
|
+
* create-react-router v0.0.0-experimental-2a01b6fd8
|
|
4
4
|
*
|
|
5
5
|
* Copyright (c) Remix Software Inc.
|
|
6
6
|
*
|
|
@@ -10,14 +10,13 @@
|
|
|
10
10
|
* @license MIT
|
|
11
11
|
*/
|
|
12
12
|
import process from "node:process";
|
|
13
|
+
import { spawn } from "node:child_process";
|
|
13
14
|
import fs, { existsSync } from "node:fs";
|
|
14
15
|
import { cp, readFile, readdir, realpath, writeFile } from "node:fs/promises";
|
|
15
16
|
import os from "node:os";
|
|
16
17
|
import path from "node:path";
|
|
17
18
|
import url, { fileURLToPath } from "node:url";
|
|
18
|
-
import
|
|
19
|
-
import { execa } from "execa";
|
|
20
|
-
import arg from "arg";
|
|
19
|
+
import { parseArgs, promisify, stripVTControlCharacters } from "node:util";
|
|
21
20
|
import * as semver from "semver";
|
|
22
21
|
import sortPackageJSON from "sort-package-json";
|
|
23
22
|
import { beep, cursor, erase } from "sisteransi";
|
|
@@ -25,7 +24,6 @@ import EventEmitter from "node:events";
|
|
|
25
24
|
import readline from "node:readline";
|
|
26
25
|
import pc from "picocolors";
|
|
27
26
|
import stream from "node:stream";
|
|
28
|
-
import { promisify } from "node:util";
|
|
29
27
|
import gunzip from "gunzip-maybe";
|
|
30
28
|
import tar from "tar-fs";
|
|
31
29
|
//#region utils.ts
|
|
@@ -155,7 +153,7 @@ function isUrl(value) {
|
|
|
155
153
|
try {
|
|
156
154
|
new URL(value);
|
|
157
155
|
return true;
|
|
158
|
-
} catch
|
|
156
|
+
} catch {
|
|
159
157
|
return false;
|
|
160
158
|
}
|
|
161
159
|
}
|
|
@@ -250,7 +248,7 @@ var Prompt = class extends EventEmitter {
|
|
|
250
248
|
let a = action(key, isSelect);
|
|
251
249
|
if (a === false) try {
|
|
252
250
|
this._(str, key);
|
|
253
|
-
} catch
|
|
251
|
+
} catch {}
|
|
254
252
|
else if (typeof this[a] === "function") this[a](key);
|
|
255
253
|
};
|
|
256
254
|
this.close = () => {
|
|
@@ -887,7 +885,7 @@ async function prompt(questions, opts = {}) {
|
|
|
887
885
|
}, question));
|
|
888
886
|
answers[name] = answer;
|
|
889
887
|
quit = await onSubmit(question, answer, answers);
|
|
890
|
-
} catch
|
|
888
|
+
} catch {
|
|
891
889
|
quit = !await onCancel(question, answers);
|
|
892
890
|
}
|
|
893
891
|
if (quit) return answers;
|
|
@@ -1064,7 +1062,7 @@ async function copyTemplate(template, destPath, options) {
|
|
|
1064
1062
|
function isLocalFilePath(input) {
|
|
1065
1063
|
try {
|
|
1066
1064
|
return input.startsWith("file://") || fs.existsSync(path.isAbsolute(input) ? input : path.resolve(process.cwd(), input));
|
|
1067
|
-
} catch
|
|
1065
|
+
} catch {
|
|
1068
1066
|
return false;
|
|
1069
1067
|
}
|
|
1070
1068
|
}
|
|
@@ -1158,7 +1156,7 @@ async function downloadAndExtractTarball(downloadPath, tarballUrl, { token, file
|
|
|
1158
1156
|
return header.name === "__IGNORE__";
|
|
1159
1157
|
}
|
|
1160
1158
|
}));
|
|
1161
|
-
} catch
|
|
1159
|
+
} catch {
|
|
1162
1160
|
throw new CopyTemplateError(`There was a problem extracting the file from the provided template. Template URL: \`${tarballUrl}\` Destination directory: \`${downloadPath}\``);
|
|
1163
1161
|
}
|
|
1164
1162
|
if (filePath && !filePathHasFiles) throw new CopyTemplateError(`The path "${filePath}" was not found in this ${isGithubUrl ? "GitHub repo." : "tarball."}`);
|
|
@@ -1187,7 +1185,7 @@ function isValidGithubRepoUrl(input) {
|
|
|
1187
1185
|
let url = new URL(input);
|
|
1188
1186
|
let pathSegments = url.pathname.slice(1).split("/");
|
|
1189
1187
|
return url.protocol === "https:" && url.hostname === "github.com" && pathSegments.length >= 2 && (pathSegments.length > 2 ? pathSegments[2] === "tree" && pathSegments.length >= 4 : true);
|
|
1190
|
-
} catch
|
|
1188
|
+
} catch {
|
|
1191
1189
|
return false;
|
|
1192
1190
|
}
|
|
1193
1191
|
}
|
|
@@ -1239,7 +1237,7 @@ var CopyTemplateError = class extends Error {
|
|
|
1239
1237
|
};
|
|
1240
1238
|
//#endregion
|
|
1241
1239
|
//#region package.json
|
|
1242
|
-
var version = "0.0.0-experimental-
|
|
1240
|
+
var version = "0.0.0-experimental-2a01b6fd8";
|
|
1243
1241
|
//#endregion
|
|
1244
1242
|
//#region index.ts
|
|
1245
1243
|
const currentFileDir = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -1276,36 +1274,48 @@ async function createReactRouter(argv) {
|
|
|
1276
1274
|
}
|
|
1277
1275
|
}
|
|
1278
1276
|
async function getContext(argv) {
|
|
1279
|
-
let
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1277
|
+
let { values, positionals } = parseArgs({
|
|
1278
|
+
args: argv,
|
|
1279
|
+
allowPositionals: true,
|
|
1280
|
+
strict: false,
|
|
1281
|
+
options: {
|
|
1282
|
+
"agent-skills": { type: "boolean" },
|
|
1283
|
+
debug: { type: "boolean" },
|
|
1284
|
+
"git-init": { type: "boolean" },
|
|
1285
|
+
help: {
|
|
1286
|
+
type: "boolean",
|
|
1287
|
+
short: "h"
|
|
1288
|
+
},
|
|
1289
|
+
install: { type: "boolean" },
|
|
1290
|
+
"no-agent-skills": { type: "boolean" },
|
|
1291
|
+
"no-color": { type: "boolean" },
|
|
1292
|
+
"no-git-init": { type: "boolean" },
|
|
1293
|
+
"no-install": { type: "boolean" },
|
|
1294
|
+
"no-motion": { type: "boolean" },
|
|
1295
|
+
overwrite: { type: "boolean" },
|
|
1296
|
+
"package-manager": { type: "string" },
|
|
1297
|
+
"react-router-version": {
|
|
1298
|
+
type: "string",
|
|
1299
|
+
short: "v"
|
|
1300
|
+
},
|
|
1301
|
+
"show-install-output": { type: "boolean" },
|
|
1302
|
+
template: { type: "string" },
|
|
1303
|
+
token: { type: "string" },
|
|
1304
|
+
version: {
|
|
1305
|
+
type: "boolean",
|
|
1306
|
+
short: "V"
|
|
1307
|
+
},
|
|
1308
|
+
yes: {
|
|
1309
|
+
type: "boolean",
|
|
1310
|
+
short: "y"
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1306
1313
|
});
|
|
1307
|
-
let
|
|
1308
|
-
let
|
|
1314
|
+
let getBooleanArg = (value) => typeof value === "boolean" ? value : void 0;
|
|
1315
|
+
let getStringArg = (value) => typeof value === "string" ? value : void 0;
|
|
1316
|
+
let selectedReactRouterVersion = getStringArg(values["react-router-version"]);
|
|
1317
|
+
let yes = getBooleanArg(values.yes);
|
|
1318
|
+
let cwd = positionals[0];
|
|
1309
1319
|
let interactive = isInteractive();
|
|
1310
1320
|
let projectName = cwd;
|
|
1311
1321
|
if (!interactive) yes = true;
|
|
@@ -1317,22 +1327,22 @@ async function getContext(argv) {
|
|
|
1317
1327
|
return {
|
|
1318
1328
|
tempDir: path.join(await realpath(os.tmpdir()), `create-react-router--${Math.random().toString(36).substr(2, 8)}`),
|
|
1319
1329
|
cwd,
|
|
1320
|
-
overwrite,
|
|
1330
|
+
overwrite: getBooleanArg(values.overwrite),
|
|
1321
1331
|
interactive,
|
|
1322
|
-
debug,
|
|
1323
|
-
agentSkills:
|
|
1324
|
-
git: git ?? (
|
|
1325
|
-
help,
|
|
1326
|
-
install: install ?? (
|
|
1327
|
-
showInstallOutput,
|
|
1328
|
-
noMotion,
|
|
1329
|
-
pkgManager: validatePackageManager(
|
|
1332
|
+
debug: getBooleanArg(values.debug) ?? false,
|
|
1333
|
+
agentSkills: getBooleanArg(values["agent-skills"]) ?? (getBooleanArg(values["no-agent-skills"]) ? false : yes),
|
|
1334
|
+
git: getBooleanArg(values["git-init"]) ?? (getBooleanArg(values["no-git-init"]) ? false : yes),
|
|
1335
|
+
help: getBooleanArg(values.help) ?? false,
|
|
1336
|
+
install: getBooleanArg(values.install) ?? (getBooleanArg(values["no-install"]) ? false : yes),
|
|
1337
|
+
showInstallOutput: getBooleanArg(values["show-install-output"]) ?? false,
|
|
1338
|
+
noMotion: getBooleanArg(values["no-motion"]),
|
|
1339
|
+
pkgManager: validatePackageManager(getStringArg(values["package-manager"]) ?? detectPackageManager() ?? "npm"),
|
|
1330
1340
|
projectName,
|
|
1331
1341
|
prompt,
|
|
1332
1342
|
reactRouterVersion: selectedReactRouterVersion || version,
|
|
1333
|
-
template,
|
|
1334
|
-
token,
|
|
1335
|
-
versionRequested
|
|
1343
|
+
template: getStringArg(values.template),
|
|
1344
|
+
token: getStringArg(values.token),
|
|
1345
|
+
versionRequested: getBooleanArg(values.version)
|
|
1336
1346
|
};
|
|
1337
1347
|
}
|
|
1338
1348
|
async function introStep(ctx) {
|
|
@@ -1424,7 +1434,7 @@ async function agentSkillsQuestionStep(ctx) {
|
|
|
1424
1434
|
let { agentSkills = true } = await ctx.prompt({
|
|
1425
1435
|
name: "agentSkills",
|
|
1426
1436
|
type: "confirm",
|
|
1427
|
-
label: title("
|
|
1437
|
+
label: title("skill"),
|
|
1428
1438
|
message: "Include the React Router agent skill?",
|
|
1429
1439
|
hint: "recommended",
|
|
1430
1440
|
initial: true
|
|
@@ -1584,9 +1594,9 @@ async function gitInitStep(ctx) {
|
|
|
1584
1594
|
};
|
|
1585
1595
|
let commitMsg = "Initial commit from create-react-router";
|
|
1586
1596
|
try {
|
|
1587
|
-
await
|
|
1588
|
-
await
|
|
1589
|
-
await
|
|
1597
|
+
await runCommand("git", ["init"], options);
|
|
1598
|
+
await runCommand("git", ["add", "."], options);
|
|
1599
|
+
await runCommand("git", [
|
|
1590
1600
|
"commit",
|
|
1591
1601
|
"-m",
|
|
1592
1602
|
commitMsg
|
|
@@ -1608,12 +1618,12 @@ async function doneStep(ctx) {
|
|
|
1608
1618
|
await sleep(100);
|
|
1609
1619
|
if (projectDir !== "") {
|
|
1610
1620
|
let enter = [`\n${prefix}Enter your project directory using`, color.cyan(`cd .${path.sep}${projectDir}`)];
|
|
1611
|
-
let len = enter[0].length +
|
|
1621
|
+
let len = enter[0].length + stripVTControlCharacters(enter[1]).length;
|
|
1612
1622
|
log(enter.join(len > max ? "\n" + prefix : " "));
|
|
1613
1623
|
}
|
|
1614
1624
|
log(`${prefix}Check out ${color.bold("README.md")} for development and deploy instructions.`);
|
|
1615
1625
|
await sleep(100);
|
|
1616
|
-
log(`\n${prefix}Join the community at ${color.cyan(`https://
|
|
1626
|
+
log(`\n${prefix}Join the community at ${color.cyan(`https://remix.run/discord`)}\n`);
|
|
1617
1627
|
await sleep(200);
|
|
1618
1628
|
}
|
|
1619
1629
|
const validPackageManagers = [
|
|
@@ -1621,14 +1631,37 @@ const validPackageManagers = [
|
|
|
1621
1631
|
"yarn",
|
|
1622
1632
|
"pnpm",
|
|
1623
1633
|
"bun",
|
|
1624
|
-
"deno"
|
|
1634
|
+
"deno",
|
|
1635
|
+
"nub"
|
|
1625
1636
|
];
|
|
1626
1637
|
function validatePackageManager(pkgManager) {
|
|
1627
1638
|
return validPackageManagers.find((name) => pkgManager === name) ?? "npm";
|
|
1628
1639
|
}
|
|
1640
|
+
/**
|
|
1641
|
+
* Determine which package manager the user prefers.
|
|
1642
|
+
*
|
|
1643
|
+
* npm, pnpm, Yarn, Bun, Deno, and nub set the user agent environment variable
|
|
1644
|
+
* that can be used to determine which package manager ran the command.
|
|
1645
|
+
*/
|
|
1646
|
+
function detectPackageManager() {
|
|
1647
|
+
let { npm_config_user_agent } = process.env;
|
|
1648
|
+
if (!npm_config_user_agent) return void 0;
|
|
1649
|
+
try {
|
|
1650
|
+
let pkgManager = npm_config_user_agent.split("/")[0];
|
|
1651
|
+
if (pkgManager === "npm") return "npm";
|
|
1652
|
+
if (pkgManager === "pnpm") return "pnpm";
|
|
1653
|
+
if (pkgManager === "yarn") return "yarn";
|
|
1654
|
+
if (pkgManager === "bun") return "bun";
|
|
1655
|
+
if (pkgManager === "deno") return "deno";
|
|
1656
|
+
if (pkgManager === "nub") return "nub";
|
|
1657
|
+
return;
|
|
1658
|
+
} catch {
|
|
1659
|
+
return;
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1629
1662
|
async function installDependencies({ pkgManager, cwd, showInstallOutput }) {
|
|
1630
1663
|
try {
|
|
1631
|
-
await
|
|
1664
|
+
await runCommand(pkgManager, ["install"], {
|
|
1632
1665
|
cwd,
|
|
1633
1666
|
stdio: showInstallOutput ? "inherit" : "ignore"
|
|
1634
1667
|
});
|
|
@@ -1637,6 +1670,16 @@ async function installDependencies({ pkgManager, cwd, showInstallOutput }) {
|
|
|
1637
1670
|
throw err;
|
|
1638
1671
|
}
|
|
1639
1672
|
}
|
|
1673
|
+
function runCommand(command, args, options) {
|
|
1674
|
+
return new Promise((resolve, reject) => {
|
|
1675
|
+
let child = spawn(command, args, options);
|
|
1676
|
+
child.on("error", reject);
|
|
1677
|
+
child.on("exit", (code, signal) => {
|
|
1678
|
+
if (code === 0) resolve();
|
|
1679
|
+
else reject(/* @__PURE__ */ new Error(signal ? `${command} exited with signal ${signal}` : `${command} exited with code ${code}`));
|
|
1680
|
+
});
|
|
1681
|
+
});
|
|
1682
|
+
}
|
|
1640
1683
|
async function updatePackageJSON(ctx) {
|
|
1641
1684
|
let packageJSONPath = path.join(ctx.cwd, "package.json");
|
|
1642
1685
|
if (!existsSync(packageJSONPath)) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-react-router",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.0-experimental-
|
|
4
|
+
"version": "0.0.0-experimental-2a01b6fd8",
|
|
5
5
|
"description": "Create a new React Router app",
|
|
6
6
|
"homepage": "https://reactrouter.com",
|
|
7
7
|
"bugs": {
|
|
@@ -34,15 +34,12 @@
|
|
|
34
34
|
}
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"arg": "^5.0.1",
|
|
38
|
-
"execa": "9.6.1",
|
|
39
37
|
"gunzip-maybe": "^1.4.2",
|
|
40
38
|
"log-update": "^8.0.0",
|
|
41
39
|
"picocolors": "^1.1.1",
|
|
42
40
|
"semver": "^7.8.1",
|
|
43
41
|
"sisteransi": "^1.0.5",
|
|
44
42
|
"sort-package-json": "^3.6.1",
|
|
45
|
-
"strip-ansi": "^7.2.0",
|
|
46
43
|
"tar-fs": "^3.1.2"
|
|
47
44
|
},
|
|
48
45
|
"devDependencies": {
|