toiljs 0.0.14 → 0.0.16

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.
Files changed (225) hide show
  1. package/.babelrc +13 -13
  2. package/.gitattributes +2 -2
  3. package/.github/ISSUE_TEMPLATE/bug_report.md +38 -38
  4. package/.github/ISSUE_TEMPLATE/bug_report.yml +90 -90
  5. package/.github/ISSUE_TEMPLATE/config.yml +8 -8
  6. package/.github/ISSUE_TEMPLATE/feature_request.md +20 -20
  7. package/.github/PULL_REQUEST_TEMPLATE.md +43 -43
  8. package/.github/changelog-config.json +45 -45
  9. package/.github/dependabot.yml +27 -27
  10. package/.github/workflows/ci.yml +191 -191
  11. package/.prettierrc.json +11 -11
  12. package/.vscode/settings.json +9 -9
  13. package/CHANGELOG.md +5 -5
  14. package/LICENSE +187 -187
  15. package/README.md +339 -315
  16. package/as-pect.asconfig.json +34 -34
  17. package/as-pect.config.js +65 -65
  18. package/assets/logo.svg +36 -36
  19. package/build/backend/.tsbuildinfo +1 -1
  20. package/build/cli/.tsbuildinfo +1 -1
  21. package/build/cli/index.js +2926 -191
  22. package/build/client/.tsbuildinfo +1 -1
  23. package/build/client/dev/devtools.d.ts +6 -0
  24. package/build/client/dev/devtools.js +442 -0
  25. package/build/client/dev/error-overlay.d.ts +9 -0
  26. package/build/client/dev/error-overlay.js +19 -4
  27. package/build/client/head/metadata.d.ts +3 -1
  28. package/build/client/head/metadata.js +8 -0
  29. package/build/client/index.d.ts +4 -4
  30. package/build/client/index.js +2 -2
  31. package/build/client/navigation/navigation.d.ts +2 -0
  32. package/build/client/navigation/navigation.js +9 -1
  33. package/build/client/navigation/prefetch.d.ts +1 -0
  34. package/build/client/navigation/prefetch.js +35 -0
  35. package/build/client/routing/Router.js +1 -1
  36. package/build/client/routing/hooks.js +6 -2
  37. package/build/client/routing/loader.d.ts +25 -0
  38. package/build/client/routing/loader.js +53 -7
  39. package/build/client/routing/mount.js +4 -3
  40. package/build/compiler/.tsbuildinfo +1 -1
  41. package/build/compiler/config.d.ts +18 -0
  42. package/build/compiler/config.js +8 -0
  43. package/build/compiler/docs.js +16 -16
  44. package/build/compiler/generate.js +3 -0
  45. package/build/compiler/index.d.ts +2 -2
  46. package/build/compiler/index.js +3 -1
  47. package/build/compiler/plugin.js +156 -0
  48. package/build/compiler/prerender.d.ts +1 -0
  49. package/build/compiler/prerender.js +2 -1
  50. package/build/compiler/seo.d.ts +2 -2
  51. package/build/compiler/seo.js +8 -6
  52. package/build/compiler/ssg.d.ts +5 -0
  53. package/build/compiler/ssg.js +121 -0
  54. package/build/io/.tsbuildinfo +1 -1
  55. package/build/logger/.tsbuildinfo +1 -1
  56. package/build/shared/.tsbuildinfo +1 -1
  57. package/eslint.config.js +48 -48
  58. package/examples/basic/client/404.tsx +11 -11
  59. package/examples/basic/client/components/.gitkeep +1 -1
  60. package/examples/basic/client/global-error.tsx +13 -13
  61. package/examples/basic/client/layout.tsx +25 -25
  62. package/examples/basic/client/public/images/.gitkeep +1 -1
  63. package/examples/basic/client/public/images/logo.svg +36 -36
  64. package/examples/basic/client/public/robots.txt +2 -2
  65. package/examples/basic/client/routes/docs/[...slug].tsx +12 -12
  66. package/examples/basic/client/routes/features/error/error.tsx +16 -16
  67. package/examples/basic/client/routes/features/template/b.tsx +14 -14
  68. package/examples/basic/client/routes/files/[[...slug]].tsx +21 -21
  69. package/examples/basic/client/routes/gallery/layout.tsx +13 -13
  70. package/examples/basic/client/routes/io.tsx +24 -24
  71. package/examples/basic/client/routes/loader-demo/loading.tsx +13 -13
  72. package/examples/basic/client/routes/search.tsx +61 -61
  73. package/examples/basic/client/toil.tsx +5 -5
  74. package/package.json +155 -147
  75. package/presets/eslint.js +88 -88
  76. package/presets/no-uint8array-tostring.js +200 -200
  77. package/presets/prettier.json +18 -18
  78. package/presets/tsconfig.json +37 -37
  79. package/src/backend/index.ts +160 -160
  80. package/src/cli/proc.ts +50 -50
  81. package/src/cli/updates.ts +69 -69
  82. package/src/cli/validate.ts +31 -31
  83. package/src/client/channel/channel.ts +146 -146
  84. package/src/client/components/Form.tsx +65 -65
  85. package/src/client/components/Script.tsx +113 -113
  86. package/src/client/components/Slot.tsx +21 -21
  87. package/src/client/dev/devtools.tsx +973 -0
  88. package/src/client/dev/error-overlay.tsx +30 -4
  89. package/src/client/head/head.ts +167 -167
  90. package/src/client/head/metadata.ts +19 -1
  91. package/src/client/index.ts +19 -9
  92. package/src/client/navigation/NavLink.tsx +86 -86
  93. package/src/client/navigation/navigation.ts +25 -5
  94. package/src/client/navigation/prefetch.ts +169 -130
  95. package/src/client/navigation/scroll.ts +53 -53
  96. package/src/client/routing/Router.tsx +8 -2
  97. package/src/client/routing/action.ts +122 -122
  98. package/src/client/routing/error-boundary.tsx +43 -43
  99. package/src/client/routing/hooks.ts +21 -6
  100. package/src/client/routing/loader.ts +325 -225
  101. package/src/client/routing/match.ts +47 -47
  102. package/src/client/routing/mount.tsx +54 -52
  103. package/src/client/routing/params-context.ts +10 -10
  104. package/src/client/routing/slot-context.ts +7 -7
  105. package/src/client/search/search.ts +189 -189
  106. package/src/client/search/use-page-search.ts +73 -73
  107. package/src/client/types.ts +73 -73
  108. package/src/compiler/config.ts +47 -1
  109. package/src/compiler/docs.ts +228 -228
  110. package/src/compiler/generate.ts +394 -391
  111. package/src/compiler/index.ts +64 -54
  112. package/src/compiler/pages.ts +70 -70
  113. package/src/compiler/plugin.ts +170 -2
  114. package/src/compiler/prerender.ts +5 -1
  115. package/src/compiler/seo.ts +23 -7
  116. package/src/compiler/ssg.ts +162 -0
  117. package/src/io/BinaryReader.ts +340 -340
  118. package/src/io/BinaryWriter.ts +385 -385
  119. package/src/io/FastMap.ts +127 -127
  120. package/src/io/index.ts +11 -11
  121. package/src/io/lengths.ts +14 -14
  122. package/src/io/types.ts +18 -18
  123. package/src/logger/index.ts +22 -22
  124. package/src/server/index.ts +10 -10
  125. package/src/server/main.ts +13 -13
  126. package/src/server/tsconfig.json +4 -4
  127. package/src/shared/index.ts +10 -10
  128. package/std/client/index.d.ts +15 -15
  129. package/std/client/package.json +3 -3
  130. package/test/assembly/example.spec.ts +7 -7
  131. package/test/channel.test.ts +21 -21
  132. package/test/dom/Link.test.tsx +47 -47
  133. package/test/dom/NavLink.test.tsx +37 -37
  134. package/test/dom/error-overlay.test.tsx +44 -44
  135. package/test/dom/loader.test.tsx +121 -121
  136. package/test/dom/navigation.test.ts +59 -59
  137. package/test/dom/revalidate.test.tsx +38 -38
  138. package/test/dom/route-head.test.tsx +78 -78
  139. package/test/dom/router-loading.test.tsx +44 -44
  140. package/test/dom/scroll.test.ts +56 -56
  141. package/test/dom/use-metadata.test.tsx +58 -0
  142. package/test/io.test.ts +93 -93
  143. package/test/navlink.test.ts +28 -28
  144. package/test/placeholder.test.ts +9 -9
  145. package/test/routes.test.ts +76 -76
  146. package/test/seo.test.ts +175 -164
  147. package/test/slot-layouts.test.ts +69 -69
  148. package/test/ssg.test.ts +36 -0
  149. package/test/update.test.ts +44 -44
  150. package/test/validate.test.ts +42 -42
  151. package/toil-routes.d.ts +7 -0
  152. package/toilconfig.json +30 -30
  153. package/tsconfig.backend.json +13 -13
  154. package/tsconfig.base.json +35 -35
  155. package/tsconfig.cli.json +13 -13
  156. package/tsconfig.client.json +14 -14
  157. package/tsconfig.compiler.json +13 -13
  158. package/tsconfig.io.json +12 -12
  159. package/tsconfig.json +22 -22
  160. package/tsconfig.logger.json +12 -12
  161. package/tsconfig.server.json +10 -10
  162. package/tsconfig.shared.json +12 -12
  163. package/vitest.config.ts +26 -26
  164. package/.idea/codeStyles/Project.xml +0 -54
  165. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  166. package/.idea/inspectionProfiles/Project_Default.xml +0 -6
  167. package/.idea/modules.xml +0 -8
  168. package/.idea/prettier.xml +0 -7
  169. package/.idea/toiljs.iml +0 -8
  170. package/.idea/vcs.xml +0 -6
  171. package/.toil/entry.tsx +0 -9
  172. package/.toil/index.html +0 -12
  173. package/.toil/routes.ts +0 -9
  174. package/build/cli/configure.d.ts +0 -16
  175. package/build/cli/configure.js +0 -272
  176. package/build/cli/create.d.ts +0 -16
  177. package/build/cli/create.js +0 -420
  178. package/build/cli/diagnostics.d.ts +0 -55
  179. package/build/cli/diagnostics.js +0 -333
  180. package/build/cli/doctor.d.ts +0 -6
  181. package/build/cli/doctor.js +0 -249
  182. package/build/cli/features.d.ts +0 -25
  183. package/build/cli/features.js +0 -107
  184. package/build/cli/index.d.ts +0 -2
  185. package/build/cli/proc.d.ts +0 -6
  186. package/build/cli/proc.js +0 -31
  187. package/build/cli/ui.d.ts +0 -9
  188. package/build/cli/ui.js +0 -75
  189. package/build/cli/update.d.ts +0 -7
  190. package/build/cli/update.js +0 -117
  191. package/build/cli/updates.d.ts +0 -10
  192. package/build/cli/updates.js +0 -45
  193. package/build/cli/validate.d.ts +0 -4
  194. package/build/cli/validate.js +0 -19
  195. package/build/client/Link.d.ts +0 -8
  196. package/build/client/Link.js +0 -44
  197. package/build/client/NavLink.d.ts +0 -14
  198. package/build/client/NavLink.js +0 -37
  199. package/build/client/Router.d.ts +0 -7
  200. package/build/client/Router.js +0 -55
  201. package/build/client/channel.d.ts +0 -23
  202. package/build/client/channel.js +0 -94
  203. package/build/client/error-boundary.d.ts +0 -16
  204. package/build/client/error-boundary.js +0 -19
  205. package/build/client/head.d.ts +0 -26
  206. package/build/client/head.js +0 -87
  207. package/build/client/hooks.d.ts +0 -17
  208. package/build/client/hooks.js +0 -48
  209. package/build/client/lazy.d.ts +0 -16
  210. package/build/client/lazy.js +0 -53
  211. package/build/client/match.d.ts +0 -2
  212. package/build/client/match.js +0 -32
  213. package/build/client/mount.d.ts +0 -2
  214. package/build/client/mount.js +0 -13
  215. package/build/client/navigation.d.ts +0 -13
  216. package/build/client/navigation.js +0 -97
  217. package/build/client/params-context.d.ts +0 -2
  218. package/build/client/params-context.js +0 -2
  219. package/build/client/prefetch.d.ts +0 -11
  220. package/build/client/prefetch.js +0 -100
  221. package/build/client/runtime.d.ts +0 -31
  222. package/build/client/runtime.js +0 -112
  223. package/build/client/scroll.d.ts +0 -8
  224. package/build/client/scroll.js +0 -36
  225. package/toil-env.d.ts +0 -16
@@ -1,203 +1,2938 @@
1
1
  #!/usr/bin/env node
2
- import { build, dev, start } from 'toiljs/compiler';
3
- import { runConfigure } from './configure.js';
4
- import { runCreate } from './create.js';
5
- import { runDoctor } from './doctor.js';
6
- import { runUpdate } from './update.js';
7
- import { PREPROCESSORS } from './features.js';
8
- import { accent, banner, bold, danger, dim, success, version } from './ui.js';
9
- function parseArgs(argv) {
10
- const flags = {};
11
- for (let i = 0; i < argv.length; i++) {
12
- const arg = argv[i];
13
- switch (arg) {
14
- case '--root':
15
- flags.root = argv[++i];
16
- break;
17
- case '--port': {
18
- const port = Number(argv[++i]);
19
- if (!Number.isNaN(port))
20
- flags.port = port;
21
- break;
22
- }
23
- case '--template':
24
- case '-t': {
25
- const t = argv[++i];
26
- if (t === 'app' || t === 'minimal')
27
- flags.template = t;
28
- break;
29
- }
30
- case '--pm':
31
- flags.pm = argv[++i];
32
- break;
33
- case '--style': {
34
- const s = argv[++i];
35
- if (PREPROCESSORS.includes(s))
36
- flags.preprocessor = s;
37
- break;
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __commonJS = (cb, mod) => function __require() {
9
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+
28
+ // node_modules/sisteransi/src/index.js
29
+ var require_src = __commonJS({
30
+ "node_modules/sisteransi/src/index.js"(exports, module) {
31
+ "use strict";
32
+ var ESC2 = "\x1B";
33
+ var CSI2 = `${ESC2}[`;
34
+ var beep = "\x07";
35
+ var cursor = {
36
+ to(x3, y) {
37
+ if (!y) return `${CSI2}${x3 + 1}G`;
38
+ return `${CSI2}${y + 1};${x3 + 1}H`;
39
+ },
40
+ move(x3, y) {
41
+ let ret = "";
42
+ if (x3 < 0) ret += `${CSI2}${-x3}D`;
43
+ else if (x3 > 0) ret += `${CSI2}${x3}C`;
44
+ if (y < 0) ret += `${CSI2}${-y}A`;
45
+ else if (y > 0) ret += `${CSI2}${y}B`;
46
+ return ret;
47
+ },
48
+ up: (count = 1) => `${CSI2}${count}A`,
49
+ down: (count = 1) => `${CSI2}${count}B`,
50
+ forward: (count = 1) => `${CSI2}${count}C`,
51
+ backward: (count = 1) => `${CSI2}${count}D`,
52
+ nextLine: (count = 1) => `${CSI2}E`.repeat(count),
53
+ prevLine: (count = 1) => `${CSI2}F`.repeat(count),
54
+ left: `${CSI2}G`,
55
+ hide: `${CSI2}?25l`,
56
+ show: `${CSI2}?25h`,
57
+ save: `${ESC2}7`,
58
+ restore: `${ESC2}8`
59
+ };
60
+ var scroll = {
61
+ up: (count = 1) => `${CSI2}S`.repeat(count),
62
+ down: (count = 1) => `${CSI2}T`.repeat(count)
63
+ };
64
+ var erase = {
65
+ screen: `${CSI2}2J`,
66
+ up: (count = 1) => `${CSI2}1J`.repeat(count),
67
+ down: (count = 1) => `${CSI2}J`.repeat(count),
68
+ line: `${CSI2}2K`,
69
+ lineEnd: `${CSI2}K`,
70
+ lineStart: `${CSI2}1K`,
71
+ lines(count) {
72
+ let clear = "";
73
+ for (let i = 0; i < count; i++)
74
+ clear += this.line + (i < count - 1 ? cursor.up() : "");
75
+ if (count)
76
+ clear += cursor.left;
77
+ return clear;
78
+ }
79
+ };
80
+ module.exports = { cursor, scroll, erase, beep };
81
+ }
82
+ });
83
+
84
+ // node_modules/picocolors/picocolors.js
85
+ var require_picocolors = __commonJS({
86
+ "node_modules/picocolors/picocolors.js"(exports, module) {
87
+ var p2 = process || {};
88
+ var argv = p2.argv || [];
89
+ var env = p2.env || {};
90
+ var isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p2.platform === "win32" || (p2.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
91
+ var formatter = (open, close, replace = open) => (input) => {
92
+ let string = "" + input, index = string.indexOf(close, open.length);
93
+ return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close;
94
+ };
95
+ var replaceClose = (string, close, replace, index) => {
96
+ let result = "", cursor = 0;
97
+ do {
98
+ result += string.substring(cursor, index) + replace;
99
+ cursor = index + close.length;
100
+ index = string.indexOf(close, cursor);
101
+ } while (~index);
102
+ return result + string.substring(cursor);
103
+ };
104
+ var createColors = (enabled = isColorSupported) => {
105
+ let f2 = enabled ? formatter : () => String;
106
+ return {
107
+ isColorSupported: enabled,
108
+ reset: f2("\x1B[0m", "\x1B[0m"),
109
+ bold: f2("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
110
+ dim: f2("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
111
+ italic: f2("\x1B[3m", "\x1B[23m"),
112
+ underline: f2("\x1B[4m", "\x1B[24m"),
113
+ inverse: f2("\x1B[7m", "\x1B[27m"),
114
+ hidden: f2("\x1B[8m", "\x1B[28m"),
115
+ strikethrough: f2("\x1B[9m", "\x1B[29m"),
116
+ black: f2("\x1B[30m", "\x1B[39m"),
117
+ red: f2("\x1B[31m", "\x1B[39m"),
118
+ green: f2("\x1B[32m", "\x1B[39m"),
119
+ yellow: f2("\x1B[33m", "\x1B[39m"),
120
+ blue: f2("\x1B[34m", "\x1B[39m"),
121
+ magenta: f2("\x1B[35m", "\x1B[39m"),
122
+ cyan: f2("\x1B[36m", "\x1B[39m"),
123
+ white: f2("\x1B[37m", "\x1B[39m"),
124
+ gray: f2("\x1B[90m", "\x1B[39m"),
125
+ bgBlack: f2("\x1B[40m", "\x1B[49m"),
126
+ bgRed: f2("\x1B[41m", "\x1B[49m"),
127
+ bgGreen: f2("\x1B[42m", "\x1B[49m"),
128
+ bgYellow: f2("\x1B[43m", "\x1B[49m"),
129
+ bgBlue: f2("\x1B[44m", "\x1B[49m"),
130
+ bgMagenta: f2("\x1B[45m", "\x1B[49m"),
131
+ bgCyan: f2("\x1B[46m", "\x1B[49m"),
132
+ bgWhite: f2("\x1B[47m", "\x1B[49m"),
133
+ blackBright: f2("\x1B[90m", "\x1B[39m"),
134
+ redBright: f2("\x1B[91m", "\x1B[39m"),
135
+ greenBright: f2("\x1B[92m", "\x1B[39m"),
136
+ yellowBright: f2("\x1B[93m", "\x1B[39m"),
137
+ blueBright: f2("\x1B[94m", "\x1B[39m"),
138
+ magentaBright: f2("\x1B[95m", "\x1B[39m"),
139
+ cyanBright: f2("\x1B[96m", "\x1B[39m"),
140
+ whiteBright: f2("\x1B[97m", "\x1B[39m"),
141
+ bgBlackBright: f2("\x1B[100m", "\x1B[49m"),
142
+ bgRedBright: f2("\x1B[101m", "\x1B[49m"),
143
+ bgGreenBright: f2("\x1B[102m", "\x1B[49m"),
144
+ bgYellowBright: f2("\x1B[103m", "\x1B[49m"),
145
+ bgBlueBright: f2("\x1B[104m", "\x1B[49m"),
146
+ bgMagentaBright: f2("\x1B[105m", "\x1B[49m"),
147
+ bgCyanBright: f2("\x1B[106m", "\x1B[49m"),
148
+ bgWhiteBright: f2("\x1B[107m", "\x1B[49m")
149
+ };
150
+ };
151
+ module.exports = createColors();
152
+ module.exports.createColors = createColors;
153
+ }
154
+ });
155
+
156
+ // src/cli/index.ts
157
+ import { build, dev, start } from "toiljs/compiler";
158
+
159
+ // src/cli/configure.ts
160
+ import fs2 from "node:fs/promises";
161
+ import path2 from "node:path";
162
+
163
+ // node_modules/@clack/core/dist/index.mjs
164
+ import { styleText as v } from "node:util";
165
+ import { stdout as x, stdin as D } from "node:process";
166
+ import * as b from "node:readline";
167
+ import G from "node:readline";
168
+
169
+ // node_modules/fast-string-truncated-width/dist/utils.js
170
+ var getCodePointsLength = /* @__PURE__ */ (() => {
171
+ const SURROGATE_PAIR_RE = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
172
+ return (input) => {
173
+ let surrogatePairsNr = 0;
174
+ SURROGATE_PAIR_RE.lastIndex = 0;
175
+ while (SURROGATE_PAIR_RE.test(input)) {
176
+ surrogatePairsNr += 1;
177
+ }
178
+ return input.length - surrogatePairsNr;
179
+ };
180
+ })();
181
+ var isFullWidth = (x3) => {
182
+ return x3 === 12288 || x3 >= 65281 && x3 <= 65376 || x3 >= 65504 && x3 <= 65510;
183
+ };
184
+ var isWideNotCJKTNotEmoji = (x3) => {
185
+ return x3 === 8987 || x3 === 9001 || x3 >= 12272 && x3 <= 12287 || x3 >= 12289 && x3 <= 12350 || x3 >= 12441 && x3 <= 12543 || x3 >= 12549 && x3 <= 12591 || x3 >= 12593 && x3 <= 12686 || x3 >= 12688 && x3 <= 12771 || x3 >= 12783 && x3 <= 12830 || x3 >= 12832 && x3 <= 12871 || x3 >= 12880 && x3 <= 19903 || x3 >= 65040 && x3 <= 65049 || x3 >= 65072 && x3 <= 65106 || x3 >= 65108 && x3 <= 65126 || x3 >= 65128 && x3 <= 65131 || x3 >= 127488 && x3 <= 127490 || x3 >= 127504 && x3 <= 127547 || x3 >= 127552 && x3 <= 127560 || x3 >= 131072 && x3 <= 196605 || x3 >= 196608 && x3 <= 262141;
186
+ };
187
+
188
+ // node_modules/fast-string-truncated-width/dist/index.js
189
+ var ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
190
+ var CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
191
+ var CJKT_WIDE_RE = /(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/yu;
192
+ var TAB_RE = /\t{1,1000}/y;
193
+ var EMOJI_RE = /[\u{1F1E6}-\u{1F1FF}]{2}|\u{1F3F4}[\u{E0061}-\u{E007A}]{2}[\u{E0030}-\u{E0039}\u{E0061}-\u{E007A}]{1,3}\u{E007F}|(?:\p{Emoji}\uFE0F\u20E3?|\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation})(?:\u200D(?:\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F\u20E3?))*/yu;
194
+ var LATIN_RE = /(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y;
195
+ var MODIFIER_RE = /\p{M}+/gu;
196
+ var NO_TRUNCATION = { limit: Infinity, ellipsis: "" };
197
+ var getStringTruncatedWidth = (input, truncationOptions = {}, widthOptions = {}) => {
198
+ const LIMIT = truncationOptions.limit ?? Infinity;
199
+ const ELLIPSIS = truncationOptions.ellipsis ?? "";
200
+ const ELLIPSIS_WIDTH = truncationOptions?.ellipsisWidth ?? (ELLIPSIS ? getStringTruncatedWidth(ELLIPSIS, NO_TRUNCATION, widthOptions).width : 0);
201
+ const ANSI_WIDTH = 0;
202
+ const CONTROL_WIDTH = widthOptions.controlWidth ?? 0;
203
+ const TAB_WIDTH = widthOptions.tabWidth ?? 8;
204
+ const EMOJI_WIDTH = widthOptions.emojiWidth ?? 2;
205
+ const FULL_WIDTH_WIDTH = 2;
206
+ const REGULAR_WIDTH = widthOptions.regularWidth ?? 1;
207
+ const WIDE_WIDTH = widthOptions.wideWidth ?? FULL_WIDTH_WIDTH;
208
+ const PARSE_BLOCKS = [
209
+ [LATIN_RE, REGULAR_WIDTH],
210
+ [ANSI_RE, ANSI_WIDTH],
211
+ [CONTROL_RE, CONTROL_WIDTH],
212
+ [TAB_RE, TAB_WIDTH],
213
+ [EMOJI_RE, EMOJI_WIDTH],
214
+ [CJKT_WIDE_RE, WIDE_WIDTH]
215
+ ];
216
+ let indexPrev = 0;
217
+ let index = 0;
218
+ let length = input.length;
219
+ let lengthExtra = 0;
220
+ let truncationEnabled = false;
221
+ let truncationIndex = length;
222
+ let truncationLimit = Math.max(0, LIMIT - ELLIPSIS_WIDTH);
223
+ let unmatchedStart = 0;
224
+ let unmatchedEnd = 0;
225
+ let width = 0;
226
+ let widthExtra = 0;
227
+ outer: while (true) {
228
+ if (unmatchedEnd > unmatchedStart || index >= length && index > indexPrev) {
229
+ const unmatched = input.slice(unmatchedStart, unmatchedEnd) || input.slice(indexPrev, index);
230
+ lengthExtra = 0;
231
+ for (const char of unmatched.replaceAll(MODIFIER_RE, "")) {
232
+ const codePoint = char.codePointAt(0) || 0;
233
+ if (isFullWidth(codePoint)) {
234
+ widthExtra = FULL_WIDTH_WIDTH;
235
+ } else if (isWideNotCJKTNotEmoji(codePoint)) {
236
+ widthExtra = WIDE_WIDTH;
237
+ } else {
238
+ widthExtra = REGULAR_WIDTH;
239
+ }
240
+ if (width + widthExtra > truncationLimit) {
241
+ truncationIndex = Math.min(truncationIndex, Math.max(unmatchedStart, indexPrev) + lengthExtra);
242
+ }
243
+ if (width + widthExtra > LIMIT) {
244
+ truncationEnabled = true;
245
+ break outer;
246
+ }
247
+ lengthExtra += char.length;
248
+ width += widthExtra;
249
+ }
250
+ unmatchedStart = unmatchedEnd = 0;
251
+ }
252
+ if (index >= length) {
253
+ break outer;
254
+ }
255
+ for (let i = 0, l = PARSE_BLOCKS.length; i < l; i++) {
256
+ const [BLOCK_RE, BLOCK_WIDTH] = PARSE_BLOCKS[i];
257
+ BLOCK_RE.lastIndex = index;
258
+ if (BLOCK_RE.test(input)) {
259
+ lengthExtra = BLOCK_RE === CJKT_WIDE_RE ? getCodePointsLength(input.slice(index, BLOCK_RE.lastIndex)) : BLOCK_RE === EMOJI_RE ? 1 : BLOCK_RE.lastIndex - index;
260
+ widthExtra = lengthExtra * BLOCK_WIDTH;
261
+ if (width + widthExtra > truncationLimit) {
262
+ truncationIndex = Math.min(truncationIndex, index + Math.floor((truncationLimit - width) / BLOCK_WIDTH));
263
+ }
264
+ if (width + widthExtra > LIMIT) {
265
+ truncationEnabled = true;
266
+ break outer;
267
+ }
268
+ width += widthExtra;
269
+ unmatchedStart = indexPrev;
270
+ unmatchedEnd = index;
271
+ index = indexPrev = BLOCK_RE.lastIndex;
272
+ continue outer;
273
+ }
274
+ }
275
+ index += 1;
276
+ }
277
+ return {
278
+ width: truncationEnabled ? truncationLimit : width,
279
+ index: truncationEnabled ? truncationIndex : length,
280
+ truncated: truncationEnabled,
281
+ ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH
282
+ };
283
+ };
284
+ var dist_default = getStringTruncatedWidth;
285
+
286
+ // node_modules/fast-string-width/dist/index.js
287
+ var NO_TRUNCATION2 = {
288
+ limit: Infinity,
289
+ ellipsis: "",
290
+ ellipsisWidth: 0
291
+ };
292
+ var fastStringWidth = (input, options = {}) => {
293
+ return dist_default(input, NO_TRUNCATION2, options).width;
294
+ };
295
+ var dist_default2 = fastStringWidth;
296
+
297
+ // node_modules/fast-wrap-ansi/lib/main.js
298
+ var ESC = "\x1B";
299
+ var CSI = "\x9B";
300
+ var END_CODE = 39;
301
+ var ANSI_ESCAPE_BELL = "\x07";
302
+ var ANSI_CSI = "[";
303
+ var ANSI_OSC = "]";
304
+ var ANSI_SGR_TERMINATOR = "m";
305
+ var ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
306
+ var GROUP_REGEX = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, "y");
307
+ var getClosingCode = (openingCode) => {
308
+ if (openingCode >= 30 && openingCode <= 37)
309
+ return 39;
310
+ if (openingCode >= 90 && openingCode <= 97)
311
+ return 39;
312
+ if (openingCode >= 40 && openingCode <= 47)
313
+ return 49;
314
+ if (openingCode >= 100 && openingCode <= 107)
315
+ return 49;
316
+ if (openingCode === 1 || openingCode === 2)
317
+ return 22;
318
+ if (openingCode === 3)
319
+ return 23;
320
+ if (openingCode === 4)
321
+ return 24;
322
+ if (openingCode === 7)
323
+ return 27;
324
+ if (openingCode === 8)
325
+ return 28;
326
+ if (openingCode === 9)
327
+ return 29;
328
+ if (openingCode === 0)
329
+ return 0;
330
+ return void 0;
331
+ };
332
+ var wrapAnsiCode = (code) => `${ESC}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
333
+ var wrapAnsiHyperlink = (url) => `${ESC}${ANSI_ESCAPE_LINK}${url}${ANSI_ESCAPE_BELL}`;
334
+ var wrapWord = (rows, word, columns) => {
335
+ const characters = word[Symbol.iterator]();
336
+ let isInsideEscape = false;
337
+ let isInsideLinkEscape = false;
338
+ let lastRow = rows.at(-1);
339
+ let visible = lastRow === void 0 ? 0 : dist_default2(lastRow);
340
+ let currentCharacter = characters.next();
341
+ let nextCharacter = characters.next();
342
+ let rawCharacterIndex = 0;
343
+ while (!currentCharacter.done) {
344
+ const character = currentCharacter.value;
345
+ const characterLength = dist_default2(character);
346
+ if (visible + characterLength <= columns) {
347
+ rows[rows.length - 1] += character;
348
+ } else {
349
+ rows.push(character);
350
+ visible = 0;
351
+ }
352
+ if (character === ESC || character === CSI) {
353
+ isInsideEscape = true;
354
+ isInsideLinkEscape = word.startsWith(ANSI_ESCAPE_LINK, rawCharacterIndex + 1);
355
+ }
356
+ if (isInsideEscape) {
357
+ if (isInsideLinkEscape) {
358
+ if (character === ANSI_ESCAPE_BELL) {
359
+ isInsideEscape = false;
360
+ isInsideLinkEscape = false;
361
+ }
362
+ } else if (character === ANSI_SGR_TERMINATOR) {
363
+ isInsideEscape = false;
364
+ }
365
+ } else {
366
+ visible += characterLength;
367
+ if (visible === columns && !nextCharacter.done) {
368
+ rows.push("");
369
+ visible = 0;
370
+ }
371
+ }
372
+ currentCharacter = nextCharacter;
373
+ nextCharacter = characters.next();
374
+ rawCharacterIndex += character.length;
375
+ }
376
+ lastRow = rows.at(-1);
377
+ if (!visible && lastRow !== void 0 && lastRow.length && rows.length > 1) {
378
+ rows[rows.length - 2] += rows.pop();
379
+ }
380
+ };
381
+ var stringVisibleTrimSpacesRight = (string) => {
382
+ const words = string.split(" ");
383
+ let last = words.length;
384
+ while (last) {
385
+ if (dist_default2(words[last - 1])) {
386
+ break;
387
+ }
388
+ last--;
389
+ }
390
+ if (last === words.length) {
391
+ return string;
392
+ }
393
+ return words.slice(0, last).join(" ") + words.slice(last).join("");
394
+ };
395
+ var exec = (string, columns, options = {}) => {
396
+ if (options.trim !== false && string.trim() === "") {
397
+ return "";
398
+ }
399
+ let returnValue = "";
400
+ let escapeCode;
401
+ let escapeUrl;
402
+ const words = string.split(" ");
403
+ let rows = [""];
404
+ let rowLength = 0;
405
+ for (let index = 0; index < words.length; index++) {
406
+ const word = words[index];
407
+ if (options.trim !== false) {
408
+ const row = rows.at(-1) ?? "";
409
+ const trimmed = row.trimStart();
410
+ if (row.length !== trimmed.length) {
411
+ rows[rows.length - 1] = trimmed;
412
+ rowLength = dist_default2(trimmed);
413
+ }
414
+ }
415
+ if (index !== 0) {
416
+ if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
417
+ rows.push("");
418
+ rowLength = 0;
419
+ }
420
+ if (rowLength || options.trim === false) {
421
+ rows[rows.length - 1] += " ";
422
+ rowLength++;
423
+ }
424
+ }
425
+ const wordLength = dist_default2(word);
426
+ if (options.hard && wordLength > columns) {
427
+ const remainingColumns = columns - rowLength;
428
+ const breaksStartingThisLine = 1 + Math.floor((wordLength - remainingColumns - 1) / columns);
429
+ const breaksStartingNextLine = Math.floor((wordLength - 1) / columns);
430
+ if (breaksStartingNextLine < breaksStartingThisLine) {
431
+ rows.push("");
432
+ }
433
+ wrapWord(rows, word, columns);
434
+ rowLength = dist_default2(rows.at(-1) ?? "");
435
+ continue;
436
+ }
437
+ if (rowLength + wordLength > columns && rowLength && wordLength) {
438
+ if (options.wordWrap === false && rowLength < columns) {
439
+ wrapWord(rows, word, columns);
440
+ rowLength = dist_default2(rows.at(-1) ?? "");
441
+ continue;
442
+ }
443
+ rows.push("");
444
+ rowLength = 0;
445
+ }
446
+ if (rowLength + wordLength > columns && options.wordWrap === false) {
447
+ wrapWord(rows, word, columns);
448
+ rowLength = dist_default2(rows.at(-1) ?? "");
449
+ continue;
450
+ }
451
+ rows[rows.length - 1] += word;
452
+ rowLength += wordLength;
453
+ }
454
+ if (options.trim !== false) {
455
+ rows = rows.map((row) => stringVisibleTrimSpacesRight(row));
456
+ }
457
+ const preString = rows.join("\n");
458
+ let inSurrogate = false;
459
+ for (let i = 0; i < preString.length; i++) {
460
+ const character = preString[i];
461
+ returnValue += character;
462
+ if (!inSurrogate) {
463
+ inSurrogate = character >= "\uD800" && character <= "\uDBFF";
464
+ if (inSurrogate) {
465
+ continue;
466
+ }
467
+ } else {
468
+ inSurrogate = false;
469
+ }
470
+ if (character === ESC || character === CSI) {
471
+ GROUP_REGEX.lastIndex = i + 1;
472
+ const groupsResult = GROUP_REGEX.exec(preString);
473
+ const groups = groupsResult?.groups;
474
+ if (groups?.code !== void 0) {
475
+ const code = Number.parseFloat(groups.code);
476
+ escapeCode = code === END_CODE ? void 0 : code;
477
+ } else if (groups?.uri !== void 0) {
478
+ escapeUrl = groups.uri.length === 0 ? void 0 : groups.uri;
479
+ }
480
+ }
481
+ if (preString[i + 1] === "\n") {
482
+ if (escapeUrl) {
483
+ returnValue += wrapAnsiHyperlink("");
484
+ }
485
+ const closingCode = escapeCode ? getClosingCode(escapeCode) : void 0;
486
+ if (escapeCode && closingCode) {
487
+ returnValue += wrapAnsiCode(closingCode);
488
+ }
489
+ } else if (character === "\n") {
490
+ if (escapeCode && getClosingCode(escapeCode)) {
491
+ returnValue += wrapAnsiCode(escapeCode);
492
+ }
493
+ if (escapeUrl) {
494
+ returnValue += wrapAnsiHyperlink(escapeUrl);
495
+ }
496
+ }
497
+ }
498
+ return returnValue;
499
+ };
500
+ var CRLF_OR_LF = /\r?\n/;
501
+ function wrapAnsi(string, columns, options) {
502
+ return String(string).normalize().split(CRLF_OR_LF).map((line) => exec(line, columns, options)).join("\n");
503
+ }
504
+
505
+ // node_modules/@clack/core/dist/index.mjs
506
+ var import_sisteransi = __toESM(require_src(), 1);
507
+ import { ReadStream as O } from "node:tty";
508
+ function f(r, t, s) {
509
+ if (!s.some((o) => !o.disabled)) return r;
510
+ const e2 = r + t, i = Math.max(s.length - 1, 0), n = e2 < 0 ? i : e2 > i ? 0 : e2;
511
+ return s[n].disabled ? f(n, t < 0 ? -1 : 1, s) : n;
512
+ }
513
+ var K = ["up", "down", "left", "right", "space", "enter", "cancel"];
514
+ var j = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
515
+ var h = { actions: new Set(K), aliases: /* @__PURE__ */ new Map([["k", "up"], ["j", "down"], ["h", "left"], ["l", "right"], ["", "cancel"], ["escape", "cancel"]]), messages: { cancel: "Canceled", error: "Something went wrong" }, withGuide: true, date: { monthNames: [...j], messages: { required: "Please enter a valid date", invalidMonth: "There are only 12 months in a year", invalidDay: (r, t) => `There are only ${r} days in ${t}`, afterMin: (r) => `Date must be on or after ${r.toISOString().slice(0, 10)}`, beforeMax: (r) => `Date must be on or before ${r.toISOString().slice(0, 10)}` } } };
516
+ function C(r, t) {
517
+ if (typeof r == "string") return h.aliases.get(r) === t;
518
+ for (const s of r) if (s !== void 0 && C(s, t)) return true;
519
+ return false;
520
+ }
521
+ function Y(r, t) {
522
+ if (r === t) return;
523
+ const s = r.split(`
524
+ `), e2 = t.split(`
525
+ `), i = Math.max(s.length, e2.length), n = [];
526
+ for (let o = 0; o < i; o++) s[o] !== e2[o] && n.push(o);
527
+ return { lines: n, numLinesBefore: s.length, numLinesAfter: e2.length, numLines: i };
528
+ }
529
+ var q = globalThis.process.platform.startsWith("win");
530
+ var k = /* @__PURE__ */ Symbol("clack:cancel");
531
+ function R(r) {
532
+ return r === k;
533
+ }
534
+ function w(r, t) {
535
+ const s = r;
536
+ s.isTTY && s.setRawMode(t);
537
+ }
538
+ function W({ input: r = D, output: t = x, overwrite: s = true, hideCursor: e2 = true } = {}) {
539
+ const i = b.createInterface({ input: r, output: t, prompt: "", tabSize: 1 });
540
+ b.emitKeypressEvents(r, i), r instanceof O && r.isTTY && r.setRawMode(true);
541
+ const n = (o, { name: u, sequence: a }) => {
542
+ const l = String(o);
543
+ if (C([l, u, a], "cancel")) {
544
+ e2 && t.write(import_sisteransi.cursor.show), process.exit(0);
545
+ return;
546
+ }
547
+ if (!s) return;
548
+ const c = u === "return" ? 0 : -1, y = u === "return" ? -1 : 0;
549
+ b.moveCursor(t, c, y, () => {
550
+ b.clearLine(t, 1, () => {
551
+ r.once("keypress", n);
552
+ });
553
+ });
554
+ };
555
+ return e2 && t.write(import_sisteransi.cursor.hide), r.once("keypress", n), () => {
556
+ r.off("keypress", n), e2 && t.write(import_sisteransi.cursor.show), r instanceof O && r.isTTY && !q && r.setRawMode(false), i.terminal = false, i.close();
557
+ };
558
+ }
559
+ var A = (r) => "columns" in r && typeof r.columns == "number" ? r.columns : 80;
560
+ var L = (r) => "rows" in r && typeof r.rows == "number" ? r.rows : 20;
561
+ function B(r, t, s, e2 = s, i = s, n) {
562
+ const o = A(r ?? x);
563
+ return wrapAnsi(t, o - s.length, { hard: true, trim: false }).split(`
564
+ `).map((u, a, l) => {
565
+ const c = n ? n(u, a) : u;
566
+ return a === 0 ? `${e2}${c}` : a === l.length - 1 ? `${i}${c}` : `${s}${c}`;
567
+ }).join(`
568
+ `);
569
+ }
570
+ function P(r, t) {
571
+ if ("~standard" in r) {
572
+ const s = r["~standard"].validate(t);
573
+ if (s instanceof Promise) throw new TypeError("Schema validation must be synchronous. Update `validate()` and remove any asynchronous logic.");
574
+ return s.issues?.at(0)?.message;
575
+ }
576
+ return r(t);
577
+ }
578
+ var m = class {
579
+ input;
580
+ output;
581
+ _abortSignal;
582
+ rl;
583
+ opts;
584
+ _render;
585
+ _track = false;
586
+ _prevFrame = "";
587
+ _subscribers = /* @__PURE__ */ new Map();
588
+ _cursor = 0;
589
+ state = "initial";
590
+ error = "";
591
+ value;
592
+ userInput = "";
593
+ constructor(t, s = true) {
594
+ const { input: e2 = D, output: i = x, render: n, signal: o, ...u } = t;
595
+ this.opts = u, this.onKeypress = this.onKeypress.bind(this), this.close = this.close.bind(this), this.render = this.render.bind(this), this._render = n.bind(this), this._track = s, this._abortSignal = o, this.input = e2, this.output = i;
596
+ }
597
+ unsubscribe() {
598
+ this._subscribers.clear();
599
+ }
600
+ setSubscriber(t, s) {
601
+ const e2 = this._subscribers.get(t) ?? [];
602
+ e2.push(s), this._subscribers.set(t, e2);
603
+ }
604
+ on(t, s) {
605
+ this.setSubscriber(t, { cb: s });
606
+ }
607
+ once(t, s) {
608
+ this.setSubscriber(t, { cb: s, once: true });
609
+ }
610
+ emit(t, ...s) {
611
+ const e2 = this._subscribers.get(t) ?? [], i = [];
612
+ for (const n of e2) n.cb(...s), n.once && i.push(() => e2.splice(e2.indexOf(n), 1));
613
+ for (const n of i) n();
614
+ }
615
+ prompt() {
616
+ return new Promise((t) => {
617
+ if (this._abortSignal) {
618
+ if (this._abortSignal.aborted) return this.state = "cancel", this.close(), t(k);
619
+ this._abortSignal.addEventListener("abort", () => {
620
+ this.state = "cancel", this.close();
621
+ }, { once: true });
622
+ }
623
+ this.rl = G.createInterface({ input: this.input, tabSize: 2, prompt: "", escapeCodeTimeout: 50, terminal: true }), this.rl.prompt(), this.opts.initialUserInput !== void 0 && this._setUserInput(this.opts.initialUserInput, true), this.input.on("keypress", this.onKeypress), w(this.input, true), this.output.on("resize", this.render), this.render(), this.once("submit", () => {
624
+ this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), w(this.input, false), t(this.value);
625
+ }), this.once("cancel", () => {
626
+ this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), w(this.input, false), t(k);
627
+ });
628
+ });
629
+ }
630
+ _isActionKey(t, s) {
631
+ return t === " ";
632
+ }
633
+ _shouldSubmit(t, s) {
634
+ return true;
635
+ }
636
+ _setValue(t) {
637
+ this.value = t, this.emit("value", this.value);
638
+ }
639
+ _setUserInput(t, s) {
640
+ this.userInput = t ?? "", this.emit("userInput", this.userInput), s && this._track && this.rl && (this.rl.write(this.userInput), this._cursor = this.rl.cursor);
641
+ }
642
+ _clearUserInput() {
643
+ this.rl?.write(null, { ctrl: true, name: "u" }), this._setUserInput("");
644
+ }
645
+ onKeypress(t, s) {
646
+ if (this._track && s.name !== "return" && (s.name && this._isActionKey(t, s) && this.rl?.write(null, { ctrl: true, name: "h" }), this._cursor = this.rl?.cursor ?? 0, this._setUserInput(this.rl?.line)), this.state === "error" && (this.state = "active"), s?.name && (!this._track && h.aliases.has(s.name) && this.emit("cursor", h.aliases.get(s.name)), h.actions.has(s.name) && this.emit("cursor", s.name)), t && (t.toLowerCase() === "y" || t.toLowerCase() === "n") && this.emit("confirm", t.toLowerCase() === "y"), this.emit("key", t, s), s?.name === "return" && this._shouldSubmit(t, s)) {
647
+ if (this.opts.validate) {
648
+ const e2 = P(this.opts.validate, this.value);
649
+ e2 && (this.error = e2 instanceof Error ? e2.message : e2, this.state = "error", this.rl?.write(this.userInput));
650
+ }
651
+ this.state !== "error" && (this.state = "submit");
652
+ }
653
+ C([t, s?.name, s?.sequence], "cancel") && (this.state = "cancel"), (this.state === "submit" || this.state === "cancel") && this.emit("finalize"), this.render(), (this.state === "submit" || this.state === "cancel") && this.close();
654
+ }
655
+ close() {
656
+ this.input.unpipe(), this.input.removeListener("keypress", this.onKeypress), this.output.write(`
657
+ `), w(this.input, false), this.rl?.close(), this.rl = void 0, this.emit(`${this.state}`, this.value), this.unsubscribe();
658
+ }
659
+ restoreCursor() {
660
+ const t = wrapAnsi(this._prevFrame, process.stdout.columns, { hard: true, trim: false }).split(`
661
+ `).length - 1;
662
+ this.output.write(import_sisteransi.cursor.move(-999, t * -1));
663
+ }
664
+ render() {
665
+ const t = wrapAnsi(this._render(this) ?? "", process.stdout.columns, { hard: true, trim: false });
666
+ if (t !== this._prevFrame) {
667
+ if (this.state === "initial") this.output.write(import_sisteransi.cursor.hide);
668
+ else {
669
+ const s = Y(this._prevFrame, t), e2 = L(this.output);
670
+ if (this.restoreCursor(), s) {
671
+ const i = Math.max(0, s.numLinesAfter - e2), n = Math.max(0, s.numLinesBefore - e2);
672
+ let o = s.lines.find((u) => u >= i);
673
+ if (o === void 0) {
674
+ this._prevFrame = t;
675
+ return;
676
+ }
677
+ if (s.lines.length === 1) {
678
+ this.output.write(import_sisteransi.cursor.move(0, o - n)), this.output.write(import_sisteransi.erase.lines(1));
679
+ const u = t.split(`
680
+ `);
681
+ this.output.write(u[o]), this._prevFrame = t, this.output.write(import_sisteransi.cursor.move(0, u.length - o - 1));
682
+ return;
683
+ } else if (s.lines.length > 1) {
684
+ if (i < n) o = i;
685
+ else {
686
+ const a = o - n;
687
+ a > 0 && this.output.write(import_sisteransi.cursor.move(0, a));
38
688
  }
39
- case '--tailwind':
40
- flags.tailwind = true;
41
- break;
42
- case '--no-tailwind':
43
- flags.tailwind = false;
44
- break;
45
- case '--ai':
46
- flags.ai = true;
47
- break;
48
- case '--no-ai':
49
- flags.ai = false;
50
- break;
51
- case '--images':
52
- flags.images = true;
53
- break;
54
- case '--no-images':
55
- flags.images = false;
56
- break;
57
- case '--install':
58
- flags.install = true;
59
- break;
60
- case '--no-install':
61
- flags.install = false;
62
- break;
63
- case '--git':
64
- flags.git = true;
65
- break;
66
- case '--no-git':
67
- flags.git = false;
68
- break;
69
- case '-y':
70
- case '--yes':
71
- flags.yes = true;
72
- break;
73
- case '--json':
74
- flags.json = true;
75
- break;
76
- case '--target':
77
- flags.target = argv[++i];
78
- break;
79
- default:
80
- if (!arg.startsWith('-') && flags.name === undefined)
81
- flags.name = arg;
689
+ this.output.write(import_sisteransi.erase.down());
690
+ const u = t.split(`
691
+ `).slice(o);
692
+ this.output.write(u.join(`
693
+ `)), this._prevFrame = t;
694
+ return;
695
+ }
82
696
  }
697
+ this.output.write(import_sisteransi.erase.down());
698
+ }
699
+ this.output.write(t), this.state === "initial" && (this.state = "active"), this._prevFrame = t;
700
+ }
701
+ }
702
+ };
703
+ var Z = class extends m {
704
+ get cursor() {
705
+ return this.value ? 0 : 1;
706
+ }
707
+ get _value() {
708
+ return this.cursor === 0;
709
+ }
710
+ constructor(t) {
711
+ super(t, false), this.value = !!t.initialValue, this.on("userInput", () => {
712
+ this.value = this._value;
713
+ }), this.on("confirm", (s) => {
714
+ this.output.write(import_sisteransi.cursor.move(0, -1)), this.value = s, this.state = "submit", this.close();
715
+ }), this.on("cursor", () => {
716
+ this.value = !this.value;
717
+ });
718
+ }
719
+ };
720
+ var ut = class extends m {
721
+ options;
722
+ cursor = 0;
723
+ get _value() {
724
+ return this.options[this.cursor].value;
725
+ }
726
+ get _enabledOptions() {
727
+ return this.options.filter((t) => t.disabled !== true);
728
+ }
729
+ toggleAll() {
730
+ const t = this._enabledOptions, s = this.value !== void 0 && this.value.length === t.length;
731
+ this.value = s ? [] : t.map((e2) => e2.value);
732
+ }
733
+ toggleInvert() {
734
+ const t = this.value;
735
+ if (!t) return;
736
+ const s = this._enabledOptions.filter((e2) => !t.includes(e2.value));
737
+ this.value = s.map((e2) => e2.value);
738
+ }
739
+ toggleValue() {
740
+ this.value === void 0 && (this.value = []);
741
+ const t = this.value.includes(this._value);
742
+ this.value = t ? this.value.filter((s) => s !== this._value) : [...this.value, this._value];
743
+ }
744
+ constructor(t) {
745
+ super(t, false), this.options = t.options, this.value = [...t.initialValues ?? []];
746
+ const s = Math.max(this.options.findIndex(({ value: e2 }) => e2 === t.cursorAt), 0);
747
+ this.cursor = this.options[s].disabled ? f(s, 1, this.options) : s, this.on("key", (e2, i) => {
748
+ i.name === "a" && this.toggleAll(), i.name === "i" && this.toggleInvert();
749
+ }), this.on("cursor", (e2) => {
750
+ switch (e2) {
751
+ case "left":
752
+ case "up":
753
+ this.cursor = f(this.cursor, -1, this.options);
754
+ break;
755
+ case "down":
756
+ case "right":
757
+ this.cursor = f(this.cursor, 1, this.options);
758
+ break;
759
+ case "space":
760
+ this.toggleValue();
761
+ break;
762
+ }
763
+ });
764
+ }
765
+ };
766
+ var ht = class extends m {
767
+ options;
768
+ cursor = 0;
769
+ get _selectedValue() {
770
+ return this.options[this.cursor];
771
+ }
772
+ changeValue() {
773
+ this.value = this._selectedValue.value;
774
+ }
775
+ constructor(t) {
776
+ super(t, false), this.options = t.options;
777
+ const s = this.options.findIndex(({ value: i }) => i === t.initialValue), e2 = s === -1 ? 0 : s;
778
+ this.cursor = this.options[e2].disabled ? f(e2, 1, this.options) : e2, this.changeValue(), this.on("cursor", (i) => {
779
+ switch (i) {
780
+ case "left":
781
+ case "up":
782
+ this.cursor = f(this.cursor, -1, this.options);
783
+ break;
784
+ case "down":
785
+ case "right":
786
+ this.cursor = f(this.cursor, 1, this.options);
787
+ break;
788
+ }
789
+ this.changeValue();
790
+ });
791
+ }
792
+ };
793
+ var ct = class extends m {
794
+ get userInputWithCursor() {
795
+ if (this.state === "submit") return this.userInput;
796
+ const t = this.userInput;
797
+ if (this.cursor >= t.length) return `${this.userInput}\u2588`;
798
+ const s = t.slice(0, this.cursor), [e2, ...i] = t.slice(this.cursor);
799
+ return `${s}${v("inverse", e2)}${i.join("")}`;
800
+ }
801
+ get cursor() {
802
+ return this._cursor;
803
+ }
804
+ constructor(t) {
805
+ super({ ...t, initialUserInput: t.initialUserInput ?? t.initialValue }), this.on("userInput", (s) => {
806
+ this._setValue(s);
807
+ }), this.on("finalize", () => {
808
+ this.value || (this.value = t.defaultValue), this.value === void 0 && (this.value = "");
809
+ });
810
+ }
811
+ };
812
+
813
+ // node_modules/@clack/prompts/dist/index.mjs
814
+ import { styleText as e, stripVTControlCharacters as ot2 } from "node:util";
815
+ import V2 from "node:process";
816
+ var import_sisteransi2 = __toESM(require_src(), 1);
817
+ function se() {
818
+ return V2.platform !== "win32" ? V2.env.TERM !== "linux" : !!V2.env.CI || !!V2.env.WT_SESSION || !!V2.env.TERMINUS_SUBLIME || V2.env.ConEmuTask === "{cmd::Cmder}" || V2.env.TERM_PROGRAM === "Terminus-Sublime" || V2.env.TERM_PROGRAM === "vscode" || V2.env.TERM === "xterm-256color" || V2.env.TERM === "alacritty" || V2.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
819
+ }
820
+ var tt = se();
821
+ var at2 = () => process.env.CI === "true";
822
+ var w2 = (t, i) => tt ? t : i;
823
+ var _t = w2("\u25C6", "*");
824
+ var ut2 = w2("\u25A0", "x");
825
+ var lt2 = w2("\u25B2", "x");
826
+ var H = w2("\u25C7", "o");
827
+ var ct2 = w2("\u250C", "T");
828
+ var $ = w2("\u2502", "|");
829
+ var x2 = w2("\u2514", "\u2014");
830
+ var xt = w2("\u2510", "T");
831
+ var Et = w2("\u2518", "\u2014");
832
+ var z2 = w2("\u25CF", ">");
833
+ var U = w2("\u25CB", " ");
834
+ var et = w2("\u25FB", "[\u2022]");
835
+ var K2 = w2("\u25FC", "[+]");
836
+ var Y2 = w2("\u25FB", "[ ]");
837
+ var Gt = w2("\u25AA", "\u2022");
838
+ var st = w2("\u2500", "-");
839
+ var $t = w2("\u256E", "+");
840
+ var Mt = w2("\u251C", "+");
841
+ var dt = w2("\u256F", "+");
842
+ var ht2 = w2("\u2570", "+");
843
+ var Ot = w2("\u256D", "+");
844
+ var pt = w2("\u25CF", "\u2022");
845
+ var mt = w2("\u25C6", "*");
846
+ var gt = w2("\u25B2", "!");
847
+ var yt = w2("\u25A0", "x");
848
+ var P2 = (t) => {
849
+ switch (t) {
850
+ case "initial":
851
+ case "active":
852
+ return e("cyan", _t);
853
+ case "cancel":
854
+ return e("red", ut2);
855
+ case "error":
856
+ return e("yellow", lt2);
857
+ case "submit":
858
+ return e("green", H);
859
+ }
860
+ };
861
+ var ft = (t) => {
862
+ switch (t) {
863
+ case "initial":
864
+ case "active":
865
+ return e("cyan", $);
866
+ case "cancel":
867
+ return e("red", $);
868
+ case "error":
869
+ return e("yellow", $);
870
+ case "submit":
871
+ return e("green", $);
872
+ }
873
+ };
874
+ var Pt = (t, i, s, r, u, n = false) => {
875
+ let a = i, c = 0;
876
+ if (n) for (let o = r - 1; o >= s && (a -= t[o].length, c++, !(a <= u)); o--) ;
877
+ else for (let o = s; o < r && (a -= t[o].length, c++, !(a <= u)); o++) ;
878
+ return { lineCount: a, removals: c };
879
+ };
880
+ var F = ({ cursor: t, options: i, style: s, output: r = process.stdout, maxItems: u = Number.POSITIVE_INFINITY, columnPadding: n = 0, rowPadding: a = 4 }) => {
881
+ const c = A(r) - n, o = L(r), l = e("dim", "..."), d = Math.max(o - a, 0), g = Math.max(Math.min(u, d), 5);
882
+ let p2 = 0;
883
+ t >= g - 3 && (p2 = Math.max(Math.min(t - g + 3, i.length - g), 0));
884
+ let f2 = g < i.length && p2 > 0, h2 = g < i.length && p2 + g < i.length;
885
+ const I = Math.min(p2 + g, i.length), m2 = [];
886
+ let y = 0;
887
+ f2 && y++, h2 && y++;
888
+ const v2 = p2 + (f2 ? 1 : 0), C2 = I - (h2 ? 1 : 0);
889
+ for (let b2 = v2; b2 < C2; b2++) {
890
+ const G2 = wrapAnsi(s(i[b2], b2 === t), c, { hard: true, trim: false }).split(`
891
+ `);
892
+ m2.push(G2), y += G2.length;
893
+ }
894
+ if (y > d) {
895
+ let b2 = 0, G2 = 0, M = y;
896
+ const N = t - v2;
897
+ let O2 = d;
898
+ const j2 = () => Pt(m2, M, 0, N, O2), k2 = () => Pt(m2, M, N + 1, m2.length, O2, true);
899
+ f2 ? ({ lineCount: M, removals: b2 } = j2(), M > O2 && (h2 || (O2 -= 1), { lineCount: M, removals: G2 } = k2())) : (h2 || (O2 -= 1), { lineCount: M, removals: G2 } = k2(), M > O2 && (O2 -= 1, { lineCount: M, removals: b2 } = j2())), b2 > 0 && (f2 = true, m2.splice(0, b2)), G2 > 0 && (h2 = true, m2.splice(m2.length - G2, G2));
900
+ }
901
+ const S = [];
902
+ f2 && S.push(l);
903
+ for (const b2 of m2) for (const G2 of b2) S.push(G2);
904
+ return h2 && S.push(l), S;
905
+ };
906
+ var le = (t) => {
907
+ const i = t.active ?? "Yes", s = t.inactive ?? "No";
908
+ return new Z({ active: i, inactive: s, signal: t.signal, input: t.input, output: t.output, initialValue: t.initialValue ?? true, render() {
909
+ const r = t.withGuide ?? h.withGuide, u = `${P2(this.state)} `, n = r ? `${e("gray", $)} ` : "", a = B(t.output, t.message, n, u), c = `${r ? `${e("gray", $)}
910
+ ` : ""}${a}
911
+ `, o = this.value ? i : s;
912
+ switch (this.state) {
913
+ case "submit": {
914
+ const l = r ? `${e("gray", $)} ` : "";
915
+ return `${c}${l}${e("dim", o)}`;
916
+ }
917
+ case "cancel": {
918
+ const l = r ? `${e("gray", $)} ` : "";
919
+ return `${c}${l}${e(["strikethrough", "dim"], o)}${r ? `
920
+ ${e("gray", $)}` : ""}`;
921
+ }
922
+ default: {
923
+ const l = r ? `${e("cyan", $)} ` : "", d = r ? e("cyan", x2) : "";
924
+ return `${c}${l}${this.value ? `${e("green", z2)} ${i}` : `${e("dim", U)} ${e("dim", i)}`}${t.vertical ? r ? `
925
+ ${e("cyan", $)} ` : `
926
+ ` : ` ${e("dim", "/")} `}${this.value ? `${e("dim", U)} ${e("dim", s)}` : `${e("green", z2)} ${s}`}
927
+ ${d}
928
+ `;
929
+ }
930
+ }
931
+ } }).prompt();
932
+ };
933
+ var ge = (t = "", i) => {
934
+ const s = i?.output ?? process.stdout, r = i?.withGuide ?? h.withGuide ? `${e("gray", x2)} ` : "";
935
+ s.write(`${r}${e("red", t)}
936
+
937
+ `);
938
+ };
939
+ var ye = (t = "", i) => {
940
+ const s = i?.output ?? process.stdout, r = i?.withGuide ?? h.withGuide ? `${e("gray", ct2)} ` : "";
941
+ s.write(`${r}${t}
942
+ `);
943
+ };
944
+ var fe = (t = "", i) => {
945
+ const s = i?.output ?? process.stdout, r = i?.withGuide ?? h.withGuide ? `${e("gray", $)}
946
+ ${e("gray", x2)} ` : "";
947
+ s.write(`${r}${t}
948
+
949
+ `);
950
+ };
951
+ var Q = (t, i) => t.split(`
952
+ `).map((s) => i(s)).join(`
953
+ `);
954
+ var we = (t) => {
955
+ const i = (r, u) => {
956
+ const n = r.label ?? String(r.value);
957
+ return u === "disabled" ? `${e("gray", Y2)} ${Q(n, (a) => e(["strikethrough", "gray"], a))}${r.hint ? ` ${e("dim", `(${r.hint ?? "disabled"})`)}` : ""}` : u === "active" ? `${e("cyan", et)} ${n}${r.hint ? ` ${e("dim", `(${r.hint})`)}` : ""}` : u === "selected" ? `${e("green", K2)} ${Q(n, (a) => e("dim", a))}${r.hint ? ` ${e("dim", `(${r.hint})`)}` : ""}` : u === "cancelled" ? `${Q(n, (a) => e(["strikethrough", "dim"], a))}` : u === "active-selected" ? `${e("green", K2)} ${n}${r.hint ? ` ${e("dim", `(${r.hint})`)}` : ""}` : u === "submitted" ? `${Q(n, (a) => e("dim", a))}` : `${e("dim", Y2)} ${Q(n, (a) => e("dim", a))}`;
958
+ }, s = t.required ?? true;
959
+ return new ut({ options: t.options, signal: t.signal, input: t.input, output: t.output, initialValues: t.initialValues, required: s, cursorAt: t.cursorAt, validate(r) {
960
+ if (s && (r === void 0 || r.length === 0)) return `Please select at least one option.
961
+ ${e("reset", e("dim", `Press ${e(["gray", "bgWhite", "inverse"], " space ")} to select, ${e("gray", e("bgWhite", e("inverse", " enter ")))} to submit`))}`;
962
+ }, render() {
963
+ const r = t.withGuide ?? h.withGuide, u = B(t.output, t.message, r ? `${ft(this.state)} ` : "", `${P2(this.state)} `), n = `${r ? `${e("gray", $)}
964
+ ` : ""}${u}
965
+ `, a = this.value ?? [], c = (o, l) => {
966
+ if (o.disabled) return i(o, "disabled");
967
+ const d = a.includes(o.value);
968
+ return l && d ? i(o, "active-selected") : d ? i(o, "selected") : i(o, l ? "active" : "inactive");
969
+ };
970
+ switch (this.state) {
971
+ case "submit": {
972
+ const o = this.options.filter(({ value: d }) => a.includes(d)).map((d) => i(d, "submitted")).join(e("dim", ", ")) || e("dim", "none"), l = B(t.output, o, r ? `${e("gray", $)} ` : "");
973
+ return `${n}${l}`;
974
+ }
975
+ case "cancel": {
976
+ const o = this.options.filter(({ value: d }) => a.includes(d)).map((d) => i(d, "cancelled")).join(e("dim", ", "));
977
+ if (o.trim() === "") return `${n}${e("gray", $)}`;
978
+ const l = B(t.output, o, r ? `${e("gray", $)} ` : "");
979
+ return `${n}${l}${r ? `
980
+ ${e("gray", $)}` : ""}`;
981
+ }
982
+ case "error": {
983
+ const o = r ? `${e("yellow", $)} ` : "", l = this.error.split(`
984
+ `).map((p2, f2) => f2 === 0 ? `${r ? `${e("yellow", x2)} ` : ""}${e("yellow", p2)}` : ` ${p2}`).join(`
985
+ `), d = n.split(`
986
+ `).length, g = l.split(`
987
+ `).length + 1;
988
+ return `${n}${o}${F({ output: t.output, options: this.options, cursor: this.cursor, maxItems: t.maxItems, columnPadding: o.length, rowPadding: d + g, style: c }).join(`
989
+ ${o}`)}
990
+ ${l}
991
+ `;
992
+ }
993
+ default: {
994
+ const o = r ? `${e("cyan", $)} ` : "", l = n.split(`
995
+ `).length, d = r ? 2 : 1;
996
+ return `${n}${o}${F({ output: t.output, options: this.options, cursor: this.cursor, maxItems: t.maxItems, columnPadding: o.length, rowPadding: l + d, style: c }).join(`
997
+ ${o}`)}
998
+ ${r ? e("cyan", x2) : ""}
999
+ `;
1000
+ }
1001
+ }
1002
+ } }).prompt();
1003
+ };
1004
+ var be = (t) => e("dim", t);
1005
+ var Se = (t, i, s) => {
1006
+ const r = { hard: true, trim: false }, u = wrapAnsi(t, i, r).split(`
1007
+ `), n = u.reduce((o, l) => Math.max(dist_default2(l), o), 0), a = u.map(s).reduce((o, l) => Math.max(dist_default2(l), o), 0), c = i - (a - n);
1008
+ return wrapAnsi(t, c, r);
1009
+ };
1010
+ var Ce = (t = "", i = "", s) => {
1011
+ const r = s?.output ?? V2.stdout, u = s?.withGuide ?? h.withGuide, n = s?.format ?? be, a = ["", ...Se(t, A(r) - 6, n).split(`
1012
+ `).map(n), ""], c = dist_default2(i), o = Math.max(a.reduce((p2, f2) => {
1013
+ const h2 = dist_default2(f2);
1014
+ return h2 > p2 ? h2 : p2;
1015
+ }, 0), c) + 2, l = a.map((p2) => `${e("gray", $)} ${p2}${" ".repeat(o - dist_default2(p2))}${e("gray", $)}`).join(`
1016
+ `), d = u ? `${e("gray", $)}
1017
+ ` : "", g = u ? Mt : ht2;
1018
+ r.write(`${d}${e("green", H)} ${e("reset", i)} ${e("gray", st.repeat(Math.max(o - c - 1, 1)) + $t)}
1019
+ ${l}
1020
+ ${e("gray", g + st.repeat(o + 2) + dt)}
1021
+ `);
1022
+ };
1023
+ var _e = (t) => e("magenta", t);
1024
+ var vt = ({ indicator: t = "dots", onCancel: i, output: s = process.stdout, cancelMessage: r, errorMessage: u, frames: n = tt ? ["\u25D2", "\u25D0", "\u25D3", "\u25D1"] : ["\u2022", "o", "O", "0"], delay: a = tt ? 80 : 120, signal: c, ...o } = {}) => {
1025
+ const l = at2();
1026
+ let d, g, p2 = false, f2 = false, h2 = "", I, m2 = performance.now();
1027
+ const y = A(s), v2 = o?.styleFrame ?? _e, C2 = (_) => {
1028
+ const A2 = _ > 1 ? u ?? h.messages.error : r ?? h.messages.cancel;
1029
+ f2 = _ === 1, p2 && (W2(A2, _), f2 && typeof i == "function" && i());
1030
+ }, S = () => C2(2), b2 = () => C2(1), G2 = () => {
1031
+ process.on("uncaughtExceptionMonitor", S), process.on("unhandledRejection", S), process.on("SIGINT", b2), process.on("SIGTERM", b2), process.on("exit", C2), c && c.addEventListener("abort", b2);
1032
+ }, M = () => {
1033
+ process.removeListener("uncaughtExceptionMonitor", S), process.removeListener("unhandledRejection", S), process.removeListener("SIGINT", b2), process.removeListener("SIGTERM", b2), process.removeListener("exit", C2), c && c.removeEventListener("abort", b2);
1034
+ }, N = () => {
1035
+ if (I === void 0) return;
1036
+ l && s.write(`
1037
+ `);
1038
+ const _ = wrapAnsi(I, y, { hard: true, trim: false }).split(`
1039
+ `);
1040
+ _.length > 1 && s.write(import_sisteransi2.cursor.up(_.length - 1)), s.write(import_sisteransi2.cursor.to(0)), s.write(import_sisteransi2.erase.down());
1041
+ }, O2 = (_) => _.replace(/\.+$/, ""), j2 = (_) => {
1042
+ const A2 = (performance.now() - _) / 1e3, L2 = Math.floor(A2 / 60), D2 = Math.floor(A2 % 60);
1043
+ return L2 > 0 ? `[${L2}m ${D2}s]` : `[${D2}s]`;
1044
+ }, k2 = o.withGuide ?? h.withGuide, rt2 = (_ = "") => {
1045
+ p2 = true, d = W({ output: s }), h2 = O2(_), m2 = performance.now(), k2 && s.write(`${e("gray", $)}
1046
+ `);
1047
+ let A2 = 0, L2 = 0;
1048
+ G2(), g = setInterval(() => {
1049
+ if (l && h2 === I) return;
1050
+ N(), I = h2;
1051
+ const D2 = v2(n[A2]);
1052
+ let Z2;
1053
+ if (l) Z2 = `${D2} ${h2}...`;
1054
+ else if (t === "timer") Z2 = `${D2} ${h2} ${j2(m2)}`;
1055
+ else {
1056
+ const Lt = ".".repeat(Math.floor(L2)).slice(0, 3);
1057
+ Z2 = `${D2} ${h2}${Lt}`;
1058
+ }
1059
+ const kt = wrapAnsi(Z2, y, { hard: true, trim: false });
1060
+ s.write(kt), A2 = A2 + 1 < n.length ? A2 + 1 : 0, L2 = L2 < 4 ? L2 + 0.125 : 0;
1061
+ }, a);
1062
+ }, W2 = (_ = "", A2 = 0, L2 = false) => {
1063
+ if (!p2) return;
1064
+ p2 = false, clearInterval(g), N();
1065
+ const D2 = A2 === 0 ? e("green", H) : A2 === 1 ? e("red", ut2) : e("red", lt2);
1066
+ h2 = _ ?? h2, L2 || (t === "timer" ? s.write(`${D2} ${h2} ${j2(m2)}
1067
+ `) : s.write(`${D2} ${h2}
1068
+ `)), M(), d();
1069
+ };
1070
+ return { start: rt2, stop: (_ = "") => W2(_, 0), message: (_ = "") => {
1071
+ h2 = O2(_ ?? h2);
1072
+ }, cancel: (_ = "") => W2(_, 1), error: (_ = "") => W2(_, 2), clear: () => W2("", 0, true), get isCancelled() {
1073
+ return f2;
1074
+ } };
1075
+ };
1076
+ var Nt = { light: w2("\u2500", "-"), heavy: w2("\u2501", "="), block: w2("\u2588", "#") };
1077
+ var it2 = (t, i) => t.includes(`
1078
+ `) ? t.split(`
1079
+ `).map((s) => i(s)).join(`
1080
+ `) : i(t);
1081
+ var Ee = (t) => {
1082
+ const i = (s, r) => {
1083
+ const u = s.label ?? String(s.value);
1084
+ switch (r) {
1085
+ case "disabled":
1086
+ return `${e("gray", U)} ${it2(u, (n) => e("gray", n))}${s.hint ? ` ${e("dim", `(${s.hint ?? "disabled"})`)}` : ""}`;
1087
+ case "selected":
1088
+ return `${it2(u, (n) => e("dim", n))}`;
1089
+ case "active":
1090
+ return `${e("green", z2)} ${u}${s.hint ? ` ${e("dim", `(${s.hint})`)}` : ""}`;
1091
+ case "cancelled":
1092
+ return `${it2(u, (n) => e(["strikethrough", "dim"], n))}`;
1093
+ default:
1094
+ return `${e("dim", U)} ${it2(u, (n) => e("dim", n))}`;
1095
+ }
1096
+ };
1097
+ return new ht({ options: t.options, signal: t.signal, input: t.input, output: t.output, initialValue: t.initialValue, render() {
1098
+ const s = t.withGuide ?? h.withGuide, r = `${P2(this.state)} `, u = `${ft(this.state)} `, n = B(t.output, t.message, u, r), a = `${s ? `${e("gray", $)}
1099
+ ` : ""}${n}
1100
+ `;
1101
+ switch (this.state) {
1102
+ case "submit": {
1103
+ const c = s ? `${e("gray", $)} ` : "", o = B(t.output, i(this.options[this.cursor], "selected"), c);
1104
+ return `${a}${o}`;
1105
+ }
1106
+ case "cancel": {
1107
+ const c = s ? `${e("gray", $)} ` : "", o = B(t.output, i(this.options[this.cursor], "cancelled"), c);
1108
+ return `${a}${o}${s ? `
1109
+ ${e("gray", $)}` : ""}`;
1110
+ }
1111
+ default: {
1112
+ const c = s ? `${e("cyan", $)} ` : "", o = s ? e("cyan", x2) : "", l = a.split(`
1113
+ `).length, d = s ? 2 : 1;
1114
+ return `${a}${c}${F({ output: t.output, cursor: this.cursor, options: this.options, maxItems: t.maxItems, columnPadding: c.length, rowPadding: l + d, style: (g, p2) => i(g, g.disabled ? "disabled" : p2 ? "active" : "inactive") }).join(`
1115
+ ${c}`)}
1116
+ ${o}
1117
+ `;
1118
+ }
83
1119
  }
84
- return flags;
1120
+ } }).prompt();
1121
+ };
1122
+ var Bt = `${e("gray", $)} `;
1123
+ var Re = (t) => new ct({ validate: t.validate, placeholder: t.placeholder, defaultValue: t.defaultValue, initialValue: t.initialValue, output: t.output, signal: t.signal, input: t.input, render() {
1124
+ const i = t?.withGuide ?? h.withGuide, s = `${`${i ? `${e("gray", $)}
1125
+ ` : ""}${P2(this.state)} `}${t.message}
1126
+ `, r = t.placeholder ? e("inverse", t.placeholder[0]) + e("dim", t.placeholder.slice(1)) : e(["inverse", "hidden"], "_"), u = this.userInput ? this.userInputWithCursor : r, n = this.value ?? "";
1127
+ switch (this.state) {
1128
+ case "error": {
1129
+ const a = this.error ? ` ${e("yellow", this.error)}` : "", c = i ? `${e("yellow", $)} ` : "", o = i ? e("yellow", x2) : "";
1130
+ return `${s.trim()}
1131
+ ${c}${u}
1132
+ ${o}${a}
1133
+ `;
1134
+ }
1135
+ case "submit": {
1136
+ const a = n ? ` ${e("dim", n)}` : "", c = i ? e("gray", $) : "";
1137
+ return `${s}${c}${a}`;
1138
+ }
1139
+ case "cancel": {
1140
+ const a = n ? ` ${e(["strikethrough", "dim"], n)}` : "", c = i ? e("gray", $) : "";
1141
+ return `${s}${c}${a}${n.trim() ? `
1142
+ ${c}` : ""}`;
1143
+ }
1144
+ default: {
1145
+ const a = i ? `${e("cyan", $)} ` : "", c = i ? e("cyan", x2) : "";
1146
+ return `${s}${a}${u}
1147
+ ${c}
1148
+ `;
1149
+ }
1150
+ }
1151
+ } }).prompt();
1152
+
1153
+ // src/cli/configure.ts
1154
+ var import_picocolors2 = __toESM(require_picocolors(), 1);
1155
+ import { loadConfig } from "toiljs/compiler";
1156
+
1157
+ // src/cli/features.ts
1158
+ var PREPROCESSORS = ["css", "sass", "less", "stylus"];
1159
+ var STYLE_EXT = {
1160
+ css: "css",
1161
+ sass: "scss",
1162
+ less: "less",
1163
+ stylus: "styl"
1164
+ };
1165
+ var PREPROCESSOR_PKG = {
1166
+ css: null,
1167
+ sass: "sass",
1168
+ less: "less",
1169
+ stylus: "stylus"
1170
+ };
1171
+ var TAILWIND_PKGS = ["tailwindcss", "@tailwindcss/vite"];
1172
+ var PKG_VERSION = {
1173
+ sass: "^1.83.0",
1174
+ less: "^4.2.1",
1175
+ stylus: "^0.64.0",
1176
+ tailwindcss: "^4.0.0",
1177
+ "@tailwindcss/vite": "^4.0.0"
1178
+ };
1179
+ var TAILWIND_ENTRY = "styles/tailwind.css";
1180
+ var TAILWIND_CSS = `@import 'tailwindcss';
1181
+ `;
1182
+ function styleEntry(p2) {
1183
+ return `styles/main.${STYLE_EXT[p2]}`;
1184
+ }
1185
+ function preprocessorForExt(ext) {
1186
+ const e2 = ext.replace(/^\./, "");
1187
+ if (e2 === "sass") return "sass";
1188
+ return PREPROCESSORS.find((p2) => STYLE_EXT[p2] === e2) ?? null;
1189
+ }
1190
+ function requiredPackages(f2) {
1191
+ const pkgs = [];
1192
+ const pp = PREPROCESSOR_PKG[f2.preprocessor];
1193
+ if (pp) pkgs.push(pp);
1194
+ if (f2.tailwind) pkgs.push(...TAILWIND_PKGS);
1195
+ return pkgs;
1196
+ }
1197
+ function packageDiff(from, to) {
1198
+ const want = new Set(requiredPackages(to));
1199
+ const had = new Set(requiredPackages(from));
1200
+ return {
1201
+ add: [...want].filter((p2) => !had.has(p2)),
1202
+ remove: [...had].filter((p2) => !want.has(p2))
1203
+ };
1204
+ }
1205
+ function styleImportLines(f2) {
1206
+ const lines = [];
1207
+ if (f2.tailwind) lines.push(`import './${TAILWIND_ENTRY}';`);
1208
+ lines.push(`import './${styleEntry(f2.preprocessor)}';`);
1209
+ return lines;
1210
+ }
1211
+ function setStyleImports(source, f2) {
1212
+ const stripped = source.replace(
1213
+ /^[ \t]*import\s+['"]\.\/styles\/[^'"]+['"];?[ \t]*\r?\n/gm,
1214
+ ""
1215
+ );
1216
+ const block = styleImportLines(f2).join("\n") + "\n";
1217
+ const lines = stripped.split("\n");
1218
+ const routesIdx = lines.findIndex((l) => /from\s+['"]toiljs\/routes['"]/.test(l));
1219
+ let insertAt;
1220
+ if (routesIdx !== -1) {
1221
+ insertAt = routesIdx + 1;
1222
+ } else {
1223
+ const lastImport = lines.reduce((acc, l, i) => /^\s*import\s/.test(l) ? i : acc, -1);
1224
+ insertAt = lastImport + 1;
1225
+ }
1226
+ const head = lines.slice(0, insertAt).join("\n");
1227
+ const tail = lines.slice(insertAt).join("\n");
1228
+ return `${head}
1229
+
1230
+ ${block}
1231
+ ${tail}`.replace(/\n{3,}/g, "\n\n");
1232
+ }
1233
+ function defaultConfigSource(images) {
1234
+ return `import { defineConfig } from 'toiljs/compiler';
1235
+
1236
+ export default defineConfig({
1237
+ client: {
1238
+ // Optimize images at build time (resize/compress imported images).
1239
+ images: ${String(images)},
1240
+ },
1241
+ });
1242
+ `;
1243
+ }
1244
+ function setConfigImages(source, enabled) {
1245
+ const value = String(enabled);
1246
+ if (/\bimages\s*:\s*(?:true|false)/.test(source)) {
1247
+ return source.replace(/\bimages\s*:\s*(?:true|false)/, `images: ${value}`);
1248
+ }
1249
+ if (/\bclient\s*:\s*\{/.test(source)) {
1250
+ return source.replace(/\bclient\s*:\s*\{/, `client: {
1251
+ images: ${value},`);
1252
+ }
1253
+ if (/defineConfig\(\s*\{/.test(source)) {
1254
+ return source.replace(
1255
+ /defineConfig\(\s*\{/,
1256
+ `defineConfig({
1257
+ client: { images: ${value} },`
1258
+ );
1259
+ }
1260
+ return null;
1261
+ }
1262
+ function detectPreprocessor(deps) {
1263
+ if ("sass" in deps) return "sass";
1264
+ if ("less" in deps) return "less";
1265
+ if ("stylus" in deps) return "stylus";
1266
+ return "css";
1267
+ }
1268
+ function detectTailwind(deps) {
1269
+ return "@tailwindcss/vite" in deps || "tailwindcss" in deps;
1270
+ }
1271
+
1272
+ // src/cli/proc.ts
1273
+ import { spawn } from "node:child_process";
1274
+ function run(cmd, args, cwd) {
1275
+ return new Promise((resolve, reject) => {
1276
+ const onWindows = process.platform === "win32";
1277
+ const child = onWindows ? spawn([cmd, ...args].join(" "), { cwd, stdio: "ignore", shell: true }) : spawn(cmd, args, { cwd, stdio: "ignore" });
1278
+ child.on("error", reject);
1279
+ child.on(
1280
+ "close",
1281
+ (code) => code === 0 ? resolve() : reject(new Error(`${cmd} exited with code ${String(code)}`))
1282
+ );
1283
+ });
1284
+ }
1285
+ function capture(cmd, args, cwd) {
1286
+ return new Promise((resolve, reject) => {
1287
+ const onWindows = process.platform === "win32";
1288
+ const child = onWindows ? spawn([cmd, ...args].join(" "), { cwd, shell: true }) : spawn(cmd, args, { cwd });
1289
+ let stdout = "";
1290
+ let stderr = "";
1291
+ child.stdout?.on("data", (d) => {
1292
+ stdout += d.toString();
1293
+ });
1294
+ child.stderr?.on("data", (d) => {
1295
+ stderr += d.toString();
1296
+ });
1297
+ child.on("error", reject);
1298
+ child.on("close", (code) => {
1299
+ resolve({ stdout, stderr, code: code ?? 1 });
1300
+ });
1301
+ });
1302
+ }
1303
+
1304
+ // src/cli/ui.ts
1305
+ var import_picocolors = __toESM(require_picocolors(), 1);
1306
+ import fs from "node:fs";
1307
+ import path from "node:path";
1308
+ import { fileURLToPath } from "node:url";
1309
+ var PRIMARY = [37, 99, 255];
1310
+ var SECONDARY = [124, 58, 237];
1311
+ var ACCENT = [34, 227, 171];
1312
+ var GRADIENT = [PRIMARY, SECONDARY, ACCENT];
1313
+ var ART = [
1314
+ "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557 ",
1315
+ "\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551 ",
1316
+ " \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 ",
1317
+ " \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 ",
1318
+ " \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557",
1319
+ " \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D"
1320
+ ];
1321
+ var dim = import_picocolors.default.dim;
1322
+ var bold = import_picocolors.default.bold;
1323
+ function colorEnabled() {
1324
+ if (process.env.NO_COLOR) return false;
1325
+ if (process.env.FORCE_COLOR) return true;
1326
+ return process.stdout.isTTY;
1327
+ }
1328
+ function rgb(color, s) {
1329
+ return colorEnabled() ? `\x1B[38;2;${color[0]};${color[1]};${color[2]}m${s}\x1B[39m` : s;
1330
+ }
1331
+ function brand(s) {
1332
+ return rgb(PRIMARY, s);
1333
+ }
1334
+ var accent = brand;
1335
+ function success(s) {
1336
+ return rgb(ACCENT, s);
1337
+ }
1338
+ var danger = import_picocolors.default.red;
1339
+ var warn = import_picocolors.default.yellow;
1340
+ function lerp(a, b2, t) {
1341
+ return Math.round(a + (b2 - a) * t);
1342
+ }
1343
+ function gradientAt(t) {
1344
+ const segments = GRADIENT.length - 1;
1345
+ const scaled = t * segments;
1346
+ const i = Math.min(Math.floor(scaled), segments - 1);
1347
+ const a = GRADIENT[i];
1348
+ const b2 = GRADIENT[i + 1];
1349
+ const localT = scaled - i;
1350
+ return [lerp(a[0], b2[0], localT), lerp(a[1], b2[1], localT), lerp(a[2], b2[2], localT)];
1351
+ }
1352
+ function gradientLine(line) {
1353
+ const n = line.length;
1354
+ let out = "";
1355
+ for (let i = 0; i < n; i++) {
1356
+ const [r, g, b2] = gradientAt(n > 1 ? i / (n - 1) : 0);
1357
+ out += `\x1B[38;2;${r};${g};${b2}m${line[i]}`;
1358
+ }
1359
+ return out + "\x1B[39m";
1360
+ }
1361
+ function version() {
1362
+ try {
1363
+ const pkgPath = path.resolve(
1364
+ path.dirname(fileURLToPath(import.meta.url)),
1365
+ "..",
1366
+ "..",
1367
+ "package.json"
1368
+ );
1369
+ const raw = fs.readFileSync(pkgPath, "utf8");
1370
+ const match = /"version"\s*:\s*"([^"]+)"/.exec(raw);
1371
+ if (match && match[1]) return match[1];
1372
+ } catch {
1373
+ }
1374
+ return "0.0.0";
1375
+ }
1376
+ function banner() {
1377
+ const lines = colorEnabled() ? ART.map(gradientLine) : ART.slice();
1378
+ const tagline = ` the most performant ${brand("react")} framework`;
1379
+ const ver = `${dim(" v")}${brand(version())}`;
1380
+ process.stdout.write("\n" + lines.join("\n") + "\n\n" + tagline + " " + ver + "\n\n");
1381
+ }
1382
+
1383
+ // src/cli/configure.ts
1384
+ var CONFIG_FILES = [
1385
+ "toil.config.ts",
1386
+ "toil.config.mts",
1387
+ "toil.config.js",
1388
+ "toil.config.mjs",
1389
+ "toiljs.config.ts",
1390
+ "toiljs.config.mts",
1391
+ "toiljs.config.js",
1392
+ "toiljs.config.mjs"
1393
+ ];
1394
+ async function readConfigFile(root) {
1395
+ for (const name of CONFIG_FILES) {
1396
+ const p2 = path2.join(root, name);
1397
+ try {
1398
+ return { path: p2, source: await fs2.readFile(p2, "utf8") };
1399
+ } catch {
1400
+ }
1401
+ }
1402
+ return null;
1403
+ }
1404
+ async function writeImagesFlag(root, enabled) {
1405
+ const existing = await readConfigFile(root);
1406
+ if (!existing) {
1407
+ await fs2.writeFile(path2.join(root, "toil.config.ts"), defaultConfigSource(enabled), "utf8");
1408
+ return true;
1409
+ }
1410
+ const next = setConfigImages(existing.source, enabled);
1411
+ if (next === null) return false;
1412
+ await fs2.writeFile(existing.path, next, "utf8");
1413
+ return true;
1414
+ }
1415
+ async function resolveImages(root) {
1416
+ try {
1417
+ return (await loadConfig({ root })).images;
1418
+ } catch {
1419
+ return true;
1420
+ }
1421
+ }
1422
+ async function resolveClientDir(root) {
1423
+ try {
1424
+ const cfg = await loadConfig({ root });
1425
+ return cfg.clientAbsDir;
1426
+ } catch {
1427
+ return path2.join(root, "client");
1428
+ }
1429
+ }
1430
+ var PREPROCESSOR_LABEL = {
1431
+ css: "Plain CSS",
1432
+ sass: "Sass (SCSS)",
1433
+ less: "Less",
1434
+ stylus: "Stylus"
1435
+ };
1436
+ function bail(value) {
1437
+ if (R(value)) {
1438
+ ge("Configuration cancelled.");
1439
+ process.exit(0);
1440
+ }
1441
+ }
1442
+ async function detectStylesheet(clientDir) {
1443
+ for (const p2 of PREPROCESSORS) {
1444
+ try {
1445
+ await fs2.access(path2.join(clientDir, styleEntry(p2)));
1446
+ return p2;
1447
+ } catch {
1448
+ }
1449
+ }
1450
+ try {
1451
+ await fs2.access(path2.join(clientDir, "styles/main.sass"));
1452
+ return preprocessorForExt("sass");
1453
+ } catch {
1454
+ return null;
1455
+ }
1456
+ }
1457
+ async function findMainStylesheet(clientDir) {
1458
+ for (const ext of ["css", "scss", "sass", "less", "styl"]) {
1459
+ const p2 = path2.join(clientDir, "styles", `main.${ext}`);
1460
+ try {
1461
+ await fs2.access(p2);
1462
+ return p2;
1463
+ } catch {
1464
+ }
1465
+ }
1466
+ return null;
1467
+ }
1468
+ async function detectPackageManager(root) {
1469
+ const lock = [
1470
+ ["pnpm-lock.yaml", "pnpm"],
1471
+ ["yarn.lock", "yarn"],
1472
+ ["bun.lockb", "bun"]
1473
+ ];
1474
+ for (const [file, pm] of lock) {
1475
+ try {
1476
+ await fs2.access(path2.join(root, file));
1477
+ return pm;
1478
+ } catch {
1479
+ }
1480
+ }
1481
+ return "npm";
1482
+ }
1483
+ async function applyStyleFiles(clientDir, from, to) {
1484
+ if (from.preprocessor !== to.preprocessor) {
1485
+ const newPath = path2.join(clientDir, styleEntry(to.preprocessor));
1486
+ await fs2.mkdir(path2.dirname(newPath), { recursive: true });
1487
+ const existing = await findMainStylesheet(clientDir);
1488
+ if (existing && path2.resolve(existing) !== path2.resolve(newPath)) {
1489
+ await fs2.rename(existing, newPath);
1490
+ } else if (!existing) {
1491
+ await fs2.writeFile(newPath, "", "utf8");
1492
+ }
1493
+ }
1494
+ const tailwindPath = path2.join(clientDir, TAILWIND_ENTRY);
1495
+ if (to.tailwind && !from.tailwind) {
1496
+ await fs2.mkdir(path2.dirname(tailwindPath), { recursive: true });
1497
+ await fs2.writeFile(tailwindPath, TAILWIND_CSS, "utf8");
1498
+ } else if (!to.tailwind && from.tailwind) {
1499
+ await fs2.rm(tailwindPath, { force: true });
1500
+ }
1501
+ for (const entry of ["toil.tsx", "toil.jsx"]) {
1502
+ const entryPath = path2.join(clientDir, entry);
1503
+ try {
1504
+ const source = await fs2.readFile(entryPath, "utf8");
1505
+ await fs2.writeFile(entryPath, setStyleImports(source, to), "utf8");
1506
+ return;
1507
+ } catch {
1508
+ }
1509
+ }
1510
+ }
1511
+ async function applyConfigure(clientDir, pkgPath, pkg, from, to) {
1512
+ await applyStyleFiles(clientDir, from, to);
1513
+ await applyPackages(pkgPath, pkg, from, to);
1514
+ }
1515
+ async function applyPackages(pkgPath, pkg, from, to) {
1516
+ const { add, remove } = packageDiff(from, to);
1517
+ const dev2 = { ...pkg.devDependencies };
1518
+ const deps = { ...pkg.dependencies };
1519
+ for (const name of add) dev2[name] = PKG_VERSION[name] ?? "latest";
1520
+ for (const name of remove) {
1521
+ delete dev2[name];
1522
+ delete deps[name];
1523
+ }
1524
+ const sortedDev = Object.fromEntries(
1525
+ Object.entries(dev2).sort(([a], [b2]) => a.localeCompare(b2))
1526
+ );
1527
+ const next = { ...pkg, devDependencies: sortedDev };
1528
+ if (Object.keys(deps).length) next.dependencies = deps;
1529
+ else delete next.dependencies;
1530
+ await fs2.writeFile(pkgPath, JSON.stringify(next, null, 4) + "\n", "utf8");
1531
+ }
1532
+ function describe(from, to) {
1533
+ const lines = [];
1534
+ if (from.preprocessor !== to.preprocessor) {
1535
+ lines.push(
1536
+ `preprocessor: ${PREPROCESSOR_LABEL[from.preprocessor]} \u2192 ${PREPROCESSOR_LABEL[to.preprocessor]}`
1537
+ );
1538
+ }
1539
+ if (from.tailwind !== to.tailwind) {
1540
+ lines.push(`Tailwind: ${from.tailwind ? "on" : "off"} \u2192 ${to.tailwind ? "on" : "off"}`);
1541
+ }
1542
+ const { add, remove } = packageDiff(from, to);
1543
+ if (add.length) lines.push(`+ ${add.join(", ")}`);
1544
+ if (remove.length) lines.push(`- ${remove.join(", ")}`);
1545
+ return lines.map((l) => dim(" ") + l).join("\n");
1546
+ }
1547
+ async function runConfigure(opts) {
1548
+ ye(accent(" toiljs configure "));
1549
+ const root = path2.resolve(opts.root ?? opts.cwd);
1550
+ const pkgPath = path2.join(root, "package.json");
1551
+ let pkg;
1552
+ try {
1553
+ pkg = JSON.parse(await fs2.readFile(pkgPath, "utf8"));
1554
+ } catch {
1555
+ ge(`No package.json in ${import_picocolors2.default.cyan(root)}, run this inside a toiljs project.`);
1556
+ process.exit(1);
1557
+ }
1558
+ const clientAbsDir = await resolveClientDir(root);
1559
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
1560
+ const current = {
1561
+ preprocessor: await detectStylesheet(clientAbsDir) ?? detectPreprocessor(deps),
1562
+ tailwind: detectTailwind(deps)
1563
+ };
1564
+ const currentImages = await resolveImages(root);
1565
+ const nonInteractive = opts.preprocessor !== void 0 || opts.tailwind !== void 0 || opts.images !== void 0;
1566
+ let target;
1567
+ let targetImages;
1568
+ if (nonInteractive) {
1569
+ target = {
1570
+ preprocessor: opts.preprocessor ?? current.preprocessor,
1571
+ tailwind: opts.tailwind ?? current.tailwind
1572
+ };
1573
+ targetImages = opts.images ?? currentImages;
1574
+ } else {
1575
+ const ppChoice = await Ee({
1576
+ message: "CSS preprocessor",
1577
+ options: PREPROCESSORS.map((value) => ({ value, label: PREPROCESSOR_LABEL[value] })),
1578
+ initialValue: current.preprocessor
1579
+ });
1580
+ bail(ppChoice);
1581
+ const twChoice = await le({
1582
+ message: "Use Tailwind CSS?",
1583
+ initialValue: current.tailwind
1584
+ });
1585
+ bail(twChoice);
1586
+ const imChoice = await le({
1587
+ message: "Optimize images at build time?",
1588
+ initialValue: currentImages
1589
+ });
1590
+ bail(imChoice);
1591
+ target = { preprocessor: ppChoice, tailwind: twChoice };
1592
+ targetImages = imChoice;
1593
+ }
1594
+ const styleChanged = target.preprocessor !== current.preprocessor || target.tailwind !== current.tailwind;
1595
+ const imagesChanged = targetImages !== currentImages;
1596
+ if (!styleChanged && !imagesChanged) {
1597
+ fe("No changes, your setup is already up to date.");
1598
+ return;
1599
+ }
1600
+ const s = vt();
1601
+ s.start("Updating project files");
1602
+ if (styleChanged) await applyConfigure(clientAbsDir, pkgPath, pkg, current, target);
1603
+ let imagesWarning = "";
1604
+ if (imagesChanged && !await writeImagesFlag(root, targetImages)) {
1605
+ imagesWarning = import_picocolors2.default.yellow(
1606
+ " Could not edit toil.config automatically, set `client.images` by hand."
1607
+ );
1608
+ }
1609
+ s.stop("Updated project files");
1610
+ if (styleChanged) {
1611
+ const pm = await detectPackageManager(root);
1612
+ if (opts.install === false) {
1613
+ Ce(`${import_picocolors2.default.cyan(`${pm} install`)} to sync the dependency changes.`, "Next step");
1614
+ } else {
1615
+ const i = vt();
1616
+ i.start(`Syncing dependencies with ${pm}`);
1617
+ try {
1618
+ await run(pm, ["install"], root);
1619
+ i.stop("Dependencies synced");
1620
+ } catch {
1621
+ i.stop(import_picocolors2.default.yellow(`Could not run \`${pm} install\`, run it yourself to finish`));
1622
+ }
1623
+ }
1624
+ }
1625
+ const summary = [
1626
+ styleChanged ? describe(current, target) : "",
1627
+ imagesChanged ? dim(" ") + `image optimization: ${currentImages ? "on" : "off"} \u2192 ${targetImages ? "on" : "off"}` : "",
1628
+ imagesWarning
1629
+ ].filter(Boolean).join("\n");
1630
+ Ce(summary, "Updated");
1631
+ fe(`Reconfigured, restart \`${accent("toiljs dev")}\` to pick up the changes.`);
1632
+ }
1633
+
1634
+ // src/cli/create.ts
1635
+ import fs3 from "node:fs/promises";
1636
+ import path4 from "node:path";
1637
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
1638
+ var import_picocolors3 = __toESM(require_picocolors(), 1);
1639
+ import { AI_HELPER_IDS, AI_HELPERS, aiHelperFiles, TOIL_DOCS, TOIL_ENV_DTS } from "toiljs/compiler";
1640
+
1641
+ // src/cli/validate.ts
1642
+ import path3 from "node:path";
1643
+ var PACKAGE_MANAGERS = ["npm", "pnpm", "yarn", "bun"];
1644
+ function isValidName(name) {
1645
+ if (!name.trim()) return "Please enter a project name.";
1646
+ if (!/^[a-z0-9._@/-]+$/i.test(name)) return "Use letters, numbers, dashes, dots or slashes.";
1647
+ return true;
1648
+ }
1649
+ function resolveProjectDir(cwd, name) {
1650
+ const target = path3.resolve(cwd, name);
1651
+ const rel = path3.relative(cwd, target);
1652
+ if (rel.startsWith("..") || path3.isAbsolute(rel)) return null;
1653
+ return target;
1654
+ }
1655
+ function isPackageManager(pm) {
1656
+ return PACKAGE_MANAGERS.includes(pm);
1657
+ }
1658
+
1659
+ // src/cli/create.ts
1660
+ var PREPROCESSOR_LABEL2 = {
1661
+ css: "Plain CSS",
1662
+ sass: "Sass (SCSS)",
1663
+ less: "Less",
1664
+ stylus: "Stylus"
1665
+ };
1666
+ var DEFAULT_STYLE_CONTENT = ":root {\n color-scheme: dark;\n}\n\nbody {\n margin: 0;\n background: #080d11;\n color: #f5f6fa;\n font-family: system-ui, -apple-system, sans-serif;\n line-height: 1.6;\n}\n\na {\n color: #2563ff;\n text-decoration: none;\n}\n\na:hover {\n color: #22e3ab;\n}\n\ncode {\n background: #11161f;\n color: #22e3ab;\n padding: 0.1rem 0.4rem;\n border-radius: 4px;\n font-size: 0.9em;\n}\n\nh1 {\n background: linear-gradient(90deg, #2563ff, #7c3aed, #22e3ab);\n -webkit-background-clip: text;\n background-clip: text;\n color: transparent;\n}\n";
1667
+ function bail2(value) {
1668
+ if (R(value)) {
1669
+ ge("Scaffolding cancelled.");
1670
+ process.exit(0);
1671
+ }
1672
+ }
1673
+ async function isEmptyDir(dir) {
1674
+ try {
1675
+ const entries = await fs3.readdir(dir);
1676
+ return entries.length === 0;
1677
+ } catch {
1678
+ return true;
1679
+ }
1680
+ }
1681
+ function scaffold(name, template, features, aiTools, images) {
1682
+ const toilVersion = version();
1683
+ const devDependencies = {
1684
+ "@types/react": "^19.2.15",
1685
+ "@types/react-dom": "^19.2.3",
1686
+ eslint: "^10.2.0",
1687
+ prettier: "^3.8.1",
1688
+ toilscript: "^0.1.2",
1689
+ typescript: "^6.0.3"
1690
+ };
1691
+ for (const dep of requiredPackages(features).sort()) {
1692
+ devDependencies[dep] = PKG_VERSION[dep] ?? "latest";
1693
+ }
1694
+ const pkg = {
1695
+ name: path4.basename(name),
1696
+ private: true,
1697
+ type: "module",
1698
+ scripts: {
1699
+ dev: "toiljs dev",
1700
+ build: "toiljs build && toilscript --target release",
1701
+ "build:client": "toiljs build",
1702
+ "build:server": "toilscript --target release",
1703
+ lint: "eslint client",
1704
+ typecheck: "tsc --noEmit",
1705
+ format: 'prettier --write "client/**/*.{ts,tsx,css,scss,less}" "client/public/**/*.html"'
1706
+ },
1707
+ dependencies: {
1708
+ toiljs: `^${toilVersion}`,
1709
+ react: "^19.2.6",
1710
+ "react-dom": "^19.2.6"
1711
+ },
1712
+ devDependencies
1713
+ };
1714
+ const files = {
1715
+ "package.json": JSON.stringify(pkg, null, 4) + "\n",
1716
+ "toil.config.ts": `import { defineConfig } from 'toiljs/compiler';
1717
+
1718
+ export default defineConfig({
1719
+ client: {
1720
+ // Optimize images at build time (resize/compress imported images).
1721
+ images: ${String(images)},
1722
+ },
1723
+ });
1724
+ `,
1725
+ "tsconfig.json": '{\n "extends": "toiljs/tsconfig",\n "include": ["client", "toil-env.d.ts", "toil-routes.d.ts"]\n}\n',
1726
+ "eslint.config.js": "import toiljs from 'toiljs/eslint';\n\nexport default toiljs;\n",
1727
+ ".prettierrc": '"toiljs/prettier"\n',
1728
+ ".gitignore": "node_modules\nbuild\n.toil\ntoil-env.d.ts\ntoil-routes.d.ts\n",
1729
+ // Use the project's pinned TypeScript (node_modules) instead of VS Code's bundled version.
1730
+ ".vscode/settings.json": JSON.stringify({ "typescript.tsdk": "node_modules/typescript/lib" }, null, 4) + "\n",
1731
+ "toil-env.d.ts": TOIL_ENV_DTS,
1732
+ // Stub typed-routes augmentation (RoutePath = string until the first dev/build regenerates it).
1733
+ "toil-routes.d.ts": "// AUTO-GENERATED by toil, do not edit.\nexport {};\n",
1734
+ "toilconfig.json": JSON.stringify(
1735
+ {
1736
+ entries: ["server/main.ts"],
1737
+ targets: {
1738
+ release: {
1739
+ outFile: "build/server/release.wasm",
1740
+ textFile: "build/server/release.wat"
1741
+ }
1742
+ },
1743
+ options: {
1744
+ sourceMap: false,
1745
+ optimizeLevel: 3,
1746
+ shrinkLevel: 1,
1747
+ converge: true,
1748
+ noAssert: false,
1749
+ enable: [
1750
+ "sign-extension",
1751
+ "mutable-globals",
1752
+ "nontrapping-f2i",
1753
+ "bulk-memory",
1754
+ "simd",
1755
+ "reference-types",
1756
+ "multi-value"
1757
+ ],
1758
+ runtime: "stub",
1759
+ memoryBase: 0,
1760
+ initialMemory: 1,
1761
+ debug: false,
1762
+ trapMode: "allow"
1763
+ }
1764
+ },
1765
+ null,
1766
+ 4
1767
+ ) + "\n",
1768
+ "server/tsconfig.json": JSON.stringify(
1769
+ {
1770
+ extends: "toilscript/std/assembly.json",
1771
+ include: ["./**/*.ts"]
1772
+ },
1773
+ null,
1774
+ 4
1775
+ ) + "\n",
1776
+ "server/index.ts": "export function add(a: i32, b: i32): i32 {\n return a + b;\n}\n",
1777
+ "server/main.ts": "import { add } from './index';\n\n@main\nfunction run(): i32 {\n return add(40, 2);\n}\n",
1778
+ "README.md": [
1779
+ "# " + path4.basename(name),
1780
+ "",
1781
+ "A [toiljs](https://toil.org) app.",
1782
+ "",
1783
+ "## Develop",
1784
+ "",
1785
+ " npm install",
1786
+ " npm run dev",
1787
+ "",
1788
+ "## Build",
1789
+ "",
1790
+ " npm run build",
1791
+ ""
1792
+ ].join("\n")
1793
+ };
1794
+ if (template === "minimal") Object.assign(files, minimalClient(name, features));
1795
+ Object.assign(files, aiHelperFiles(aiTools));
1796
+ for (const [docName, content] of Object.entries(TOIL_DOCS)) {
1797
+ files[`.toil/docs/${docName}`] = content;
1798
+ }
1799
+ return files;
1800
+ }
1801
+ function minimalClient(name, features) {
1802
+ const files = {
1803
+ "client/public/index.html": `<!doctype html>
1804
+ <html lang="en">
1805
+ <head>
1806
+ <meta charset="utf-8" />
1807
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
1808
+ <meta name="theme-color" content="#080D11" />
1809
+ <meta name="description" content="" />
1810
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
1811
+ <link rel="manifest" href="/manifest.webmanifest" />
1812
+ <title>${path4.basename(name)}</title>
1813
+ </head>
1814
+ <body>
1815
+ <div id="root"></div>
1816
+ </body>
1817
+ </html>
1818
+ `,
1819
+ "client/public/favicon.svg": '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">\n <defs>\n <linearGradient id="g" x1="0" y1="0" x2="1" y2="1">\n <stop offset="0" stop-color="#2563FF" />\n <stop offset="0.5" stop-color="#7C3AED" />\n <stop offset="1" stop-color="#22E3AB" />\n </linearGradient>\n </defs>\n <rect width="32" height="32" rx="7" fill="#080D11" />\n <path d="M9 10h14v3.2h-5.4V24h-3.2V13.2H9z" fill="url(#g)" />\n</svg>\n',
1820
+ "client/public/robots.txt": "User-agent: *\nAllow: /\n",
1821
+ "client/public/manifest.webmanifest": JSON.stringify(
1822
+ {
1823
+ name: path4.basename(name),
1824
+ short_name: path4.basename(name),
1825
+ start_url: "/",
1826
+ display: "standalone",
1827
+ background_color: "#080D11",
1828
+ theme_color: "#080D11",
1829
+ icons: [{ src: "/favicon.svg", type: "image/svg+xml", sizes: "any" }]
1830
+ },
1831
+ null,
1832
+ 4
1833
+ ) + "\n",
1834
+ "client/public/images/.gitkeep": "# Place images and other static assets here; served at /images/*.\n",
1835
+ "client/toil.tsx": "import { routes, layout, notFound, globalError, slots } from 'toiljs/routes';\n\n" + styleImportLines(features).join("\n") + "\n\nToil.mount(routes, layout, notFound, globalError, slots);\n",
1836
+ [`client/${styleEntry(features.preprocessor)}`]: DEFAULT_STYLE_CONTENT,
1837
+ "client/components/.gitkeep": "# Place shared React components here.\n",
1838
+ "client/layout.tsx": `import { type ReactNode } from 'react';
1839
+
1840
+ export default function Layout({ children }: { children?: ReactNode }) {
1841
+ return (
1842
+ <div style={{ maxWidth: 680, margin: '0 auto', padding: '3rem 1.5rem' }}>
1843
+ <header
1844
+ style={{
1845
+ display: 'flex',
1846
+ gap: '1rem',
1847
+ alignItems: 'baseline',
1848
+ borderBottom: '1px solid #1b2330',
1849
+ paddingBottom: '0.75rem',
1850
+ marginBottom: '1.5rem',
1851
+ }}>
1852
+ <strong style={{ color: '#2563FF', fontSize: '1.1rem' }}>${path4.basename(name)}</strong>
1853
+ <nav style={{ display: 'flex', gap: '1rem' }}>
1854
+ <Toil.Link href="/">home</Toil.Link>
1855
+ </nav>
1856
+ </header>
1857
+ {children}
1858
+ </div>
1859
+ );
1860
+ }
1861
+ `,
1862
+ "client/routes/index.tsx": "export default function Home() {\n return (\n <main>\n <h1>Welcome to toiljs</h1>\n <p>File-based routing, bundled by Vite, zero config.</p>\n </main>\n );\n}\n"
1863
+ };
1864
+ if (features.tailwind) files[`client/${TAILWIND_ENTRY}`] = TAILWIND_CSS;
1865
+ return files;
1866
+ }
1867
+ function appClientDir() {
1868
+ return path4.resolve(
1869
+ path4.dirname(fileURLToPath2(import.meta.url)),
1870
+ "..",
1871
+ "..",
1872
+ "examples",
1873
+ "basic",
1874
+ "client"
1875
+ );
1876
+ }
1877
+ async function applyStyling(clientDir, features) {
1878
+ if (features.preprocessor === "css" && !features.tailwind) return;
1879
+ const entry = styleEntry(features.preprocessor);
1880
+ if (entry !== "styles/main.css") {
1881
+ await fs3.rename(path4.join(clientDir, "styles", "main.css"), path4.join(clientDir, entry));
1882
+ }
1883
+ if (features.tailwind) {
1884
+ await fs3.writeFile(path4.join(clientDir, TAILWIND_ENTRY), TAILWIND_CSS, "utf8");
1885
+ }
1886
+ const toilPath = path4.join(clientDir, "toil.tsx");
1887
+ await fs3.writeFile(
1888
+ toilPath,
1889
+ setStyleImports(await fs3.readFile(toilPath, "utf8"), features),
1890
+ "utf8"
1891
+ );
1892
+ }
1893
+ async function writeFiles(dir, files) {
1894
+ for (const [rel, contents] of Object.entries(files)) {
1895
+ const full = path4.join(dir, rel);
1896
+ await fs3.mkdir(path4.dirname(full), { recursive: true });
1897
+ await fs3.writeFile(full, contents, "utf8");
1898
+ }
1899
+ }
1900
+ async function runCreate(opts) {
1901
+ ye(accent(" toiljs create "));
1902
+ let name = opts.name;
1903
+ if (!name) {
1904
+ if (opts.yes) {
1905
+ name = "my-toil-app";
1906
+ } else {
1907
+ const answer = await Re({
1908
+ message: "Project name",
1909
+ placeholder: "my-toil-app",
1910
+ defaultValue: "my-toil-app",
1911
+ validate: (v2) => {
1912
+ const result = isValidName(v2 || "my-toil-app");
1913
+ return result === true ? void 0 : result;
1914
+ }
1915
+ });
1916
+ bail2(answer);
1917
+ name = answer.trim() || "my-toil-app";
1918
+ }
1919
+ }
1920
+ const valid = isValidName(name);
1921
+ if (valid !== true) {
1922
+ ge(valid);
1923
+ process.exit(1);
1924
+ }
1925
+ const targetDir = resolveProjectDir(opts.cwd, name);
1926
+ if (targetDir === null) {
1927
+ ge('Project name must stay inside the current directory (no "..", no absolute paths).');
1928
+ process.exit(1);
1929
+ }
1930
+ const rel = path4.relative(opts.cwd, targetDir) || ".";
1931
+ if (!await isEmptyDir(targetDir)) {
1932
+ if (opts.yes) {
1933
+ ge(`Directory ${import_picocolors3.default.cyan(rel)} is not empty.`);
1934
+ process.exit(1);
1935
+ }
1936
+ const proceed = await le({
1937
+ message: `Directory ${import_picocolors3.default.cyan(rel)} is not empty. Scaffold into it anyway?`,
1938
+ initialValue: false
1939
+ });
1940
+ bail2(proceed);
1941
+ if (!proceed) {
1942
+ ge("Scaffolding cancelled.");
1943
+ process.exit(0);
1944
+ }
1945
+ }
1946
+ let template = opts.template ?? "app";
1947
+ if (!opts.template && !opts.yes) {
1948
+ const templateOptions = [
1949
+ {
1950
+ value: "app",
1951
+ label: "App",
1952
+ hint: "the full ToilJS starter, landing page, layout, styles, demo routes"
1953
+ },
1954
+ { value: "minimal", label: "Minimal", hint: "just a layout and a home route" }
1955
+ ];
1956
+ const choice = await Ee({
1957
+ message: "Which template?",
1958
+ options: templateOptions,
1959
+ initialValue: "app"
1960
+ });
1961
+ bail2(choice);
1962
+ template = choice === "minimal" ? "minimal" : "app";
1963
+ }
1964
+ let preprocessor = opts.preprocessor ?? "css";
1965
+ let tailwind = opts.tailwind ?? false;
1966
+ if (!opts.yes) {
1967
+ if (opts.preprocessor === void 0) {
1968
+ const choice = await Ee({
1969
+ message: "Styling",
1970
+ options: PREPROCESSORS.map((value) => ({
1971
+ value,
1972
+ label: PREPROCESSOR_LABEL2[value]
1973
+ })),
1974
+ initialValue: "css"
1975
+ });
1976
+ bail2(choice);
1977
+ preprocessor = choice;
1978
+ }
1979
+ if (opts.tailwind === void 0) {
1980
+ const tw = await le({ message: "Add Tailwind CSS?", initialValue: false });
1981
+ bail2(tw);
1982
+ tailwind = tw;
1983
+ }
1984
+ }
1985
+ const features = { preprocessor, tailwind };
1986
+ let aiTools = opts.ai === false ? [] : [...AI_HELPER_IDS];
1987
+ if (opts.ai === void 0 && !opts.yes) {
1988
+ const picked = await we({
1989
+ message: "AI assistant files (read by Claude, Cursor, Codex, Copilot)",
1990
+ options: [
1991
+ ...AI_HELPERS.map((h2) => ({ value: h2.id, label: h2.label })),
1992
+ { value: "none", label: "None" }
1993
+ ],
1994
+ initialValues: [...AI_HELPER_IDS],
1995
+ required: false
1996
+ });
1997
+ bail2(picked);
1998
+ aiTools = picked.includes("none") ? [] : picked;
1999
+ }
2000
+ let images = opts.images ?? true;
2001
+ if (opts.images === void 0 && !opts.yes) {
2002
+ const im = await le({ message: "Optimize images at build time?", initialValue: true });
2003
+ bail2(im);
2004
+ images = im;
2005
+ }
2006
+ let initGit = opts.git ?? false;
2007
+ let install = opts.install ?? false;
2008
+ const pm = opts.pm ?? "npm";
2009
+ if (!isPackageManager(pm)) {
2010
+ ge(`Unsupported package manager: ${pm} (use npm, pnpm, yarn, or bun).`);
2011
+ process.exit(1);
2012
+ }
2013
+ if (!opts.yes) {
2014
+ if (opts.git === void 0) {
2015
+ const g = await le({
2016
+ message: "Initialize a git repository?",
2017
+ initialValue: true
2018
+ });
2019
+ bail2(g);
2020
+ initGit = g;
2021
+ }
2022
+ if (opts.install === void 0) {
2023
+ const i = await le({ message: "Install dependencies now?", initialValue: false });
2024
+ bail2(i);
2025
+ install = i;
2026
+ }
2027
+ }
2028
+ const s = vt();
2029
+ s.start("Scaffolding project");
2030
+ await writeFiles(targetDir, scaffold(name, template, features, aiTools, images));
2031
+ if (template === "app") {
2032
+ await fs3.cp(appClientDir(), path4.join(targetDir, "client"), { recursive: true });
2033
+ const indexHtml = path4.join(targetDir, "client", "public", "index.html");
2034
+ const html = await fs3.readFile(indexHtml, "utf8");
2035
+ await fs3.writeFile(
2036
+ indexHtml,
2037
+ html.replace(/<title>[^<]*<\/title>/, `<title>${path4.basename(name)}</title>`)
2038
+ );
2039
+ await applyStyling(path4.join(targetDir, "client"), features);
2040
+ }
2041
+ s.stop(`Scaffolded ${import_picocolors3.default.cyan(rel)}`);
2042
+ if (initGit) {
2043
+ const g = vt();
2044
+ g.start("Initializing git repository");
2045
+ try {
2046
+ await run("git", ["init", "-q"], targetDir);
2047
+ await run("git", ["add", "-A"], targetDir);
2048
+ g.stop("Initialized git repository");
2049
+ } catch {
2050
+ g.stop(import_picocolors3.default.yellow("Skipped git init (git not available)"));
2051
+ }
2052
+ }
2053
+ if (install) {
2054
+ const i = vt();
2055
+ i.start(`Installing dependencies with ${pm}`);
2056
+ try {
2057
+ await run(pm, ["install"], targetDir);
2058
+ i.stop("Installed dependencies");
2059
+ } catch {
2060
+ i.stop(import_picocolors3.default.yellow(`Could not install with ${pm}, run it yourself later`));
2061
+ install = false;
2062
+ }
2063
+ }
2064
+ const steps = [];
2065
+ if (rel !== ".") steps.push(`cd ${rel}`);
2066
+ if (!install) steps.push("npm install");
2067
+ steps.push(`${accent("npm run dev")} ${dim("start the dev server")}`);
2068
+ steps.push(`${accent("npm run build")} ${dim("build for production")}`);
2069
+ Ce(steps.map((l) => dim(" ") + l).join("\n"), "Next steps");
2070
+ fe(`Created ${accent(path4.basename(name))}, happy building! ${dim("\xB7 v" + version())}`);
2071
+ }
2072
+
2073
+ // src/cli/doctor.ts
2074
+ import fs4 from "node:fs";
2075
+ import { createRequire } from "node:module";
2076
+ import path5 from "node:path";
2077
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
2078
+ import { loadConfig as loadConfig2, scanRoutes } from "toiljs/compiler";
2079
+
2080
+ // src/cli/diagnostics.ts
2081
+ function parseVersion(v2) {
2082
+ const m2 = /(\d+)(?:\.(\d+))?(?:\.(\d+))?/.exec(v2);
2083
+ if (!m2) return [0, 0, 0];
2084
+ return [Number(m2[1]), Number(m2[2] ?? 0), Number(m2[3] ?? 0)];
2085
+ }
2086
+ function satisfiesMin(version2, range) {
2087
+ const [a, b2, c] = parseVersion(version2);
2088
+ const [x3, y, z3] = parseVersion(range);
2089
+ if (a !== x3) return a > x3;
2090
+ if (b2 !== y) return b2 > y;
2091
+ return c >= z3;
2092
+ }
2093
+ function checkNode(current, requiredRange) {
2094
+ const ok = satisfiesMin(current, requiredRange);
2095
+ return {
2096
+ id: "node",
2097
+ label: "Node.js",
2098
+ status: ok ? "pass" : "fail",
2099
+ detail: `${current} (requires ${requiredRange})`,
2100
+ fix: ok ? void 0 : `Upgrade Node to ${requiredRange}.`
2101
+ };
2102
+ }
2103
+ function checkPeer(name, installed, range) {
2104
+ if (installed === null) {
2105
+ return {
2106
+ id: `peer:${name}`,
2107
+ label: name,
2108
+ status: "fail",
2109
+ detail: `not installed (requires ${range})`,
2110
+ fix: `Install ${name}@"${range}".`
2111
+ };
2112
+ }
2113
+ const ok = satisfiesMin(installed, range);
2114
+ return {
2115
+ id: `peer:${name}`,
2116
+ label: name,
2117
+ status: ok ? "pass" : "warn",
2118
+ detail: `${installed} (requires ${range})`,
2119
+ fix: ok ? void 0 : `Update ${name} to ${range}.`
2120
+ };
2121
+ }
2122
+ function checkPackageManager(lockfiles) {
2123
+ if (lockfiles.length === 0) {
2124
+ return {
2125
+ id: "pm",
2126
+ label: "Package manager",
2127
+ status: "warn",
2128
+ detail: "no lockfile found",
2129
+ fix: "Run an install (npm/pnpm/yarn/bun) to create a lockfile."
2130
+ };
2131
+ }
2132
+ return { id: "pm", label: "Package manager", status: "pass", detail: lockfiles.join(", ") };
2133
+ }
2134
+ function checkToiljsInstalled(version2) {
2135
+ return version2 ? { id: "toiljs", label: "toiljs", status: "pass", detail: version2 } : {
2136
+ id: "toiljs",
2137
+ label: "toiljs",
2138
+ status: "fail",
2139
+ detail: "not a dependency of this project",
2140
+ fix: "Add toiljs to dependencies, or run from the project root with --root."
2141
+ };
2142
+ }
2143
+ function checkDir(id, label, exists, fix) {
2144
+ return exists ? { id, label, status: "pass" } : { id, label, status: "fail", detail: "missing", fix };
2145
+ }
2146
+ function checkMountSlots(entrySource) {
2147
+ const label = "App entry mount()";
2148
+ if (entrySource === null) {
2149
+ return {
2150
+ id: "mount",
2151
+ label,
2152
+ status: "warn",
2153
+ detail: "entry file not found",
2154
+ fix: "Ensure client/toil.tsx calls Toil.mount(...)."
2155
+ };
2156
+ }
2157
+ const call = /\bmount\s*\(([^)]*)\)/.exec(entrySource);
2158
+ if (!call) {
2159
+ return {
2160
+ id: "mount",
2161
+ label,
2162
+ status: "warn",
2163
+ detail: "no mount() call found",
2164
+ fix: "Call Toil.mount(routes, layout, notFound, globalError, slots)."
2165
+ };
2166
+ }
2167
+ const hasSlots = /\bslots\b/.test(call[1]);
2168
+ return hasSlots ? { id: "mount", label, status: "pass", detail: "passes slots" } : {
2169
+ id: "mount",
2170
+ label,
2171
+ status: "warn",
2172
+ detail: "mount() is missing the slots argument",
2173
+ fix: "Pass slots last: mount(routes, layout, notFound, globalError, slots). Without it, parallel and intercepting routes are ignored."
2174
+ };
2175
+ }
2176
+ function checkRootElement(indexHtml) {
2177
+ const label = "index.html mount target";
2178
+ if (indexHtml === null) {
2179
+ return {
2180
+ id: "root-el",
2181
+ label,
2182
+ status: "fail",
2183
+ detail: "index.html not found",
2184
+ fix: 'Add public/index.html with <div id="root"></div>.'
2185
+ };
2186
+ }
2187
+ const ok = /id\s*=\s*["']root["']/.test(indexHtml);
2188
+ return ok ? { id: "root-el", label, status: "pass" } : {
2189
+ id: "root-el",
2190
+ label,
2191
+ status: "fail",
2192
+ detail: 'no element with id="root"',
2193
+ fix: 'Add <div id="root"></div> to public/index.html.'
2194
+ };
2195
+ }
2196
+ function checkRoutesPresent(routeCount) {
2197
+ return routeCount > 0 ? {
2198
+ id: "routes",
2199
+ label: "Routes",
2200
+ status: "pass",
2201
+ detail: `${routeCount} route${routeCount === 1 ? "" : "s"}`
2202
+ } : {
2203
+ id: "routes",
2204
+ label: "Routes",
2205
+ status: "fail",
2206
+ detail: "no routes found",
2207
+ fix: "Add a page, e.g. client/routes/index.tsx."
2208
+ };
2209
+ }
2210
+ function checkDuplicatePatterns(patterns) {
2211
+ const seen = /* @__PURE__ */ new Set();
2212
+ const dupes = /* @__PURE__ */ new Set();
2213
+ for (const p2 of patterns) {
2214
+ if (seen.has(p2)) dupes.add(p2);
2215
+ else seen.add(p2);
2216
+ }
2217
+ return dupes.size === 0 ? { id: "route-dupes", label: "Unique route patterns", status: "pass" } : {
2218
+ id: "route-dupes",
2219
+ label: "Unique route patterns",
2220
+ status: "warn",
2221
+ detail: `duplicate: ${[...dupes].join(", ")}`,
2222
+ fix: "Two route files map to the same URL; rename or remove one."
2223
+ };
2224
+ }
2225
+ function isBrokenRelativeAsset(value) {
2226
+ if (value === "") return false;
2227
+ if (value.startsWith("/")) return false;
2228
+ if (/^[a-z][a-z0-9+.-]*:/i.test(value)) return false;
2229
+ if (value.startsWith("#") || value.startsWith("?")) return false;
2230
+ return /\.(svgz?|png|jpe?g|gif|webp|avif|ico|css|m?js|woff2?|ttf|otf|eot|mp4|webm|json)$/i.test(
2231
+ value
2232
+ );
2233
+ }
2234
+ function findRelativeAssets(files) {
2235
+ const issues = [];
2236
+ const attr = /\b(?:src|href)\s*=\s*(?:"([^"]*)"|'([^']*)')/g;
2237
+ for (const file of files) {
2238
+ const lines = file.source.split("\n");
2239
+ for (let i = 0; i < lines.length; i++) {
2240
+ attr.lastIndex = 0;
2241
+ let m2;
2242
+ while ((m2 = attr.exec(lines[i])) !== null) {
2243
+ const value = m2[1] ?? m2[2] ?? "";
2244
+ if (isBrokenRelativeAsset(value)) {
2245
+ issues.push({ file: file.path, line: i + 1, value });
2246
+ }
2247
+ }
2248
+ }
2249
+ }
2250
+ return issues;
2251
+ }
2252
+ function checkRelativeAssets(issues) {
2253
+ if (issues.length === 0) return { id: "rel-assets", label: "Asset paths", status: "pass" };
2254
+ const shown = issues.slice(0, 5).map((i) => `${i.file}:${String(i.line)} "${i.value}"`).join("; ");
2255
+ const more = issues.length > 5 ? `, and ${String(issues.length - 5)} more` : "";
2256
+ return {
2257
+ id: "rel-assets",
2258
+ label: "Asset paths",
2259
+ status: "warn",
2260
+ detail: `${String(issues.length)} relative reference(s): ${shown}${more}`,
2261
+ fix: 'Use a root-absolute path (e.g. "/images/logo.svg") or import the asset; relative paths 404 on nested routes.'
2262
+ };
2263
+ }
2264
+ function checkConfigLoads(loaded, error) {
2265
+ return loaded ? { id: "config", label: "toil.config loads", status: "pass" } : {
2266
+ id: "config",
2267
+ label: "toil.config loads",
2268
+ status: "fail",
2269
+ detail: error ?? "failed to load",
2270
+ fix: "Fix the error in your toil.config.* so dev/build can read it."
2271
+ };
2272
+ }
2273
+ function checkBasePath(base) {
2274
+ const ok = base === "/" || base.startsWith("/") && base.endsWith("/");
2275
+ return ok ? { id: "base", label: "Base path", status: "pass", detail: base } : {
2276
+ id: "base",
2277
+ label: "Base path",
2278
+ status: "warn",
2279
+ detail: `"${base}"`,
2280
+ fix: 'A non-root base should start and end with "/" (e.g. "/app/").'
2281
+ };
2282
+ }
2283
+ function checkSeoUrl(seoConfigured, hasUrl) {
2284
+ if (!seoConfigured) {
2285
+ return {
2286
+ id: "seo-url",
2287
+ label: "SEO site url",
2288
+ status: "pass",
2289
+ detail: "SEO not configured"
2290
+ };
2291
+ }
2292
+ return hasUrl ? { id: "seo-url", label: "SEO site url", status: "pass" } : {
2293
+ id: "seo-url",
2294
+ label: "SEO site url",
2295
+ status: "warn",
2296
+ detail: "seo is set without a url",
2297
+ fix: "Set client.seo.url so sitemap.xml and canonical links are absolute."
2298
+ };
2299
+ }
2300
+ function checkStyling(f2) {
2301
+ const label = "Styling";
2302
+ if (f2.preprocessorImported && f2.preprocessorImported !== "css" && !f2.preprocessorInstalled) {
2303
+ return {
2304
+ id: "styling",
2305
+ label,
2306
+ status: "fail",
2307
+ detail: `${f2.preprocessorImported} stylesheet imported but ${f2.preprocessorImported} is not installed`,
2308
+ fix: `Install ${f2.preprocessorImported}, or run toiljs configure.`
2309
+ };
2310
+ }
2311
+ if (f2.tailwindImported && !f2.tailwindInstalled) {
2312
+ return {
2313
+ id: "styling",
2314
+ label,
2315
+ status: "fail",
2316
+ detail: "Tailwind entry imported but @tailwindcss/vite is not installed",
2317
+ fix: "Run toiljs configure --tailwind, or install @tailwindcss/vite."
2318
+ };
2319
+ }
2320
+ return { id: "styling", label, status: "pass" };
2321
+ }
2322
+ function checkToilconfig(present) {
2323
+ return present ? { id: "toilconfig", label: "Server target (toilconfig.json)", status: "pass" } : {
2324
+ id: "toilconfig",
2325
+ label: "Server target (toilconfig.json)",
2326
+ status: "warn",
2327
+ detail: "no toilconfig.json (no WebAssembly server)",
2328
+ fix: "Add toilconfig.json + a server/ entry if you want a WASM backend."
2329
+ };
2330
+ }
2331
+ function checkServerEntry(missing) {
2332
+ return missing.length === 0 ? { id: "server-entry", label: "Server entries", status: "pass" } : {
2333
+ id: "server-entry",
2334
+ label: "Server entries",
2335
+ status: "fail",
2336
+ detail: `missing: ${missing.join(", ")}`,
2337
+ fix: 'Create the entry file(s) listed in toilconfig.json "entries", or update them.'
2338
+ };
2339
+ }
2340
+ function checkToilscriptInstalled(installed) {
2341
+ return installed ? { id: "toilscript", label: "toilscript compiler", status: "pass" } : {
2342
+ id: "toilscript",
2343
+ label: "toilscript compiler",
2344
+ status: "warn",
2345
+ detail: "toilconfig.json present but toilscript is not installed",
2346
+ fix: "Install toilscript to compile the server to WebAssembly."
2347
+ };
2348
+ }
2349
+ function checkWasmBuilt(exists) {
2350
+ return exists ? { id: "wasm", label: "Server build", status: "pass" } : {
2351
+ id: "wasm",
2352
+ label: "Server build",
2353
+ status: "warn",
2354
+ detail: "no compiled .wasm found",
2355
+ fix: "Run your server build (toilscript) before toiljs start."
2356
+ };
2357
+ }
2358
+ function summarize(groups) {
2359
+ let pass = 0;
2360
+ let warn2 = 0;
2361
+ let fail = 0;
2362
+ for (const group of groups) {
2363
+ for (const check of group.checks) {
2364
+ if (check.status === "pass") pass++;
2365
+ else if (check.status === "warn") warn2++;
2366
+ else fail++;
2367
+ }
2368
+ }
2369
+ return { pass, warn: warn2, fail };
2370
+ }
2371
+ function hasFailures(summary) {
2372
+ return summary.fail > 0;
2373
+ }
2374
+
2375
+ // src/cli/doctor.ts
2376
+ function readJsonObject(file) {
2377
+ try {
2378
+ const parsed = JSON.parse(fs4.readFileSync(file, "utf8"));
2379
+ return typeof parsed === "object" && parsed !== null ? parsed : null;
2380
+ } catch {
2381
+ return null;
2382
+ }
2383
+ }
2384
+ function stringRecord(value) {
2385
+ if (typeof value !== "object" || value === null) return {};
2386
+ const out = {};
2387
+ for (const [k2, v2] of Object.entries(value)) if (typeof v2 === "string") out[k2] = v2;
2388
+ return out;
2389
+ }
2390
+ function readFile(file) {
2391
+ try {
2392
+ return fs4.readFileSync(file, "utf8");
2393
+ } catch {
2394
+ return null;
2395
+ }
2396
+ }
2397
+ function frameworkMeta() {
2398
+ const pkgPath = path5.resolve(
2399
+ path5.dirname(fileURLToPath3(import.meta.url)),
2400
+ "..",
2401
+ "..",
2402
+ "package.json"
2403
+ );
2404
+ const pkg = readJsonObject(pkgPath);
2405
+ const engines = pkg ? stringRecord(pkg.engines) : {};
2406
+ const peers = pkg ? stringRecord(pkg.peerDependencies) : {};
2407
+ return { node: engines.node ?? ">=24.0.0", peers };
2408
+ }
2409
+ var LOCKFILES = ["package-lock.json", "pnpm-lock.yaml", "yarn.lock", "bun.lockb"];
2410
+ function readEntry(clientAbsDir) {
2411
+ for (const name of ["toil.tsx", "toil.jsx", "main.tsx", "main.jsx"]) {
2412
+ const source = readFile(path5.join(clientAbsDir, name));
2413
+ if (source !== null && /toiljs\/routes|\bmount\s*\(/.test(source)) return source;
2414
+ }
2415
+ return null;
2416
+ }
2417
+ function collectSources(root, dir, cap) {
2418
+ const out = [];
2419
+ const visit = (current) => {
2420
+ if (out.length >= cap) return;
2421
+ let entries;
2422
+ try {
2423
+ entries = fs4.readdirSync(current, { withFileTypes: true });
2424
+ } catch {
2425
+ return;
2426
+ }
2427
+ for (const entry of entries) {
2428
+ if (out.length >= cap) break;
2429
+ const full = path5.join(current, entry.name);
2430
+ if (entry.isDirectory()) {
2431
+ if (entry.name !== "node_modules") visit(full);
2432
+ } else if (/\.(tsx|jsx)$/.test(entry.name)) {
2433
+ const source = readFile(full);
2434
+ if (source !== null) out.push({ path: path5.relative(root, full), source });
2435
+ }
2436
+ }
2437
+ };
2438
+ visit(dir);
2439
+ return out;
2440
+ }
2441
+ function glyph(status) {
2442
+ if (status === "pass") return success("\u2713");
2443
+ if (status === "warn") return warn("\u26A0");
2444
+ return danger("\u2717");
2445
+ }
2446
+ function renderHuman(groups) {
2447
+ const summary = summarize(groups);
2448
+ const out = [];
2449
+ for (const group of groups) {
2450
+ out.push(" " + bold(group.title));
2451
+ for (const check of group.checks) {
2452
+ let line = ` ${glyph(check.status)} ${check.label}`;
2453
+ if (check.detail) line += dim(` ${check.detail}`);
2454
+ out.push(line);
2455
+ if (check.fix && check.status !== "pass")
2456
+ out.push(" " + dim(`fix: ${check.fix}`));
2457
+ }
2458
+ out.push("");
2459
+ }
2460
+ const parts = [success(`${String(summary.pass)} passed`)];
2461
+ if (summary.warn > 0) {
2462
+ parts.push(warn(`${String(summary.warn)} warning${summary.warn === 1 ? "" : "s"}`));
2463
+ }
2464
+ if (summary.fail > 0) parts.push(danger(`${String(summary.fail)} failed`));
2465
+ out.push(" " + parts.join(dim(", ")));
2466
+ out.push("");
2467
+ process.stdout.write(out.join("\n") + "\n");
2468
+ }
2469
+ async function runDoctor(opts) {
2470
+ const root = path5.resolve(opts.root ?? opts.cwd);
2471
+ const meta = frameworkMeta();
2472
+ const projectPkg = readJsonObject(path5.join(root, "package.json"));
2473
+ const deps = {
2474
+ ...projectPkg ? stringRecord(projectPkg.dependencies) : {},
2475
+ ...projectPkg ? stringRecord(projectPkg.devDependencies) : {}
2476
+ };
2477
+ let cfg = null;
2478
+ let configError;
2479
+ try {
2480
+ cfg = await loadConfig2({ root });
2481
+ } catch (err) {
2482
+ configError = err instanceof Error ? err.message : String(err);
2483
+ }
2484
+ const clientAbsDir = cfg ? cfg.clientAbsDir : path5.join(root, "client");
2485
+ const routesAbsDir = cfg ? cfg.routesAbsDir : path5.join(clientAbsDir, "routes");
2486
+ const publicDir = cfg ? cfg.publicDir : path5.join(clientAbsDir, "public");
2487
+ const entrySource = readEntry(clientAbsDir);
2488
+ const indexHtml = readFile(path5.join(publicDir, "index.html"));
2489
+ const routes = scanRoutes(routesAbsDir);
2490
+ const mainPatterns = routes.filter((r) => r.slot === void 0).map((r) => r.pattern);
2491
+ const assetIssues = findRelativeAssets(collectSources(root, clientAbsDir, 200));
2492
+ let preprocessorImported = null;
2493
+ let tailwindImported = false;
2494
+ if (entrySource) {
2495
+ const styleImport = /import\s+['"]\.\/styles\/main\.([a-z]+)['"]/.exec(entrySource);
2496
+ if (styleImport) preprocessorImported = preprocessorForExt(styleImport[1]);
2497
+ tailwindImported = entrySource.includes(TAILWIND_ENTRY);
2498
+ }
2499
+ const ppPkg = preprocessorImported ? PREPROCESSOR_PKG[preprocessorImported] : null;
2500
+ const preprocessorInstalled = ppPkg === null || ppPkg in deps;
2501
+ const toilconfig = readJsonObject(path5.join(root, "toilconfig.json"));
2502
+ const serverPresent = toilconfig !== null;
2503
+ let missingEntries = [];
2504
+ let toilscriptInstalled = false;
2505
+ let wasmExists = false;
2506
+ if (toilconfig) {
2507
+ const entries = Array.isArray(toilconfig.entries) ? toilconfig.entries.filter((e2) => typeof e2 === "string") : [];
2508
+ missingEntries = entries.filter((e2) => !fs4.existsSync(path5.join(root, e2)));
2509
+ try {
2510
+ createRequire(path5.join(root, "package.json")).resolve("toilscript");
2511
+ toilscriptInstalled = true;
2512
+ } catch {
2513
+ toilscriptInstalled = false;
2514
+ }
2515
+ const targets = typeof toilconfig.targets === "object" && toilconfig.targets !== null ? toilconfig.targets : {};
2516
+ const outFiles = [];
2517
+ for (const target of Object.values(targets)) {
2518
+ if (typeof target === "object" && target !== null) {
2519
+ const outFile = target.outFile;
2520
+ if (typeof outFile === "string") outFiles.push(outFile);
2521
+ }
2522
+ }
2523
+ wasmExists = outFiles.some((f2) => fs4.existsSync(path5.join(root, f2)));
2524
+ if (!wasmExists && outFiles.length === 0) {
2525
+ try {
2526
+ wasmExists = fs4.readdirSync(path5.join(root, "build", "server")).some((f2) => f2.endsWith(".wasm"));
2527
+ } catch {
2528
+ wasmExists = false;
2529
+ }
2530
+ }
2531
+ }
2532
+ const peerName = (n) => checkPeer(n, deps[n] ?? null, meta.peers[n] ?? "*");
2533
+ const peerChecks = Object.keys(meta.peers).map(peerName);
2534
+ const groups = [
2535
+ {
2536
+ title: "Environment",
2537
+ checks: [
2538
+ checkNode(process.versions.node, meta.node),
2539
+ checkToiljsInstalled("toiljs" in deps ? version() : null),
2540
+ ...peerChecks,
2541
+ checkPackageManager(LOCKFILES.filter((f2) => fs4.existsSync(path5.join(root, f2))))
2542
+ ]
2543
+ },
2544
+ {
2545
+ title: "Project + routing",
2546
+ checks: [
2547
+ checkDir(
2548
+ "client-dir",
2549
+ "client/ directory",
2550
+ fs4.existsSync(clientAbsDir),
2551
+ "Create a client/ directory for your app."
2552
+ ),
2553
+ checkDir(
2554
+ "routes-dir",
2555
+ "routes/ directory",
2556
+ fs4.existsSync(routesAbsDir),
2557
+ "Create client/routes/ and add an index.tsx."
2558
+ ),
2559
+ checkRootElement(indexHtml),
2560
+ checkMountSlots(entrySource),
2561
+ checkRoutesPresent(routes.length),
2562
+ checkDuplicatePatterns(mainPatterns),
2563
+ checkRelativeAssets(assetIssues)
2564
+ ]
2565
+ },
2566
+ {
2567
+ title: "Config + assets",
2568
+ checks: [
2569
+ checkConfigLoads(cfg !== null, configError),
2570
+ checkBasePath(cfg ? cfg.base : "/"),
2571
+ checkSeoUrl(cfg?.seo != null, cfg?.seo?.url != null),
2572
+ checkStyling({
2573
+ preprocessorImported,
2574
+ preprocessorInstalled,
2575
+ tailwindImported,
2576
+ tailwindInstalled: detectTailwind(deps)
2577
+ })
2578
+ ]
2579
+ },
2580
+ {
2581
+ title: "Server / WASM",
2582
+ checks: serverPresent ? [
2583
+ checkToilconfig(true),
2584
+ checkServerEntry(missingEntries),
2585
+ checkToilscriptInstalled(toilscriptInstalled),
2586
+ checkWasmBuilt(wasmExists)
2587
+ ] : [checkToilconfig(false)]
2588
+ }
2589
+ ];
2590
+ const summary = summarize(groups);
2591
+ if (opts.json) {
2592
+ process.stdout.write(JSON.stringify({ groups, summary }, null, 2) + "\n");
2593
+ } else {
2594
+ process.stdout.write("\n" + accent(" Doctor") + dim(` ${root}`) + "\n\n");
2595
+ renderHuman(groups);
2596
+ }
2597
+ if (hasFailures(summary)) process.exitCode = 1;
2598
+ }
2599
+
2600
+ // src/cli/update.ts
2601
+ import fs5 from "node:fs";
2602
+ import path6 from "node:path";
2603
+
2604
+ // src/cli/updates.ts
2605
+ function parseVersion2(v2) {
2606
+ const m2 = /(\d+)(?:\.(\d+))?(?:\.(\d+))?/.exec(v2);
2607
+ if (!m2) return [0, 0, 0];
2608
+ return [Number(m2[1]), Number(m2[2] ?? 0), Number(m2[3] ?? 0)];
2609
+ }
2610
+ function classifyBump(from, to) {
2611
+ const [fa, fb, fc] = parseVersion2(from);
2612
+ const [ta, tb, tc] = parseVersion2(to);
2613
+ if (ta !== fa) return "major";
2614
+ if (tb !== fb) return "minor";
2615
+ if (tc !== fc) return "patch";
2616
+ return "other";
2617
+ }
2618
+ function parseNcuJson(stdout) {
2619
+ const start2 = stdout.indexOf("{");
2620
+ const end = stdout.lastIndexOf("}");
2621
+ if (start2 === -1 || end <= start2) return {};
2622
+ try {
2623
+ const parsed = JSON.parse(stdout.slice(start2, end + 1));
2624
+ if (typeof parsed !== "object" || parsed === null) return {};
2625
+ const out = {};
2626
+ for (const [k2, v2] of Object.entries(parsed)) if (typeof v2 === "string") out[k2] = v2;
2627
+ return out;
2628
+ } catch {
2629
+ return {};
2630
+ }
2631
+ }
2632
+ var SEVERITY = { major: 0, minor: 1, patch: 2, other: 3 };
2633
+ function buildRows(upgraded, currentDeps) {
2634
+ return Object.entries(upgraded).map(([name, to]) => {
2635
+ const from = currentDeps[name] ?? "?";
2636
+ return { name, from, to, bump: classifyBump(from, to) };
2637
+ }).sort((a, b2) => SEVERITY[a.bump] - SEVERITY[b2.bump] || a.name.localeCompare(b2.name));
2638
+ }
2639
+
2640
+ // src/cli/update.ts
2641
+ function detectPackageManager2(root) {
2642
+ if (fs5.existsSync(path6.join(root, "pnpm-lock.yaml"))) return { name: "pnpm", ncuName: "pnpm" };
2643
+ if (fs5.existsSync(path6.join(root, "yarn.lock"))) return { name: "yarn", ncuName: "yarn" };
2644
+ if (fs5.existsSync(path6.join(root, "bun.lockb"))) return { name: "bun", ncuName: "bun" };
2645
+ return { name: "npm", ncuName: "npm" };
2646
+ }
2647
+ function readDependencies(pkgPath) {
2648
+ const parsed = JSON.parse(fs5.readFileSync(pkgPath, "utf8"));
2649
+ if (typeof parsed !== "object" || parsed === null) return {};
2650
+ const pkg = parsed;
2651
+ const merge = (v2) => {
2652
+ if (typeof v2 !== "object" || v2 === null) return {};
2653
+ const out = {};
2654
+ for (const [k2, val] of Object.entries(v2)) if (typeof val === "string") out[k2] = val;
2655
+ return out;
2656
+ };
2657
+ return { ...merge(pkg.dependencies), ...merge(pkg.devDependencies) };
2658
+ }
2659
+ function bumpColor(bump, text) {
2660
+ if (bump === "major") return danger(text);
2661
+ if (bump === "minor") return warn(text);
2662
+ if (bump === "patch") return success(text);
2663
+ return dim(text);
2664
+ }
2665
+ function rowLine(row) {
2666
+ return `${row.name} ${dim(row.from)} ${dim("->")} ${bumpColor(row.bump, row.to)}`;
2667
+ }
2668
+ var TARGETS = /* @__PURE__ */ new Set(["latest", "minor", "patch", "newest", "greatest"]);
2669
+ async function runUpdate(opts) {
2670
+ const root = path6.resolve(opts.root ?? opts.cwd);
2671
+ const pkgPath = path6.join(root, "package.json");
2672
+ if (!fs5.existsSync(pkgPath)) {
2673
+ throw new Error("No package.json here. Run from your project root or pass --root <dir>.");
2674
+ }
2675
+ const currentDeps = readDependencies(pkgPath);
2676
+ const pm = detectPackageManager2(root);
2677
+ const target = opts.target && TARGETS.has(opts.target) ? opts.target : "latest";
2678
+ const ncuArgs = (extra) => [
2679
+ "--yes",
2680
+ "npm-check-updates",
2681
+ "--packageManager",
2682
+ pm.ncuName,
2683
+ "--target",
2684
+ target,
2685
+ ...extra
2686
+ ];
2687
+ ye(accent("toiljs update"));
2688
+ const s = vt();
2689
+ s.start("Checking the registry for updates");
2690
+ const res = await capture("npx", ncuArgs(["--jsonUpgraded"]), root);
2691
+ if (res.code !== 0 && res.stdout.indexOf("{") === -1) {
2692
+ s.stop("Could not check for updates");
2693
+ Ce(dim(res.stderr.trim() || "npm-check-updates failed."), "Error");
2694
+ process.exitCode = 1;
2695
+ return;
2696
+ }
2697
+ const rows = buildRows(parseNcuJson(res.stdout), currentDeps);
2698
+ if (rows.length === 0) {
2699
+ s.stop("Everything is up to date");
2700
+ fe(success("Nothing to update."));
2701
+ return;
2702
+ }
2703
+ s.stop(`${String(rows.length)} update${rows.length === 1 ? "" : "s"} available`);
2704
+ const counts = { major: 0, minor: 0, patch: 0, other: 0 };
2705
+ for (const r of rows) counts[r.bump]++;
2706
+ Ce(
2707
+ rows.map(rowLine).join("\n"),
2708
+ `${danger(`${String(counts.major)} major`)} ${warn(`${String(counts.minor)} minor`)} ${success(`${String(counts.patch)} patch`)}`
2709
+ );
2710
+ let selected;
2711
+ if (opts.yes) {
2712
+ selected = rows.map((r) => r.name);
2713
+ } else {
2714
+ const answer = await we({
2715
+ message: "Select packages to update (space to toggle, enter to confirm)",
2716
+ options: rows.map((r) => ({
2717
+ value: r.name,
2718
+ label: r.name,
2719
+ hint: `${r.from} -> ${r.to}`
2720
+ })),
2721
+ initialValues: rows.map((r) => r.name),
2722
+ required: false
2723
+ });
2724
+ if (R(answer)) {
2725
+ ge("Update cancelled.");
2726
+ return;
2727
+ }
2728
+ selected = answer;
2729
+ }
2730
+ if (selected.length === 0) {
2731
+ fe(dim("No packages selected."));
2732
+ return;
2733
+ }
2734
+ s.start("Updating package.json");
2735
+ const applyAll = selected.length === rows.length;
2736
+ await run("npx", ncuArgs(applyAll ? ["-u"] : ["-u", "--filter", selected.join(" ")]), root);
2737
+ s.stop("package.json updated");
2738
+ s.start(`Installing with ${pm.name}`);
2739
+ await run(pm.name, ["install"], root);
2740
+ s.stop("Dependencies installed");
2741
+ fe(
2742
+ success(`Updated ${String(selected.length)} package${selected.length === 1 ? "" : "s"}.`)
2743
+ );
2744
+ }
2745
+
2746
+ // src/cli/index.ts
2747
+ function parseArgs(argv) {
2748
+ const flags = {};
2749
+ for (let i = 0; i < argv.length; i++) {
2750
+ const arg = argv[i];
2751
+ switch (arg) {
2752
+ case "--root":
2753
+ flags.root = argv[++i];
2754
+ break;
2755
+ case "--port": {
2756
+ const port = Number(argv[++i]);
2757
+ if (!Number.isNaN(port)) flags.port = port;
2758
+ break;
2759
+ }
2760
+ case "--template":
2761
+ case "-t": {
2762
+ const t = argv[++i];
2763
+ if (t === "app" || t === "minimal") flags.template = t;
2764
+ break;
2765
+ }
2766
+ case "--pm":
2767
+ flags.pm = argv[++i];
2768
+ break;
2769
+ case "--style": {
2770
+ const s = argv[++i];
2771
+ if (PREPROCESSORS.includes(s))
2772
+ flags.preprocessor = s;
2773
+ break;
2774
+ }
2775
+ case "--tailwind":
2776
+ flags.tailwind = true;
2777
+ break;
2778
+ case "--no-tailwind":
2779
+ flags.tailwind = false;
2780
+ break;
2781
+ case "--ai":
2782
+ flags.ai = true;
2783
+ break;
2784
+ case "--no-ai":
2785
+ flags.ai = false;
2786
+ break;
2787
+ case "--images":
2788
+ flags.images = true;
2789
+ break;
2790
+ case "--no-images":
2791
+ flags.images = false;
2792
+ break;
2793
+ case "--install":
2794
+ flags.install = true;
2795
+ break;
2796
+ case "--no-install":
2797
+ flags.install = false;
2798
+ break;
2799
+ case "--git":
2800
+ flags.git = true;
2801
+ break;
2802
+ case "--no-git":
2803
+ flags.git = false;
2804
+ break;
2805
+ case "-y":
2806
+ case "--yes":
2807
+ flags.yes = true;
2808
+ break;
2809
+ case "--json":
2810
+ flags.json = true;
2811
+ break;
2812
+ case "--target":
2813
+ flags.target = argv[++i];
2814
+ break;
2815
+ default:
2816
+ if (!arg.startsWith("-") && flags.name === void 0) flags.name = arg;
2817
+ }
2818
+ }
2819
+ return flags;
85
2820
  }
86
2821
  function printHelp() {
87
- const cmd = (name, desc) => ` ${accent(name.padEnd(15))}${dim(desc)}`;
88
- process.stdout.write([
89
- `${bold('Usage')} ${dim('toiljs')} <command> [options]`,
90
- '',
91
- bold('Commands'),
92
- cmd('create [name]', 'scaffold a new toiljs app'),
93
- cmd('configure', 'toggle styling features (Sass/Less/Stylus, Tailwind)'),
94
- cmd('dev', 'start the dev server with HMR'),
95
- cmd('build', 'build the optimized production bundle'),
96
- cmd('start', 'self-host the built app (hyper-express / uWS)'),
97
- cmd('doctor', 'diagnose project setup and dependencies'),
98
- cmd('update', 'check for and apply dependency updates'),
99
- '',
100
- bold('Options'),
101
- cmd('--root <dir>', 'project root (default: current directory)'),
102
- cmd('--port <n>', 'dev server port'),
103
- cmd('-t, --template', 'create: app | minimal'),
104
- cmd('--style <name>', 'create/configure: css | sass | less | stylus'),
105
- cmd('--tailwind', 'create/configure: enable Tailwind (--no-tailwind to remove)'),
106
- cmd('--no-ai', 'create: skip AI assistant files (CLAUDE.md, etc.)'),
107
- cmd('-y, --yes', 'create: accept defaults (non-interactive)'),
108
- cmd('--no-install', "create: don't install dependencies"),
109
- cmd('--json', 'doctor: machine-readable output'),
110
- cmd('--target <t>', 'update: latest | minor | patch | newest | greatest'),
111
- cmd('-v, --version', 'print the toiljs version'),
112
- '',
113
- ].join('\n') + '\n');
2822
+ const cmd = (name, desc) => ` ${accent(name.padEnd(15))}${dim(desc)}`;
2823
+ process.stdout.write(
2824
+ [
2825
+ `${bold("Usage")} ${dim("toiljs")} <command> [options]`,
2826
+ "",
2827
+ bold("Commands"),
2828
+ cmd("create [name]", "scaffold a new toiljs app"),
2829
+ cmd("configure", "toggle styling features (Sass/Less/Stylus, Tailwind)"),
2830
+ cmd("dev", "start the dev server with HMR"),
2831
+ cmd("build", "build the optimized production bundle"),
2832
+ cmd("start", "self-host the built app (hyper-express / uWS)"),
2833
+ cmd("doctor", "diagnose project setup and dependencies"),
2834
+ cmd("update", "check for and apply dependency updates"),
2835
+ "",
2836
+ bold("Options"),
2837
+ cmd("--root <dir>", "project root (default: current directory)"),
2838
+ cmd("--port <n>", "dev server port"),
2839
+ cmd("-t, --template", "create: app | minimal"),
2840
+ cmd("--style <name>", "create/configure: css | sass | less | stylus"),
2841
+ cmd("--tailwind", "create/configure: enable Tailwind (--no-tailwind to remove)"),
2842
+ cmd("--no-ai", "create: skip AI assistant files (CLAUDE.md, etc.)"),
2843
+ cmd("-y, --yes", "create: accept defaults (non-interactive)"),
2844
+ cmd("--no-install", "create: don't install dependencies"),
2845
+ cmd("--json", "doctor: machine-readable output"),
2846
+ cmd("--target <t>", "update: latest | minor | patch | newest | greatest"),
2847
+ cmd("-v, --version", "print the toiljs version"),
2848
+ ""
2849
+ ].join("\n") + "\n"
2850
+ );
114
2851
  }
115
2852
  async function main() {
116
- const [command, ...rest] = process.argv.slice(2);
117
- if (command === '--version' || command === '-v') {
118
- process.stdout.write(version() + '\n');
119
- return;
120
- }
121
- const flags = parseArgs(rest);
122
- switch (command) {
123
- case 'create':
124
- banner();
125
- await runCreate({
126
- name: flags.name,
127
- template: flags.template,
128
- preprocessor: flags.preprocessor,
129
- tailwind: flags.tailwind,
130
- ai: flags.ai,
131
- images: flags.images,
132
- install: flags.install,
133
- git: flags.git,
134
- pm: flags.pm,
135
- yes: flags.yes,
136
- cwd: process.cwd(),
137
- });
138
- break;
139
- case 'configure':
140
- banner();
141
- await runConfigure({
142
- root: flags.root,
143
- preprocessor: flags.preprocessor,
144
- tailwind: flags.tailwind,
145
- images: flags.images,
146
- install: flags.install,
147
- cwd: process.cwd(),
148
- });
149
- break;
150
- case 'dev':
151
- banner();
152
- process.stdout.write(dim(' starting dev server…') + '\n\n');
153
- await dev({ root: flags.root, port: flags.port });
154
- break;
155
- case 'build':
156
- banner();
157
- process.stdout.write(dim(' building for production…') + '\n\n');
158
- await build({ root: flags.root });
159
- process.stdout.write('\n' + success(' ') + bold('build complete') + '\n\n');
160
- break;
161
- case 'start': {
162
- banner();
163
- process.stdout.write(dim(' self-hosting the built app…') + '\n\n');
164
- const server = await start({ root: flags.root, port: flags.port });
165
- process.stdout.write(accent(' ➜ ') +
166
- bold(`http://localhost:${String(server.port)}`) +
167
- dim(` ws channel: ${server.wsPath}`) +
168
- '\n\n');
169
- break;
170
- }
171
- case 'doctor':
172
- if (!flags.json)
173
- banner();
174
- await runDoctor({ root: flags.root, cwd: process.cwd(), json: flags.json });
175
- break;
176
- case 'update':
177
- banner();
178
- await runUpdate({
179
- root: flags.root,
180
- cwd: process.cwd(),
181
- yes: flags.yes,
182
- target: flags.target,
183
- });
184
- break;
185
- case 'help':
186
- case '--help':
187
- case '-h':
188
- case undefined:
189
- banner();
190
- printHelp();
191
- break;
192
- default:
193
- banner();
194
- process.stdout.write(dim(` unknown command: ${command}`) + '\n\n');
195
- printHelp();
196
- process.exitCode = 1;
2853
+ const [command, ...rest] = process.argv.slice(2);
2854
+ if (command === "--version" || command === "-v") {
2855
+ process.stdout.write(version() + "\n");
2856
+ return;
2857
+ }
2858
+ const flags = parseArgs(rest);
2859
+ switch (command) {
2860
+ case "create":
2861
+ banner();
2862
+ await runCreate({
2863
+ name: flags.name,
2864
+ template: flags.template,
2865
+ preprocessor: flags.preprocessor,
2866
+ tailwind: flags.tailwind,
2867
+ ai: flags.ai,
2868
+ images: flags.images,
2869
+ install: flags.install,
2870
+ git: flags.git,
2871
+ pm: flags.pm,
2872
+ yes: flags.yes,
2873
+ cwd: process.cwd()
2874
+ });
2875
+ break;
2876
+ case "configure":
2877
+ banner();
2878
+ await runConfigure({
2879
+ root: flags.root,
2880
+ preprocessor: flags.preprocessor,
2881
+ tailwind: flags.tailwind,
2882
+ images: flags.images,
2883
+ install: flags.install,
2884
+ cwd: process.cwd()
2885
+ });
2886
+ break;
2887
+ case "dev":
2888
+ banner();
2889
+ process.stdout.write(dim(" starting dev server\u2026") + "\n\n");
2890
+ await dev({ root: flags.root, port: flags.port });
2891
+ break;
2892
+ case "build":
2893
+ banner();
2894
+ process.stdout.write(dim(" building for production\u2026") + "\n\n");
2895
+ await build({ root: flags.root });
2896
+ process.stdout.write("\n" + success(" \u2713 ") + bold("build complete") + "\n\n");
2897
+ break;
2898
+ case "start": {
2899
+ banner();
2900
+ process.stdout.write(dim(" self-hosting the built app\u2026") + "\n\n");
2901
+ const server = await start({ root: flags.root, port: flags.port });
2902
+ process.stdout.write(
2903
+ accent(" \u279C ") + bold(`http://localhost:${String(server.port)}`) + dim(` ws channel: ${server.wsPath}`) + "\n\n"
2904
+ );
2905
+ break;
197
2906
  }
2907
+ case "doctor":
2908
+ if (!flags.json) banner();
2909
+ await runDoctor({ root: flags.root, cwd: process.cwd(), json: flags.json });
2910
+ break;
2911
+ case "update":
2912
+ banner();
2913
+ await runUpdate({
2914
+ root: flags.root,
2915
+ cwd: process.cwd(),
2916
+ yes: flags.yes,
2917
+ target: flags.target
2918
+ });
2919
+ break;
2920
+ case "help":
2921
+ case "--help":
2922
+ case "-h":
2923
+ case void 0:
2924
+ banner();
2925
+ printHelp();
2926
+ break;
2927
+ default:
2928
+ banner();
2929
+ process.stdout.write(dim(` unknown command: ${command}`) + "\n\n");
2930
+ printHelp();
2931
+ process.exitCode = 1;
2932
+ }
198
2933
  }
199
2934
  main().catch((err) => {
200
- const message = err instanceof Error ? err.message : String(err);
201
- process.stderr.write('\n' + danger(' ') + message + '\n');
202
- process.exitCode = 1;
2935
+ const message = err instanceof Error ? err.message : String(err);
2936
+ process.stderr.write("\n" + danger(" \u2717 ") + message + "\n");
2937
+ process.exitCode = 1;
203
2938
  });