reset-framework-cli 1.1.2 → 1.1.5

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 (34) hide show
  1. package/LICENSE +20 -20
  2. package/README.md +47 -47
  3. package/package.json +4 -4
  4. package/src/commands/build.js +114 -113
  5. package/src/commands/dev.js +148 -144
  6. package/src/commands/doctor.js +89 -89
  7. package/src/commands/init.js +838 -903
  8. package/src/commands/package.js +49 -44
  9. package/src/index.js +213 -213
  10. package/src/lib/context.js +66 -66
  11. package/src/lib/framework.js +150 -28
  12. package/src/lib/logger.js +11 -11
  13. package/src/lib/output.js +214 -106
  14. package/src/lib/process.js +253 -156
  15. package/src/lib/project.js +559 -475
  16. package/src/lib/toolchain.js +62 -62
  17. package/src/lib/ui.js +244 -244
  18. package/templates/basic/README.md +15 -15
  19. package/templates/basic/frontend/README.md +73 -73
  20. package/templates/basic/frontend/eslint.config.js +23 -23
  21. package/templates/basic/frontend/index.html +13 -13
  22. package/templates/basic/frontend/package.json +31 -31
  23. package/templates/basic/frontend/public/icons.svg +24 -24
  24. package/templates/basic/frontend/src/App.css +216 -138
  25. package/templates/basic/frontend/src/App.tsx +77 -76
  26. package/templates/basic/frontend/src/assets/vite.svg +1 -1
  27. package/templates/basic/frontend/src/index.css +111 -111
  28. package/templates/basic/frontend/src/lib/reset.ts +1 -1
  29. package/templates/basic/frontend/src/main.tsx +10 -10
  30. package/templates/basic/frontend/tsconfig.app.json +28 -28
  31. package/templates/basic/frontend/tsconfig.json +7 -7
  32. package/templates/basic/frontend/tsconfig.node.json +26 -26
  33. package/templates/basic/frontend/vite.config.ts +16 -16
  34. package/templates/basic/reset.config.json +58 -58
@@ -1,62 +1,62 @@
1
- import { existsSync } from "node:fs"
2
- import { homedir } from "node:os"
3
- import path from "node:path"
4
-
5
- import { runCommand } from "./process.js"
6
-
7
- function toToolchainPath(root) {
8
- return path.join(root, "scripts", "buildsystems", "vcpkg.cmake")
9
- }
10
-
11
- export function getVcpkgToolchainCandidates() {
12
- const candidates = []
13
-
14
- if (typeof process.env.CMAKE_TOOLCHAIN_FILE === "string" && process.env.CMAKE_TOOLCHAIN_FILE.trim() !== "") {
15
- candidates.push(process.env.CMAKE_TOOLCHAIN_FILE)
16
- }
17
-
18
- if (typeof process.env.VCPKG_ROOT === "string" && process.env.VCPKG_ROOT.trim() !== "") {
19
- candidates.push(toToolchainPath(process.env.VCPKG_ROOT))
20
- }
21
-
22
- candidates.push(toToolchainPath(path.join(homedir(), ".vcpkg")))
23
- candidates.push(toToolchainPath(path.join(homedir(), ".reset-framework-cli", "vcpkg")))
24
-
25
- return [...new Set(candidates)]
26
- }
27
-
28
- export function findVcpkgToolchainFile() {
29
- return getVcpkgToolchainCandidates().find((candidate) => existsSync(candidate)) ?? null
30
- }
31
-
32
- export async function ensureVcpkgToolchain(options = {}) {
33
- const { dryRun = false } = options
34
- const existing = findVcpkgToolchainFile()
35
-
36
- if (existing) {
37
- return existing
38
- }
39
-
40
- const vcpkgRoot = path.join(homedir(), ".reset-framework-cli", "vcpkg")
41
- const toolchainFile = toToolchainPath(vcpkgRoot)
42
-
43
- if (!existsSync(vcpkgRoot)) {
44
- await runCommand("git", ["clone", "https://github.com/microsoft/vcpkg", vcpkgRoot], {
45
- dryRun
46
- })
47
- }
48
-
49
- if (process.platform === "win32") {
50
- await runCommand("cmd", ["/c", "bootstrap-vcpkg.bat", "-disableMetrics"], {
51
- cwd: vcpkgRoot,
52
- dryRun
53
- })
54
- } else {
55
- await runCommand("bash", ["./bootstrap-vcpkg.sh", "-disableMetrics"], {
56
- cwd: vcpkgRoot,
57
- dryRun
58
- })
59
- }
60
-
61
- return toolchainFile
62
- }
1
+ import { existsSync } from "node:fs"
2
+ import { homedir } from "node:os"
3
+ import path from "node:path"
4
+
5
+ import { runCommand } from "./process.js"
6
+
7
+ function toToolchainPath(root) {
8
+ return path.join(root, "scripts", "buildsystems", "vcpkg.cmake")
9
+ }
10
+
11
+ export function getVcpkgToolchainCandidates() {
12
+ const candidates = []
13
+
14
+ if (typeof process.env.CMAKE_TOOLCHAIN_FILE === "string" && process.env.CMAKE_TOOLCHAIN_FILE.trim() !== "") {
15
+ candidates.push(process.env.CMAKE_TOOLCHAIN_FILE)
16
+ }
17
+
18
+ if (typeof process.env.VCPKG_ROOT === "string" && process.env.VCPKG_ROOT.trim() !== "") {
19
+ candidates.push(toToolchainPath(process.env.VCPKG_ROOT))
20
+ }
21
+
22
+ candidates.push(toToolchainPath(path.join(homedir(), ".vcpkg")))
23
+ candidates.push(toToolchainPath(path.join(homedir(), ".reset-framework-cli", "vcpkg")))
24
+
25
+ return [...new Set(candidates)]
26
+ }
27
+
28
+ export function findVcpkgToolchainFile() {
29
+ return getVcpkgToolchainCandidates().find((candidate) => existsSync(candidate)) ?? null
30
+ }
31
+
32
+ export async function ensureVcpkgToolchain(options = {}) {
33
+ const { dryRun = false } = options
34
+ const existing = findVcpkgToolchainFile()
35
+
36
+ if (existing) {
37
+ return existing
38
+ }
39
+
40
+ const vcpkgRoot = path.join(homedir(), ".reset-framework-cli", "vcpkg")
41
+ const toolchainFile = toToolchainPath(vcpkgRoot)
42
+
43
+ if (!existsSync(vcpkgRoot)) {
44
+ await runCommand("git", ["clone", "https://github.com/microsoft/vcpkg", vcpkgRoot], {
45
+ dryRun
46
+ })
47
+ }
48
+
49
+ if (process.platform === "win32") {
50
+ await runCommand("cmd", ["/c", "bootstrap-vcpkg.bat", "-disableMetrics"], {
51
+ cwd: vcpkgRoot,
52
+ dryRun
53
+ })
54
+ } else {
55
+ await runCommand("bash", ["./bootstrap-vcpkg.sh", "-disableMetrics"], {
56
+ cwd: vcpkgRoot,
57
+ dryRun
58
+ })
59
+ }
60
+
61
+ return toolchainFile
62
+ }
package/src/lib/ui.js CHANGED
@@ -1,244 +1,244 @@
1
- import readline from "node:readline/promises"
2
- import { stdin as input, stdout as output } from "node:process"
3
-
4
- const ansi = {
5
- reset: "\u001b[0m",
6
- bold: "\u001b[1m",
7
- dim: "\u001b[2m",
8
- cyan: "\u001b[36m",
9
- gray: "\u001b[90m",
10
- green: "\u001b[32m",
11
- yellow: "\u001b[33m",
12
- red: "\u001b[31m"
13
- }
14
-
15
- function style(text, code) {
16
- if (!output.isTTY) {
17
- return text
18
- }
19
-
20
- return `${code}${text}${ansi.reset}`
21
- }
22
-
23
- export function isInteractiveSession() {
24
- return Boolean(input.isTTY && output.isTTY)
25
- }
26
-
27
- export function bold(text) {
28
- return style(text, ansi.bold)
29
- }
30
-
31
- export function dim(text) {
32
- return style(text, ansi.dim)
33
- }
34
-
35
- export function accent(text) {
36
- return style(text, ansi.cyan)
37
- }
38
-
39
- export function success(text) {
40
- return style(text, ansi.green)
41
- }
42
-
43
- export function warning(text) {
44
- return style(text, ansi.yellow)
45
- }
46
-
47
- export function danger(text) {
48
- return style(text, ansi.red)
49
- }
50
-
51
- export function printBanner(title, subtitle) {
52
- console.log(bold(title))
53
- if (subtitle) {
54
- console.log(dim(subtitle))
55
- }
56
- console.log("")
57
- }
58
-
59
- export function printSection(title) {
60
- console.log(accent(title))
61
- }
62
-
63
- export function printMutedLine(text = "") {
64
- console.log(dim(text))
65
- }
66
-
67
- export function printKeyValueTable(entries) {
68
- if (entries.length === 0) {
69
- return
70
- }
71
-
72
- const width = entries.reduce((max, [key]) => Math.max(max, key.length), 0)
73
-
74
- for (const [key, value] of entries) {
75
- console.log(` ${dim(key.padEnd(width))} ${value}`)
76
- }
77
- }
78
-
79
- function formatStatus(status, width) {
80
- const normalized = String(status).toLowerCase()
81
- const padded = normalized.toUpperCase().padEnd(width)
82
-
83
- if (normalized === "ok" || normalized === "done" || normalized === "ready") {
84
- return success(padded)
85
- }
86
-
87
- if (normalized === "warn" || normalized === "skip") {
88
- return warning(padded)
89
- }
90
-
91
- if (normalized === "missing" || normalized === "error") {
92
- return danger(padded)
93
- }
94
-
95
- return accent(padded)
96
- }
97
-
98
- export function printStatusTable(entries) {
99
- if (entries.length === 0) {
100
- return
101
- }
102
-
103
- const statusWidth = entries.reduce((max, [status]) => Math.max(max, String(status).length), 0)
104
- const labelWidth = entries.reduce((max, [, label]) => Math.max(max, label.length), 0)
105
-
106
- for (const [status, label, detail = ""] of entries) {
107
- const suffix = detail ? ` ${detail}` : ""
108
- console.log(` ${formatStatus(status, statusWidth)} ${label.padEnd(labelWidth)}${suffix}`)
109
- }
110
- }
111
-
112
- export function printCommandList(commands) {
113
- if (commands.length === 0) {
114
- return
115
- }
116
-
117
- const width = commands.reduce((max, command) => Math.max(max, command.name.length), 0)
118
-
119
- for (const command of commands) {
120
- console.log(` ${bold(command.name.padEnd(width))} ${command.description}`)
121
- }
122
- }
123
-
124
- export function createProgress(total, label = "Progress") {
125
- let current = 0
126
- let lastWidth = 0
127
-
128
- function render(message) {
129
- const width = 24
130
- const ratio = total === 0 ? 1 : current / total
131
- const filled = Math.round(ratio * width)
132
- const percentage = `${Math.round(ratio * 100)}`.padStart(3, " ")
133
- const bar = `${"#".repeat(filled)}${"-".repeat(width - filled)}`
134
- const line = `${dim(label)} [${bar}] ${percentage}% ${message}`
135
-
136
- if (output.isTTY) {
137
- const padded = line.padEnd(lastWidth, " ")
138
- output.write(`\r${padded}`)
139
- lastWidth = Math.max(lastWidth, line.length)
140
- if (current >= total) {
141
- output.write("\n")
142
- }
143
- return
144
- }
145
-
146
- console.log(line)
147
- }
148
-
149
- return {
150
- tick(message) {
151
- current += 1
152
- render(message)
153
- },
154
- complete(message) {
155
- current = total
156
- render(message)
157
- }
158
- }
159
- }
160
-
161
- export async function withPromptSession(callback) {
162
- const rl = readline.createInterface({ input, output })
163
-
164
- try {
165
- return await callback(rl)
166
- } finally {
167
- rl.close()
168
- }
169
- }
170
-
171
- export async function promptText(rl, options) {
172
- const { label, defaultValue = "", validate } = options
173
-
174
- while (true) {
175
- const suffix = defaultValue ? ` ${dim(`[${defaultValue}]`)}` : ""
176
- const answer = (await rl.question(`${label}${suffix}: `)).trim()
177
- const value = answer === "" ? defaultValue : answer
178
-
179
- if (!validate) {
180
- return value
181
- }
182
-
183
- const result = validate(value)
184
- if (result === true) {
185
- return value
186
- }
187
-
188
- console.log(dim(typeof result === "string" ? result : "Invalid value"))
189
- }
190
- }
191
-
192
- export async function promptConfirm(rl, options) {
193
- const { label, defaultValue = true } = options
194
- const hint = defaultValue ? "[Y/n]" : "[y/N]"
195
-
196
- while (true) {
197
- const answer = (await rl.question(`${label} ${dim(hint)}: `)).trim().toLowerCase()
198
-
199
- if (answer === "") {
200
- return defaultValue
201
- }
202
-
203
- if (answer === "y" || answer === "yes") {
204
- return true
205
- }
206
-
207
- if (answer === "n" || answer === "no") {
208
- return false
209
- }
210
- }
211
- }
212
-
213
- export async function promptSelect(rl, options) {
214
- const { label, choices, defaultValue } = options
215
-
216
- printSection(label)
217
- for (let index = 0; index < choices.length; index += 1) {
218
- const choice = choices[index]
219
- const marker = `${index + 1}.`
220
- const recommended = choice.value === defaultValue ? ` ${dim("(recommended)")}` : ""
221
-
222
- console.log(` ${marker} ${choice.label}${recommended}`)
223
- if (choice.description) {
224
- console.log(` ${dim(choice.description)}`)
225
- }
226
- }
227
-
228
- const fallbackIndex = Math.max(
229
- 0,
230
- choices.findIndex((choice) => choice.value === defaultValue)
231
- )
232
-
233
- while (true) {
234
- const answer = (await rl.question(`Choose ${dim(`[${fallbackIndex + 1}]`)}: `)).trim()
235
- const selectedIndex = answer === "" ? fallbackIndex : Number.parseInt(answer, 10) - 1
236
-
237
- if (choices[selectedIndex]) {
238
- console.log("")
239
- return choices[selectedIndex].value
240
- }
241
-
242
- console.log(dim("Select one of the listed options."))
243
- }
244
- }
1
+ import readline from "node:readline/promises"
2
+ import { stdin as input, stdout as output } from "node:process"
3
+
4
+ const ansi = {
5
+ reset: "\u001b[0m",
6
+ bold: "\u001b[1m",
7
+ dim: "\u001b[2m",
8
+ cyan: "\u001b[36m",
9
+ gray: "\u001b[90m",
10
+ green: "\u001b[32m",
11
+ yellow: "\u001b[33m",
12
+ red: "\u001b[31m"
13
+ }
14
+
15
+ function style(text, code) {
16
+ if (!output.isTTY) {
17
+ return text
18
+ }
19
+
20
+ return `${code}${text}${ansi.reset}`
21
+ }
22
+
23
+ export function isInteractiveSession() {
24
+ return Boolean(input.isTTY && output.isTTY)
25
+ }
26
+
27
+ export function bold(text) {
28
+ return style(text, ansi.bold)
29
+ }
30
+
31
+ export function dim(text) {
32
+ return style(text, ansi.dim)
33
+ }
34
+
35
+ export function accent(text) {
36
+ return style(text, ansi.cyan)
37
+ }
38
+
39
+ export function success(text) {
40
+ return style(text, ansi.green)
41
+ }
42
+
43
+ export function warning(text) {
44
+ return style(text, ansi.yellow)
45
+ }
46
+
47
+ export function danger(text) {
48
+ return style(text, ansi.red)
49
+ }
50
+
51
+ export function printBanner(title, subtitle) {
52
+ console.log(bold(title))
53
+ if (subtitle) {
54
+ console.log(dim(subtitle))
55
+ }
56
+ console.log("")
57
+ }
58
+
59
+ export function printSection(title) {
60
+ console.log(accent(title))
61
+ }
62
+
63
+ export function printMutedLine(text = "") {
64
+ console.log(dim(text))
65
+ }
66
+
67
+ export function printKeyValueTable(entries) {
68
+ if (entries.length === 0) {
69
+ return
70
+ }
71
+
72
+ const width = entries.reduce((max, [key]) => Math.max(max, key.length), 0)
73
+
74
+ for (const [key, value] of entries) {
75
+ console.log(` ${dim(key.padEnd(width))} ${value}`)
76
+ }
77
+ }
78
+
79
+ function formatStatus(status, width) {
80
+ const normalized = String(status).toLowerCase()
81
+ const padded = normalized.toUpperCase().padEnd(width)
82
+
83
+ if (normalized === "ok" || normalized === "done" || normalized === "ready") {
84
+ return success(padded)
85
+ }
86
+
87
+ if (normalized === "warn" || normalized === "skip") {
88
+ return warning(padded)
89
+ }
90
+
91
+ if (normalized === "missing" || normalized === "error") {
92
+ return danger(padded)
93
+ }
94
+
95
+ return accent(padded)
96
+ }
97
+
98
+ export function printStatusTable(entries) {
99
+ if (entries.length === 0) {
100
+ return
101
+ }
102
+
103
+ const statusWidth = entries.reduce((max, [status]) => Math.max(max, String(status).length), 0)
104
+ const labelWidth = entries.reduce((max, [, label]) => Math.max(max, label.length), 0)
105
+
106
+ for (const [status, label, detail = ""] of entries) {
107
+ const suffix = detail ? ` ${detail}` : ""
108
+ console.log(` ${formatStatus(status, statusWidth)} ${label.padEnd(labelWidth)}${suffix}`)
109
+ }
110
+ }
111
+
112
+ export function printCommandList(commands) {
113
+ if (commands.length === 0) {
114
+ return
115
+ }
116
+
117
+ const width = commands.reduce((max, command) => Math.max(max, command.name.length), 0)
118
+
119
+ for (const command of commands) {
120
+ console.log(` ${bold(command.name.padEnd(width))} ${command.description}`)
121
+ }
122
+ }
123
+
124
+ export function createProgress(total, label = "Progress") {
125
+ let current = 0
126
+ let lastWidth = 0
127
+
128
+ function render(message) {
129
+ const width = 24
130
+ const ratio = total === 0 ? 1 : current / total
131
+ const filled = Math.round(ratio * width)
132
+ const percentage = `${Math.round(ratio * 100)}`.padStart(3, " ")
133
+ const bar = `${"#".repeat(filled)}${"-".repeat(width - filled)}`
134
+ const line = `${dim(label)} [${bar}] ${percentage}% ${message}`
135
+
136
+ if (output.isTTY) {
137
+ const padded = line.padEnd(lastWidth, " ")
138
+ output.write(`\r${padded}`)
139
+ lastWidth = Math.max(lastWidth, line.length)
140
+ if (current >= total) {
141
+ output.write("\n")
142
+ }
143
+ return
144
+ }
145
+
146
+ console.log(line)
147
+ }
148
+
149
+ return {
150
+ tick(message) {
151
+ current += 1
152
+ render(message)
153
+ },
154
+ complete(message) {
155
+ current = total
156
+ render(message)
157
+ }
158
+ }
159
+ }
160
+
161
+ export async function withPromptSession(callback) {
162
+ const rl = readline.createInterface({ input, output })
163
+
164
+ try {
165
+ return await callback(rl)
166
+ } finally {
167
+ rl.close()
168
+ }
169
+ }
170
+
171
+ export async function promptText(rl, options) {
172
+ const { label, defaultValue = "", validate } = options
173
+
174
+ while (true) {
175
+ const suffix = defaultValue ? ` ${dim(`[${defaultValue}]`)}` : ""
176
+ const answer = (await rl.question(`${label}${suffix}: `)).trim()
177
+ const value = answer === "" ? defaultValue : answer
178
+
179
+ if (!validate) {
180
+ return value
181
+ }
182
+
183
+ const result = validate(value)
184
+ if (result === true) {
185
+ return value
186
+ }
187
+
188
+ console.log(dim(typeof result === "string" ? result : "Invalid value"))
189
+ }
190
+ }
191
+
192
+ export async function promptConfirm(rl, options) {
193
+ const { label, defaultValue = true } = options
194
+ const hint = defaultValue ? "[Y/n]" : "[y/N]"
195
+
196
+ while (true) {
197
+ const answer = (await rl.question(`${label} ${dim(hint)}: `)).trim().toLowerCase()
198
+
199
+ if (answer === "") {
200
+ return defaultValue
201
+ }
202
+
203
+ if (answer === "y" || answer === "yes") {
204
+ return true
205
+ }
206
+
207
+ if (answer === "n" || answer === "no") {
208
+ return false
209
+ }
210
+ }
211
+ }
212
+
213
+ export async function promptSelect(rl, options) {
214
+ const { label, choices, defaultValue } = options
215
+
216
+ printSection(label)
217
+ for (let index = 0; index < choices.length; index += 1) {
218
+ const choice = choices[index]
219
+ const marker = `${index + 1}.`
220
+ const recommended = choice.value === defaultValue ? ` ${dim("(recommended)")}` : ""
221
+
222
+ console.log(` ${marker} ${choice.label}${recommended}`)
223
+ if (choice.description) {
224
+ console.log(` ${dim(choice.description)}`)
225
+ }
226
+ }
227
+
228
+ const fallbackIndex = Math.max(
229
+ 0,
230
+ choices.findIndex((choice) => choice.value === defaultValue)
231
+ )
232
+
233
+ while (true) {
234
+ const answer = (await rl.question(`Choose ${dim(`[${fallbackIndex + 1}]`)}: `)).trim()
235
+ const selectedIndex = answer === "" ? fallbackIndex : Number.parseInt(answer, 10) - 1
236
+
237
+ if (choices[selectedIndex]) {
238
+ console.log("")
239
+ return choices[selectedIndex].value
240
+ }
241
+
242
+ console.log(dim("Select one of the listed options."))
243
+ }
244
+ }
@@ -1,15 +1,15 @@
1
- # Reset App
2
-
3
- Generated with `reset-framework-cli`.
4
-
5
- ## Commands
6
-
7
- - `reset-framework-cli dev`
8
- - `reset-framework-cli build`
9
- - `reset-framework-cli package`
10
-
11
- ## Project files
12
-
13
- - `reset.config.json`: desktop app metadata and runtime config
14
- - `frontend/` or project root: web frontend source, depending on the selected layout
15
- - `.reset/`: generated build output and native runtime cache
1
+ # Reset App
2
+
3
+ Generated with `reset-framework-cli`.
4
+
5
+ ## Commands
6
+
7
+ - `reset-framework-cli dev`
8
+ - `reset-framework-cli build`
9
+ - `reset-framework-cli package`
10
+
11
+ ## Project files
12
+
13
+ - `reset.config.json`: desktop app metadata and runtime config
14
+ - `frontend/` or project root: web frontend source, depending on the selected layout
15
+ - `.reset/`: generated build output and native runtime cache