create-react-router 7.15.1 → 8.0.0-pre.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/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * create-react-router v7.15.1
3
+ * create-react-router v8.0.0-pre.0
4
4
  *
5
5
  * Copyright (c) Remix Software Inc.
6
6
  *
@@ -9,1996 +9,1628 @@
9
9
  *
10
10
  * @license MIT
11
11
  */
12
- "use strict";
13
- var __create = Object.create;
14
- var __defProp = Object.defineProperty;
15
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
16
- var __getOwnPropNames = Object.getOwnPropertyNames;
17
- var __getProtoOf = Object.getPrototypeOf;
18
- var __hasOwnProp = Object.prototype.hasOwnProperty;
19
- var __copyProps = (to, from, except, desc) => {
20
- if (from && typeof from === "object" || typeof from === "function") {
21
- for (let key of __getOwnPropNames(from))
22
- if (!__hasOwnProp.call(to, key) && key !== except)
23
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
24
- }
25
- return to;
26
- };
27
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
28
- // If the importer is in node compatibility mode or this is not an ESM
29
- // file that has been converted to a CommonJS file using a Babel-
30
- // compatible transform (i.e. "__esModule" has not been set), then set
31
- // "default" to the CommonJS "module.exports" for node compatibility.
32
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
33
- mod
34
- ));
35
-
36
- // cli.ts
37
- var import_node_process7 = __toESM(require("process"));
38
-
39
- // index.ts
40
- var import_node_process6 = __toESM(require("process"));
41
- var import_node_fs3 = require("fs");
42
- var import_promises2 = require("fs/promises");
43
- var import_node_os2 = __toESM(require("os"));
44
- var import_node_path3 = __toESM(require("path"));
45
- var import_strip_ansi = __toESM(require("strip-ansi"));
46
- var import_execa = __toESM(require("execa"));
47
- var import_arg = __toESM(require("arg"));
48
- var semver = __toESM(require("semver"));
49
- var import_sort_package_json = __toESM(require("sort-package-json"));
50
-
51
- // package.json
52
- var version = "7.15.1";
53
-
54
- // prompt.ts
55
- var import_node_process3 = __toESM(require("process"));
56
-
57
- // prompts-confirm.ts
58
- var import_sisteransi3 = require("sisteransi");
59
-
60
- // prompts-prompt-base.ts
61
- var import_node_process2 = __toESM(require("process"));
62
- var import_node_events = __toESM(require("events"));
63
- var import_node_readline = __toESM(require("readline"));
64
- var import_sisteransi2 = require("sisteransi");
65
-
66
- // utils.ts
67
- var import_node_fs = __toESM(require("fs"));
68
- var import_promises = require("fs/promises");
69
- var import_node_path = __toESM(require("path"));
70
- var import_node_process = __toESM(require("process"));
71
- var import_node_os = __toESM(require("os"));
72
- var import_sisteransi = require("sisteransi");
73
- var import_picocolors = __toESM(require("picocolors"));
74
- var SUPPORTS_COLOR = import_picocolors.default.isColorSupported;
75
- var color = {
76
- supportsColor: SUPPORTS_COLOR,
77
- heading: safeColor(import_picocolors.default.bold),
78
- arg: safeColor(import_picocolors.default.yellowBright),
79
- error: safeColor(import_picocolors.default.red),
80
- warning: safeColor(import_picocolors.default.yellow),
81
- hint: safeColor(import_picocolors.default.blue),
82
- bold: safeColor(import_picocolors.default.bold),
83
- black: safeColor(import_picocolors.default.black),
84
- white: safeColor(import_picocolors.default.white),
85
- blue: safeColor(import_picocolors.default.blue),
86
- cyan: safeColor(import_picocolors.default.cyan),
87
- red: safeColor(import_picocolors.default.red),
88
- yellow: safeColor(import_picocolors.default.yellow),
89
- green: safeColor(import_picocolors.default.green),
90
- blackBright: safeColor(import_picocolors.default.blackBright),
91
- whiteBright: safeColor(import_picocolors.default.whiteBright),
92
- blueBright: safeColor(import_picocolors.default.blueBright),
93
- cyanBright: safeColor(import_picocolors.default.cyanBright),
94
- redBright: safeColor(import_picocolors.default.redBright),
95
- yellowBright: safeColor(import_picocolors.default.yellowBright),
96
- greenBright: safeColor(import_picocolors.default.greenBright),
97
- bgBlack: safeColor(import_picocolors.default.bgBlack),
98
- bgWhite: safeColor(import_picocolors.default.bgWhite),
99
- bgBlue: safeColor(import_picocolors.default.bgBlue),
100
- bgCyan: safeColor(import_picocolors.default.bgCyan),
101
- bgRed: safeColor(import_picocolors.default.bgRed),
102
- bgYellow: safeColor(import_picocolors.default.bgYellow),
103
- bgGreen: safeColor(import_picocolors.default.bgGreen),
104
- bgBlackBright: safeColor(import_picocolors.default.bgBlackBright),
105
- bgWhiteBright: safeColor(import_picocolors.default.bgWhiteBright),
106
- bgBlueBright: safeColor(import_picocolors.default.bgBlueBright),
107
- bgCyanBright: safeColor(import_picocolors.default.bgCyanBright),
108
- bgRedBright: safeColor(import_picocolors.default.bgRedBright),
109
- bgYellowBright: safeColor(import_picocolors.default.bgYellowBright),
110
- bgGreenBright: safeColor(import_picocolors.default.bgGreenBright),
111
- gray: safeColor(import_picocolors.default.gray),
112
- dim: safeColor(import_picocolors.default.dim),
113
- reset: safeColor(import_picocolors.default.reset),
114
- inverse: safeColor(import_picocolors.default.inverse),
115
- hex: (hex) => safeColor(hexColor(hex)),
116
- underline: import_picocolors.default.underline
12
+ import process from "node:process";
13
+ import fs, { existsSync } from "node:fs";
14
+ import { cp, readFile, readdir, realpath, writeFile } from "node:fs/promises";
15
+ import os from "node:os";
16
+ import path from "node:path";
17
+ import stripAnsi from "strip-ansi";
18
+ import { execa } from "execa";
19
+ import arg from "arg";
20
+ import * as semver from "semver";
21
+ import sortPackageJSON from "sort-package-json";
22
+ import { beep, cursor, erase } from "sisteransi";
23
+ import EventEmitter from "node:events";
24
+ import readline from "node:readline";
25
+ import pc from "picocolors";
26
+ import url from "node:url";
27
+ import stream from "node:stream";
28
+ import { promisify } from "node:util";
29
+ import gunzip from "gunzip-maybe";
30
+ import tar from "tar-fs";
31
+ //#region utils.ts
32
+ const SUPPORTS_COLOR = pc.isColorSupported;
33
+ const color = {
34
+ supportsColor: SUPPORTS_COLOR,
35
+ heading: safeColor(pc.bold),
36
+ arg: safeColor(pc.yellowBright),
37
+ error: safeColor(pc.red),
38
+ warning: safeColor(pc.yellow),
39
+ hint: safeColor(pc.blue),
40
+ bold: safeColor(pc.bold),
41
+ black: safeColor(pc.black),
42
+ white: safeColor(pc.white),
43
+ blue: safeColor(pc.blue),
44
+ cyan: safeColor(pc.cyan),
45
+ red: safeColor(pc.red),
46
+ yellow: safeColor(pc.yellow),
47
+ green: safeColor(pc.green),
48
+ blackBright: safeColor(pc.blackBright),
49
+ whiteBright: safeColor(pc.whiteBright),
50
+ blueBright: safeColor(pc.blueBright),
51
+ cyanBright: safeColor(pc.cyanBright),
52
+ redBright: safeColor(pc.redBright),
53
+ yellowBright: safeColor(pc.yellowBright),
54
+ greenBright: safeColor(pc.greenBright),
55
+ bgBlack: safeColor(pc.bgBlack),
56
+ bgWhite: safeColor(pc.bgWhite),
57
+ bgBlue: safeColor(pc.bgBlue),
58
+ bgCyan: safeColor(pc.bgCyan),
59
+ bgRed: safeColor(pc.bgRed),
60
+ bgYellow: safeColor(pc.bgYellow),
61
+ bgGreen: safeColor(pc.bgGreen),
62
+ bgBlackBright: safeColor(pc.bgBlackBright),
63
+ bgWhiteBright: safeColor(pc.bgWhiteBright),
64
+ bgBlueBright: safeColor(pc.bgBlueBright),
65
+ bgCyanBright: safeColor(pc.bgCyanBright),
66
+ bgRedBright: safeColor(pc.bgRedBright),
67
+ bgYellowBright: safeColor(pc.bgYellowBright),
68
+ bgGreenBright: safeColor(pc.bgGreenBright),
69
+ gray: safeColor(pc.gray),
70
+ dim: safeColor(pc.dim),
71
+ reset: safeColor(pc.reset),
72
+ inverse: safeColor(pc.inverse),
73
+ hex: (hex) => safeColor(hexColor(hex)),
74
+ underline: pc.underline
117
75
  };
76
+ /**
77
+ * Converts a hex color string to an ANSI true-color (24-bit) formatter.
78
+ * Used by the loading indicator gradient animation.
79
+ */
118
80
  function hexColor(hex) {
119
- let h = hex.replace("#", "");
120
- let r = parseInt(h.substring(0, 2), 16);
121
- let g = parseInt(h.substring(2, 4), 16);
122
- let b = parseInt(h.substring(4, 6), 16);
123
- return (input) => `\x1B[38;2;${r};${g};${b}m${input}\x1B[39m`;
81
+ let h = hex.replace("#", "");
82
+ let r = parseInt(h.substring(0, 2), 16);
83
+ let g = parseInt(h.substring(2, 4), 16);
84
+ let b = parseInt(h.substring(4, 6), 16);
85
+ return (input) => `\x1b[38;2;${r};${g};${b}m${input}\x1b[39m`;
124
86
  }
125
87
  function safeColor(style) {
126
- return SUPPORTS_COLOR ? style : identity;
88
+ return SUPPORTS_COLOR ? style : identity;
127
89
  }
128
- var unicode = { enabled: import_node_os.default.platform() !== "win32" };
129
- var shouldUseAscii = () => !unicode.enabled;
90
+ const unicode = { enabled: os.platform() !== "win32" };
91
+ const shouldUseAscii = () => !unicode.enabled;
130
92
  function isInteractive() {
131
- if ("CREATE_REACT_ROUTER_FORCE_INTERACTIVE" in import_node_process.default.env) {
132
- return true;
133
- }
134
- return Boolean(
135
- import_node_process.default.stdout.isTTY && import_node_process.default.env.TERM !== "dumb" && !("CI" in import_node_process.default.env)
136
- );
93
+ if ("CREATE_REACT_ROUTER_FORCE_INTERACTIVE" in process.env) return true;
94
+ return Boolean(process.stdout.isTTY && process.env.TERM !== "dumb" && !("CI" in process.env));
137
95
  }
138
96
  function log(message) {
139
- return import_node_process.default.stdout.write(message + "\n");
97
+ return process.stdout.write(message + "\n");
140
98
  }
141
- var stderr = import_node_process.default.stderr;
99
+ let stderr = process.stderr;
142
100
  function logError(message) {
143
- return stderr.write(message + "\n");
101
+ return stderr.write(message + "\n");
144
102
  }
145
103
  function logBullet(logger, colorizePrefix, colorizeText, symbol, prefix, text) {
146
- let textParts = Array.isArray(text) ? text : [text || ""].filter(Boolean);
147
- let formattedText = textParts.map((textPart) => colorizeText(textPart)).join("");
148
- if (import_node_process.default.stdout.columns < 80) {
149
- logger(
150
- `${" ".repeat(5)} ${colorizePrefix(symbol)} ${colorizePrefix(prefix)}`
151
- );
152
- logger(`${" ".repeat(9)}${formattedText}`);
153
- } else {
154
- logger(
155
- `${" ".repeat(5)} ${colorizePrefix(symbol)} ${colorizePrefix(
156
- prefix
157
- )} ${formattedText}`
158
- );
159
- }
104
+ let formattedText = (Array.isArray(text) ? text : [text || ""].filter(Boolean)).map((textPart) => colorizeText(textPart)).join("");
105
+ if (process.stdout.columns < 80) {
106
+ logger(`${" ".repeat(5)} ${colorizePrefix(symbol)} ${colorizePrefix(prefix)}`);
107
+ logger(`${" ".repeat(9)}${formattedText}`);
108
+ } else logger(`${" ".repeat(5)} ${colorizePrefix(symbol)} ${colorizePrefix(prefix)} ${formattedText}`);
160
109
  }
161
110
  function debug(prefix, text) {
162
- logBullet(log, color.yellow, color.dim, "\u25CF", prefix, text);
111
+ logBullet(log, color.yellow, color.dim, "", prefix, text);
163
112
  }
164
113
  function info(prefix, text) {
165
- logBullet(log, color.cyan, color.dim, "\u25FC", prefix, text);
114
+ logBullet(log, color.cyan, color.dim, "", prefix, text);
166
115
  }
167
116
  function error(prefix, text) {
168
- log("");
169
- logBullet(logError, color.red, color.error, "\u25B2", prefix, text);
117
+ log("");
118
+ logBullet(logError, color.red, color.error, "", prefix, text);
170
119
  }
171
120
  function sleep(ms) {
172
- return new Promise((resolve) => setTimeout(resolve, ms));
121
+ return new Promise((resolve) => setTimeout(resolve, ms));
173
122
  }
174
123
  function toValidProjectName(projectName) {
175
- if (isValidProjectName(projectName)) {
176
- return projectName;
177
- }
178
- return projectName.trim().toLowerCase().replace(/\s+/g, "-").replace(/^[._]/, "").replace(/[^a-z\d\-~]+/g, "-").replace(/^-+/, "").replace(/-+$/, "");
124
+ if (isValidProjectName(projectName)) return projectName;
125
+ return projectName.trim().toLowerCase().replace(/\s+/g, "-").replace(/^[._]/, "").replace(/[^a-z\d\-~]+/g, "-").replace(/^-+/, "").replace(/-+$/, "");
179
126
  }
180
127
  function isValidProjectName(projectName) {
181
- return /^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(
182
- projectName
183
- );
128
+ return /^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(projectName);
184
129
  }
185
130
  function identity(v) {
186
- return v;
131
+ return v;
187
132
  }
188
133
  function strip(str) {
189
- let pattern = [
190
- "[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)",
191
- "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))"
192
- ].join("|");
193
- let RGX = new RegExp(pattern, "g");
194
- return typeof str === "string" ? str.replace(RGX, "") : str;
134
+ let pattern = ["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)", "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))"].join("|");
135
+ let RGX = new RegExp(pattern, "g");
136
+ return typeof str === "string" ? str.replace(RGX, "") : str;
195
137
  }
196
138
  function reverse(arr) {
197
- return [...arr].reverse();
139
+ return [...arr].reverse();
198
140
  }
199
141
  function isValidJsonObject(obj) {
200
- return !!(obj && typeof obj === "object" && !Array.isArray(obj));
142
+ return !!(obj && typeof obj === "object" && !Array.isArray(obj));
201
143
  }
202
144
  async function directoryExists(p) {
203
- try {
204
- let stat = await import_node_fs.default.promises.stat(p);
205
- return stat.isDirectory();
206
- } catch {
207
- return false;
208
- }
145
+ try {
146
+ return (await fs.promises.stat(p)).isDirectory();
147
+ } catch {
148
+ return false;
149
+ }
209
150
  }
210
151
  async function ensureDirectory(dir) {
211
- if (!await directoryExists(dir)) {
212
- await import_node_fs.default.promises.mkdir(dir, { recursive: true });
213
- }
152
+ if (!await directoryExists(dir)) await fs.promises.mkdir(dir, { recursive: true });
214
153
  }
215
154
  function isUrl(value) {
216
- try {
217
- new URL(value);
218
- return true;
219
- } catch (e) {
220
- return false;
221
- }
222
- }
223
- function clear(prompt2, perLine) {
224
- if (!perLine) return import_sisteransi.erase.line + import_sisteransi.cursor.to(0);
225
- let rows = 0;
226
- let lines2 = prompt2.split(/\r?\n/);
227
- for (let line of lines2) {
228
- rows += 1 + Math.floor(Math.max(strip(line).length - 1, 0) / perLine);
229
- }
230
- return import_sisteransi.erase.lines(rows);
155
+ try {
156
+ new URL(value);
157
+ return true;
158
+ } catch (e) {
159
+ return false;
160
+ }
161
+ }
162
+ function clear(prompt, perLine) {
163
+ if (!perLine) return erase.line + cursor.to(0);
164
+ let rows = 0;
165
+ let lines = prompt.split(/\r?\n/);
166
+ for (let line of lines) rows += 1 + Math.floor(Math.max(strip(line).length - 1, 0) / perLine);
167
+ return erase.lines(rows);
231
168
  }
232
169
  function lines(msg, perLine) {
233
- let lines2 = String(strip(msg) || "").split(/\r?\n/);
234
- if (!perLine) return lines2.length;
235
- return lines2.map((l) => Math.ceil(l.length / perLine)).reduce((a, b) => a + b);
170
+ let lines = String(strip(msg) || "").split(/\r?\n/);
171
+ if (!perLine) return lines.length;
172
+ return lines.map((l) => Math.ceil(l.length / perLine)).reduce((a, b) => a + b);
236
173
  }
237
174
  function action(key, isSelect) {
238
- if (key.meta && key.name !== "escape") return;
239
- if (key.ctrl) {
240
- if (key.name === "a") return "first";
241
- if (key.name === "c") return "abort";
242
- if (key.name === "d") return "abort";
243
- if (key.name === "e") return "last";
244
- if (key.name === "g") return "reset";
245
- }
246
- if (isSelect) {
247
- if (key.name === "j") return "down";
248
- if (key.name === "k") return "up";
249
- }
250
- if (key.name === "return") return "submit";
251
- if (key.name === "enter") return "submit";
252
- if (key.name === "backspace") return "delete";
253
- if (key.name === "delete") return "deleteForward";
254
- if (key.name === "abort") return "abort";
255
- if (key.name === "escape") return "exit";
256
- if (key.name === "tab") return "next";
257
- if (key.name === "pagedown") return "nextPage";
258
- if (key.name === "pageup") return "prevPage";
259
- if (key.name === "home") return "home";
260
- if (key.name === "end") return "end";
261
- if (key.name === "up") return "up";
262
- if (key.name === "down") return "down";
263
- if (key.name === "right") return "right";
264
- if (key.name === "left") return "left";
265
- return false;
175
+ if (key.meta && key.name !== "escape") return;
176
+ if (key.ctrl) {
177
+ if (key.name === "a") return "first";
178
+ if (key.name === "c") return "abort";
179
+ if (key.name === "d") return "abort";
180
+ if (key.name === "e") return "last";
181
+ if (key.name === "g") return "reset";
182
+ }
183
+ if (isSelect) {
184
+ if (key.name === "j") return "down";
185
+ if (key.name === "k") return "up";
186
+ }
187
+ if (key.name === "return") return "submit";
188
+ if (key.name === "enter") return "submit";
189
+ if (key.name === "backspace") return "delete";
190
+ if (key.name === "delete") return "deleteForward";
191
+ if (key.name === "abort") return "abort";
192
+ if (key.name === "escape") return "exit";
193
+ if (key.name === "tab") return "next";
194
+ if (key.name === "pagedown") return "nextPage";
195
+ if (key.name === "pageup") return "prevPage";
196
+ if (key.name === "home") return "home";
197
+ if (key.name === "end") return "end";
198
+ if (key.name === "up") return "up";
199
+ if (key.name === "down") return "down";
200
+ if (key.name === "right") return "right";
201
+ if (key.name === "left") return "left";
202
+ return false;
266
203
  }
267
204
  function stripDirectoryFromPath(dir, filePath) {
268
- let stripped = filePath;
269
- if (dir.endsWith(import_node_path.default.sep) && filePath.startsWith(dir) || !dir.endsWith(import_node_path.default.sep) && filePath.startsWith(dir + import_node_path.default.sep)) {
270
- stripped = filePath.slice(dir.length);
271
- if (stripped.startsWith(import_node_path.default.sep)) {
272
- stripped = stripped.slice(1);
273
- }
274
- }
275
- return stripped;
276
- }
277
- var IGNORED_TEMPLATE_DIRECTORIES = [".git", "node_modules"];
205
+ let stripped = filePath;
206
+ if (dir.endsWith(path.sep) && filePath.startsWith(dir) || !dir.endsWith(path.sep) && filePath.startsWith(dir + path.sep)) {
207
+ stripped = filePath.slice(dir.length);
208
+ if (stripped.startsWith(path.sep)) stripped = stripped.slice(1);
209
+ }
210
+ return stripped;
211
+ }
212
+ const IGNORED_TEMPLATE_DIRECTORIES = [".git", "node_modules"];
278
213
  async function getDirectoryFilesRecursive(dir) {
279
- return (await (0, import_promises.readdir)(dir, { recursive: true })).filter((file) => {
280
- let parts = file.split(import_node_path.default.sep);
281
- return parts.length <= 1 || !IGNORED_TEMPLATE_DIRECTORIES.includes(parts[0]);
282
- });
214
+ return (await readdir(dir, { recursive: true })).filter((file) => {
215
+ let parts = file.split(path.sep);
216
+ return parts.length <= 1 || !IGNORED_TEMPLATE_DIRECTORIES.includes(parts[0]);
217
+ });
283
218
  }
284
-
285
- // prompts-prompt-base.ts
286
- var Prompt = class extends import_node_events.default {
287
- firstRender;
288
- in;
289
- out;
290
- onRender;
291
- close;
292
- aborted;
293
- exited;
294
- closed;
295
- name = "Prompt";
296
- constructor(opts = {}) {
297
- super();
298
- this.firstRender = true;
299
- this.in = opts.stdin || import_node_process2.default.stdin;
300
- this.out = opts.stdout || import_node_process2.default.stdout;
301
- this.onRender = (opts.onRender || (() => void 0)).bind(this);
302
- let rl = import_node_readline.default.createInterface({
303
- input: this.in,
304
- escapeCodeTimeout: 50
305
- });
306
- import_node_readline.default.emitKeypressEvents(this.in, rl);
307
- if (this.in.isTTY) this.in.setRawMode(true);
308
- let isSelect = ["SelectPrompt", "MultiSelectPrompt"].indexOf(this.constructor.name) > -1;
309
- let keypress = (str, key) => {
310
- if (this.in.isTTY) this.in.setRawMode(true);
311
- let a = action(key, isSelect);
312
- if (a === false) {
313
- try {
314
- this._(str, key);
315
- } catch (e) {
316
- }
317
- } else if (typeof this[a] === "function") {
318
- this[a](key);
319
- }
320
- };
321
- this.close = () => {
322
- this.out.write(import_sisteransi2.cursor.show);
323
- this.in.removeListener("keypress", keypress);
324
- if (this.in.isTTY) this.in.setRawMode(false);
325
- rl.close();
326
- this.emit(
327
- this.aborted ? "abort" : this.exited ? "exit" : "submit",
328
- // @ts-expect-error
329
- this.value
330
- );
331
- this.closed = true;
332
- };
333
- this.in.on("keypress", keypress);
334
- }
335
- get type() {
336
- throw new Error("Method type not implemented.");
337
- }
338
- bell() {
339
- this.out.write(import_sisteransi2.beep);
340
- }
341
- fire() {
342
- this.emit("state", {
343
- // @ts-expect-error
344
- value: this.value,
345
- aborted: !!this.aborted,
346
- exited: !!this.exited
347
- });
348
- }
349
- render() {
350
- this.onRender(color);
351
- if (this.firstRender) this.firstRender = false;
352
- }
353
- _(c, key) {
354
- throw new Error("Method _ not implemented.");
355
- }
219
+ //#endregion
220
+ //#region prompts-prompt-base.ts
221
+ /**
222
+ * Adapted from https://github.com/withastro/cli-kit
223
+ * @license MIT License Copyright (c) 2022 Nate Moore
224
+ */
225
+ var Prompt = class extends EventEmitter {
226
+ firstRender;
227
+ in;
228
+ out;
229
+ onRender;
230
+ close;
231
+ aborted;
232
+ exited;
233
+ closed;
234
+ name = "Prompt";
235
+ constructor(opts = {}) {
236
+ super();
237
+ this.firstRender = true;
238
+ this.in = opts.stdin || process.stdin;
239
+ this.out = opts.stdout || process.stdout;
240
+ this.onRender = (opts.onRender || (() => void 0)).bind(this);
241
+ let rl = readline.createInterface({
242
+ input: this.in,
243
+ escapeCodeTimeout: 50
244
+ });
245
+ readline.emitKeypressEvents(this.in, rl);
246
+ if (this.in.isTTY) this.in.setRawMode(true);
247
+ let isSelect = ["SelectPrompt", "MultiSelectPrompt"].indexOf(this.constructor.name) > -1;
248
+ let keypress = (str, key) => {
249
+ if (this.in.isTTY) this.in.setRawMode(true);
250
+ let a = action(key, isSelect);
251
+ if (a === false) try {
252
+ this._(str, key);
253
+ } catch (e) {}
254
+ else if (typeof this[a] === "function") this[a](key);
255
+ };
256
+ this.close = () => {
257
+ this.out.write(cursor.show);
258
+ this.in.removeListener("keypress", keypress);
259
+ if (this.in.isTTY) this.in.setRawMode(false);
260
+ rl.close();
261
+ this.emit(this.aborted ? "abort" : this.exited ? "exit" : "submit", this.value);
262
+ this.closed = true;
263
+ };
264
+ this.in.on("keypress", keypress);
265
+ }
266
+ get type() {
267
+ throw new Error("Method type not implemented.");
268
+ }
269
+ bell() {
270
+ this.out.write(beep);
271
+ }
272
+ fire() {
273
+ this.emit("state", {
274
+ value: this.value,
275
+ aborted: !!this.aborted,
276
+ exited: !!this.exited
277
+ });
278
+ }
279
+ render() {
280
+ this.onRender(color);
281
+ if (this.firstRender) this.firstRender = false;
282
+ }
283
+ _(c, key) {
284
+ throw new Error("Method _ not implemented.");
285
+ }
356
286
  };
357
-
358
- // prompts-confirm.ts
287
+ //#endregion
288
+ //#region prompts-confirm.ts
289
+ /**
290
+ * Adapted from https://github.com/withastro/cli-kit
291
+ * @license MIT License Copyright (c) 2022 Nate Moore
292
+ */
359
293
  var ConfirmPrompt = class extends Prompt {
360
- label;
361
- msg;
362
- value;
363
- initialValue;
364
- hint;
365
- choices;
366
- cursor;
367
- done;
368
- name = "ConfirmPrompt";
369
- // set by render which is called in constructor
370
- outputText;
371
- constructor(opts) {
372
- super(opts);
373
- this.label = opts.label;
374
- this.hint = opts.hint;
375
- this.msg = opts.message;
376
- this.value = opts.initial;
377
- this.initialValue = !!opts.initial;
378
- this.choices = [
379
- { value: true, label: "Yes" },
380
- { value: false, label: "No" }
381
- ];
382
- this.cursor = this.choices.findIndex((c) => c.value === this.initialValue);
383
- this.render();
384
- }
385
- get type() {
386
- return "confirm";
387
- }
388
- exit() {
389
- this.abort();
390
- }
391
- abort() {
392
- this.done = this.aborted = true;
393
- this.fire();
394
- this.render();
395
- this.out.write("\n");
396
- this.close();
397
- }
398
- submit() {
399
- this.value = this.value || false;
400
- this.cursor = this.choices.findIndex((c) => c.value === this.value);
401
- this.done = true;
402
- this.aborted = false;
403
- this.fire();
404
- this.render();
405
- this.out.write("\n");
406
- this.close();
407
- }
408
- moveCursor(n) {
409
- this.cursor = n;
410
- this.value = this.choices[n].value;
411
- this.fire();
412
- }
413
- reset() {
414
- this.moveCursor(0);
415
- this.fire();
416
- this.render();
417
- }
418
- first() {
419
- this.moveCursor(0);
420
- this.render();
421
- }
422
- last() {
423
- this.moveCursor(this.choices.length - 1);
424
- this.render();
425
- }
426
- left() {
427
- if (this.cursor === 0) {
428
- this.moveCursor(this.choices.length - 1);
429
- } else {
430
- this.moveCursor(this.cursor - 1);
431
- }
432
- this.render();
433
- }
434
- right() {
435
- if (this.cursor === this.choices.length - 1) {
436
- this.moveCursor(0);
437
- } else {
438
- this.moveCursor(this.cursor + 1);
439
- }
440
- this.render();
441
- }
442
- _(c, key) {
443
- if (!Number.isNaN(Number.parseInt(c))) {
444
- let n = Number.parseInt(c) - 1;
445
- this.moveCursor(n);
446
- this.render();
447
- return this.submit();
448
- }
449
- if (c.toLowerCase() === "y") {
450
- this.value = true;
451
- return this.submit();
452
- }
453
- if (c.toLowerCase() === "n") {
454
- this.value = false;
455
- return this.submit();
456
- }
457
- return;
458
- }
459
- render() {
460
- if (this.closed) {
461
- return;
462
- }
463
- if (this.firstRender) {
464
- this.out.write(import_sisteransi3.cursor.hide);
465
- } else {
466
- this.out.write(clear(this.outputText, this.out.columns));
467
- }
468
- super.render();
469
- let outputText = [
470
- "\n",
471
- this.label,
472
- " ",
473
- this.msg,
474
- this.done ? "" : this.hint ? color.dim(` (${this.hint})`) : "",
475
- "\n"
476
- ];
477
- outputText.push(" ".repeat(strip(this.label).length));
478
- if (this.done) {
479
- outputText.push(" ", color.dim(`${this.choices[this.cursor].label}`));
480
- } else {
481
- outputText.push(
482
- " ",
483
- this.choices.map(
484
- (choice, i) => i === this.cursor ? `${color.green("\u25CF")} ${choice.label} ` : color.dim(`\u25CB ${choice.label} `)
485
- ).join(color.dim(" "))
486
- );
487
- }
488
- this.outputText = outputText.join("");
489
- this.out.write(import_sisteransi3.erase.line + import_sisteransi3.cursor.to(0) + this.outputText);
490
- }
294
+ label;
295
+ msg;
296
+ value;
297
+ initialValue;
298
+ hint;
299
+ choices;
300
+ cursor;
301
+ done;
302
+ name = "ConfirmPrompt";
303
+ outputText;
304
+ constructor(opts) {
305
+ super(opts);
306
+ this.label = opts.label;
307
+ this.hint = opts.hint;
308
+ this.msg = opts.message;
309
+ this.value = opts.initial;
310
+ this.initialValue = !!opts.initial;
311
+ this.choices = [{
312
+ value: true,
313
+ label: "Yes"
314
+ }, {
315
+ value: false,
316
+ label: "No"
317
+ }];
318
+ this.cursor = this.choices.findIndex((c) => c.value === this.initialValue);
319
+ this.render();
320
+ }
321
+ get type() {
322
+ return "confirm";
323
+ }
324
+ exit() {
325
+ this.abort();
326
+ }
327
+ abort() {
328
+ this.done = this.aborted = true;
329
+ this.fire();
330
+ this.render();
331
+ this.out.write("\n");
332
+ this.close();
333
+ }
334
+ submit() {
335
+ this.value = this.value || false;
336
+ this.cursor = this.choices.findIndex((c) => c.value === this.value);
337
+ this.done = true;
338
+ this.aborted = false;
339
+ this.fire();
340
+ this.render();
341
+ this.out.write("\n");
342
+ this.close();
343
+ }
344
+ moveCursor(n) {
345
+ this.cursor = n;
346
+ this.value = this.choices[n].value;
347
+ this.fire();
348
+ }
349
+ reset() {
350
+ this.moveCursor(0);
351
+ this.fire();
352
+ this.render();
353
+ }
354
+ first() {
355
+ this.moveCursor(0);
356
+ this.render();
357
+ }
358
+ last() {
359
+ this.moveCursor(this.choices.length - 1);
360
+ this.render();
361
+ }
362
+ left() {
363
+ if (this.cursor === 0) this.moveCursor(this.choices.length - 1);
364
+ else this.moveCursor(this.cursor - 1);
365
+ this.render();
366
+ }
367
+ right() {
368
+ if (this.cursor === this.choices.length - 1) this.moveCursor(0);
369
+ else this.moveCursor(this.cursor + 1);
370
+ this.render();
371
+ }
372
+ _(c, key) {
373
+ if (!Number.isNaN(Number.parseInt(c))) {
374
+ let n = Number.parseInt(c) - 1;
375
+ this.moveCursor(n);
376
+ this.render();
377
+ return this.submit();
378
+ }
379
+ if (c.toLowerCase() === "y") {
380
+ this.value = true;
381
+ return this.submit();
382
+ }
383
+ if (c.toLowerCase() === "n") {
384
+ this.value = false;
385
+ return this.submit();
386
+ }
387
+ }
388
+ render() {
389
+ if (this.closed) return;
390
+ if (this.firstRender) this.out.write(cursor.hide);
391
+ else this.out.write(clear(this.outputText, this.out.columns));
392
+ super.render();
393
+ let outputText = [
394
+ "\n",
395
+ this.label,
396
+ " ",
397
+ this.msg,
398
+ this.done ? "" : this.hint ? color.dim(` (${this.hint})`) : "",
399
+ "\n"
400
+ ];
401
+ outputText.push(" ".repeat(strip(this.label).length));
402
+ if (this.done) outputText.push(" ", color.dim(`${this.choices[this.cursor].label}`));
403
+ else outputText.push(" ", this.choices.map((choice, i) => i === this.cursor ? `${color.green("●")} ${choice.label} ` : color.dim(`○ ${choice.label} `)).join(color.dim(" ")));
404
+ this.outputText = outputText.join("");
405
+ this.out.write(erase.line + cursor.to(0) + this.outputText);
406
+ }
491
407
  };
492
-
493
- // prompts-select.ts
494
- var import_sisteransi4 = require("sisteransi");
408
+ //#endregion
409
+ //#region prompts-select.ts
410
+ /**
411
+ * Adapted from https://github.com/withastro/cli-kit
412
+ * @license MIT License Copyright (c) 2022 Nate Moore
413
+ */
495
414
  var SelectPrompt = class extends Prompt {
496
- choices;
497
- label;
498
- msg;
499
- hint;
500
- value;
501
- initialValue;
502
- search;
503
- done;
504
- cursor;
505
- name = "SelectPrompt";
506
- _timeout;
507
- // set by render which is called in constructor
508
- outputText;
509
- constructor(opts) {
510
- if (!opts.choices || !Array.isArray(opts.choices) || opts.choices.length < 1) {
511
- throw new Error("SelectPrompt must contain choices");
512
- }
513
- super(opts);
514
- this.label = opts.label;
515
- this.hint = opts.hint;
516
- this.msg = opts.message;
517
- this.value = opts.initial;
518
- this.choices = opts.choices;
519
- this.initialValue = opts.initial || this.choices[0].value;
520
- this.cursor = this.choices.findIndex((c) => c.value === this.initialValue);
521
- this.search = null;
522
- this.render();
523
- }
524
- get type() {
525
- return "select";
526
- }
527
- exit() {
528
- this.abort();
529
- }
530
- abort() {
531
- this.done = this.aborted = true;
532
- this.cursor = this.choices.findIndex((c) => c.value === this.initialValue);
533
- this.fire();
534
- this.render();
535
- this.out.write("\n");
536
- this.close();
537
- }
538
- submit() {
539
- this.value = this.value || void 0;
540
- this.cursor = this.choices.findIndex((c) => c.value === this.value);
541
- this.done = true;
542
- this.aborted = false;
543
- this.fire();
544
- this.render();
545
- this.out.write("\n");
546
- this.close();
547
- }
548
- delete() {
549
- this.search = null;
550
- this.render();
551
- }
552
- _(c, key) {
553
- if (this._timeout) clearTimeout(this._timeout);
554
- if (!Number.isNaN(Number.parseInt(c))) {
555
- let n2 = Number.parseInt(c) - 1;
556
- this.moveCursor(n2);
557
- this.render();
558
- return this.submit();
559
- }
560
- this.search = this.search || "";
561
- this.search += c.toLowerCase();
562
- let choices = !this.search ? this.choices.slice(this.cursor) : this.choices;
563
- let n = choices.findIndex(
564
- (c2) => c2.label.toLowerCase().includes(this.search)
565
- );
566
- if (n > -1) {
567
- this.moveCursor(n);
568
- this.render();
569
- }
570
- this._timeout = setTimeout(() => {
571
- this.search = null;
572
- }, 500);
573
- }
574
- moveCursor(n) {
575
- this.cursor = n;
576
- this.value = this.choices[n].value;
577
- this.fire();
578
- }
579
- reset() {
580
- this.moveCursor(0);
581
- this.fire();
582
- this.render();
583
- }
584
- first() {
585
- this.moveCursor(0);
586
- this.render();
587
- }
588
- last() {
589
- this.moveCursor(this.choices.length - 1);
590
- this.render();
591
- }
592
- up() {
593
- if (this.cursor === 0) {
594
- this.moveCursor(this.choices.length - 1);
595
- } else {
596
- this.moveCursor(this.cursor - 1);
597
- }
598
- this.render();
599
- }
600
- down() {
601
- if (this.cursor === this.choices.length - 1) {
602
- this.moveCursor(0);
603
- } else {
604
- this.moveCursor(this.cursor + 1);
605
- }
606
- this.render();
607
- }
608
- highlight(label) {
609
- if (!this.search) return label;
610
- let n = label.toLowerCase().indexOf(this.search.toLowerCase());
611
- if (n === -1) return label;
612
- return [
613
- label.slice(0, n),
614
- color.underline(label.slice(n, n + this.search.length)),
615
- label.slice(n + this.search.length)
616
- ].join("");
617
- }
618
- render() {
619
- if (this.closed) return;
620
- if (this.firstRender) this.out.write(import_sisteransi4.cursor.hide);
621
- else this.out.write(clear(this.outputText, this.out.columns));
622
- super.render();
623
- let outputText = [
624
- "\n",
625
- this.label,
626
- " ",
627
- this.msg,
628
- this.done ? "" : this.hint ? (this.out.columns < 80 ? "\n" + " ".repeat(8) : "") + color.dim(` (${this.hint})`) : "",
629
- "\n"
630
- ];
631
- let prefix = " ".repeat(strip(this.label).length);
632
- if (this.done) {
633
- outputText.push(
634
- `${prefix} `,
635
- color.dim(`${this.choices[this.cursor]?.label}`)
636
- );
637
- } else {
638
- outputText.push(
639
- this.choices.map(
640
- (choice, i) => i === this.cursor ? `${prefix} ${color.green(
641
- shouldUseAscii() ? ">" : "\u25CF"
642
- )} ${this.highlight(choice.label)} ${choice.hint ? color.dim(choice.hint) : ""}` : color.dim(
643
- `${prefix} ${shouldUseAscii() ? "\u2014" : "\u25CB"} ${choice.label} `
644
- )
645
- ).join("\n")
646
- );
647
- }
648
- this.outputText = outputText.join("");
649
- this.out.write(import_sisteransi4.erase.line + import_sisteransi4.cursor.to(0) + this.outputText);
650
- }
415
+ choices;
416
+ label;
417
+ msg;
418
+ hint;
419
+ value;
420
+ initialValue;
421
+ search;
422
+ done;
423
+ cursor;
424
+ name = "SelectPrompt";
425
+ _timeout;
426
+ outputText;
427
+ constructor(opts) {
428
+ if (!opts.choices || !Array.isArray(opts.choices) || opts.choices.length < 1) throw new Error("SelectPrompt must contain choices");
429
+ super(opts);
430
+ this.label = opts.label;
431
+ this.hint = opts.hint;
432
+ this.msg = opts.message;
433
+ this.value = opts.initial;
434
+ this.choices = opts.choices;
435
+ this.initialValue = opts.initial || this.choices[0].value;
436
+ this.cursor = this.choices.findIndex((c) => c.value === this.initialValue);
437
+ this.search = null;
438
+ this.render();
439
+ }
440
+ get type() {
441
+ return "select";
442
+ }
443
+ exit() {
444
+ this.abort();
445
+ }
446
+ abort() {
447
+ this.done = this.aborted = true;
448
+ this.cursor = this.choices.findIndex((c) => c.value === this.initialValue);
449
+ this.fire();
450
+ this.render();
451
+ this.out.write("\n");
452
+ this.close();
453
+ }
454
+ submit() {
455
+ this.value = this.value || void 0;
456
+ this.cursor = this.choices.findIndex((c) => c.value === this.value);
457
+ this.done = true;
458
+ this.aborted = false;
459
+ this.fire();
460
+ this.render();
461
+ this.out.write("\n");
462
+ this.close();
463
+ }
464
+ delete() {
465
+ this.search = null;
466
+ this.render();
467
+ }
468
+ _(c, key) {
469
+ if (this._timeout) clearTimeout(this._timeout);
470
+ if (!Number.isNaN(Number.parseInt(c))) {
471
+ let n = Number.parseInt(c) - 1;
472
+ this.moveCursor(n);
473
+ this.render();
474
+ return this.submit();
475
+ }
476
+ this.search = this.search || "";
477
+ this.search += c.toLowerCase();
478
+ let n = (!this.search ? this.choices.slice(this.cursor) : this.choices).findIndex((c) => c.label.toLowerCase().includes(this.search));
479
+ if (n > -1) {
480
+ this.moveCursor(n);
481
+ this.render();
482
+ }
483
+ this._timeout = setTimeout(() => {
484
+ this.search = null;
485
+ }, 500);
486
+ }
487
+ moveCursor(n) {
488
+ this.cursor = n;
489
+ this.value = this.choices[n].value;
490
+ this.fire();
491
+ }
492
+ reset() {
493
+ this.moveCursor(0);
494
+ this.fire();
495
+ this.render();
496
+ }
497
+ first() {
498
+ this.moveCursor(0);
499
+ this.render();
500
+ }
501
+ last() {
502
+ this.moveCursor(this.choices.length - 1);
503
+ this.render();
504
+ }
505
+ up() {
506
+ if (this.cursor === 0) this.moveCursor(this.choices.length - 1);
507
+ else this.moveCursor(this.cursor - 1);
508
+ this.render();
509
+ }
510
+ down() {
511
+ if (this.cursor === this.choices.length - 1) this.moveCursor(0);
512
+ else this.moveCursor(this.cursor + 1);
513
+ this.render();
514
+ }
515
+ highlight(label) {
516
+ if (!this.search) return label;
517
+ let n = label.toLowerCase().indexOf(this.search.toLowerCase());
518
+ if (n === -1) return label;
519
+ return [
520
+ label.slice(0, n),
521
+ color.underline(label.slice(n, n + this.search.length)),
522
+ label.slice(n + this.search.length)
523
+ ].join("");
524
+ }
525
+ render() {
526
+ if (this.closed) return;
527
+ if (this.firstRender) this.out.write(cursor.hide);
528
+ else this.out.write(clear(this.outputText, this.out.columns));
529
+ super.render();
530
+ let outputText = [
531
+ "\n",
532
+ this.label,
533
+ " ",
534
+ this.msg,
535
+ this.done ? "" : this.hint ? (this.out.columns < 80 ? "\n" + " ".repeat(8) : "") + color.dim(` (${this.hint})`) : "",
536
+ "\n"
537
+ ];
538
+ let prefix = " ".repeat(strip(this.label).length);
539
+ if (this.done) outputText.push(`${prefix} `, color.dim(`${this.choices[this.cursor]?.label}`));
540
+ else outputText.push(this.choices.map((choice, i) => i === this.cursor ? `${prefix} ${color.green(shouldUseAscii() ? ">" : "●")} ${this.highlight(choice.label)} ${choice.hint ? color.dim(choice.hint) : ""}` : color.dim(`${prefix} ${shouldUseAscii() ? "—" : "○"} ${choice.label} `)).join("\n"));
541
+ this.outputText = outputText.join("");
542
+ this.out.write(erase.line + cursor.to(0) + this.outputText);
543
+ }
651
544
  };
652
-
653
- // prompts-multi-select.ts
654
- var import_sisteransi5 = require("sisteransi");
545
+ //#endregion
546
+ //#region prompts-multi-select.ts
547
+ /**
548
+ * Adapted from https://github.com/withastro/cli-kit
549
+ * @license MIT License Copyright (c) 2022 Nate Moore
550
+ */
655
551
  var MultiSelectPrompt = class extends Prompt {
656
- choices;
657
- label;
658
- msg;
659
- hint;
660
- value;
661
- initialValue;
662
- done;
663
- cursor;
664
- name = "MultiSelectPrompt";
665
- // set by render which is called in constructor
666
- outputText;
667
- constructor(opts) {
668
- if (!opts.choices || !Array.isArray(opts.choices) || opts.choices.length < 1) {
669
- throw new Error("MultiSelectPrompt must contain choices");
670
- }
671
- super(opts);
672
- this.label = opts.label;
673
- this.msg = opts.message;
674
- this.hint = opts.hint;
675
- this.value = [];
676
- this.choices = opts.choices.map((choice) => ({ ...choice, selected: false })) || [];
677
- this.initialValue = opts.initial || this.choices[0].value;
678
- this.cursor = this.choices.findIndex((c) => c.value === this.initialValue);
679
- this.render();
680
- }
681
- get type() {
682
- return "multiselect";
683
- }
684
- exit() {
685
- this.abort();
686
- }
687
- abort() {
688
- this.done = this.aborted = true;
689
- this.cursor = this.choices.findIndex((c) => c.value === this.initialValue);
690
- this.fire();
691
- this.render();
692
- this.out.write("\n");
693
- this.close();
694
- }
695
- submit() {
696
- return this.toggle();
697
- }
698
- finish() {
699
- this.value = this.value;
700
- this.done = true;
701
- this.aborted = false;
702
- this.fire();
703
- this.render();
704
- this.out.write("\n");
705
- this.close();
706
- }
707
- moveCursor(n) {
708
- this.cursor = n;
709
- this.fire();
710
- }
711
- toggle() {
712
- let choice = this.choices[this.cursor];
713
- if (!choice) return;
714
- choice.selected = !choice.selected;
715
- this.render();
716
- }
717
- _(c, key) {
718
- if (c === " ") {
719
- return this.toggle();
720
- }
721
- if (c.toLowerCase() === "c") {
722
- return this.finish();
723
- }
724
- return;
725
- }
726
- reset() {
727
- this.moveCursor(0);
728
- this.fire();
729
- this.render();
730
- }
731
- first() {
732
- this.moveCursor(0);
733
- this.render();
734
- }
735
- last() {
736
- this.moveCursor(this.choices.length - 1);
737
- this.render();
738
- }
739
- up() {
740
- if (this.cursor === 0) {
741
- this.moveCursor(this.choices.length - 1);
742
- } else {
743
- this.moveCursor(this.cursor - 1);
744
- }
745
- this.render();
746
- }
747
- down() {
748
- if (this.cursor === this.choices.length - 1) {
749
- this.moveCursor(0);
750
- } else {
751
- this.moveCursor(this.cursor + 1);
752
- }
753
- this.render();
754
- }
755
- render() {
756
- if (this.closed) return;
757
- if (this.firstRender) {
758
- this.out.write(import_sisteransi5.cursor.hide);
759
- } else {
760
- this.out.write(clear(this.outputText, this.out.columns));
761
- }
762
- super.render();
763
- let outputText = ["\n", this.label, " ", this.msg, "\n"];
764
- let prefix = " ".repeat(strip(this.label).length);
765
- if (this.done) {
766
- outputText.push(
767
- this.choices.map(
768
- (choice) => choice.selected ? `${prefix} ${color.dim(`${choice.label}`)}
769
- ` : ""
770
- ).join("").trimEnd()
771
- );
772
- } else {
773
- outputText.push(
774
- this.choices.map(
775
- (choice, i) => i === this.cursor ? `${prefix.slice(0, -2)}${color.cyanBright("\u25B6")} ${choice.selected ? color.green("\u25A0") : color.whiteBright("\u25A1")} ${color.underline(choice.label)} ${choice.hint ? color.dim(choice.hint) : ""}` : color[choice.selected ? "reset" : "dim"](
776
- `${prefix} ${choice.selected ? color.green("\u25A0") : "\u25A1"} ${choice.label} `
777
- )
778
- ).join("\n")
779
- );
780
- outputText.push(
781
- `
782
-
783
- ${prefix} Press ${color.inverse(" C ")} to continue`
784
- );
785
- }
786
- this.outputText = outputText.join("");
787
- this.out.write(import_sisteransi5.erase.line + import_sisteransi5.cursor.to(0) + this.outputText);
788
- }
552
+ choices;
553
+ label;
554
+ msg;
555
+ hint;
556
+ value;
557
+ initialValue;
558
+ done;
559
+ cursor;
560
+ name = "MultiSelectPrompt";
561
+ outputText;
562
+ constructor(opts) {
563
+ if (!opts.choices || !Array.isArray(opts.choices) || opts.choices.length < 1) throw new Error("MultiSelectPrompt must contain choices");
564
+ super(opts);
565
+ this.label = opts.label;
566
+ this.msg = opts.message;
567
+ this.hint = opts.hint;
568
+ this.value = [];
569
+ this.choices = opts.choices.map((choice) => ({
570
+ ...choice,
571
+ selected: false
572
+ })) || [];
573
+ this.initialValue = opts.initial || this.choices[0].value;
574
+ this.cursor = this.choices.findIndex((c) => c.value === this.initialValue);
575
+ this.render();
576
+ }
577
+ get type() {
578
+ return "multiselect";
579
+ }
580
+ exit() {
581
+ this.abort();
582
+ }
583
+ abort() {
584
+ this.done = this.aborted = true;
585
+ this.cursor = this.choices.findIndex((c) => c.value === this.initialValue);
586
+ this.fire();
587
+ this.render();
588
+ this.out.write("\n");
589
+ this.close();
590
+ }
591
+ submit() {
592
+ return this.toggle();
593
+ }
594
+ finish() {
595
+ this.value = this.value;
596
+ this.done = true;
597
+ this.aborted = false;
598
+ this.fire();
599
+ this.render();
600
+ this.out.write("\n");
601
+ this.close();
602
+ }
603
+ moveCursor(n) {
604
+ this.cursor = n;
605
+ this.fire();
606
+ }
607
+ toggle() {
608
+ let choice = this.choices[this.cursor];
609
+ if (!choice) return;
610
+ choice.selected = !choice.selected;
611
+ this.render();
612
+ }
613
+ _(c, key) {
614
+ if (c === " ") return this.toggle();
615
+ if (c.toLowerCase() === "c") return this.finish();
616
+ }
617
+ reset() {
618
+ this.moveCursor(0);
619
+ this.fire();
620
+ this.render();
621
+ }
622
+ first() {
623
+ this.moveCursor(0);
624
+ this.render();
625
+ }
626
+ last() {
627
+ this.moveCursor(this.choices.length - 1);
628
+ this.render();
629
+ }
630
+ up() {
631
+ if (this.cursor === 0) this.moveCursor(this.choices.length - 1);
632
+ else this.moveCursor(this.cursor - 1);
633
+ this.render();
634
+ }
635
+ down() {
636
+ if (this.cursor === this.choices.length - 1) this.moveCursor(0);
637
+ else this.moveCursor(this.cursor + 1);
638
+ this.render();
639
+ }
640
+ render() {
641
+ if (this.closed) return;
642
+ if (this.firstRender) this.out.write(cursor.hide);
643
+ else this.out.write(clear(this.outputText, this.out.columns));
644
+ super.render();
645
+ let outputText = [
646
+ "\n",
647
+ this.label,
648
+ " ",
649
+ this.msg,
650
+ "\n"
651
+ ];
652
+ let prefix = " ".repeat(strip(this.label).length);
653
+ if (this.done) outputText.push(this.choices.map((choice) => choice.selected ? `${prefix} ${color.dim(`${choice.label}`)}\n` : "").join("").trimEnd());
654
+ else {
655
+ outputText.push(this.choices.map((choice, i) => i === this.cursor ? `${prefix.slice(0, -2)}${color.cyanBright("▶")} ${choice.selected ? color.green("■") : color.whiteBright("□")} ${color.underline(choice.label)} ${choice.hint ? color.dim(choice.hint) : ""}` : color[choice.selected ? "reset" : "dim"](`${prefix} ${choice.selected ? color.green("■") : "□"} ${choice.label} `)).join("\n"));
656
+ outputText.push(`\n\n${prefix} Press ${color.inverse(" C ")} to continue`);
657
+ }
658
+ this.outputText = outputText.join("");
659
+ this.out.write(erase.line + cursor.to(0) + this.outputText);
660
+ }
789
661
  };
790
-
791
- // prompts-text.ts
792
- var import_sisteransi6 = require("sisteransi");
662
+ //#endregion
663
+ //#region prompts-text.ts
664
+ /**
665
+ * Adapted from https://github.com/withastro/cli-kit
666
+ * @license MIT License Copyright (c) 2022 Nate Moore
667
+ */
793
668
  var TextPrompt = class extends Prompt {
794
- transform;
795
- label;
796
- scale;
797
- msg;
798
- initial;
799
- hint;
800
- validator;
801
- errorMsg;
802
- cursor;
803
- cursorOffset;
804
- clear;
805
- done;
806
- error;
807
- red;
808
- outputError;
809
- name = "TextPrompt";
810
- // set by value setter, value is set in constructor
811
- _value;
812
- placeholder;
813
- rendered;
814
- // set by render which is called in constructor
815
- outputText;
816
- constructor(opts) {
817
- super(opts);
818
- this.transform = { render: (v) => v, scale: 1 };
819
- this.label = opts.label;
820
- this.scale = this.transform.scale;
821
- this.msg = opts.message;
822
- this.hint = opts.hint;
823
- this.initial = opts.initial || "";
824
- this.validator = opts.validate || (() => true);
825
- this.value = "";
826
- this.errorMsg = opts.error || "Please enter a valid value";
827
- this.cursor = Number(!!this.initial);
828
- this.cursorOffset = 0;
829
- this.clear = clear(``, this.out.columns);
830
- this.render();
831
- }
832
- get type() {
833
- return "text";
834
- }
835
- set value(v) {
836
- if (!v && this.initial) {
837
- this.placeholder = true;
838
- this.rendered = color.dim(this.initial);
839
- } else {
840
- this.placeholder = false;
841
- this.rendered = this.transform.render(v);
842
- }
843
- this._value = v;
844
- this.fire();
845
- }
846
- get value() {
847
- return this._value;
848
- }
849
- reset() {
850
- this.value = "";
851
- this.cursor = Number(!!this.initial);
852
- this.cursorOffset = 0;
853
- this.fire();
854
- this.render();
855
- }
856
- exit() {
857
- this.abort();
858
- }
859
- abort() {
860
- this.value = this.value || this.initial;
861
- this.done = this.aborted = true;
862
- this.error = false;
863
- this.red = false;
864
- this.fire();
865
- this.render();
866
- this.out.write("\n");
867
- this.close();
868
- }
869
- async validate() {
870
- let valid2 = await this.validator(this.value);
871
- if (typeof valid2 === `string`) {
872
- this.errorMsg = valid2;
873
- valid2 = false;
874
- }
875
- this.error = !valid2;
876
- }
877
- async submit() {
878
- this.value = this.value || this.initial;
879
- this.cursorOffset = 0;
880
- this.cursor = this.rendered.length;
881
- await this.validate();
882
- if (this.error) {
883
- this.red = true;
884
- this.fire();
885
- this.render();
886
- return;
887
- }
888
- this.done = true;
889
- this.aborted = false;
890
- this.fire();
891
- this.render();
892
- this.out.write("\n");
893
- this.close();
894
- }
895
- next() {
896
- if (!this.placeholder) return this.bell();
897
- this.value = this.initial;
898
- this.cursor = this.rendered.length;
899
- this.fire();
900
- this.render();
901
- }
902
- moveCursor(n) {
903
- if (this.placeholder) return;
904
- this.cursor = this.cursor + n;
905
- this.cursorOffset += n;
906
- }
907
- _(c, key) {
908
- let s1 = this.value.slice(0, this.cursor);
909
- let s2 = this.value.slice(this.cursor);
910
- this.value = `${s1}${c}${s2}`;
911
- this.red = false;
912
- this.cursor = this.placeholder ? 0 : s1.length + 1;
913
- this.render();
914
- }
915
- delete() {
916
- if (this.isCursorAtStart()) return this.bell();
917
- let s1 = this.value.slice(0, this.cursor - 1);
918
- let s2 = this.value.slice(this.cursor);
919
- this.value = `${s1}${s2}`;
920
- this.red = false;
921
- this.outputError = "";
922
- this.error = false;
923
- if (this.isCursorAtStart()) {
924
- this.cursorOffset = 0;
925
- } else {
926
- this.cursorOffset++;
927
- this.moveCursor(-1);
928
- }
929
- this.render();
930
- }
931
- deleteForward() {
932
- if (this.cursor * this.scale >= this.rendered.length || this.placeholder)
933
- return this.bell();
934
- let s1 = this.value.slice(0, this.cursor);
935
- let s2 = this.value.slice(this.cursor + 1);
936
- this.value = `${s1}${s2}`;
937
- this.red = false;
938
- this.outputError = "";
939
- this.error = false;
940
- if (this.isCursorAtEnd()) {
941
- this.cursorOffset = 0;
942
- } else {
943
- this.cursorOffset++;
944
- }
945
- this.render();
946
- }
947
- first() {
948
- this.cursor = 0;
949
- this.render();
950
- }
951
- last() {
952
- this.cursor = this.value.length;
953
- this.render();
954
- }
955
- left() {
956
- if (this.cursor <= 0 || this.placeholder) return this.bell();
957
- this.moveCursor(-1);
958
- this.render();
959
- }
960
- right() {
961
- if (this.cursor * this.scale >= this.rendered.length || this.placeholder)
962
- return this.bell();
963
- this.moveCursor(1);
964
- this.render();
965
- }
966
- isCursorAtStart() {
967
- return this.cursor === 0 || this.placeholder && this.cursor === 1;
968
- }
969
- isCursorAtEnd() {
970
- return this.cursor === this.rendered.length || this.placeholder && this.cursor === this.rendered.length + 1;
971
- }
972
- render() {
973
- if (this.closed) return;
974
- if (!this.firstRender) {
975
- if (this.outputError)
976
- this.out.write(
977
- import_sisteransi6.cursor.down(lines(this.outputError, this.out.columns) - 1) + clear(this.outputError, this.out.columns)
978
- );
979
- this.out.write(clear(this.outputText, this.out.columns));
980
- }
981
- super.render();
982
- this.outputError = "";
983
- let prefix = " ".repeat(strip(this.label).length);
984
- this.outputText = [
985
- "\n",
986
- this.label,
987
- " ",
988
- this.msg,
989
- this.done ? "" : this.hint ? (this.out.columns < 80 ? "\n" + " ".repeat(8) : "") + color.dim(` (${this.hint})`) : "",
990
- "\n" + prefix,
991
- " ",
992
- this.done ? color.dim(this.rendered) : this.rendered
993
- ].join("");
994
- if (this.error) {
995
- this.outputError += ` ${color.redBright(
996
- (shouldUseAscii() ? "> " : "\u25B6 ") + this.errorMsg
997
- )}`;
998
- }
999
- this.out.write(
1000
- import_sisteransi6.erase.line + import_sisteransi6.cursor.to(0) + this.outputText + import_sisteransi6.cursor.save + this.outputError + import_sisteransi6.cursor.restore + import_sisteransi6.cursor.move(
1001
- this.placeholder ? (this.rendered.length - 9) * -1 : this.cursorOffset,
1002
- 0
1003
- )
1004
- );
1005
- }
669
+ transform;
670
+ label;
671
+ scale;
672
+ msg;
673
+ initial;
674
+ hint;
675
+ validator;
676
+ errorMsg;
677
+ cursor;
678
+ cursorOffset;
679
+ clear;
680
+ done;
681
+ error;
682
+ red;
683
+ outputError;
684
+ name = "TextPrompt";
685
+ _value;
686
+ placeholder;
687
+ rendered;
688
+ outputText;
689
+ constructor(opts) {
690
+ super(opts);
691
+ this.transform = {
692
+ render: (v) => v,
693
+ scale: 1
694
+ };
695
+ this.label = opts.label;
696
+ this.scale = this.transform.scale;
697
+ this.msg = opts.message;
698
+ this.hint = opts.hint;
699
+ this.initial = opts.initial || "";
700
+ this.validator = opts.validate || (() => true);
701
+ this.value = "";
702
+ this.errorMsg = opts.error || "Please enter a valid value";
703
+ this.cursor = Number(!!this.initial);
704
+ this.cursorOffset = 0;
705
+ this.clear = clear(``, this.out.columns);
706
+ this.render();
707
+ }
708
+ get type() {
709
+ return "text";
710
+ }
711
+ set value(v) {
712
+ if (!v && this.initial) {
713
+ this.placeholder = true;
714
+ this.rendered = color.dim(this.initial);
715
+ } else {
716
+ this.placeholder = false;
717
+ this.rendered = this.transform.render(v);
718
+ }
719
+ this._value = v;
720
+ this.fire();
721
+ }
722
+ get value() {
723
+ return this._value;
724
+ }
725
+ reset() {
726
+ this.value = "";
727
+ this.cursor = Number(!!this.initial);
728
+ this.cursorOffset = 0;
729
+ this.fire();
730
+ this.render();
731
+ }
732
+ exit() {
733
+ this.abort();
734
+ }
735
+ abort() {
736
+ this.value = this.value || this.initial;
737
+ this.done = this.aborted = true;
738
+ this.error = false;
739
+ this.red = false;
740
+ this.fire();
741
+ this.render();
742
+ this.out.write("\n");
743
+ this.close();
744
+ }
745
+ async validate() {
746
+ let valid = await this.validator(this.value);
747
+ if (typeof valid === `string`) {
748
+ this.errorMsg = valid;
749
+ valid = false;
750
+ }
751
+ this.error = !valid;
752
+ }
753
+ async submit() {
754
+ this.value = this.value || this.initial;
755
+ this.cursorOffset = 0;
756
+ this.cursor = this.rendered.length;
757
+ await this.validate();
758
+ if (this.error) {
759
+ this.red = true;
760
+ this.fire();
761
+ this.render();
762
+ return;
763
+ }
764
+ this.done = true;
765
+ this.aborted = false;
766
+ this.fire();
767
+ this.render();
768
+ this.out.write("\n");
769
+ this.close();
770
+ }
771
+ next() {
772
+ if (!this.placeholder) return this.bell();
773
+ this.value = this.initial;
774
+ this.cursor = this.rendered.length;
775
+ this.fire();
776
+ this.render();
777
+ }
778
+ moveCursor(n) {
779
+ if (this.placeholder) return;
780
+ this.cursor = this.cursor + n;
781
+ this.cursorOffset += n;
782
+ }
783
+ _(c, key) {
784
+ let s1 = this.value.slice(0, this.cursor);
785
+ let s2 = this.value.slice(this.cursor);
786
+ this.value = `${s1}${c}${s2}`;
787
+ this.red = false;
788
+ this.cursor = this.placeholder ? 0 : s1.length + 1;
789
+ this.render();
790
+ }
791
+ delete() {
792
+ if (this.isCursorAtStart()) return this.bell();
793
+ let s1 = this.value.slice(0, this.cursor - 1);
794
+ let s2 = this.value.slice(this.cursor);
795
+ this.value = `${s1}${s2}`;
796
+ this.red = false;
797
+ this.outputError = "";
798
+ this.error = false;
799
+ if (this.isCursorAtStart()) this.cursorOffset = 0;
800
+ else {
801
+ this.cursorOffset++;
802
+ this.moveCursor(-1);
803
+ }
804
+ this.render();
805
+ }
806
+ deleteForward() {
807
+ if (this.cursor * this.scale >= this.rendered.length || this.placeholder) return this.bell();
808
+ let s1 = this.value.slice(0, this.cursor);
809
+ let s2 = this.value.slice(this.cursor + 1);
810
+ this.value = `${s1}${s2}`;
811
+ this.red = false;
812
+ this.outputError = "";
813
+ this.error = false;
814
+ if (this.isCursorAtEnd()) this.cursorOffset = 0;
815
+ else this.cursorOffset++;
816
+ this.render();
817
+ }
818
+ first() {
819
+ this.cursor = 0;
820
+ this.render();
821
+ }
822
+ last() {
823
+ this.cursor = this.value.length;
824
+ this.render();
825
+ }
826
+ left() {
827
+ if (this.cursor <= 0 || this.placeholder) return this.bell();
828
+ this.moveCursor(-1);
829
+ this.render();
830
+ }
831
+ right() {
832
+ if (this.cursor * this.scale >= this.rendered.length || this.placeholder) return this.bell();
833
+ this.moveCursor(1);
834
+ this.render();
835
+ }
836
+ isCursorAtStart() {
837
+ return this.cursor === 0 || this.placeholder && this.cursor === 1;
838
+ }
839
+ isCursorAtEnd() {
840
+ return this.cursor === this.rendered.length || this.placeholder && this.cursor === this.rendered.length + 1;
841
+ }
842
+ render() {
843
+ if (this.closed) return;
844
+ if (!this.firstRender) {
845
+ if (this.outputError) this.out.write(cursor.down(lines(this.outputError, this.out.columns) - 1) + clear(this.outputError, this.out.columns));
846
+ this.out.write(clear(this.outputText, this.out.columns));
847
+ }
848
+ super.render();
849
+ this.outputError = "";
850
+ let prefix = " ".repeat(strip(this.label).length);
851
+ this.outputText = [
852
+ "\n",
853
+ this.label,
854
+ " ",
855
+ this.msg,
856
+ this.done ? "" : this.hint ? (this.out.columns < 80 ? "\n" + " ".repeat(8) : "") + color.dim(` (${this.hint})`) : "",
857
+ "\n" + prefix,
858
+ " ",
859
+ this.done ? color.dim(this.rendered) : this.rendered
860
+ ].join("");
861
+ if (this.error) this.outputError += ` ${color.redBright((shouldUseAscii() ? "> " : "▶ ") + this.errorMsg)}`;
862
+ this.out.write(erase.line + cursor.to(0) + this.outputText + cursor.save + this.outputError + cursor.restore + cursor.move(this.placeholder ? (this.rendered.length - 9) * -1 : this.cursorOffset, 0));
863
+ }
1006
864
  };
1007
-
1008
- // prompt.ts
1009
- var prompts = {
1010
- text: (args) => toPrompt(TextPrompt, args),
1011
- confirm: (args) => toPrompt(ConfirmPrompt, args),
1012
- select: (args) => toPrompt(SelectPrompt, args),
1013
- multiselect: (args) => toPrompt(MultiSelectPrompt, args)
865
+ //#endregion
866
+ //#region prompt.ts
867
+ const prompts = {
868
+ text: (args) => toPrompt(TextPrompt, args),
869
+ confirm: (args) => toPrompt(ConfirmPrompt, args),
870
+ select: (args) => toPrompt(SelectPrompt, args),
871
+ multiselect: (args) => toPrompt(MultiSelectPrompt, args)
1014
872
  };
1015
873
  async function prompt(questions, opts = {}) {
1016
- let {
1017
- onSubmit = identity,
1018
- onCancel = () => import_node_process3.default.exit(0),
1019
- stdin = import_node_process3.default.stdin,
1020
- stdout = import_node_process3.default.stdout
1021
- } = opts;
1022
- let answers = {};
1023
- let questionsArray = Array.isArray(questions) ? questions : [questions];
1024
- let answer;
1025
- let quit;
1026
- let name;
1027
- let type;
1028
- for (let question of questionsArray) {
1029
- ({ name, type } = question);
1030
- try {
1031
- answer = await prompts[type](Object.assign({ stdin, stdout }, question));
1032
- answers[name] = answer;
1033
- quit = await onSubmit(question, answer, answers);
1034
- } catch (e) {
1035
- quit = !await onCancel(question, answers);
1036
- }
1037
- if (quit) {
1038
- return answers;
1039
- }
1040
- }
1041
- return answers;
874
+ let { onSubmit = identity, onCancel = () => process.exit(0), stdin = process.stdin, stdout = process.stdout } = opts;
875
+ let answers = {};
876
+ let questionsArray = Array.isArray(questions) ? questions : [questions];
877
+ let answer;
878
+ let quit;
879
+ let name;
880
+ let type;
881
+ for (let question of questionsArray) {
882
+ ({name, type} = question);
883
+ try {
884
+ answer = await prompts[type](Object.assign({
885
+ stdin,
886
+ stdout
887
+ }, question));
888
+ answers[name] = answer;
889
+ quit = await onSubmit(question, answer, answers);
890
+ } catch (e) {
891
+ quit = !await onCancel(question, answers);
892
+ }
893
+ if (quit) return answers;
894
+ }
895
+ return answers;
1042
896
  }
1043
897
  function toPrompt(el, args, opts = {}) {
1044
- if (el !== TextPrompt && el !== ConfirmPrompt && el !== SelectPrompt && el !== MultiSelectPrompt) {
1045
- throw new Error(`Invalid prompt type: ${el.name}`);
1046
- }
1047
- return new Promise((res, rej) => {
1048
- let p = new el(
1049
- args,
1050
- // @ts-expect-error
1051
- opts
1052
- );
1053
- let onAbort = args.onAbort || opts.onAbort || identity;
1054
- let onSubmit = args.onSubmit || opts.onSubmit || identity;
1055
- let onExit = args.onExit || opts.onExit || identity;
1056
- p.on("state", args.onState || identity);
1057
- p.on("submit", (x) => res(onSubmit(x)));
1058
- p.on("exit", (x) => res(onExit(x)));
1059
- p.on("abort", (x) => rej(onAbort(x)));
1060
- });
1061
- }
1062
-
1063
- // loading-indicator.ts
1064
- var import_node_process4 = __toESM(require("process"));
1065
- var import_node_readline2 = __toESM(require("readline"));
1066
- var import_sisteransi7 = require("sisteransi");
1067
- var GRADIENT_COLORS = [
1068
- "#ffffff",
1069
- "#dadada",
1070
- "#dadada",
1071
- "#a8deaa",
1072
- "#a8deaa",
1073
- "#a8deaa",
1074
- "#d0f0bd",
1075
- "#d0f0bd",
1076
- "#ffffed",
1077
- "#ffffed",
1078
- "#ffffed",
1079
- "#ffffed",
1080
- "#ffffed",
1081
- "#ffffed",
1082
- "#ffffed",
1083
- "#ffffed",
1084
- "#ffffed",
1085
- "#f7f8ca",
1086
- "#f7f8ca",
1087
- "#eae6ba",
1088
- "#eae6ba",
1089
- "#eae6ba",
1090
- "#dadada",
1091
- "#dadada",
1092
- "#ffffff"
898
+ if (el !== TextPrompt && el !== ConfirmPrompt && el !== SelectPrompt && el !== MultiSelectPrompt) throw new Error(`Invalid prompt type: ${el.name}`);
899
+ return new Promise((res, rej) => {
900
+ let p = new el(args, opts);
901
+ let onAbort = args.onAbort || opts.onAbort || identity;
902
+ let onSubmit = args.onSubmit || opts.onSubmit || identity;
903
+ let onExit = args.onExit || opts.onExit || identity;
904
+ p.on("state", args.onState || identity);
905
+ p.on("submit", (x) => res(onSubmit(x)));
906
+ p.on("exit", (x) => res(onExit(x)));
907
+ p.on("abort", (x) => rej(onAbort(x)));
908
+ });
909
+ }
910
+ //#endregion
911
+ //#region loading-indicator.ts
912
+ const GRADIENT_COLORS = [
913
+ "#ffffff",
914
+ "#dadada",
915
+ "#dadada",
916
+ "#a8deaa",
917
+ "#a8deaa",
918
+ "#a8deaa",
919
+ "#d0f0bd",
920
+ "#d0f0bd",
921
+ "#ffffed",
922
+ "#ffffed",
923
+ "#ffffed",
924
+ "#ffffed",
925
+ "#ffffed",
926
+ "#ffffed",
927
+ "#ffffed",
928
+ "#ffffed",
929
+ "#ffffed",
930
+ "#f7f8ca",
931
+ "#f7f8ca",
932
+ "#eae6ba",
933
+ "#eae6ba",
934
+ "#eae6ba",
935
+ "#dadada",
936
+ "#dadada",
937
+ "#ffffff"
1093
938
  ];
1094
- var MAX_FRAMES = 8;
1095
- var LEADING_FRAMES = Array.from(
1096
- { length: MAX_FRAMES * 2 },
1097
- () => GRADIENT_COLORS[0]
1098
- );
1099
- var TRAILING_FRAMES = Array.from(
1100
- { length: MAX_FRAMES * 2 },
1101
- () => GRADIENT_COLORS[GRADIENT_COLORS.length - 1]
1102
- );
1103
- var INDICATOR_FULL_FRAMES = [
1104
- ...LEADING_FRAMES,
1105
- ...GRADIENT_COLORS,
1106
- ...TRAILING_FRAMES,
1107
- ...reverse(GRADIENT_COLORS)
939
+ const MAX_FRAMES = 8;
940
+ const LEADING_FRAMES = Array.from({ length: MAX_FRAMES * 2 }, () => GRADIENT_COLORS[0]);
941
+ const TRAILING_FRAMES = Array.from({ length: MAX_FRAMES * 2 }, () => GRADIENT_COLORS[GRADIENT_COLORS.length - 1]);
942
+ const INDICATOR_FULL_FRAMES = [
943
+ ...LEADING_FRAMES,
944
+ ...GRADIENT_COLORS,
945
+ ...TRAILING_FRAMES,
946
+ ...reverse(GRADIENT_COLORS)
1108
947
  ];
1109
- var INDICATOR_GRADIENT = reverse(
1110
- INDICATOR_FULL_FRAMES.map((_, i) => loadingIndicatorFrame(i))
1111
- );
1112
- async function renderLoadingIndicator({
1113
- start,
1114
- end,
1115
- while: update = () => sleep(100),
1116
- noMotion = false,
1117
- stdin = import_node_process4.default.stdin,
1118
- stdout = import_node_process4.default.stdout
1119
- }) {
1120
- let act = update();
1121
- let tooSlow = /* @__PURE__ */ Object.create(null);
1122
- let result = await Promise.race([sleep(500).then(() => tooSlow), act]);
1123
- if (result === tooSlow) {
1124
- let loading = await gradient(color.green(start), {
1125
- stdin,
1126
- stdout,
1127
- noMotion
1128
- });
1129
- await act;
1130
- loading.stop();
1131
- }
1132
- stdout.write(`${" ".repeat(5)} ${color.green("\u2714")} ${color.green(end)}
1133
- `);
948
+ const INDICATOR_GRADIENT = reverse(INDICATOR_FULL_FRAMES.map((_, i) => loadingIndicatorFrame(i)));
949
+ async function renderLoadingIndicator({ start, end, while: update = () => sleep(100), noMotion = false, stdin = process.stdin, stdout = process.stdout }) {
950
+ let act = update();
951
+ let tooSlow = Object.create(null);
952
+ if (await Promise.race([sleep(500).then(() => tooSlow), act]) === tooSlow) {
953
+ let loading = await gradient(color.green(start), {
954
+ stdin,
955
+ stdout,
956
+ noMotion
957
+ });
958
+ await act;
959
+ loading.stop();
960
+ }
961
+ stdout.write(`${" ".repeat(5)} ${color.green("✔")} ${color.green(end)}\n`);
1134
962
  }
1135
963
  function loadingIndicatorFrame(offset = 0) {
1136
- let frames = INDICATOR_FULL_FRAMES.slice(offset, offset + (MAX_FRAMES - 2));
1137
- if (frames.length < MAX_FRAMES - 2) {
1138
- let filled = new Array(MAX_FRAMES - frames.length - 2).fill(
1139
- GRADIENT_COLORS[0]
1140
- );
1141
- frames.push(...filled);
1142
- }
1143
- return frames;
964
+ let frames = INDICATOR_FULL_FRAMES.slice(offset, offset + (MAX_FRAMES - 2));
965
+ if (frames.length < MAX_FRAMES - 2) {
966
+ let filled = new Array(MAX_FRAMES - frames.length - 2).fill(GRADIENT_COLORS[0]);
967
+ frames.push(...filled);
968
+ }
969
+ return frames;
1144
970
  }
1145
971
  function getGradientAnimationFrames() {
1146
- return INDICATOR_GRADIENT.map(
1147
- (colors) => " " + colors.map((g, i) => color.hex(g)("\u2588")).join("")
1148
- );
1149
- }
1150
- async function gradient(text, { stdin = import_node_process4.default.stdin, stdout = import_node_process4.default.stdout, noMotion = false } = {}) {
1151
- let { createLogUpdate } = await import("log-update");
1152
- let logUpdate = createLogUpdate(stdout);
1153
- let frameIndex = 0;
1154
- let frames = getGradientAnimationFrames();
1155
- let interval;
1156
- let rl = import_node_readline2.default.createInterface({ input: stdin, escapeCodeTimeout: 50 });
1157
- import_node_readline2.default.emitKeypressEvents(stdin, rl);
1158
- if (stdin.isTTY) stdin.setRawMode(true);
1159
- function keypress(char) {
1160
- if (char === "") {
1161
- loadingIndicator2.stop();
1162
- import_node_process4.default.exit(0);
1163
- }
1164
- if (stdin.isTTY) stdin.setRawMode(true);
1165
- stdout.write(import_sisteransi7.cursor.hide + import_sisteransi7.erase.lines(1));
1166
- }
1167
- let done = false;
1168
- let loadingIndicator2 = {
1169
- start() {
1170
- stdout.write(import_sisteransi7.cursor.hide);
1171
- stdin.on("keypress", keypress);
1172
- logUpdate(`${frames[0]} ${text}`);
1173
- async function loop() {
1174
- if (done) return;
1175
- if (frameIndex < frames.length - 1) {
1176
- frameIndex++;
1177
- } else {
1178
- frameIndex = 0;
1179
- }
1180
- let frame = frames[frameIndex];
1181
- logUpdate(
1182
- `${(noMotion ? getMotionlessFrame(frameIndex) : color.supportsColor ? frame : getColorlessFrame(frameIndex)).padEnd(MAX_FRAMES - 1, " ")} ${text}`
1183
- );
1184
- if (!done) await sleep(20);
1185
- loop();
1186
- }
1187
- loop();
1188
- },
1189
- stop() {
1190
- done = true;
1191
- stdin.removeListener("keypress", keypress);
1192
- clearInterval(interval);
1193
- logUpdate.clear();
1194
- rl.close();
1195
- }
1196
- };
1197
- loadingIndicator2.start();
1198
- return loadingIndicator2;
972
+ return INDICATOR_GRADIENT.map((colors) => " " + colors.map((g, i) => color.hex(g)("█")).join(""));
973
+ }
974
+ async function gradient(text, { stdin = process.stdin, stdout = process.stdout, noMotion = false } = {}) {
975
+ let { createLogUpdate } = await import("log-update");
976
+ let logUpdate = createLogUpdate(stdout);
977
+ let frameIndex = 0;
978
+ let frames = getGradientAnimationFrames();
979
+ let rl = readline.createInterface({
980
+ input: stdin,
981
+ escapeCodeTimeout: 50
982
+ });
983
+ readline.emitKeypressEvents(stdin, rl);
984
+ if (stdin.isTTY) stdin.setRawMode(true);
985
+ function keypress(char) {
986
+ if (char === "") {
987
+ loadingIndicator.stop();
988
+ process.exit(0);
989
+ }
990
+ if (stdin.isTTY) stdin.setRawMode(true);
991
+ stdout.write(cursor.hide + erase.lines(1));
992
+ }
993
+ let done = false;
994
+ let loadingIndicator = {
995
+ start() {
996
+ stdout.write(cursor.hide);
997
+ stdin.on("keypress", keypress);
998
+ logUpdate(`${frames[0]} ${text}`);
999
+ async function loop() {
1000
+ if (done) return;
1001
+ if (frameIndex < frames.length - 1) frameIndex++;
1002
+ else frameIndex = 0;
1003
+ let frame = frames[frameIndex];
1004
+ logUpdate(`${(noMotion ? getMotionlessFrame(frameIndex) : color.supportsColor ? frame : getColorlessFrame(frameIndex)).padEnd(MAX_FRAMES - 1, " ")} ${text}`);
1005
+ if (!done) await sleep(20);
1006
+ loop();
1007
+ }
1008
+ loop();
1009
+ },
1010
+ stop() {
1011
+ done = true;
1012
+ stdin.removeListener("keypress", keypress);
1013
+ logUpdate.clear();
1014
+ rl.close();
1015
+ }
1016
+ };
1017
+ loadingIndicator.start();
1018
+ return loadingIndicator;
1199
1019
  }
1200
1020
  function getColorlessFrame(frameIndex) {
1201
- return (frameIndex % 3 === 0 ? ".. .. " : frameIndex % 3 === 1 ? " .. .." : ". .. .").padEnd(MAX_FRAMES - 1 + 20, " ");
1021
+ return (frameIndex % 3 === 0 ? ".. .. " : frameIndex % 3 === 1 ? " .. .." : ". .. .").padEnd(27, " ");
1202
1022
  }
1203
1023
  function getMotionlessFrame(frameIndex) {
1204
- return " ".repeat(MAX_FRAMES - 1);
1205
- }
1206
-
1207
- // copy-template.ts
1208
- var import_node_process5 = __toESM(require("process"));
1209
- var import_node_url = __toESM(require("url"));
1210
- var import_node_fs2 = __toESM(require("fs"));
1211
- var import_node_path2 = __toESM(require("path"));
1212
- var import_node_stream = __toESM(require("stream"));
1213
- var import_node_util = require("util");
1214
- var import_web_fetch = require("@remix-run/web-fetch");
1215
- var import_gunzip_maybe = __toESM(require("gunzip-maybe"));
1216
- var import_tar_fs = __toESM(require("tar-fs"));
1217
- var import_proxy_agent = require("proxy-agent");
1218
- var defaultAgent = new import_proxy_agent.ProxyAgent();
1219
- var httpsAgent = new import_proxy_agent.ProxyAgent();
1220
- httpsAgent.protocol = "https:";
1221
- function agent(url2) {
1222
- return new URL(url2).protocol === "https:" ? httpsAgent : defaultAgent;
1024
+ return " ".repeat(MAX_FRAMES - 1);
1223
1025
  }
1026
+ //#endregion
1027
+ //#region copy-template.ts
1224
1028
  async function copyTemplate(template, destPath, options) {
1225
- let { log: log2 = () => {
1226
- } } = options;
1227
- try {
1228
- if (isLocalFilePath(template)) {
1229
- log2(`Using the template from local file at "${template}"`);
1230
- let filepath = template.startsWith("file://") ? import_node_url.default.fileURLToPath(template) : template;
1231
- let isLocalDir = await copyTemplateFromLocalFilePath(filepath, destPath);
1232
- return isLocalDir ? { localTemplateDirectory: filepath } : void 0;
1233
- }
1234
- if (isGithubRepoShorthand(template)) {
1235
- log2(`Using the template from the "${template}" repo`);
1236
- await copyTemplateFromGithubRepoShorthand(template, destPath, options);
1237
- return;
1238
- }
1239
- if (isValidGithubRepoUrl(template)) {
1240
- log2(`Using the template from "${template}"`);
1241
- await copyTemplateFromGithubRepoUrl(template, destPath, options);
1242
- return;
1243
- }
1244
- if (isUrl(template)) {
1245
- log2(`Using the template from "${template}"`);
1246
- await copyTemplateFromGenericUrl(template, destPath, options);
1247
- return;
1248
- }
1249
- throw new CopyTemplateError(
1250
- `"${color.bold(template)}" is an invalid template. Run ${color.bold(
1251
- "create-react-router --help"
1252
- )} to see supported template formats.`
1253
- );
1254
- } catch (error2) {
1255
- await options.onError(error2);
1256
- }
1029
+ let { log = () => {} } = options;
1030
+ /**
1031
+ * Valid templates are:
1032
+ * - local file or directory on disk
1033
+ * - GitHub owner/repo shorthand
1034
+ * - GitHub owner/repo/directory shorthand
1035
+ * - full GitHub repo URL
1036
+ * - any tarball URL
1037
+ */
1038
+ try {
1039
+ if (isLocalFilePath(template)) {
1040
+ log(`Using the template from local file at "${template}"`);
1041
+ let filepath = template.startsWith("file://") ? url.fileURLToPath(template) : template;
1042
+ return await copyTemplateFromLocalFilePath(filepath, destPath) ? { localTemplateDirectory: filepath } : void 0;
1043
+ }
1044
+ if (isGithubRepoShorthand(template)) {
1045
+ log(`Using the template from the "${template}" repo`);
1046
+ await copyTemplateFromGithubRepoShorthand(template, destPath, options);
1047
+ return;
1048
+ }
1049
+ if (isValidGithubRepoUrl(template)) {
1050
+ log(`Using the template from "${template}"`);
1051
+ await copyTemplateFromGithubRepoUrl(template, destPath, options);
1052
+ return;
1053
+ }
1054
+ if (isUrl(template)) {
1055
+ log(`Using the template from "${template}"`);
1056
+ await copyTemplateFromGenericUrl(template, destPath, options);
1057
+ return;
1058
+ }
1059
+ throw new CopyTemplateError(`"${color.bold(template)}" is an invalid template. Run ${color.bold("create-react-router --help")} to see supported template formats.`);
1060
+ } catch (error) {
1061
+ await options.onError(error);
1062
+ }
1257
1063
  }
1258
1064
  function isLocalFilePath(input) {
1259
- try {
1260
- return input.startsWith("file://") || import_node_fs2.default.existsSync(
1261
- import_node_path2.default.isAbsolute(input) ? input : import_node_path2.default.resolve(import_node_process5.default.cwd(), input)
1262
- );
1263
- } catch (e) {
1264
- return false;
1265
- }
1065
+ try {
1066
+ return input.startsWith("file://") || fs.existsSync(path.isAbsolute(input) ? input : path.resolve(process.cwd(), input));
1067
+ } catch (e) {
1068
+ return false;
1069
+ }
1266
1070
  }
1267
- async function copyTemplateFromRemoteTarball(url2, destPath, options) {
1268
- return await downloadAndExtractTarball(destPath, url2, options);
1071
+ async function copyTemplateFromRemoteTarball(url, destPath, options) {
1072
+ return await downloadAndExtractTarball(destPath, url, options);
1269
1073
  }
1270
1074
  async function copyTemplateFromGithubRepoShorthand(repoShorthand, destPath, options) {
1271
- let [owner, name, ...path4] = repoShorthand.split("/");
1272
- let filePath = path4.length ? path4.join("/") : null;
1273
- await downloadAndExtractRepoTarball(
1274
- { owner, name, filePath },
1275
- destPath,
1276
- options
1277
- );
1075
+ let [owner, name, ...path] = repoShorthand.split("/");
1076
+ await downloadAndExtractRepoTarball({
1077
+ owner,
1078
+ name,
1079
+ filePath: path.length ? path.join("/") : null
1080
+ }, destPath, options);
1278
1081
  }
1279
1082
  async function copyTemplateFromGithubRepoUrl(repoUrl, destPath, options) {
1280
- await downloadAndExtractRepoTarball(getRepoInfo(repoUrl), destPath, options);
1083
+ await downloadAndExtractRepoTarball(getRepoInfo(repoUrl), destPath, options);
1281
1084
  }
1282
- async function copyTemplateFromGenericUrl(url2, destPath, options) {
1283
- await copyTemplateFromRemoteTarball(url2, destPath, options);
1085
+ async function copyTemplateFromGenericUrl(url, destPath, options) {
1086
+ await copyTemplateFromRemoteTarball(url, destPath, options);
1284
1087
  }
1285
1088
  async function copyTemplateFromLocalFilePath(filePath, destPath) {
1286
- if (filePath.endsWith(".tar.gz") || filePath.endsWith(".tgz")) {
1287
- await extractLocalTarball(filePath, destPath);
1288
- return false;
1289
- }
1290
- if (import_node_fs2.default.statSync(filePath).isDirectory()) {
1291
- return true;
1292
- }
1293
- throw new CopyTemplateError(
1294
- "The provided template is not a valid local directory or tarball."
1295
- );
1296
- }
1297
- var pipeline = (0, import_node_util.promisify)(import_node_stream.default.pipeline);
1089
+ if (filePath.endsWith(".tar.gz") || filePath.endsWith(".tgz")) {
1090
+ await extractLocalTarball(filePath, destPath);
1091
+ return false;
1092
+ }
1093
+ if (fs.statSync(filePath).isDirectory()) return true;
1094
+ throw new CopyTemplateError("The provided template is not a valid local directory or tarball.");
1095
+ }
1096
+ const pipeline = promisify(stream.pipeline);
1298
1097
  async function extractLocalTarball(tarballPath, destPath) {
1299
- try {
1300
- await pipeline(
1301
- import_node_fs2.default.createReadStream(tarballPath),
1302
- (0, import_gunzip_maybe.default)(),
1303
- import_tar_fs.default.extract(destPath, { strip: 1 })
1304
- );
1305
- } catch (error2) {
1306
- throw new CopyTemplateError(
1307
- `There was a problem extracting the file from the provided template. Template filepath: \`${tarballPath}\` Destination directory: \`${destPath}\` ${error2}`
1308
- );
1309
- }
1098
+ try {
1099
+ await pipeline(fs.createReadStream(tarballPath), gunzip(), tar.extract(destPath, { strip: 1 }));
1100
+ } catch (error) {
1101
+ throw new CopyTemplateError(`There was a problem extracting the file from the provided template. Template filepath: \`${tarballPath}\` Destination directory: \`${destPath}\` ${error}`);
1102
+ }
1310
1103
  }
1311
1104
  async function downloadAndExtractRepoTarball(repo, destPath, options) {
1312
- if (repo.branch && repo.filePath) {
1313
- let tarballURL = `https://codeload.github.com/${repo.owner}/${repo.name}/tar.gz/${repo.branch}`;
1314
- return await downloadAndExtractTarball(destPath, tarballURL, {
1315
- ...options,
1316
- filePath: repo.filePath
1317
- });
1318
- }
1319
- let url2 = `https://api.github.com/repos/${repo.owner}/${repo.name}/tarball`;
1320
- if (repo.branch) {
1321
- url2 += `/${repo.branch}`;
1322
- }
1323
- return await downloadAndExtractTarball(destPath, url2, {
1324
- ...options,
1325
- filePath: repo.filePath ?? null
1326
- });
1105
+ if (repo.branch && repo.filePath) return await downloadAndExtractTarball(destPath, `https://codeload.github.com/${repo.owner}/${repo.name}/tar.gz/${repo.branch}`, {
1106
+ ...options,
1107
+ filePath: repo.filePath
1108
+ });
1109
+ let url = `https://api.github.com/repos/${repo.owner}/${repo.name}/tarball`;
1110
+ if (repo.branch) url += `/${repo.branch}`;
1111
+ return await downloadAndExtractTarball(destPath, url, {
1112
+ ...options,
1113
+ filePath: repo.filePath ?? null
1114
+ });
1327
1115
  }
1328
1116
  async function downloadAndExtractTarball(downloadPath, tarballUrl, { token, filePath }) {
1329
- let resourceUrl = tarballUrl;
1330
- let headers = {};
1331
- let isGithubUrl = new URL(tarballUrl).host.endsWith("github.com");
1332
- if (token && isGithubUrl) {
1333
- headers.Authorization = `token ${token}`;
1334
- }
1335
- if (isGithubReleaseAssetUrl(tarballUrl)) {
1336
- let info2 = getGithubReleaseAssetInfo(tarballUrl);
1337
- headers.Accept = "application/vnd.github.v3+json";
1338
- let releaseUrl = info2.tag === "latest" ? `https://api.github.com/repos/${info2.owner}/${info2.name}/releases/latest` : `https://api.github.com/repos/${info2.owner}/${info2.name}/releases/tags/${info2.tag}`;
1339
- let response2 = await (0, import_web_fetch.fetch)(releaseUrl, {
1340
- agent: agent("https://api.github.com"),
1341
- headers
1342
- });
1343
- if (response2.status !== 200) {
1344
- throw new CopyTemplateError(
1345
- `There was a problem fetching the file from GitHub. The request responded with a ${response2.status} status. Please try again later.`
1346
- );
1347
- }
1348
- let body = await response2.json();
1349
- if (!body || typeof body !== "object" || !body.assets || !Array.isArray(body.assets)) {
1350
- throw new CopyTemplateError(
1351
- "There was a problem fetching the file from GitHub. No asset was found at that url. Please try again later."
1352
- );
1353
- }
1354
- let assetId = body.assets.find((asset) => {
1355
- return info2.tag === "latest" ? asset?.browser_download_url?.includes(info2.asset) : asset?.browser_download_url === tarballUrl;
1356
- })?.id;
1357
- if (assetId == null) {
1358
- throw new CopyTemplateError(
1359
- "There was a problem fetching the file from GitHub. No asset was found at that url. Please try again later."
1360
- );
1361
- }
1362
- resourceUrl = `https://api.github.com/repos/${info2.owner}/${info2.name}/releases/assets/${assetId}`;
1363
- headers.Accept = "application/octet-stream";
1364
- }
1365
- let response = await (0, import_web_fetch.fetch)(resourceUrl, {
1366
- agent: agent(resourceUrl),
1367
- headers
1368
- });
1369
- if (!response.body || response.status !== 200) {
1370
- if (token) {
1371
- throw new CopyTemplateError(
1372
- `There was a problem fetching the file${isGithubUrl ? " from GitHub" : ""}. The request responded with a ${response.status} status. Perhaps your \`--token\`is expired or invalid.`
1373
- );
1374
- }
1375
- throw new CopyTemplateError(
1376
- `There was a problem fetching the file${isGithubUrl ? " from GitHub" : ""}. The request responded with a ${response.status} status. Please try again later.`
1377
- );
1378
- }
1379
- if (filePath) {
1380
- filePath = filePath.split(import_node_path2.default.sep).join(import_node_path2.default.posix.sep);
1381
- }
1382
- let filePathHasFiles = false;
1383
- try {
1384
- let input = new import_node_stream.default.PassThrough();
1385
- writeReadableStreamToWritable(response.body, input);
1386
- await pipeline(
1387
- input,
1388
- (0, import_gunzip_maybe.default)(),
1389
- import_tar_fs.default.extract(downloadPath, {
1390
- map(header) {
1391
- let originalDirName = header.name.split("/")[0];
1392
- header.name = header.name.replace(`${originalDirName}/`, "");
1393
- if (filePath) {
1394
- if (filePath.endsWith(import_node_path2.default.posix.sep) && header.name.startsWith(filePath) || !filePath.endsWith(import_node_path2.default.posix.sep) && header.name.startsWith(filePath + import_node_path2.default.posix.sep)) {
1395
- filePathHasFiles = true;
1396
- header.name = header.name.replace(filePath, "");
1397
- } else {
1398
- header.name = "__IGNORE__";
1399
- }
1400
- }
1401
- return header;
1402
- },
1403
- ignore(_filename, header) {
1404
- if (!header) {
1405
- throw Error("Header is undefined");
1406
- }
1407
- return header.name === "__IGNORE__";
1408
- }
1409
- })
1410
- );
1411
- } catch (e) {
1412
- throw new CopyTemplateError(
1413
- `There was a problem extracting the file from the provided template. Template URL: \`${tarballUrl}\` Destination directory: \`${downloadPath}\``
1414
- );
1415
- }
1416
- if (filePath && !filePathHasFiles) {
1417
- throw new CopyTemplateError(
1418
- `The path "${filePath}" was not found in this ${isGithubUrl ? "GitHub repo." : "tarball."}`
1419
- );
1420
- }
1421
- }
1422
- async function writeReadableStreamToWritable(stream2, writable) {
1423
- let reader = stream2.getReader();
1424
- let flushable = writable;
1425
- try {
1426
- while (true) {
1427
- let { done, value } = await reader.read();
1428
- if (done) {
1429
- writable.end();
1430
- break;
1431
- }
1432
- writable.write(value);
1433
- if (typeof flushable.flush === "function") {
1434
- flushable.flush();
1435
- }
1436
- }
1437
- } catch (error2) {
1438
- writable.destroy(error2);
1439
- throw error2;
1440
- }
1117
+ let resourceUrl = tarballUrl;
1118
+ let headers = {};
1119
+ let isGithubUrl = new URL(tarballUrl).host.endsWith("github.com");
1120
+ if (token && isGithubUrl) headers.Authorization = `token ${token}`;
1121
+ if (isGithubReleaseAssetUrl(tarballUrl)) {
1122
+ let info = getGithubReleaseAssetInfo(tarballUrl);
1123
+ headers.Accept = "application/vnd.github.v3+json";
1124
+ let releaseUrl = info.tag === "latest" ? `https://api.github.com/repos/${info.owner}/${info.name}/releases/latest` : `https://api.github.com/repos/${info.owner}/${info.name}/releases/tags/${info.tag}`;
1125
+ let response = await fetch(releaseUrl, { headers });
1126
+ if (response.status !== 200) throw new CopyTemplateError(`There was a problem fetching the file from GitHub. The request responded with a ${response.status} status. Please try again later.`);
1127
+ let body = await response.json();
1128
+ if (!body || typeof body !== "object" || !body.assets || !Array.isArray(body.assets)) throw new CopyTemplateError("There was a problem fetching the file from GitHub. No asset was found at that url. Please try again later.");
1129
+ let assetId = body.assets.find((asset) => {
1130
+ return info.tag === "latest" ? asset?.browser_download_url?.includes(info.asset) : asset?.browser_download_url === tarballUrl;
1131
+ })?.id;
1132
+ if (assetId == null) throw new CopyTemplateError("There was a problem fetching the file from GitHub. No asset was found at that url. Please try again later.");
1133
+ resourceUrl = `https://api.github.com/repos/${info.owner}/${info.name}/releases/assets/${assetId}`;
1134
+ headers.Accept = "application/octet-stream";
1135
+ }
1136
+ let response = await fetch(resourceUrl, { headers });
1137
+ if (!response.body || response.status !== 200) {
1138
+ if (token) throw new CopyTemplateError(`There was a problem fetching the file${isGithubUrl ? " from GitHub" : ""}. The request responded with a ${response.status} status. Perhaps your \`--token\`is expired or invalid.`);
1139
+ throw new CopyTemplateError(`There was a problem fetching the file${isGithubUrl ? " from GitHub" : ""}. The request responded with a ${response.status} status. Please try again later.`);
1140
+ }
1141
+ if (filePath) filePath = filePath.split(path.sep).join(path.posix.sep);
1142
+ let filePathHasFiles = false;
1143
+ try {
1144
+ let input = new stream.PassThrough();
1145
+ writeReadableStreamToWritable(response.body, input);
1146
+ await pipeline(input, gunzip(), tar.extract(downloadPath, {
1147
+ map(header) {
1148
+ let originalDirName = header.name.split("/")[0];
1149
+ header.name = header.name.replace(`${originalDirName}/`, "");
1150
+ if (filePath) if (filePath.endsWith(path.posix.sep) && header.name.startsWith(filePath) || !filePath.endsWith(path.posix.sep) && header.name.startsWith(filePath + path.posix.sep)) {
1151
+ filePathHasFiles = true;
1152
+ header.name = header.name.replace(filePath, "");
1153
+ } else header.name = "__IGNORE__";
1154
+ return header;
1155
+ },
1156
+ ignore(_filename, header) {
1157
+ if (!header) throw Error("Header is undefined");
1158
+ return header.name === "__IGNORE__";
1159
+ }
1160
+ }));
1161
+ } catch (e) {
1162
+ throw new CopyTemplateError(`There was a problem extracting the file from the provided template. Template URL: \`${tarballUrl}\` Destination directory: \`${downloadPath}\``);
1163
+ }
1164
+ if (filePath && !filePathHasFiles) throw new CopyTemplateError(`The path "${filePath}" was not found in this ${isGithubUrl ? "GitHub repo." : "tarball."}`);
1165
+ }
1166
+ async function writeReadableStreamToWritable(stream, writable) {
1167
+ let reader = stream.getReader();
1168
+ let flushable = writable;
1169
+ try {
1170
+ while (true) {
1171
+ let { done, value } = await reader.read();
1172
+ if (done) {
1173
+ writable.end();
1174
+ break;
1175
+ }
1176
+ writable.write(value);
1177
+ if (typeof flushable.flush === "function") flushable.flush();
1178
+ }
1179
+ } catch (error) {
1180
+ writable.destroy(error);
1181
+ throw error;
1182
+ }
1441
1183
  }
1442
1184
  function isValidGithubRepoUrl(input) {
1443
- if (!isUrl(input)) {
1444
- return false;
1445
- }
1446
- try {
1447
- let url2 = new URL(input);
1448
- let pathSegments = url2.pathname.slice(1).split("/");
1449
- return url2.protocol === "https:" && url2.hostname === "github.com" && // The pathname must have at least 2 segments. If it has more than 2, the
1450
- // third must be "tree" and it must have at least 4 segments.
1451
- // https://github.com/:owner/:repo
1452
- // https://github.com/:owner/:repo/tree/:ref
1453
- pathSegments.length >= 2 && (pathSegments.length > 2 ? pathSegments[2] === "tree" && pathSegments.length >= 4 : true);
1454
- } catch (e) {
1455
- return false;
1456
- }
1185
+ if (!isUrl(input)) return false;
1186
+ try {
1187
+ let url = new URL(input);
1188
+ let pathSegments = url.pathname.slice(1).split("/");
1189
+ return url.protocol === "https:" && url.hostname === "github.com" && pathSegments.length >= 2 && (pathSegments.length > 2 ? pathSegments[2] === "tree" && pathSegments.length >= 4 : true);
1190
+ } catch (e) {
1191
+ return false;
1192
+ }
1457
1193
  }
1458
1194
  function isGithubRepoShorthand(value) {
1459
- if (isUrl(value)) {
1460
- return false;
1461
- }
1462
- return /^[\w-]+\/[\w-.]+(\/[\w-.]+)*$/.test(value);
1463
- }
1464
- function isGithubReleaseAssetUrl(url2) {
1465
- return url2.startsWith("https://github.com") && (url2.includes("/releases/download/") || url2.includes("/releases/latest/download/"));
1195
+ if (isUrl(value)) return false;
1196
+ return /^[\w-]+\/[\w-.]+(\/[\w-.]+)*$/.test(value);
1197
+ }
1198
+ function isGithubReleaseAssetUrl(url) {
1199
+ /**
1200
+ * Accounts for the following formats:
1201
+ * https://github.com/owner/repository/releases/download/v0.0.1/template.tar.gz
1202
+ * ~or~
1203
+ * https://github.com/owner/repository/releases/latest/download/template.tar.gz
1204
+ */
1205
+ return url.startsWith("https://github.com") && (url.includes("/releases/download/") || url.includes("/releases/latest/download/"));
1466
1206
  }
1467
1207
  function getGithubReleaseAssetInfo(browserUrl) {
1468
- let url2 = new URL(browserUrl);
1469
- let [, owner, name, , downloadOrLatest, tag, asset] = url2.pathname.split("/");
1470
- if (downloadOrLatest === "latest" && tag === "download") {
1471
- tag = "latest";
1472
- }
1473
- return {
1474
- browserUrl,
1475
- owner,
1476
- name,
1477
- asset,
1478
- tag
1479
- };
1208
+ let [, owner, name, , downloadOrLatest, tag, asset] = new URL(browserUrl).pathname.split("/");
1209
+ if (downloadOrLatest === "latest" && tag === "download") tag = "latest";
1210
+ return {
1211
+ browserUrl,
1212
+ owner,
1213
+ name,
1214
+ asset,
1215
+ tag
1216
+ };
1480
1217
  }
1481
1218
  function getRepoInfo(validatedGithubUrl) {
1482
- let url2 = new URL(validatedGithubUrl);
1483
- let [, owner, name, tree, branch, ...file] = url2.pathname.split("/");
1484
- let filePath = file.join("/");
1485
- if (tree === void 0) {
1486
- return {
1487
- owner,
1488
- name,
1489
- branch: null,
1490
- filePath: null
1491
- };
1492
- }
1493
- return {
1494
- owner,
1495
- name,
1496
- // If we've validated the GitHub URL and there is a tree, there will also be
1497
- // a branch
1498
- branch,
1499
- filePath: filePath === "" || filePath === "/" ? null : filePath
1500
- };
1219
+ let [, owner, name, tree, branch, ...file] = new URL(validatedGithubUrl).pathname.split("/");
1220
+ let filePath = file.join("/");
1221
+ if (tree === void 0) return {
1222
+ owner,
1223
+ name,
1224
+ branch: null,
1225
+ filePath: null
1226
+ };
1227
+ return {
1228
+ owner,
1229
+ name,
1230
+ branch,
1231
+ filePath: filePath === "" || filePath === "/" ? null : filePath
1232
+ };
1501
1233
  }
1502
1234
  var CopyTemplateError = class extends Error {
1503
- constructor(message) {
1504
- super(message);
1505
- this.name = "CopyTemplateError";
1506
- }
1235
+ constructor(message) {
1236
+ super(message);
1237
+ this.name = "CopyTemplateError";
1238
+ }
1507
1239
  };
1508
-
1509
- // index.ts
1510
- async function createReactRouter(argv2) {
1511
- let ctx = await getContext(argv2);
1512
- if (ctx.help) {
1513
- printHelp(ctx);
1514
- return;
1515
- }
1516
- if (ctx.versionRequested) {
1517
- log(version);
1518
- return;
1519
- }
1520
- let steps = [
1521
- introStep,
1522
- projectNameStep,
1523
- copyTemplateToTempDirStep,
1524
- copyTempDirToAppDirStep,
1525
- gitInitQuestionStep,
1526
- installDependenciesQuestionStep,
1527
- installDependenciesStep,
1528
- gitInitStep,
1529
- doneStep
1530
- ];
1531
- try {
1532
- for (let step of steps) {
1533
- await step(ctx);
1534
- }
1535
- } catch (err) {
1536
- if (ctx.debug) {
1537
- console.error(err);
1538
- }
1539
- throw err;
1540
- }
1541
- }
1542
- async function getContext(argv2) {
1543
- let flags = (0, import_arg.default)(
1544
- {
1545
- "--debug": Boolean,
1546
- "--react-router-version": String,
1547
- "-v": "--react-router-version",
1548
- "--template": String,
1549
- "--token": String,
1550
- "--yes": Boolean,
1551
- "-y": "--yes",
1552
- "--install": Boolean,
1553
- "--no-install": Boolean,
1554
- "--package-manager": String,
1555
- "--show-install-output": Boolean,
1556
- "--git-init": Boolean,
1557
- "--no-git-init": Boolean,
1558
- "--help": Boolean,
1559
- "-h": "--help",
1560
- "--version": Boolean,
1561
- "--V": "--version",
1562
- "--no-color": Boolean,
1563
- "--no-motion": Boolean,
1564
- "--overwrite": Boolean
1565
- },
1566
- { argv: argv2, permissive: true }
1567
- );
1568
- let {
1569
- "--debug": debug2 = false,
1570
- "--help": help = false,
1571
- "--react-router-version": selectedReactRouterVersion,
1572
- "--template": template,
1573
- "--token": token,
1574
- "--install": install,
1575
- "--no-install": noInstall,
1576
- "--package-manager": pkgManager,
1577
- "--show-install-output": showInstallOutput = false,
1578
- "--git-init": git,
1579
- "--no-git-init": noGit,
1580
- "--no-motion": noMotion,
1581
- "--yes": yes,
1582
- "--version": versionRequested,
1583
- "--overwrite": overwrite
1584
- } = flags;
1585
- let cwd = flags["_"][0];
1586
- let interactive = isInteractive();
1587
- let projectName = cwd;
1588
- if (!interactive) {
1589
- yes = true;
1590
- }
1591
- if (selectedReactRouterVersion) {
1592
- if (semver.valid(selectedReactRouterVersion)) {
1593
- } else if (semver.coerce(selectedReactRouterVersion)) {
1594
- selectedReactRouterVersion = semver.coerce(
1595
- selectedReactRouterVersion
1596
- ).version;
1597
- } else {
1598
- log(
1599
- `
1600
- ${color.warning(
1601
- `${selectedReactRouterVersion} is an invalid version specifier. Using React Router v${version}.`
1602
- )}`
1603
- );
1604
- selectedReactRouterVersion = void 0;
1605
- }
1606
- }
1607
- let context = {
1608
- tempDir: import_node_path3.default.join(
1609
- await (0, import_promises2.realpath)(import_node_os2.default.tmpdir()),
1610
- `create-react-router--${Math.random().toString(36).substr(2, 8)}`
1611
- ),
1612
- cwd,
1613
- overwrite,
1614
- interactive,
1615
- debug: debug2,
1616
- git: git ?? (noGit ? false : yes),
1617
- help,
1618
- install: install ?? (noInstall ? false : yes),
1619
- showInstallOutput,
1620
- noMotion,
1621
- pkgManager: validatePackageManager(
1622
- pkgManager ?? // npm, pnpm, Yarn, Bun and Deno (v2.0.5+) set the user agent environment variable that can be used
1623
- // to determine which package manager ran the command.
1624
- (import_node_process6.default.env.npm_config_user_agent ?? "npm").split("/")[0]
1625
- ),
1626
- projectName,
1627
- prompt,
1628
- reactRouterVersion: selectedReactRouterVersion || version,
1629
- template,
1630
- token,
1631
- versionRequested
1632
- };
1633
- return context;
1240
+ //#endregion
1241
+ //#region package.json
1242
+ var version = "8.0.0-pre.0";
1243
+ //#endregion
1244
+ //#region index.ts
1245
+ async function createReactRouter(argv) {
1246
+ let ctx = await getContext(argv);
1247
+ if (ctx.help) {
1248
+ printHelp(ctx);
1249
+ return;
1250
+ }
1251
+ if (ctx.versionRequested) {
1252
+ log(version);
1253
+ return;
1254
+ }
1255
+ let steps = [
1256
+ introStep,
1257
+ projectNameStep,
1258
+ copyTemplateToTempDirStep,
1259
+ copyTempDirToAppDirStep,
1260
+ gitInitQuestionStep,
1261
+ installDependenciesQuestionStep,
1262
+ installDependenciesStep,
1263
+ gitInitStep,
1264
+ doneStep
1265
+ ];
1266
+ try {
1267
+ for (let step of steps) await step(ctx);
1268
+ } catch (err) {
1269
+ if (ctx.debug) console.error(err);
1270
+ throw err;
1271
+ }
1272
+ }
1273
+ async function getContext(argv) {
1274
+ let flags = arg({
1275
+ "--debug": Boolean,
1276
+ "--react-router-version": String,
1277
+ "-v": "--react-router-version",
1278
+ "--template": String,
1279
+ "--token": String,
1280
+ "--yes": Boolean,
1281
+ "-y": "--yes",
1282
+ "--install": Boolean,
1283
+ "--no-install": Boolean,
1284
+ "--package-manager": String,
1285
+ "--show-install-output": Boolean,
1286
+ "--git-init": Boolean,
1287
+ "--no-git-init": Boolean,
1288
+ "--help": Boolean,
1289
+ "-h": "--help",
1290
+ "--version": Boolean,
1291
+ "--V": "--version",
1292
+ "--no-color": Boolean,
1293
+ "--no-motion": Boolean,
1294
+ "--overwrite": Boolean
1295
+ }, {
1296
+ argv,
1297
+ permissive: true
1298
+ });
1299
+ let { "--debug": debug = false, "--help": help = false, "--react-router-version": selectedReactRouterVersion, "--template": template, "--token": token, "--install": install, "--no-install": noInstall, "--package-manager": pkgManager, "--show-install-output": showInstallOutput = false, "--git-init": git, "--no-git-init": noGit, "--no-motion": noMotion, "--yes": yes, "--version": versionRequested, "--overwrite": overwrite } = flags;
1300
+ let cwd = flags["_"][0];
1301
+ let interactive = isInteractive();
1302
+ let projectName = cwd;
1303
+ if (!interactive) yes = true;
1304
+ if (selectedReactRouterVersion) if (semver.valid(selectedReactRouterVersion)) {} else if (semver.coerce(selectedReactRouterVersion)) selectedReactRouterVersion = semver.coerce(selectedReactRouterVersion).version;
1305
+ else {
1306
+ log(`\n${color.warning(`${selectedReactRouterVersion} is an invalid version specifier. Using React Router v${version}.`)}`);
1307
+ selectedReactRouterVersion = void 0;
1308
+ }
1309
+ return {
1310
+ tempDir: path.join(await realpath(os.tmpdir()), `create-react-router--${Math.random().toString(36).substr(2, 8)}`),
1311
+ cwd,
1312
+ overwrite,
1313
+ interactive,
1314
+ debug,
1315
+ git: git ?? (noGit ? false : yes),
1316
+ help,
1317
+ install: install ?? (noInstall ? false : yes),
1318
+ showInstallOutput,
1319
+ noMotion,
1320
+ pkgManager: validatePackageManager(pkgManager ?? (process.env.npm_config_user_agent ?? "npm").split("/")[0]),
1321
+ projectName,
1322
+ prompt,
1323
+ reactRouterVersion: selectedReactRouterVersion || version,
1324
+ template,
1325
+ token,
1326
+ versionRequested
1327
+ };
1634
1328
  }
1635
1329
  async function introStep(ctx) {
1636
- log(
1637
- `
1638
- ${" ".repeat(9)}${color.green(
1639
- color.bold("create-react-router")
1640
- )} ${color.bold(`v${ctx.reactRouterVersion}`)}`
1641
- );
1642
- if (!ctx.interactive) {
1643
- log("");
1644
- info("Shell is not interactive.", [
1645
- `Using default options. This is equivalent to running with the `,
1646
- color.reset("--yes"),
1647
- ` flag.`
1648
- ]);
1649
- }
1330
+ log(`\n${" ".repeat(9)}${color.green(color.bold("create-react-router"))} ${color.bold(`v${ctx.reactRouterVersion}`)}`);
1331
+ if (!ctx.interactive) {
1332
+ log("");
1333
+ info("Shell is not interactive.", [
1334
+ `Using default options. This is equivalent to running with the `,
1335
+ color.reset("--yes"),
1336
+ ` flag.`
1337
+ ]);
1338
+ }
1650
1339
  }
1651
1340
  async function projectNameStep(ctx) {
1652
- if (!ctx.interactive && !ctx.cwd) {
1653
- error("Oh no!", "No project directory provided");
1654
- throw new Error("No project directory provided");
1655
- }
1656
- if (ctx.cwd) {
1657
- await sleep(100);
1658
- info("Directory:", [
1659
- "Using ",
1660
- color.reset(ctx.cwd),
1661
- " as project directory"
1662
- ]);
1663
- }
1664
- if (!ctx.cwd) {
1665
- let { name: name2 } = await ctx.prompt({
1666
- name: "name",
1667
- type: "text",
1668
- label: title("dir"),
1669
- message: "Where should we create your new project?",
1670
- initial: "./my-react-router-app"
1671
- });
1672
- ctx.cwd = name2;
1673
- ctx.projectName = toValidProjectName(name2);
1674
- return;
1675
- }
1676
- let name = ctx.cwd;
1677
- if (name === "." || name === "./") {
1678
- let parts = import_node_process6.default.cwd().split(import_node_path3.default.sep);
1679
- name = parts[parts.length - 1];
1680
- } else if (name.startsWith("./") || name.startsWith("../")) {
1681
- let parts = name.split("/");
1682
- name = parts[parts.length - 1];
1683
- }
1684
- ctx.projectName = toValidProjectName(name);
1341
+ if (!ctx.interactive && !ctx.cwd) {
1342
+ error("Oh no!", "No project directory provided");
1343
+ throw new Error("No project directory provided");
1344
+ }
1345
+ if (ctx.cwd) {
1346
+ await sleep(100);
1347
+ info("Directory:", [
1348
+ "Using ",
1349
+ color.reset(ctx.cwd),
1350
+ " as project directory"
1351
+ ]);
1352
+ }
1353
+ if (!ctx.cwd) {
1354
+ let { name } = await ctx.prompt({
1355
+ name: "name",
1356
+ type: "text",
1357
+ label: title("dir"),
1358
+ message: "Where should we create your new project?",
1359
+ initial: "./my-react-router-app"
1360
+ });
1361
+ ctx.cwd = name;
1362
+ ctx.projectName = toValidProjectName(name);
1363
+ return;
1364
+ }
1365
+ let name = ctx.cwd;
1366
+ if (name === "." || name === "./") {
1367
+ let parts = process.cwd().split(path.sep);
1368
+ name = parts[parts.length - 1];
1369
+ } else if (name.startsWith("./") || name.startsWith("../")) {
1370
+ let parts = name.split("/");
1371
+ name = parts[parts.length - 1];
1372
+ }
1373
+ ctx.projectName = toValidProjectName(name);
1685
1374
  }
1686
1375
  async function copyTemplateToTempDirStep(ctx) {
1687
- if (ctx.template) {
1688
- log("");
1689
- info("Template:", ["Using ", color.reset(ctx.template), "..."]);
1690
- } else {
1691
- log("");
1692
- info("Using default template", [
1693
- "See https://github.com/remix-run/react-router-templates for more"
1694
- ]);
1695
- }
1696
- let template = ctx.template ?? "https://github.com/remix-run/react-router-templates/tree/main/default";
1697
- await loadingIndicator({
1698
- start: "Template copying...",
1699
- end: "Template copied",
1700
- while: async () => {
1701
- await ensureDirectory(ctx.tempDir);
1702
- if (ctx.debug) {
1703
- debug(`Extracting to: ${ctx.tempDir}`);
1704
- }
1705
- let result = await copyTemplate(template, ctx.tempDir, {
1706
- debug: ctx.debug,
1707
- token: ctx.token,
1708
- async onError(err) {
1709
- error(
1710
- "Oh no!",
1711
- err instanceof CopyTemplateError ? err.message : "Something went wrong. Run `create-react-router --debug` to see more info.\n\nOpen an issue to report the problem at https://github.com/remix-run/react-router/issues/new"
1712
- );
1713
- throw err;
1714
- },
1715
- async log(message) {
1716
- if (ctx.debug) {
1717
- debug(message);
1718
- await sleep(500);
1719
- }
1720
- }
1721
- });
1722
- if (result?.localTemplateDirectory) {
1723
- ctx.tempDir = import_node_path3.default.resolve(result.localTemplateDirectory);
1724
- }
1725
- },
1726
- ctx
1727
- });
1376
+ if (ctx.template) {
1377
+ log("");
1378
+ info("Template:", [
1379
+ "Using ",
1380
+ color.reset(ctx.template),
1381
+ "..."
1382
+ ]);
1383
+ } else {
1384
+ log("");
1385
+ info("Using default template", ["See https://github.com/remix-run/react-router-templates for more"]);
1386
+ }
1387
+ let template = ctx.template ?? "https://github.com/remix-run/react-router-templates/tree/main/default";
1388
+ await loadingIndicator({
1389
+ start: "Template copying...",
1390
+ end: "Template copied",
1391
+ while: async () => {
1392
+ await ensureDirectory(ctx.tempDir);
1393
+ if (ctx.debug) debug(`Extracting to: ${ctx.tempDir}`);
1394
+ let result = await copyTemplate(template, ctx.tempDir, {
1395
+ debug: ctx.debug,
1396
+ token: ctx.token,
1397
+ async onError(err) {
1398
+ error("Oh no!", err instanceof CopyTemplateError ? err.message : "Something went wrong. Run `create-react-router --debug` to see more info.\n\nOpen an issue to report the problem at https://github.com/remix-run/react-router/issues/new");
1399
+ throw err;
1400
+ },
1401
+ async log(message) {
1402
+ if (ctx.debug) {
1403
+ debug(message);
1404
+ await sleep(500);
1405
+ }
1406
+ }
1407
+ });
1408
+ if (result?.localTemplateDirectory) ctx.tempDir = path.resolve(result.localTemplateDirectory);
1409
+ },
1410
+ ctx
1411
+ });
1728
1412
  }
1729
1413
  async function copyTempDirToAppDirStep(ctx) {
1730
- await ensureDirectory(ctx.cwd);
1731
- let files1 = await getDirectoryFilesRecursive(ctx.tempDir);
1732
- let files2 = await getDirectoryFilesRecursive(ctx.cwd);
1733
- let collisions = files1.filter((f) => files2.includes(f)).sort((a, b) => a.localeCompare(b));
1734
- if (collisions.length > 0) {
1735
- let getFileList = (prefix) => {
1736
- let moreFiles = collisions.length - 5;
1737
- let lines2 = ["", ...collisions.slice(0, 5)];
1738
- if (moreFiles > 0) {
1739
- lines2.push(`and ${moreFiles} more...`);
1740
- }
1741
- return lines2.join(`
1742
- ${prefix}`);
1743
- };
1744
- if (ctx.overwrite) {
1745
- info(
1746
- "Overwrite:",
1747
- `overwriting files due to \`--overwrite\`:${getFileList(" ")}`
1748
- );
1749
- } else if (!ctx.interactive) {
1750
- error(
1751
- "Oh no!",
1752
- `Destination directory contains files that would be overwritten
1753
- and no \`--overwrite\` flag was included in a non-interactive
1754
- environment. The following files would be overwritten:` + getFileList(" ")
1755
- );
1756
- throw new Error(
1757
- "File collisions detected in a non-interactive environment"
1758
- );
1759
- } else {
1760
- if (ctx.debug) {
1761
- debug(`Colliding files:${getFileList(" ")}`);
1762
- }
1763
- let { overwrite } = await ctx.prompt({
1764
- name: "overwrite",
1765
- type: "confirm",
1766
- label: title("overwrite"),
1767
- message: `Your project directory contains files that will be overwritten by
1414
+ await ensureDirectory(ctx.cwd);
1415
+ let files1 = await getDirectoryFilesRecursive(ctx.tempDir);
1416
+ let files2 = await getDirectoryFilesRecursive(ctx.cwd);
1417
+ let collisions = files1.filter((f) => files2.includes(f)).sort((a, b) => a.localeCompare(b));
1418
+ if (collisions.length > 0) {
1419
+ let getFileList = (prefix) => {
1420
+ let moreFiles = collisions.length - 5;
1421
+ let lines = ["", ...collisions.slice(0, 5)];
1422
+ if (moreFiles > 0) lines.push(`and ${moreFiles} more...`);
1423
+ return lines.join(`\n${prefix}`);
1424
+ };
1425
+ if (ctx.overwrite) info("Overwrite:", `overwriting files due to \`--overwrite\`:${getFileList(" ")}`);
1426
+ else if (!ctx.interactive) {
1427
+ error("Oh no!", "Destination directory contains files that would be overwritten\n and no `--overwrite` flag was included in a non-interactive\n environment. The following files would be overwritten:" + getFileList(" "));
1428
+ throw new Error("File collisions detected in a non-interactive environment");
1429
+ } else {
1430
+ if (ctx.debug) debug(`Colliding files:${getFileList(" ")}`);
1431
+ let { overwrite } = await ctx.prompt({
1432
+ name: "overwrite",
1433
+ type: "confirm",
1434
+ label: title("overwrite"),
1435
+ message: `Your project directory contains files that will be overwritten by
1768
1436
  this template (you can force with \`--overwrite\`)
1769
1437
 
1770
- Files that would be overwritten:${getFileList(" ")}
1771
-
1772
- Do you wish to continue?
1773
- `,
1774
- initial: false
1775
- });
1776
- if (!overwrite) {
1777
- throw new Error("Exiting to avoid overwriting files");
1778
- }
1779
- }
1780
- }
1781
- await (0, import_promises2.cp)(ctx.tempDir, ctx.cwd, {
1782
- filter(src) {
1783
- let file = stripDirectoryFromPath(ctx.tempDir, src);
1784
- let isIgnored = IGNORED_TEMPLATE_DIRECTORIES.includes(file);
1785
- if (isIgnored) {
1786
- if (ctx.debug) {
1787
- debug(`Skipping copy of ${file} directory from template`);
1788
- }
1789
- return false;
1790
- }
1791
- return true;
1792
- },
1793
- recursive: true
1794
- });
1795
- await updatePackageJSON(ctx);
1438
+ Files that would be overwritten:${getFileList(" ")}\n\n Do you wish to continue?\n `,
1439
+ initial: false
1440
+ });
1441
+ if (!overwrite) throw new Error("Exiting to avoid overwriting files");
1442
+ }
1443
+ }
1444
+ await cp(ctx.tempDir, ctx.cwd, {
1445
+ filter(src) {
1446
+ let file = stripDirectoryFromPath(ctx.tempDir, src);
1447
+ if (IGNORED_TEMPLATE_DIRECTORIES.includes(file)) {
1448
+ if (ctx.debug) debug(`Skipping copy of ${file} directory from template`);
1449
+ return false;
1450
+ }
1451
+ return true;
1452
+ },
1453
+ recursive: true
1454
+ });
1455
+ await updatePackageJSON(ctx);
1796
1456
  }
1797
1457
  async function installDependenciesQuestionStep(ctx) {
1798
- if (ctx.install === void 0) {
1799
- let { deps = true } = await ctx.prompt({
1800
- name: "deps",
1801
- type: "confirm",
1802
- label: title("deps"),
1803
- message: `Install dependencies with ${ctx.pkgManager}?`,
1804
- hint: "recommended",
1805
- initial: true
1806
- });
1807
- ctx.install = deps;
1808
- }
1458
+ if (ctx.install === void 0) {
1459
+ let { deps = true } = await ctx.prompt({
1460
+ name: "deps",
1461
+ type: "confirm",
1462
+ label: title("deps"),
1463
+ message: `Install dependencies with ${ctx.pkgManager}?`,
1464
+ hint: "recommended",
1465
+ initial: true
1466
+ });
1467
+ ctx.install = deps;
1468
+ }
1809
1469
  }
1810
1470
  async function installDependenciesStep(ctx) {
1811
- let { install, pkgManager, showInstallOutput, cwd } = ctx;
1812
- if (!install) {
1813
- await sleep(100);
1814
- info("Skipping install step.", [
1815
- "Remember to install dependencies after setup with ",
1816
- color.reset(`${pkgManager} install`),
1817
- "."
1818
- ]);
1819
- return;
1820
- }
1821
- function runInstall() {
1822
- return installDependencies({
1823
- cwd,
1824
- pkgManager,
1825
- showInstallOutput
1826
- });
1827
- }
1828
- if (showInstallOutput) {
1829
- log("");
1830
- info(`Install`, `Dependencies installing with ${pkgManager}...`);
1831
- log("");
1832
- await runInstall();
1833
- log("");
1834
- return;
1835
- }
1836
- log("");
1837
- await loadingIndicator({
1838
- start: `Dependencies installing with ${pkgManager}...`,
1839
- end: "Dependencies installed",
1840
- while: runInstall,
1841
- ctx
1842
- });
1471
+ let { install, pkgManager, showInstallOutput, cwd } = ctx;
1472
+ if (!install) {
1473
+ await sleep(100);
1474
+ info("Skipping install step.", [
1475
+ "Remember to install dependencies after setup with ",
1476
+ color.reset(`${pkgManager} install`),
1477
+ "."
1478
+ ]);
1479
+ return;
1480
+ }
1481
+ function runInstall() {
1482
+ return installDependencies({
1483
+ cwd,
1484
+ pkgManager,
1485
+ showInstallOutput
1486
+ });
1487
+ }
1488
+ if (showInstallOutput) {
1489
+ log("");
1490
+ info(`Install`, `Dependencies installing with ${pkgManager}...`);
1491
+ log("");
1492
+ await runInstall();
1493
+ log("");
1494
+ return;
1495
+ }
1496
+ log("");
1497
+ await loadingIndicator({
1498
+ start: `Dependencies installing with ${pkgManager}...`,
1499
+ end: "Dependencies installed",
1500
+ while: runInstall,
1501
+ ctx
1502
+ });
1843
1503
  }
1844
1504
  async function gitInitQuestionStep(ctx) {
1845
- if ((0, import_node_fs3.existsSync)(import_node_path3.default.join(ctx.cwd, ".git"))) {
1846
- info("Nice!", `Git has already been initialized`);
1847
- return;
1848
- }
1849
- let git = ctx.git;
1850
- if (ctx.git === void 0) {
1851
- ({ git } = await ctx.prompt({
1852
- name: "git",
1853
- type: "confirm",
1854
- label: title("git"),
1855
- message: `Initialize a new git repository?`,
1856
- hint: "recommended",
1857
- initial: true
1858
- }));
1859
- }
1860
- ctx.git = git ?? false;
1505
+ if (existsSync(path.join(ctx.cwd, ".git"))) {
1506
+ info("Nice!", `Git has already been initialized`);
1507
+ return;
1508
+ }
1509
+ let git = ctx.git;
1510
+ if (ctx.git === void 0) ({git} = await ctx.prompt({
1511
+ name: "git",
1512
+ type: "confirm",
1513
+ label: title("git"),
1514
+ message: `Initialize a new git repository?`,
1515
+ hint: "recommended",
1516
+ initial: true
1517
+ }));
1518
+ ctx.git = git ?? false;
1861
1519
  }
1862
1520
  async function gitInitStep(ctx) {
1863
- if (!ctx.git) {
1864
- return;
1865
- }
1866
- if ((0, import_node_fs3.existsSync)(import_node_path3.default.join(ctx.cwd, ".git"))) {
1867
- log("");
1868
- info("Nice!", `Git has already been initialized`);
1869
- return;
1870
- }
1871
- log("");
1872
- await loadingIndicator({
1873
- start: "Git initializing...",
1874
- end: "Git initialized",
1875
- while: async () => {
1876
- let options = { cwd: ctx.cwd, stdio: "ignore" };
1877
- let commitMsg = "Initial commit from create-react-router";
1878
- try {
1879
- await (0, import_execa.default)("git", ["init"], options);
1880
- await (0, import_execa.default)("git", ["add", "."], options);
1881
- await (0, import_execa.default)("git", ["commit", "-m", commitMsg], options);
1882
- } catch (err) {
1883
- error("Oh no!", "Failed to initialize git.");
1884
- throw err;
1885
- }
1886
- },
1887
- ctx
1888
- });
1521
+ if (!ctx.git) return;
1522
+ if (existsSync(path.join(ctx.cwd, ".git"))) {
1523
+ log("");
1524
+ info("Nice!", `Git has already been initialized`);
1525
+ return;
1526
+ }
1527
+ log("");
1528
+ await loadingIndicator({
1529
+ start: "Git initializing...",
1530
+ end: "Git initialized",
1531
+ while: async () => {
1532
+ let options = {
1533
+ cwd: ctx.cwd,
1534
+ stdio: "ignore"
1535
+ };
1536
+ let commitMsg = "Initial commit from create-react-router";
1537
+ try {
1538
+ await execa("git", ["init"], options);
1539
+ await execa("git", ["add", "."], options);
1540
+ await execa("git", [
1541
+ "commit",
1542
+ "-m",
1543
+ commitMsg
1544
+ ], options);
1545
+ } catch (err) {
1546
+ error("Oh no!", "Failed to initialize git.");
1547
+ throw err;
1548
+ }
1549
+ },
1550
+ ctx
1551
+ });
1889
1552
  }
1890
1553
  async function doneStep(ctx) {
1891
- let projectDir = import_node_path3.default.relative(import_node_process6.default.cwd(), ctx.cwd);
1892
- let max = import_node_process6.default.stdout.columns;
1893
- let prefix = max < 80 ? " " : " ".repeat(9);
1894
- await sleep(200);
1895
- log(`
1896
- ${color.bgWhite(color.black(" done "))} That's it!`);
1897
- await sleep(100);
1898
- if (projectDir !== "") {
1899
- let enter = [
1900
- `
1901
- ${prefix}Enter your project directory using`,
1902
- color.cyan(`cd .${import_node_path3.default.sep}${projectDir}`)
1903
- ];
1904
- let len = enter[0].length + (0, import_strip_ansi.default)(enter[1]).length;
1905
- log(enter.join(len > max ? "\n" + prefix : " "));
1906
- }
1907
- log(
1908
- `${prefix}Check out ${color.bold(
1909
- "README.md"
1910
- )} for development and deploy instructions.`
1911
- );
1912
- await sleep(100);
1913
- log(
1914
- `
1915
- ${prefix}Join the community at ${color.cyan(`https://rmx.as/discord`)}
1916
- `
1917
- );
1918
- await sleep(200);
1919
- }
1920
- var validPackageManagers = ["npm", "yarn", "pnpm", "bun", "deno"];
1554
+ let projectDir = path.relative(process.cwd(), ctx.cwd);
1555
+ let max = process.stdout.columns;
1556
+ let prefix = max < 80 ? " " : " ".repeat(9);
1557
+ await sleep(200);
1558
+ log(`\n ${color.bgWhite(color.black(" done "))} That's it!`);
1559
+ await sleep(100);
1560
+ if (projectDir !== "") {
1561
+ let enter = [`\n${prefix}Enter your project directory using`, color.cyan(`cd .${path.sep}${projectDir}`)];
1562
+ let len = enter[0].length + stripAnsi(enter[1]).length;
1563
+ log(enter.join(len > max ? "\n" + prefix : " "));
1564
+ }
1565
+ log(`${prefix}Check out ${color.bold("README.md")} for development and deploy instructions.`);
1566
+ await sleep(100);
1567
+ log(`\n${prefix}Join the community at ${color.cyan(`https://rmx.as/discord`)}\n`);
1568
+ await sleep(200);
1569
+ }
1570
+ const validPackageManagers = [
1571
+ "npm",
1572
+ "yarn",
1573
+ "pnpm",
1574
+ "bun",
1575
+ "deno"
1576
+ ];
1921
1577
  function validatePackageManager(pkgManager) {
1922
- return validPackageManagers.find((name) => pkgManager === name) ?? "npm";
1923
- }
1924
- async function installDependencies({
1925
- pkgManager,
1926
- cwd,
1927
- showInstallOutput
1928
- }) {
1929
- try {
1930
- await (0, import_execa.default)(pkgManager, ["install"], {
1931
- cwd,
1932
- stdio: showInstallOutput ? "inherit" : "ignore"
1933
- });
1934
- } catch (err) {
1935
- error("Oh no!", "Failed to install dependencies.");
1936
- throw err;
1937
- }
1578
+ return validPackageManagers.find((name) => pkgManager === name) ?? "npm";
1579
+ }
1580
+ async function installDependencies({ pkgManager, cwd, showInstallOutput }) {
1581
+ try {
1582
+ await execa(pkgManager, ["install"], {
1583
+ cwd,
1584
+ stdio: showInstallOutput ? "inherit" : "ignore"
1585
+ });
1586
+ } catch (err) {
1587
+ error("Oh no!", "Failed to install dependencies.");
1588
+ throw err;
1589
+ }
1938
1590
  }
1939
1591
  async function updatePackageJSON(ctx) {
1940
- let packageJSONPath = import_node_path3.default.join(ctx.cwd, "package.json");
1941
- if (!(0, import_node_fs3.existsSync)(packageJSONPath)) {
1942
- let relativePath = import_node_path3.default.relative(import_node_process6.default.cwd(), ctx.cwd);
1943
- error(
1944
- "Oh no!",
1945
- `The provided template must be a React Router project with a \`package.json\` file, but that file does not exist in ${color.bold(relativePath)}.`
1946
- );
1947
- throw new Error(`package.json does not exist in ${ctx.cwd}`);
1948
- }
1949
- let contents = await (0, import_promises2.readFile)(packageJSONPath, "utf-8");
1950
- let packageJSON;
1951
- try {
1952
- packageJSON = JSON.parse(contents);
1953
- if (!isValidJsonObject(packageJSON)) {
1954
- throw Error();
1955
- }
1956
- } catch (err) {
1957
- error(
1958
- "Oh no!",
1959
- `The provided template must be a React Router project with a \`package.json\` file, but that file is invalid.`
1960
- );
1961
- throw err;
1962
- }
1963
- for (let pkgKey of ["dependencies", "devDependencies"]) {
1964
- let dependencies = packageJSON[pkgKey];
1965
- if (!dependencies) continue;
1966
- if (!isValidJsonObject(dependencies)) {
1967
- error(
1968
- "Oh no!",
1969
- `The provided template must be a React Router project with a \`package.json\` file, but its ${pkgKey} value is invalid.`
1970
- );
1971
- throw new Error(`package.json ${pkgKey} are invalid`);
1972
- }
1973
- for (let dependency in dependencies) {
1974
- let version2 = dependencies[dependency];
1975
- if ((dependency.startsWith("@react-router/") || dependency === "react-router" || dependency === "react-router-dom") && version2 === "*") {
1976
- dependencies[dependency] = semver.prerelease(ctx.reactRouterVersion) ? (
1977
- // Templates created from prereleases should pin to a specific version
1978
- ctx.reactRouterVersion
1979
- ) : "^" + ctx.reactRouterVersion;
1980
- }
1981
- }
1982
- }
1983
- packageJSON.name = ctx.projectName;
1984
- (0, import_promises2.writeFile)(
1985
- packageJSONPath,
1986
- JSON.stringify((0, import_sort_package_json.default)(packageJSON), null, 2),
1987
- "utf-8"
1988
- );
1592
+ let packageJSONPath = path.join(ctx.cwd, "package.json");
1593
+ if (!existsSync(packageJSONPath)) {
1594
+ let relativePath = path.relative(process.cwd(), ctx.cwd);
1595
+ error("Oh no!", `The provided template must be a React Router project with a \`package.json\` file, but that file does not exist in ${color.bold(relativePath)}.`);
1596
+ throw new Error(`package.json does not exist in ${ctx.cwd}`);
1597
+ }
1598
+ let contents = await readFile(packageJSONPath, "utf-8");
1599
+ let packageJSON;
1600
+ try {
1601
+ packageJSON = JSON.parse(contents);
1602
+ if (!isValidJsonObject(packageJSON)) throw Error();
1603
+ } catch (err) {
1604
+ error("Oh no!", "The provided template must be a React Router project with a `package.json` file, but that file is invalid.");
1605
+ throw err;
1606
+ }
1607
+ for (let pkgKey of ["dependencies", "devDependencies"]) {
1608
+ let dependencies = packageJSON[pkgKey];
1609
+ if (!dependencies) continue;
1610
+ if (!isValidJsonObject(dependencies)) {
1611
+ error("Oh no!", `The provided template must be a React Router project with a \`package.json\` file, but its ${pkgKey} value is invalid.`);
1612
+ throw new Error(`package.json ${pkgKey} are invalid`);
1613
+ }
1614
+ for (let dependency in dependencies) {
1615
+ let version = dependencies[dependency];
1616
+ if ((dependency.startsWith("@react-router/") || dependency === "react-router") && version === "*") dependencies[dependency] = semver.prerelease(ctx.reactRouterVersion) ? ctx.reactRouterVersion : "^" + ctx.reactRouterVersion;
1617
+ }
1618
+ }
1619
+ packageJSON.name = ctx.projectName;
1620
+ writeFile(packageJSONPath, JSON.stringify(sortPackageJSON(packageJSON), null, 2), "utf-8");
1989
1621
  }
1990
1622
  async function loadingIndicator(args) {
1991
- let { ctx, ...rest } = args;
1992
- await renderLoadingIndicator({
1993
- ...rest,
1994
- noMotion: args.ctx.noMotion
1995
- });
1623
+ let { ctx, ...rest } = args;
1624
+ await renderLoadingIndicator({
1625
+ ...rest,
1626
+ noMotion: args.ctx.noMotion
1627
+ });
1996
1628
  }
1997
1629
  function title(text) {
1998
- return align(color.bgWhite(` ${color.black(text)} `), "end", 7) + " ";
1630
+ return align(color.bgWhite(` ${color.black(text)} `), "end", 7) + " ";
1999
1631
  }
2000
1632
  function printHelp(ctx) {
2001
- let output = `
1633
+ log(`
2002
1634
  ${title("create-react-router")}
2003
1635
 
2004
1636
  ${color.heading("Usage")}:
@@ -2034,51 +1666,39 @@ React Router projects are created from templates. A template can be:
2034
1666
  - a file path to a directory of files
2035
1667
  - a file path to a tarball
2036
1668
  ${[
2037
- "remix-run/react-router/templates/basic",
2038
- "remix-run/react-router/examples/basic",
2039
- ":username/:repo",
2040
- ":username/:repo/:directory",
2041
- "https://github.com/:username/:repo",
2042
- "https://github.com/:username/:repo/tree/:branch",
2043
- "https://github.com/:username/:repo/tree/:branch/:directory",
2044
- "https://github.com/:username/:repo/archive/refs/tags/:tag.tar.gz",
2045
- "https://example.com/template.tar.gz",
2046
- "./path/to/template",
2047
- "./path/to/template.tar.gz"
2048
- ].reduce((str, example) => {
2049
- return `${str}
2050
- ${color.dim("$")} ${color.greenBright("create-react-router")} my-app ${color.arg(`--template ${example}`)}`;
2051
- }, "")}
1669
+ "remix-run/react-router/templates/basic",
1670
+ "remix-run/react-router/examples/basic",
1671
+ ":username/:repo",
1672
+ ":username/:repo/:directory",
1673
+ "https://github.com/:username/:repo",
1674
+ "https://github.com/:username/:repo/tree/:branch",
1675
+ "https://github.com/:username/:repo/tree/:branch/:directory",
1676
+ "https://github.com/:username/:repo/archive/refs/tags/:tag.tar.gz",
1677
+ "https://example.com/template.tar.gz",
1678
+ "./path/to/template",
1679
+ "./path/to/template.tar.gz"
1680
+ ].reduce((str, example) => {
1681
+ return `${str}\n${color.dim("$")} ${color.greenBright("create-react-router")} my-app ${color.arg(`--template ${example}`)}`;
1682
+ }, "")}
2052
1683
 
2053
1684
  To create a new project from a template in a private GitHub repo,
2054
1685
  pass the \`token\` flag with a personal access token with access
2055
1686
  to that repo.
2056
- `;
2057
- log(output);
1687
+ `);
2058
1688
  }
2059
1689
  function align(text, dir, len) {
2060
- let pad = Math.max(len - strip(text).length, 0);
2061
- switch (dir) {
2062
- case "start":
2063
- return text + " ".repeat(pad);
2064
- case "end":
2065
- return " ".repeat(pad) + text;
2066
- case "center":
2067
- return " ".repeat(Math.floor(pad / 2)) + text + " ".repeat(Math.floor(pad / 2));
2068
- default:
2069
- return text;
2070
- }
2071
- }
2072
-
2073
- // cli.ts
2074
- import_node_process7.default.on("SIGINT", () => import_node_process7.default.exit(0));
2075
- import_node_process7.default.on("SIGTERM", () => import_node_process7.default.exit(0));
2076
- var argv = import_node_process7.default.argv.slice(2).filter((arg2) => arg2 !== "--");
2077
- createReactRouter(argv).then(
2078
- () => import_node_process7.default.exit(0),
2079
- () => import_node_process7.default.exit(1)
2080
- );
2081
- /**
2082
- * Adapted from https://github.com/withastro/cli-kit
2083
- * @license MIT License Copyright (c) 2022 Nate Moore
2084
- */
1690
+ let pad = Math.max(len - strip(text).length, 0);
1691
+ switch (dir) {
1692
+ case "start": return text + " ".repeat(pad);
1693
+ case "end": return " ".repeat(pad) + text;
1694
+ case "center": return " ".repeat(Math.floor(pad / 2)) + text + " ".repeat(Math.floor(pad / 2));
1695
+ default: return text;
1696
+ }
1697
+ }
1698
+ //#endregion
1699
+ //#region cli.ts
1700
+ process.on("SIGINT", () => process.exit(0));
1701
+ process.on("SIGTERM", () => process.exit(0));
1702
+ createReactRouter(process.argv.slice(2).filter((arg) => arg !== "--")).then(() => process.exit(0), () => process.exit(1));
1703
+ //#endregion
1704
+ export {};