create-vidra-app 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -6
- package/dist/cli.js +520 -229
- package/dist/index.js +136 -56
- package/package.json +10 -1
- package/templates/react-vite/README.md +7 -3
- package/templates/react-vite/package.json +2 -1
package/dist/cli.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
// src/cli.ts
|
|
2
|
-
import chalk7 from "chalk";
|
|
3
|
-
|
|
4
1
|
// src/commands/build.ts
|
|
5
2
|
import path5 from "path";
|
|
6
3
|
import fs4 from "fs-extra";
|
|
7
4
|
import { execSync as execSync3 } from "child_process";
|
|
8
|
-
import chalk5 from "chalk";
|
|
9
5
|
|
|
10
6
|
// src/utils.ts
|
|
11
7
|
var parseArgs = (argv) => {
|
|
@@ -14,7 +10,17 @@ var parseArgs = (argv) => {
|
|
|
14
10
|
const arg = argv[i];
|
|
15
11
|
if (arg.startsWith("--")) {
|
|
16
12
|
const [key, val] = arg.slice(2).split("=");
|
|
17
|
-
|
|
13
|
+
if (val !== void 0) {
|
|
14
|
+
args[key] = val;
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
const next = argv[i + 1];
|
|
18
|
+
if (next !== void 0 && !next.startsWith("--")) {
|
|
19
|
+
args[key] = next;
|
|
20
|
+
i++;
|
|
21
|
+
} else {
|
|
22
|
+
args[key] = true;
|
|
23
|
+
}
|
|
18
24
|
} else {
|
|
19
25
|
args._.push(arg);
|
|
20
26
|
}
|
|
@@ -24,10 +30,69 @@ var parseArgs = (argv) => {
|
|
|
24
30
|
|
|
25
31
|
// src/exec.ts
|
|
26
32
|
import { execSync } from "child_process";
|
|
33
|
+
|
|
34
|
+
// src/theme.ts
|
|
27
35
|
import chalk from "chalk";
|
|
28
|
-
var
|
|
29
|
-
|
|
30
|
-
|
|
36
|
+
var CLI_VERSION = "0.1.5";
|
|
37
|
+
var STEP_LABEL_WIDTH = 16;
|
|
38
|
+
var lime = chalk.hex("#c8f751");
|
|
39
|
+
var value = chalk.hex("#e8e8ec");
|
|
40
|
+
var dim = chalk.hex("#7a7a86");
|
|
41
|
+
var amber = chalk.hex("#ffcf5c");
|
|
42
|
+
var green = chalk.hex("#86d98f");
|
|
43
|
+
var red = chalk.hex("#ff8585");
|
|
44
|
+
var slate = chalk.hex("#a9b0bd");
|
|
45
|
+
var uiColor = chalk.hex("#6fd3e0");
|
|
46
|
+
var hostColor = chalk.hex("#a48ce8");
|
|
47
|
+
var GLYPH_CHAR = {
|
|
48
|
+
done: "\u2713",
|
|
49
|
+
active: "\u25B8",
|
|
50
|
+
error: "\u2717",
|
|
51
|
+
manual: "?",
|
|
52
|
+
plan: "\u25C6",
|
|
53
|
+
skip: "\u2298"
|
|
54
|
+
};
|
|
55
|
+
var GLYPH_COLOR = {
|
|
56
|
+
done: green,
|
|
57
|
+
active: lime,
|
|
58
|
+
error: red,
|
|
59
|
+
manual: amber,
|
|
60
|
+
plan: slate,
|
|
61
|
+
skip: slate
|
|
62
|
+
};
|
|
63
|
+
var glyph = (name) => GLYPH_COLOR[name](GLYPH_CHAR[name]);
|
|
64
|
+
var TAG_COLOR = {
|
|
65
|
+
ui: uiColor,
|
|
66
|
+
host: hostColor
|
|
67
|
+
};
|
|
68
|
+
var TAG_WIDTH = 6;
|
|
69
|
+
var tag = (name) => TAG_COLOR[name](`[${name}]`.padEnd(TAG_WIDTH));
|
|
70
|
+
var blankTag = () => " ".repeat(TAG_WIDTH);
|
|
71
|
+
var wordmark = () => lime("vidra");
|
|
72
|
+
var header = (sub, context) => {
|
|
73
|
+
const base = ` ${wordmark()} ${value(sub)}`;
|
|
74
|
+
return context ? `${base} ${dim(`\u2014 ${context}`)}` : base;
|
|
75
|
+
};
|
|
76
|
+
var kv = (label, val, width = 9) => ` ${dim(label.padEnd(width))} ${value(val)}`;
|
|
77
|
+
var row = (opts) => {
|
|
78
|
+
const parts = [` ${glyph(opts.glyph)}`];
|
|
79
|
+
if (opts.label !== void 0) {
|
|
80
|
+
const padded = opts.labelWidth ? opts.label.padEnd(opts.labelWidth) : opts.label;
|
|
81
|
+
parts.push(value(padded));
|
|
82
|
+
}
|
|
83
|
+
if (opts.detail) parts.push(opts.detail);
|
|
84
|
+
return parts.join(" ");
|
|
85
|
+
};
|
|
86
|
+
var taggedRow = (glyphName, tagName, text) => ` ${glyph(glyphName)} ${tagName ? tag(tagName) : blankTag()} ${text}`;
|
|
87
|
+
var streamPrefix = (tagName) => ` ${dim("\xB7")} ${tag(tagName)}`;
|
|
88
|
+
var footer = (content) => ` ${content}`;
|
|
89
|
+
var fixLine = (cmd, label = "fix:") => ` ${amber(label)} ${lime(cmd)}`;
|
|
90
|
+
var planBadge = (text = "PLAN ONLY \xB7 BEING BUILT") => amber(`[ ${text} ]`);
|
|
91
|
+
|
|
92
|
+
// src/exec.ts
|
|
93
|
+
var toText = (value2) => {
|
|
94
|
+
if (value2 == null) return "";
|
|
95
|
+
return Buffer.isBuffer(value2) ? value2.toString() : value2;
|
|
31
96
|
};
|
|
32
97
|
var formatProcessError = (error) => {
|
|
33
98
|
const err = error;
|
|
@@ -49,7 +114,6 @@ var formatBuildError = (error) => {
|
|
|
49
114
|
// src/project.ts
|
|
50
115
|
import path from "path";
|
|
51
116
|
import fs from "fs-extra";
|
|
52
|
-
import chalk2 from "chalk";
|
|
53
117
|
var detectPlatform = () => {
|
|
54
118
|
switch (process.platform) {
|
|
55
119
|
case "darwin":
|
|
@@ -88,9 +152,15 @@ var detectProject = (cwd) => {
|
|
|
88
152
|
dir = parent;
|
|
89
153
|
}
|
|
90
154
|
console.error(
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
155
|
+
row({
|
|
156
|
+
glyph: "error",
|
|
157
|
+
detail: dim(
|
|
158
|
+
"Could not detect Vidra project. Run this command from your project root."
|
|
159
|
+
)
|
|
160
|
+
})
|
|
161
|
+
);
|
|
162
|
+
console.error(
|
|
163
|
+
footer(dim("expected: package.json, ui/, src/<Name>.Host/<Name>.Host.csproj"))
|
|
94
164
|
);
|
|
95
165
|
process.exit(1);
|
|
96
166
|
};
|
|
@@ -161,7 +231,6 @@ var macosTarget = {
|
|
|
161
231
|
// src/signing.ts
|
|
162
232
|
import path3 from "path";
|
|
163
233
|
import { execFileSync } from "child_process";
|
|
164
|
-
import chalk3 from "chalk";
|
|
165
234
|
var signMacAppBundleIfPossible = (appBundle, options) => {
|
|
166
235
|
if (process.platform !== "darwin") return;
|
|
167
236
|
const identity = resolveMacCodeSigningIdentity();
|
|
@@ -176,20 +245,30 @@ var signMacAppBundleIfPossible = (appBundle, options) => {
|
|
|
176
245
|
}
|
|
177
246
|
);
|
|
178
247
|
options.log(
|
|
179
|
-
|
|
248
|
+
row({
|
|
249
|
+
glyph: "done",
|
|
250
|
+
label: "codesign",
|
|
251
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
252
|
+
detail: identity ? `${value(label)} ${dim(`with ${identity}`)}` : `${value(label)} ${dim("ad-hoc (-)")}`
|
|
253
|
+
})
|
|
180
254
|
);
|
|
181
255
|
} catch (error) {
|
|
182
256
|
options.warn(
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
257
|
+
row({
|
|
258
|
+
glyph: "manual",
|
|
259
|
+
label: "codesign",
|
|
260
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
261
|
+
detail: dim("could not sign the app bundle; it may fail to launch")
|
|
262
|
+
})
|
|
186
263
|
);
|
|
187
264
|
options.warn(
|
|
188
|
-
|
|
189
|
-
|
|
265
|
+
footer(
|
|
266
|
+
dim(
|
|
267
|
+
"install Xcode or the Command Line Tools (provides `codesign`), or set VIDRA_MACOS_CODESIGN_KEY."
|
|
268
|
+
)
|
|
190
269
|
)
|
|
191
270
|
);
|
|
192
|
-
options.warn(
|
|
271
|
+
options.warn(dim(formatExecError(error)));
|
|
193
272
|
}
|
|
194
273
|
};
|
|
195
274
|
var resolveMacCodeSigningIdentity = () => {
|
|
@@ -206,7 +285,7 @@ var resolveMacCodeSigningIdentity = () => {
|
|
|
206
285
|
encoding: "utf8"
|
|
207
286
|
}
|
|
208
287
|
);
|
|
209
|
-
const identities = output.split(/\r?\n/).map((line) => line.match(/"([^"]+)"/)?.[1] ?? null).filter((
|
|
288
|
+
const identities = output.split(/\r?\n/).map((line) => line.match(/"([^"]+)"/)?.[1] ?? null).filter((value2) => value2 !== null);
|
|
210
289
|
return identities.find((identity) => identity.startsWith("Apple Development:")) ?? identities.find((identity) => identity.startsWith("Developer ID Application:")) ?? null;
|
|
211
290
|
} catch {
|
|
212
291
|
return null;
|
|
@@ -225,45 +304,74 @@ var formatExecError = (error) => {
|
|
|
225
304
|
|
|
226
305
|
// src/targets/windows.ts
|
|
227
306
|
import path4 from "path";
|
|
307
|
+
import os2 from "os";
|
|
228
308
|
import fs3 from "fs-extra";
|
|
309
|
+
import { execFileSync as execFileSync2 } from "child_process";
|
|
229
310
|
var windowsTarget = {
|
|
230
311
|
name: "windows",
|
|
231
312
|
framework: "net10.0-windows10.0.19041.0",
|
|
232
|
-
|
|
313
|
+
// `RuntimeIdentifierOverride` (rather than `-r`/`RuntimeIdentifier`) is the
|
|
314
|
+
// MAUI-recommended way to set the Windows RID — it sidesteps WindowsAppSDK
|
|
315
|
+
// issue #3337, which otherwise pulls in the wrong packaging assets.
|
|
316
|
+
extraPublishArgs: "-p:WindowsPackageType=None -p:SelfContained=true -p:WindowsAppSDKSelfContained=true -p:RuntimeIdentifierOverride=win-x64",
|
|
233
317
|
findBundle(publishDir, _projectName) {
|
|
234
|
-
const
|
|
235
|
-
if (
|
|
236
|
-
|
|
237
|
-
withFileTypes: true
|
|
238
|
-
})) {
|
|
239
|
-
if (!entry.isDirectory()) continue;
|
|
240
|
-
const subDir = path4.join(appPackagesDir, entry.name);
|
|
241
|
-
for (const file of fs3.readdirSync(subDir)) {
|
|
242
|
-
if (file.endsWith(".msix")) {
|
|
243
|
-
return path4.join(subDir, file);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
return null;
|
|
318
|
+
const preferred = path4.join(publishDir, "win-x64", "publish");
|
|
319
|
+
if (dirContainsExe(preferred)) return preferred;
|
|
320
|
+
return findDirWithExe(publishDir);
|
|
248
321
|
},
|
|
249
|
-
async package(
|
|
250
|
-
const outName = `${meta.projectName}-${meta.displayVersion}-windows.
|
|
322
|
+
async package(publishOutputDir, outputDir, meta) {
|
|
323
|
+
const outName = `${meta.projectName}-${meta.displayVersion}-windows.zip`;
|
|
251
324
|
const outPath = path4.join(outputDir, outName);
|
|
252
|
-
fs3.
|
|
325
|
+
if (fs3.existsSync(outPath)) fs3.removeSync(outPath);
|
|
326
|
+
const staging = fs3.mkdtempSync(path4.join(os2.tmpdir(), "vidra-zip-"));
|
|
327
|
+
const stagedApp = path4.join(staging, meta.projectName);
|
|
328
|
+
try {
|
|
329
|
+
fs3.copySync(publishOutputDir, stagedApp);
|
|
330
|
+
execFileSync2(
|
|
331
|
+
"powershell",
|
|
332
|
+
[
|
|
333
|
+
"-NoProfile",
|
|
334
|
+
"-NonInteractive",
|
|
335
|
+
"-Command",
|
|
336
|
+
`Compress-Archive -Path "${stagedApp}" -DestinationPath "${outPath}" -Force`
|
|
337
|
+
],
|
|
338
|
+
{ stdio: "pipe" }
|
|
339
|
+
);
|
|
340
|
+
} finally {
|
|
341
|
+
fs3.removeSync(staging);
|
|
342
|
+
}
|
|
253
343
|
return outPath;
|
|
254
344
|
}
|
|
255
345
|
};
|
|
346
|
+
var dirContainsExe = (dir) => fs3.existsSync(dir) && fs3.readdirSync(dir, { withFileTypes: true }).some((e) => e.isFile() && e.name.toLowerCase().endsWith(".exe"));
|
|
347
|
+
var findDirWithExe = (root) => {
|
|
348
|
+
if (!fs3.existsSync(root)) return null;
|
|
349
|
+
let fallback = null;
|
|
350
|
+
const walk = (dir) => {
|
|
351
|
+
if (dirContainsExe(dir)) {
|
|
352
|
+
if (path4.basename(dir) === "publish") return dir;
|
|
353
|
+
fallback ??= dir;
|
|
354
|
+
}
|
|
355
|
+
for (const e of fs3.readdirSync(dir, { withFileTypes: true })) {
|
|
356
|
+
if (e.isDirectory()) {
|
|
357
|
+
const found = walk(path4.join(dir, e.name));
|
|
358
|
+
if (found) return found;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
return null;
|
|
362
|
+
};
|
|
363
|
+
return walk(root) ?? fallback;
|
|
364
|
+
};
|
|
256
365
|
|
|
257
366
|
// src/doctor.ts
|
|
258
|
-
import { execFileSync as
|
|
367
|
+
import { execFileSync as execFileSync3 } from "child_process";
|
|
259
368
|
import prompts from "prompts";
|
|
260
|
-
import chalk4 from "chalk";
|
|
261
369
|
var DOTNET = process.platform === "win32" ? "dotnet.exe" : "dotnet";
|
|
262
370
|
var MAUI_DOCS = "https://learn.microsoft.com/dotnet/maui/get-started/installation";
|
|
263
371
|
var bufToStr = (v) => v == null ? "" : Buffer.isBuffer(v) ? v.toString() : v;
|
|
264
372
|
var run = (cmd, args) => {
|
|
265
373
|
try {
|
|
266
|
-
const stdout =
|
|
374
|
+
const stdout = execFileSync3(cmd, args, {
|
|
267
375
|
encoding: "utf-8",
|
|
268
376
|
stdio: ["ignore", "pipe", "pipe"]
|
|
269
377
|
});
|
|
@@ -384,19 +492,32 @@ var collectRequirements = (opts = {}) => {
|
|
|
384
492
|
}
|
|
385
493
|
return reqs;
|
|
386
494
|
};
|
|
495
|
+
var STATUS_GLYPH = {
|
|
496
|
+
ok: "done",
|
|
497
|
+
missing: "error",
|
|
498
|
+
unknown: "manual"
|
|
499
|
+
};
|
|
387
500
|
var printRequirements = (reqs) => {
|
|
501
|
+
const labelWidth = Math.max(0, ...reqs.map((r) => r.name.length)) + 2;
|
|
388
502
|
for (const r of reqs) {
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
503
|
+
console.log(
|
|
504
|
+
row({
|
|
505
|
+
glyph: STATUS_GLYPH[r.status],
|
|
506
|
+
label: r.name,
|
|
507
|
+
labelWidth,
|
|
508
|
+
detail: r.detail ? dim(r.detail) : void 0
|
|
509
|
+
})
|
|
510
|
+
);
|
|
392
511
|
if (r.status === "missing" && r.fix) {
|
|
393
|
-
console.log(
|
|
512
|
+
console.log(fixLine(r.fix));
|
|
394
513
|
}
|
|
395
514
|
}
|
|
396
515
|
};
|
|
397
516
|
var runDoctor = async () => {
|
|
398
517
|
console.log();
|
|
399
|
-
console.log(` ${
|
|
518
|
+
console.log(` ${lime("vidra")} ${value("doctor")}`);
|
|
519
|
+
console.log();
|
|
520
|
+
console.log(footer(dim("checking your environment\u2026")));
|
|
400
521
|
console.log();
|
|
401
522
|
const reqs = collectRequirements();
|
|
402
523
|
printRequirements(reqs);
|
|
@@ -404,17 +525,22 @@ var runDoctor = async () => {
|
|
|
404
525
|
const missing = reqs.filter((r) => r.status === "missing");
|
|
405
526
|
if (missing.length === 0) {
|
|
406
527
|
console.log(
|
|
407
|
-
|
|
408
|
-
"
|
|
409
|
-
|
|
528
|
+
footer(
|
|
529
|
+
`${dim("all checks passed \u2014 you're ready to run")} ${lime(
|
|
530
|
+
"vidra dev"
|
|
531
|
+
)}${dim(".")}`
|
|
532
|
+
)
|
|
410
533
|
);
|
|
411
534
|
console.log();
|
|
412
535
|
return 0;
|
|
413
536
|
}
|
|
537
|
+
const n = missing.length;
|
|
414
538
|
console.log(
|
|
415
|
-
|
|
416
|
-
`${
|
|
417
|
-
|
|
539
|
+
footer(
|
|
540
|
+
`${dim(
|
|
541
|
+
`${n} issue${n === 1 ? "" : "s"} found. apply the ${n === 1 ? "fix" : "fixes"} above, then re-run`
|
|
542
|
+
)} ${lime("vidra doctor")}${dim(".")}`
|
|
543
|
+
)
|
|
418
544
|
);
|
|
419
545
|
console.log();
|
|
420
546
|
return 1;
|
|
@@ -422,25 +548,32 @@ var runDoctor = async () => {
|
|
|
422
548
|
var installWorkload = (csprojPath) => {
|
|
423
549
|
const args = csprojPath ? ["workload", "restore", csprojPath] : ["workload", "install", "maui"];
|
|
424
550
|
console.log();
|
|
425
|
-
console.log(` ${chalk4.dim(`Running: ${DOTNET} ${args.join(" ")}`)}`);
|
|
426
551
|
console.log(
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
552
|
+
row({
|
|
553
|
+
glyph: "active",
|
|
554
|
+
detail: `${dim("running")} ${value(`${DOTNET} ${args.join(" ")}`)}`
|
|
555
|
+
})
|
|
556
|
+
);
|
|
557
|
+
console.log(
|
|
558
|
+
footer(
|
|
559
|
+
dim("this can download several hundred MB and take a few minutes.")
|
|
560
|
+
)
|
|
430
561
|
);
|
|
431
562
|
console.log();
|
|
432
563
|
try {
|
|
433
|
-
|
|
564
|
+
execFileSync3(DOTNET, args, { stdio: "inherit" });
|
|
434
565
|
return true;
|
|
435
566
|
} catch {
|
|
436
567
|
console.error();
|
|
437
|
-
console.error(
|
|
568
|
+
console.error(row({ glyph: "error", label: "workload install failed" }));
|
|
438
569
|
console.error(
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
570
|
+
footer(
|
|
571
|
+
dim(
|
|
572
|
+
"if this is a permissions error, your SDK is in a system location and needs elevation:"
|
|
573
|
+
)
|
|
574
|
+
)
|
|
442
575
|
);
|
|
443
|
-
console.error(
|
|
576
|
+
console.error(fixLine("sudo dotnet workload install maui"));
|
|
444
577
|
console.error();
|
|
445
578
|
return false;
|
|
446
579
|
}
|
|
@@ -449,9 +582,15 @@ var ensureMauiWorkload = async (opts = {}) => {
|
|
|
449
582
|
const dotnet = checkDotnetSdk();
|
|
450
583
|
if (dotnet.status === "missing") {
|
|
451
584
|
console.log();
|
|
452
|
-
console.log(
|
|
585
|
+
console.log(
|
|
586
|
+
row({
|
|
587
|
+
glyph: "error",
|
|
588
|
+
label: dotnet.name,
|
|
589
|
+
detail: dotnet.detail ? dim(dotnet.detail) : void 0
|
|
590
|
+
})
|
|
591
|
+
);
|
|
453
592
|
if (dotnet.fix) {
|
|
454
|
-
console.log(
|
|
593
|
+
console.log(fixLine(dotnet.fix));
|
|
455
594
|
}
|
|
456
595
|
return false;
|
|
457
596
|
}
|
|
@@ -459,7 +598,11 @@ var ensureMauiWorkload = async (opts = {}) => {
|
|
|
459
598
|
if (isMauiWorkloadInstalled()) return true;
|
|
460
599
|
console.log();
|
|
461
600
|
console.log(
|
|
462
|
-
|
|
601
|
+
row({
|
|
602
|
+
glyph: "error",
|
|
603
|
+
label: ".NET MAUI workload",
|
|
604
|
+
detail: dim("required but not installed")
|
|
605
|
+
})
|
|
463
606
|
);
|
|
464
607
|
const interactive = opts.interactive ?? isInteractive();
|
|
465
608
|
if (interactive) {
|
|
@@ -477,80 +620,91 @@ var ensureMauiWorkload = async (opts = {}) => {
|
|
|
477
620
|
}
|
|
478
621
|
if (install) {
|
|
479
622
|
if (installWorkload(opts.csprojPath) && isMauiWorkloadInstalled()) {
|
|
480
|
-
console.log(
|
|
623
|
+
console.log(
|
|
624
|
+
row({
|
|
625
|
+
glyph: "done",
|
|
626
|
+
label: ".NET MAUI workload",
|
|
627
|
+
detail: dim("installed")
|
|
628
|
+
})
|
|
629
|
+
);
|
|
481
630
|
return true;
|
|
482
631
|
}
|
|
483
632
|
return false;
|
|
484
633
|
}
|
|
485
634
|
}
|
|
486
|
-
console.log(
|
|
487
|
-
|
|
488
|
-
);
|
|
489
|
-
console.log(` ${chalk4.dim("docs:")} ${chalk4.cyan(MAUI_DOCS)}`);
|
|
635
|
+
console.log(fixLine("dotnet workload install maui", "run:"));
|
|
636
|
+
console.log(fixLine(MAUI_DOCS, "docs:"));
|
|
490
637
|
return false;
|
|
491
638
|
};
|
|
492
639
|
var printWorkloadHint = () => {
|
|
493
640
|
console.error();
|
|
494
641
|
console.error(
|
|
495
|
-
|
|
496
|
-
);
|
|
497
|
-
console.error(
|
|
498
|
-
` ${chalk4.dim("fix: ")} ${chalk4.cyan("dotnet workload install maui")}`
|
|
499
|
-
);
|
|
500
|
-
console.error(
|
|
501
|
-
` ${chalk4.dim("check:")} ${chalk4.cyan("vidra doctor")}`
|
|
642
|
+
row({ glyph: "manual", label: "this looks like a missing .NET MAUI workload." })
|
|
502
643
|
);
|
|
644
|
+
console.error(fixLine("dotnet workload install maui"));
|
|
645
|
+
console.error(fixLine("vidra doctor", "check:"));
|
|
503
646
|
console.error();
|
|
504
647
|
};
|
|
505
648
|
var printXcodeHint = () => {
|
|
506
649
|
console.error();
|
|
507
650
|
console.error(
|
|
508
|
-
|
|
509
|
-
"
|
|
510
|
-
|
|
651
|
+
row({
|
|
652
|
+
glyph: "manual",
|
|
653
|
+
label: "Mac Catalyst needs the full Xcode app, not just the Command Line Tools."
|
|
654
|
+
})
|
|
511
655
|
);
|
|
512
|
-
console.error(` ${
|
|
656
|
+
console.error(` ${dim("1.")} ${value("install Xcode from the App Store")}`);
|
|
513
657
|
console.error(
|
|
514
|
-
` ${
|
|
658
|
+
` ${dim("2.")} ${lime(
|
|
515
659
|
"sudo xcode-select -s /Applications/Xcode.app/Contents/Developer"
|
|
516
660
|
)}`
|
|
517
661
|
);
|
|
518
|
-
console.error(
|
|
519
|
-
|
|
520
|
-
);
|
|
521
|
-
console.error(` ${chalk4.dim("check:")} ${chalk4.cyan("vidra doctor")}`);
|
|
662
|
+
console.error(` ${dim("3.")} ${lime("sudo xcodebuild -runFirstLaunch")}`);
|
|
663
|
+
console.error(fixLine("vidra doctor", "check:"));
|
|
522
664
|
console.error();
|
|
523
665
|
};
|
|
524
666
|
|
|
525
667
|
// src/commands/build.ts
|
|
526
|
-
var VERSION = "0.1.0";
|
|
527
668
|
var TARGETS = {
|
|
528
669
|
macos: macosTarget,
|
|
529
670
|
windows: windowsTarget
|
|
530
671
|
};
|
|
672
|
+
var packageLabel = (target) => target.name === "macos" ? "package DMG" : "package ZIP";
|
|
673
|
+
var artifactName = (project, target) => `${project.projectName}-${project.displayVersion}-${target.name}.${target.name === "macos" ? "dmg" : "zip"}`;
|
|
531
674
|
var buildCommand = async (argv) => {
|
|
532
675
|
const args = parseArgs(["_", "_", ...argv]);
|
|
533
676
|
const verbose = !!args["verbose"];
|
|
677
|
+
const plan = !!args["plan"] || !!args["dry-run"];
|
|
534
678
|
const targetName = args["target"] || detectPlatform();
|
|
535
|
-
console.log();
|
|
536
|
-
console.log(
|
|
537
|
-
` ${chalk5.bold.cyan("vidra build")} ${chalk5.dim(`v${VERSION}`)}`
|
|
538
|
-
);
|
|
539
|
-
console.log();
|
|
540
679
|
const target = TARGETS[targetName];
|
|
541
680
|
if (!target) {
|
|
542
681
|
const supported = Object.keys(TARGETS).join(", ");
|
|
682
|
+
console.error();
|
|
543
683
|
console.error(
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
684
|
+
row({
|
|
685
|
+
glyph: "error",
|
|
686
|
+
detail: dim(`unsupported target: ${targetName} \u2014 supported: ${supported}`)
|
|
687
|
+
})
|
|
547
688
|
);
|
|
548
689
|
process.exit(1);
|
|
549
690
|
}
|
|
550
691
|
const project = detectProject(process.cwd());
|
|
551
|
-
console.log(` ${chalk5.dim("Project:")} ${chalk5.cyan(project.projectName)}`);
|
|
552
|
-
console.log(` ${chalk5.dim("Target:")} ${chalk5.cyan(target.name)} (${target.framework})`);
|
|
553
692
|
console.log();
|
|
693
|
+
console.log(
|
|
694
|
+
header("build", `${target.name} \xB7 Release${plan ? " \xB7 plan" : ""}`)
|
|
695
|
+
);
|
|
696
|
+
console.log(kv("project", project.projectName));
|
|
697
|
+
console.log(kv("target", target.framework));
|
|
698
|
+
console.log();
|
|
699
|
+
if (plan) {
|
|
700
|
+
printBuildPlan(project, target);
|
|
701
|
+
console.log();
|
|
702
|
+
console.log(
|
|
703
|
+
footer(`${dim("nothing has run. re-run without")} ${lime("--plan")} ${dim("to apply.")}`)
|
|
704
|
+
);
|
|
705
|
+
console.log();
|
|
706
|
+
return;
|
|
707
|
+
}
|
|
554
708
|
if (!await ensureMauiWorkload({ csprojPath: project.csprojPath })) {
|
|
555
709
|
process.exit(1);
|
|
556
710
|
}
|
|
@@ -560,13 +714,13 @@ var buildCommand = async (argv) => {
|
|
|
560
714
|
const bundlePath = target.findBundle(publishDir, project.projectName);
|
|
561
715
|
if (!bundlePath) {
|
|
562
716
|
console.error(
|
|
563
|
-
|
|
717
|
+
row({
|
|
718
|
+
glyph: "error",
|
|
719
|
+
detail: dim(`could not find build artifact in ${publishDir}`)
|
|
720
|
+
})
|
|
564
721
|
);
|
|
565
722
|
process.exit(1);
|
|
566
723
|
}
|
|
567
|
-
console.log(
|
|
568
|
-
` ${chalk5.dim("Bundle:")} ${chalk5.cyan(path5.basename(bundlePath))}`
|
|
569
|
-
);
|
|
570
724
|
if (target.name === "macos") {
|
|
571
725
|
signMacAppBundleIfPossible(bundlePath, {
|
|
572
726
|
verbose,
|
|
@@ -574,36 +728,77 @@ var buildCommand = async (argv) => {
|
|
|
574
728
|
warn: console.warn
|
|
575
729
|
});
|
|
576
730
|
}
|
|
577
|
-
const
|
|
578
|
-
fs4.ensureDirSync(outputDir);
|
|
731
|
+
const outputPath = await stepPackage(project, target, bundlePath);
|
|
579
732
|
console.log();
|
|
580
|
-
console.log(` ${chalk5.dim(`Packaging for ${target.name}...`)}`);
|
|
581
|
-
const startPkg = Date.now();
|
|
582
|
-
let outputPath;
|
|
583
|
-
try {
|
|
584
|
-
outputPath = await target.package(bundlePath, outputDir, {
|
|
585
|
-
projectName: project.projectName,
|
|
586
|
-
displayVersion: project.displayVersion
|
|
587
|
-
});
|
|
588
|
-
} catch (e) {
|
|
589
|
-
console.error(chalk5.red(` Packaging failed.`));
|
|
590
|
-
console.error(chalk5.dim(formatProcessError(e)));
|
|
591
|
-
process.exit(1);
|
|
592
|
-
}
|
|
593
|
-
const pkgTime = ((Date.now() - startPkg) / 1e3).toFixed(1);
|
|
594
|
-
const sizeBytes = fs4.statSync(outputPath).size;
|
|
595
|
-
const sizeMB = (sizeBytes / (1024 * 1024)).toFixed(1);
|
|
596
733
|
console.log(
|
|
597
|
-
|
|
734
|
+
footer(
|
|
735
|
+
`${dim("done \u2014")} ${value(path5.relative(project.root, outputPath))}`
|
|
736
|
+
)
|
|
598
737
|
);
|
|
599
738
|
console.log();
|
|
739
|
+
};
|
|
740
|
+
var printBuildPlan = (project, target) => {
|
|
600
741
|
console.log(
|
|
601
|
-
|
|
742
|
+
row({
|
|
743
|
+
glyph: "done",
|
|
744
|
+
label: "build UI",
|
|
745
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
746
|
+
detail: `${dim("vite \u2192")} ${value("ui/dist")}`
|
|
747
|
+
})
|
|
602
748
|
);
|
|
603
|
-
console.log(
|
|
749
|
+
console.log(
|
|
750
|
+
row({
|
|
751
|
+
glyph: "done",
|
|
752
|
+
label: "copy assets",
|
|
753
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
754
|
+
detail: `${dim("\u2192")} ${value("Resources/Raw/wwwroot")}`
|
|
755
|
+
})
|
|
756
|
+
);
|
|
757
|
+
console.log(
|
|
758
|
+
row({
|
|
759
|
+
glyph: "done",
|
|
760
|
+
label: "publish .NET",
|
|
761
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
762
|
+
detail: `${dim("Release \xB7")} ${value(target.framework)}`
|
|
763
|
+
})
|
|
764
|
+
);
|
|
765
|
+
if (target.name === "macos") {
|
|
766
|
+
console.log(
|
|
767
|
+
row({
|
|
768
|
+
glyph: "done",
|
|
769
|
+
label: "codesign .app",
|
|
770
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
771
|
+
detail: dim("Apple Development, or ad-hoc (-)")
|
|
772
|
+
})
|
|
773
|
+
);
|
|
774
|
+
console.log(
|
|
775
|
+
row({
|
|
776
|
+
glyph: "plan",
|
|
777
|
+
label: "notarize",
|
|
778
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
779
|
+
detail: planBadge()
|
|
780
|
+
})
|
|
781
|
+
);
|
|
782
|
+
console.log(
|
|
783
|
+
row({
|
|
784
|
+
glyph: "active",
|
|
785
|
+
label: "package DMG",
|
|
786
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
787
|
+
detail: `${dim("hdiutil UDZO \u2192")} ${value(artifactName(project, target))}`
|
|
788
|
+
})
|
|
789
|
+
);
|
|
790
|
+
} else {
|
|
791
|
+
console.log(
|
|
792
|
+
row({
|
|
793
|
+
glyph: "active",
|
|
794
|
+
label: "package ZIP",
|
|
795
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
796
|
+
detail: `${dim("self-contained \u2192")} ${value(artifactName(project, target))}`
|
|
797
|
+
})
|
|
798
|
+
);
|
|
799
|
+
}
|
|
604
800
|
};
|
|
605
801
|
var stepBuildUi = (project, verbose) => {
|
|
606
|
-
console.log(` ${chalk5.dim("Building UI...")}`);
|
|
607
802
|
const start = Date.now();
|
|
608
803
|
try {
|
|
609
804
|
execSync3("npm run build", {
|
|
@@ -611,19 +806,38 @@ var stepBuildUi = (project, verbose) => {
|
|
|
611
806
|
stdio: verbose ? "inherit" : "pipe"
|
|
612
807
|
});
|
|
613
808
|
} catch (e) {
|
|
614
|
-
console.error(
|
|
615
|
-
|
|
809
|
+
console.error(
|
|
810
|
+
row({
|
|
811
|
+
glyph: "error",
|
|
812
|
+
label: "build UI",
|
|
813
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
814
|
+
detail: dim("vite build failed")
|
|
815
|
+
})
|
|
816
|
+
);
|
|
817
|
+
console.error(dim(formatBuildError(e)));
|
|
616
818
|
process.exit(1);
|
|
617
819
|
}
|
|
618
820
|
const elapsed = ((Date.now() - start) / 1e3).toFixed(1);
|
|
619
|
-
console.log(
|
|
620
|
-
|
|
821
|
+
console.log(
|
|
822
|
+
row({
|
|
823
|
+
glyph: "done",
|
|
824
|
+
label: "build UI",
|
|
825
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
826
|
+
detail: `${dim("vite \u2192")} ${value("ui/dist")} ${dim(`(${elapsed}s)`)}`
|
|
827
|
+
})
|
|
828
|
+
);
|
|
621
829
|
};
|
|
622
830
|
var stepCopyAssets = (project) => {
|
|
623
|
-
console.log(` ${chalk5.dim("Copying assets to host project...")}`);
|
|
624
831
|
const viteDist = path5.join(project.uiDir, "dist");
|
|
625
832
|
if (!fs4.existsSync(viteDist)) {
|
|
626
|
-
console.error(
|
|
833
|
+
console.error(
|
|
834
|
+
row({
|
|
835
|
+
glyph: "error",
|
|
836
|
+
label: "copy assets",
|
|
837
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
838
|
+
detail: dim("ui/dist not found \u2014 vite build may have failed")
|
|
839
|
+
})
|
|
840
|
+
);
|
|
627
841
|
process.exit(1);
|
|
628
842
|
}
|
|
629
843
|
const wwwroot = path5.join(project.hostDir, "Resources", "Raw", "wwwroot");
|
|
@@ -631,9 +845,13 @@ var stepCopyAssets = (project) => {
|
|
|
631
845
|
fs4.copySync(viteDist, wwwroot);
|
|
632
846
|
const fileCount = countFiles(wwwroot);
|
|
633
847
|
console.log(
|
|
634
|
-
|
|
848
|
+
row({
|
|
849
|
+
glyph: "done",
|
|
850
|
+
label: "copy assets",
|
|
851
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
852
|
+
detail: `${dim("\u2192")} ${value("Resources/Raw/wwwroot")} ${dim(`(${fileCount} files)`)}`
|
|
853
|
+
})
|
|
635
854
|
);
|
|
636
|
-
console.log();
|
|
637
855
|
};
|
|
638
856
|
var countFiles = (dir) => {
|
|
639
857
|
let count = 0;
|
|
@@ -647,9 +865,6 @@ var countFiles = (dir) => {
|
|
|
647
865
|
return count;
|
|
648
866
|
};
|
|
649
867
|
var stepDotnetPublish = (project, target, verbose) => {
|
|
650
|
-
console.log(
|
|
651
|
-
` ${chalk5.dim(`Publishing .NET host (${target.framework})...`)}`
|
|
652
|
-
);
|
|
653
868
|
const start = Date.now();
|
|
654
869
|
const extraArgs = target.extraPublishArgs ?? "-p:CreatePackage=false";
|
|
655
870
|
try {
|
|
@@ -662,37 +877,73 @@ var stepDotnetPublish = (project, target, verbose) => {
|
|
|
662
877
|
);
|
|
663
878
|
} catch (e) {
|
|
664
879
|
const output = formatBuildError(e);
|
|
665
|
-
console.error(
|
|
666
|
-
|
|
880
|
+
console.error(
|
|
881
|
+
row({
|
|
882
|
+
glyph: "error",
|
|
883
|
+
label: "publish .NET",
|
|
884
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
885
|
+
detail: dim("dotnet publish failed")
|
|
886
|
+
})
|
|
887
|
+
);
|
|
888
|
+
console.error(dim(output));
|
|
667
889
|
if (looksLikeMissingWorkload(output)) printWorkloadHint();
|
|
668
890
|
else if (looksLikeMissingXcode(output)) printXcodeHint();
|
|
669
891
|
if (!verbose) {
|
|
670
|
-
console.error(
|
|
671
|
-
chalk5.dim(" Re-run with --verbose for the full build log.")
|
|
672
|
-
);
|
|
892
|
+
console.error(footer(dim("re-run with --verbose for the full build log.")));
|
|
673
893
|
}
|
|
674
894
|
process.exit(1);
|
|
675
895
|
}
|
|
676
896
|
const elapsed = ((Date.now() - start) / 1e3).toFixed(1);
|
|
677
897
|
console.log(
|
|
678
|
-
|
|
898
|
+
row({
|
|
899
|
+
glyph: "done",
|
|
900
|
+
label: "publish .NET",
|
|
901
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
902
|
+
detail: `${dim("Release \xB7")} ${value(target.framework)} ${dim(`(${elapsed}s)`)}`
|
|
903
|
+
})
|
|
679
904
|
);
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
905
|
+
return path5.join(project.hostDir, "bin", "Release", target.framework);
|
|
906
|
+
};
|
|
907
|
+
var stepPackage = async (project, target, bundlePath) => {
|
|
908
|
+
const outputDir = path5.join(project.root, "dist");
|
|
909
|
+
fs4.ensureDirSync(outputDir);
|
|
910
|
+
const start = Date.now();
|
|
911
|
+
let outputPath;
|
|
912
|
+
try {
|
|
913
|
+
outputPath = await target.package(bundlePath, outputDir, {
|
|
914
|
+
projectName: project.projectName,
|
|
915
|
+
displayVersion: project.displayVersion
|
|
916
|
+
});
|
|
917
|
+
} catch (e) {
|
|
918
|
+
console.error(
|
|
919
|
+
row({
|
|
920
|
+
glyph: "error",
|
|
921
|
+
label: packageLabel(target),
|
|
922
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
923
|
+
detail: dim("packaging failed")
|
|
924
|
+
})
|
|
925
|
+
);
|
|
926
|
+
console.error(dim(formatProcessError(e)));
|
|
927
|
+
process.exit(1);
|
|
928
|
+
}
|
|
929
|
+
const pkgTime = ((Date.now() - start) / 1e3).toFixed(1);
|
|
930
|
+
const sizeMB = (fs4.statSync(outputPath).size / (1024 * 1024)).toFixed(1);
|
|
931
|
+
console.log(
|
|
932
|
+
row({
|
|
933
|
+
glyph: "done",
|
|
934
|
+
label: packageLabel(target),
|
|
935
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
936
|
+
detail: `${value(path5.basename(outputPath))} ${dim(`(${sizeMB} MB, ${pkgTime}s)`)}`
|
|
937
|
+
})
|
|
685
938
|
);
|
|
686
|
-
return
|
|
939
|
+
return outputPath;
|
|
687
940
|
};
|
|
688
941
|
|
|
689
942
|
// src/commands/dev.ts
|
|
690
943
|
import path6 from "path";
|
|
691
944
|
import fs5 from "fs-extra";
|
|
692
|
-
import { execFileSync as
|
|
945
|
+
import { execFileSync as execFileSync4, spawn } from "child_process";
|
|
693
946
|
import { request } from "http";
|
|
694
|
-
import chalk6 from "chalk";
|
|
695
|
-
var VERSION2 = "0.1.0";
|
|
696
947
|
var POLL_INTERVAL_MS = 500;
|
|
697
948
|
var POLL_TIMEOUT_MS = 3e4;
|
|
698
949
|
var NPM_COMMAND = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
@@ -718,9 +969,10 @@ var startSession = async (argv, opts) => {
|
|
|
718
969
|
if (!target) {
|
|
719
970
|
const supported = Object.keys(TARGETS2).join(", ");
|
|
720
971
|
console.error(
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
972
|
+
row({
|
|
973
|
+
glyph: "error",
|
|
974
|
+
detail: dim(`unsupported target: ${targetName} \u2014 supported: ${supported}`)
|
|
975
|
+
})
|
|
724
976
|
);
|
|
725
977
|
process.exit(1);
|
|
726
978
|
}
|
|
@@ -751,14 +1003,9 @@ var DevSession = class {
|
|
|
751
1003
|
async run() {
|
|
752
1004
|
this.installSignalHandlers();
|
|
753
1005
|
console.log();
|
|
754
|
-
console.log(
|
|
755
|
-
|
|
756
|
-
);
|
|
757
|
-
console.log();
|
|
758
|
-
console.log(` ${chalk6.dim("Project:")} ${chalk6.cyan(this.project.projectName)}`);
|
|
759
|
-
console.log(
|
|
760
|
-
` ${chalk6.dim("Target:")} ${chalk6.cyan(this.target.name)} (${this.target.framework})`
|
|
761
|
-
);
|
|
1006
|
+
console.log(header(this.vite ? "dev" : "run", this.target.name));
|
|
1007
|
+
console.log(kv("project", this.project.projectName));
|
|
1008
|
+
console.log(kv("target", this.target.framework));
|
|
762
1009
|
console.log();
|
|
763
1010
|
let vite;
|
|
764
1011
|
if (this.vite) {
|
|
@@ -766,23 +1013,50 @@ var DevSession = class {
|
|
|
766
1013
|
try {
|
|
767
1014
|
await waitForServer(this.viteUrl, POLL_TIMEOUT_MS);
|
|
768
1015
|
} catch (error) {
|
|
769
|
-
console.error(
|
|
1016
|
+
console.error(row({ glyph: "error", detail: dim(error.message) }));
|
|
770
1017
|
this.shutdown(1);
|
|
771
1018
|
}
|
|
772
|
-
console.log(
|
|
773
|
-
|
|
1019
|
+
console.log(
|
|
1020
|
+
taggedRow("active", "ui", `${dim("vite ready \u2014")} ${value(this.viteUrl)}`)
|
|
1021
|
+
);
|
|
774
1022
|
} else {
|
|
775
1023
|
console.log(
|
|
776
|
-
|
|
1024
|
+
taggedRow(
|
|
1025
|
+
"skip",
|
|
1026
|
+
"ui",
|
|
1027
|
+
`${dim("vite not started \u2014")} ${value("npm run dev:ui")}`
|
|
1028
|
+
)
|
|
777
1029
|
);
|
|
778
|
-
console.log();
|
|
779
1030
|
}
|
|
780
1031
|
const host = this.target.name === "macos" ? this.launchMacosHost() : this.launchWindowsHost();
|
|
1032
|
+
if (this.vite) {
|
|
1033
|
+
console.log(
|
|
1034
|
+
taggedRow(
|
|
1035
|
+
"active",
|
|
1036
|
+
null,
|
|
1037
|
+
`${lime("hot reload active")} ${dim("\u2014 edit ui/src and save")}`
|
|
1038
|
+
)
|
|
1039
|
+
);
|
|
1040
|
+
console.log();
|
|
1041
|
+
console.log(
|
|
1042
|
+
footer(
|
|
1043
|
+
`${dim("watching")} ${value("ui/")} ${dim(
|
|
1044
|
+
"\xB7 hot reload on save \xB7 ctrl-c to stop"
|
|
1045
|
+
)}`
|
|
1046
|
+
)
|
|
1047
|
+
);
|
|
1048
|
+
} else {
|
|
1049
|
+
console.log();
|
|
1050
|
+
console.log(
|
|
1051
|
+
footer(dim("host only \xB7 serve the UI separately \xB7 ctrl-c to stop"))
|
|
1052
|
+
);
|
|
1053
|
+
}
|
|
1054
|
+
console.log();
|
|
781
1055
|
await waitForExit(...vite ? [vite, host] : [host]);
|
|
782
1056
|
}
|
|
783
1057
|
installSignalHandlers() {
|
|
784
1058
|
process.on("SIGINT", () => {
|
|
785
|
-
console.log("\n
|
|
1059
|
+
console.log("\n" + footer(dim("shutting down\u2026")));
|
|
786
1060
|
this.shutdown(0);
|
|
787
1061
|
});
|
|
788
1062
|
process.on("SIGTERM", () => {
|
|
@@ -790,19 +1064,24 @@ var DevSession = class {
|
|
|
790
1064
|
});
|
|
791
1065
|
}
|
|
792
1066
|
startVite() {
|
|
793
|
-
console.log(
|
|
1067
|
+
console.log(taggedRow("active", "ui", dim("starting dev server\u2026")));
|
|
794
1068
|
const vite = spawn(NPM_COMMAND, ["run", "dev"], {
|
|
795
1069
|
cwd: this.project.uiDir,
|
|
796
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
1070
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
1071
|
+
shell: process.platform === "win32"
|
|
797
1072
|
});
|
|
798
1073
|
return this.registerChild(vite, "ui", "Vite dev server");
|
|
799
1074
|
}
|
|
800
1075
|
launchMacosHost() {
|
|
801
1076
|
console.log(
|
|
802
|
-
|
|
1077
|
+
taggedRow(
|
|
1078
|
+
"active",
|
|
1079
|
+
"host",
|
|
1080
|
+
`${dim("building")} ${value(this.target.framework)} ${dim("\u2026")}`
|
|
1081
|
+
)
|
|
803
1082
|
);
|
|
804
1083
|
try {
|
|
805
|
-
|
|
1084
|
+
execFileSync4(
|
|
806
1085
|
DOTNET_COMMAND,
|
|
807
1086
|
[
|
|
808
1087
|
"build",
|
|
@@ -819,14 +1098,12 @@ var DevSession = class {
|
|
|
819
1098
|
);
|
|
820
1099
|
} catch (error) {
|
|
821
1100
|
const output = formatBuildError(error);
|
|
822
|
-
console.error(
|
|
823
|
-
console.error(
|
|
1101
|
+
console.error(taggedRow("error", "host", dim("MAUI build failed")));
|
|
1102
|
+
console.error(dim(output));
|
|
824
1103
|
if (looksLikeMissingWorkload(output)) printWorkloadHint();
|
|
825
1104
|
else if (looksLikeMissingXcode(output)) printXcodeHint();
|
|
826
1105
|
if (!this.verbose) {
|
|
827
|
-
console.error(
|
|
828
|
-
chalk6.dim(" Re-run with --verbose for the full build log.")
|
|
829
|
-
);
|
|
1106
|
+
console.error(footer(dim("re-run with --verbose for the full build log.")));
|
|
830
1107
|
}
|
|
831
1108
|
process.exit(1);
|
|
832
1109
|
}
|
|
@@ -837,9 +1114,12 @@ var DevSession = class {
|
|
|
837
1114
|
);
|
|
838
1115
|
if (!appBundle) {
|
|
839
1116
|
console.error(
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
1117
|
+
row({
|
|
1118
|
+
glyph: "error",
|
|
1119
|
+
detail: dim(
|
|
1120
|
+
`could not find .app bundle in ${path6.join(this.project.hostDir, "bin", this.buildConfig, this.target.framework)}`
|
|
1121
|
+
)
|
|
1122
|
+
})
|
|
843
1123
|
);
|
|
844
1124
|
process.exit(1);
|
|
845
1125
|
}
|
|
@@ -851,11 +1131,16 @@ var DevSession = class {
|
|
|
851
1131
|
const binary = findMacExecutable(appBundle);
|
|
852
1132
|
if (!binary) {
|
|
853
1133
|
console.error(
|
|
854
|
-
|
|
1134
|
+
row({
|
|
1135
|
+
glyph: "error",
|
|
1136
|
+
detail: dim(`could not find the app executable in ${appBundle}`)
|
|
1137
|
+
})
|
|
855
1138
|
);
|
|
856
1139
|
process.exit(1);
|
|
857
1140
|
}
|
|
858
|
-
console.log(
|
|
1141
|
+
console.log(
|
|
1142
|
+
taggedRow("done", "host", `${dim("launched")} ${value(path6.basename(appBundle))}`)
|
|
1143
|
+
);
|
|
859
1144
|
const host = spawn(binary, [], {
|
|
860
1145
|
cwd: this.project.root,
|
|
861
1146
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -864,7 +1149,7 @@ var DevSession = class {
|
|
|
864
1149
|
return this.registerChild(host, "host", path6.basename(binary));
|
|
865
1150
|
}
|
|
866
1151
|
launchWindowsHost() {
|
|
867
|
-
console.log(
|
|
1152
|
+
console.log(taggedRow("active", "host", dim("launching\u2026")));
|
|
868
1153
|
const host = spawn(
|
|
869
1154
|
DOTNET_COMMAND,
|
|
870
1155
|
[
|
|
@@ -884,17 +1169,16 @@ var DevSession = class {
|
|
|
884
1169
|
);
|
|
885
1170
|
return this.registerChild(host, "host", "MAUI host");
|
|
886
1171
|
}
|
|
887
|
-
registerChild(child,
|
|
1172
|
+
registerChild(child, tag2, label) {
|
|
888
1173
|
this.children.push(child);
|
|
889
|
-
prefixStream(child.stdout,
|
|
890
|
-
prefixStream(child.stderr,
|
|
1174
|
+
prefixStream(child.stdout, tag2);
|
|
1175
|
+
prefixStream(child.stderr, tag2);
|
|
891
1176
|
child.on("exit", (code, signal) => {
|
|
892
1177
|
if (this.shuttingDown) return;
|
|
893
|
-
if (
|
|
1178
|
+
if (tag2 === "ui") {
|
|
894
1179
|
const exitCode = code ?? 1;
|
|
895
1180
|
console.error(
|
|
896
|
-
|
|
897
|
-
${label} exited with code ${exitCode}.`)
|
|
1181
|
+
"\n" + row({ glyph: "error", detail: dim(`${label} exited with code ${exitCode}`) })
|
|
898
1182
|
);
|
|
899
1183
|
this.shutdown(exitCode);
|
|
900
1184
|
return;
|
|
@@ -902,12 +1186,14 @@ var DevSession = class {
|
|
|
902
1186
|
const failed = code !== null && code !== 0 || signal !== null;
|
|
903
1187
|
if (failed) {
|
|
904
1188
|
console.error(
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
1189
|
+
"\n" + row({
|
|
1190
|
+
glyph: "error",
|
|
1191
|
+
detail: dim(
|
|
1192
|
+
`${label} exited with ${signal ? `signal ${signal}` : `code ${code}`}`
|
|
1193
|
+
)
|
|
1194
|
+
})
|
|
909
1195
|
);
|
|
910
|
-
if (
|
|
1196
|
+
if (tag2 === "host" && this.target.name === "macos") {
|
|
911
1197
|
printMacLaunchHint();
|
|
912
1198
|
}
|
|
913
1199
|
}
|
|
@@ -915,9 +1201,10 @@ var DevSession = class {
|
|
|
915
1201
|
});
|
|
916
1202
|
child.on("error", (error) => {
|
|
917
1203
|
if (this.shuttingDown) return;
|
|
918
|
-
console.error(
|
|
919
|
-
|
|
920
|
-
|
|
1204
|
+
console.error(
|
|
1205
|
+
"\n" + row({ glyph: "error", detail: dim(`failed to start ${label}: ${error.message}`) })
|
|
1206
|
+
);
|
|
1207
|
+
if (tag2 === "host" && this.target.name === "macos") {
|
|
921
1208
|
printMacLaunchHint();
|
|
922
1209
|
}
|
|
923
1210
|
this.shutdown(1);
|
|
@@ -935,23 +1222,26 @@ var DevSession = class {
|
|
|
935
1222
|
};
|
|
936
1223
|
var ensureTargetMatchesHostOs = (targetName) => {
|
|
937
1224
|
if (targetName === "macos" && process.platform !== "darwin") {
|
|
938
|
-
console.error(
|
|
1225
|
+
console.error(
|
|
1226
|
+
row({ glyph: "error", detail: dim("the macOS target can only run on macOS") })
|
|
1227
|
+
);
|
|
939
1228
|
process.exit(1);
|
|
940
1229
|
}
|
|
941
1230
|
if (targetName === "windows" && process.platform !== "win32") {
|
|
942
1231
|
console.error(
|
|
943
|
-
|
|
1232
|
+
row({ glyph: "error", detail: dim("the Windows target can only run on Windows") })
|
|
944
1233
|
);
|
|
945
1234
|
process.exit(1);
|
|
946
1235
|
}
|
|
947
1236
|
};
|
|
948
|
-
var prefixStream = (stream,
|
|
1237
|
+
var prefixStream = (stream, tag2) => {
|
|
949
1238
|
if (!stream) return;
|
|
1239
|
+
const prefix = streamPrefix(tag2);
|
|
950
1240
|
stream.on("data", (chunk) => {
|
|
951
1241
|
const lines = chunk.toString().split("\n");
|
|
952
1242
|
for (const line of lines) {
|
|
953
1243
|
if (line.length > 0) {
|
|
954
|
-
process.stdout.write(
|
|
1244
|
+
process.stdout.write(`${prefix} ${line}
|
|
955
1245
|
`);
|
|
956
1246
|
}
|
|
957
1247
|
}
|
|
@@ -1028,7 +1318,7 @@ var killChild = (child) => {
|
|
|
1028
1318
|
if (!child.pid || child.exitCode !== null) return;
|
|
1029
1319
|
if (process.platform === "win32") {
|
|
1030
1320
|
try {
|
|
1031
|
-
|
|
1321
|
+
execFileSync4("taskkill", ["/PID", String(child.pid), "/T", "/F"], {
|
|
1032
1322
|
stdio: "ignore"
|
|
1033
1323
|
});
|
|
1034
1324
|
} catch {
|
|
@@ -1040,48 +1330,50 @@ var killChild = (child) => {
|
|
|
1040
1330
|
};
|
|
1041
1331
|
var printMacLaunchHint = () => {
|
|
1042
1332
|
console.error();
|
|
1043
|
-
console.error(chalk6.yellow(" The host built but the app couldn't launch."));
|
|
1044
1333
|
console.error(
|
|
1045
|
-
|
|
1046
|
-
|
|
1334
|
+
row({ glyph: "manual", label: "the host built but the app couldn't launch." })
|
|
1335
|
+
);
|
|
1336
|
+
console.error(
|
|
1337
|
+
footer(
|
|
1338
|
+
dim(
|
|
1339
|
+
"on macOS this is usually code signing / Gatekeeper for a locally built app:"
|
|
1340
|
+
)
|
|
1047
1341
|
)
|
|
1048
1342
|
);
|
|
1049
1343
|
console.error(
|
|
1050
|
-
`
|
|
1344
|
+
` ${dim("\u2022")} ${dim("install full Xcode, then run")} ${lime("vidra doctor")} ${dim("to verify")}`
|
|
1051
1345
|
);
|
|
1052
1346
|
console.error(
|
|
1053
|
-
`
|
|
1347
|
+
` ${dim("\u2022")} ${dim("approve it once in Finder: right-click the")} ${value(".app")} ${dim("and choose")} ${value("Open")}`
|
|
1054
1348
|
);
|
|
1055
1349
|
console.error(
|
|
1056
|
-
`
|
|
1350
|
+
` ${dim("\u2022")} ${dim("or provide a signing identity via")} ${value("VIDRA_MACOS_CODESIGN_KEY")}`
|
|
1057
1351
|
);
|
|
1058
1352
|
console.error();
|
|
1059
1353
|
};
|
|
1060
1354
|
|
|
1061
1355
|
// src/cli.ts
|
|
1062
|
-
var VERSION3 = "0.1.5";
|
|
1063
1356
|
var printHelp = () => {
|
|
1357
|
+
const cmd = (name, desc) => ` ${value(name.padEnd(10))} ${dim(desc)}`;
|
|
1358
|
+
const ex = (args, comment) => ` ${lime("vidra")} ${value(args.padEnd(22))} ${dim(`# ${comment}`)}`;
|
|
1064
1359
|
console.log(`
|
|
1065
|
-
${
|
|
1360
|
+
${wordmark()} ${dim(`v${CLI_VERSION}`)}
|
|
1066
1361
|
|
|
1067
|
-
${
|
|
1068
|
-
vidra <command> [options]
|
|
1362
|
+
${dim("usage")}
|
|
1363
|
+
${lime("vidra")} ${dim("<command> [options]")}
|
|
1069
1364
|
|
|
1070
|
-
${
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1365
|
+
${dim("commands")}
|
|
1366
|
+
${cmd("dev", "start vite + the native host (hot reload)")}
|
|
1367
|
+
${cmd("run", "launch the native host only")}
|
|
1368
|
+
${cmd("build", "build & package for distribution")}
|
|
1369
|
+
${cmd("doctor", "check your environment")}
|
|
1370
|
+
${cmd("help", "show this message")}
|
|
1076
1371
|
|
|
1077
|
-
${
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
vidra build --target macos ${chalk7.dim("# macOS DMG")}
|
|
1083
|
-
vidra build --verbose ${chalk7.dim("# show full build output")}
|
|
1084
|
-
vidra doctor ${chalk7.dim("# verify .NET SDK + MAUI workload")}
|
|
1372
|
+
${dim("examples")}
|
|
1373
|
+
${ex("dev --target windows", "run the windows host")}
|
|
1374
|
+
${ex("build --plan", "preview the build, run nothing")}
|
|
1375
|
+
${ex("build --target macos", "build & package a macOS DMG")}
|
|
1376
|
+
${ex("doctor", "verify .NET SDK + MAUI workload")}
|
|
1085
1377
|
`);
|
|
1086
1378
|
};
|
|
1087
1379
|
var main = async () => {
|
|
@@ -1108,16 +1400,15 @@ var main = async () => {
|
|
|
1108
1400
|
break;
|
|
1109
1401
|
case "--version":
|
|
1110
1402
|
case "-v":
|
|
1111
|
-
console.log(
|
|
1403
|
+
console.log(CLI_VERSION);
|
|
1112
1404
|
break;
|
|
1113
1405
|
default:
|
|
1114
|
-
console.error(
|
|
1115
|
-
`));
|
|
1406
|
+
console.error(row({ glyph: "error", detail: dim(`unknown command: ${command}`) }));
|
|
1116
1407
|
printHelp();
|
|
1117
1408
|
process.exit(1);
|
|
1118
1409
|
}
|
|
1119
1410
|
};
|
|
1120
1411
|
main().catch((e) => {
|
|
1121
|
-
console.error(
|
|
1412
|
+
console.error(row({ glyph: "error", detail: dim(e.message) }));
|
|
1122
1413
|
process.exit(1);
|
|
1123
1414
|
});
|