create-vidra-app 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +561 -214
- package/dist/index.js +142 -54
- package/package.json +10 -1
- package/templates/react-vite/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
// src/cli.ts
|
|
2
|
-
import chalk6 from "chalk";
|
|
3
|
-
|
|
4
1
|
// src/commands/build.ts
|
|
5
2
|
import path5 from "path";
|
|
6
3
|
import fs4 from "fs-extra";
|
|
7
|
-
import { execSync as
|
|
8
|
-
import chalk4 from "chalk";
|
|
4
|
+
import { execSync as execSync3 } from "child_process";
|
|
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
|
}
|
|
@@ -22,10 +28,92 @@ var parseArgs = (argv) => {
|
|
|
22
28
|
return args;
|
|
23
29
|
};
|
|
24
30
|
|
|
31
|
+
// src/exec.ts
|
|
32
|
+
import { execSync } from "child_process";
|
|
33
|
+
|
|
34
|
+
// src/theme.ts
|
|
35
|
+
import chalk from "chalk";
|
|
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;
|
|
96
|
+
};
|
|
97
|
+
var formatProcessError = (error) => {
|
|
98
|
+
const err = error;
|
|
99
|
+
const combined = [toText(err.stderr), toText(err.stdout)].map((s) => s.trim()).filter((s) => s.length > 0).join("\n").trim();
|
|
100
|
+
return combined.length > 0 ? combined : err.message ?? String(error);
|
|
101
|
+
};
|
|
102
|
+
var formatBuildError = (error) => {
|
|
103
|
+
const raw = formatProcessError(error);
|
|
104
|
+
const lines = raw.split(/\r?\n/);
|
|
105
|
+
const errorLines = lines.filter(
|
|
106
|
+
(line) => /(:\s*error\b|\berror\s+[A-Z]{2,}\d+|Build FAILED|MSB\d{4}|NETSDK\d{4})/i.test(
|
|
107
|
+
line
|
|
108
|
+
)
|
|
109
|
+
);
|
|
110
|
+
const picked = errorLines.length > 0 ? errorLines : lines.filter((line) => line.trim().length > 0).slice(-30);
|
|
111
|
+
return picked.join("\n").trim();
|
|
112
|
+
};
|
|
113
|
+
|
|
25
114
|
// src/project.ts
|
|
26
115
|
import path from "path";
|
|
27
116
|
import fs from "fs-extra";
|
|
28
|
-
import chalk from "chalk";
|
|
29
117
|
var detectPlatform = () => {
|
|
30
118
|
switch (process.platform) {
|
|
31
119
|
case "darwin":
|
|
@@ -64,9 +152,15 @@ var detectProject = (cwd) => {
|
|
|
64
152
|
dir = parent;
|
|
65
153
|
}
|
|
66
154
|
console.error(
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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"))
|
|
70
164
|
);
|
|
71
165
|
process.exit(1);
|
|
72
166
|
};
|
|
@@ -97,7 +191,7 @@ var readCsprojVersion = (csprojPath) => {
|
|
|
97
191
|
// src/targets/macos.ts
|
|
98
192
|
import path2 from "path";
|
|
99
193
|
import fs2 from "fs-extra";
|
|
100
|
-
import { execSync } from "child_process";
|
|
194
|
+
import { execSync as execSync2 } from "child_process";
|
|
101
195
|
import os from "os";
|
|
102
196
|
var macosTarget = {
|
|
103
197
|
name: "macos",
|
|
@@ -123,7 +217,7 @@ var macosTarget = {
|
|
|
123
217
|
if (fs2.existsSync(dmgPath)) {
|
|
124
218
|
fs2.removeSync(dmgPath);
|
|
125
219
|
}
|
|
126
|
-
|
|
220
|
+
execSync2(
|
|
127
221
|
`hdiutil create -volname "${volName}" -srcfolder "${staging}" -ov -format UDZO "${dmgPath}"`,
|
|
128
222
|
{ stdio: "pipe" }
|
|
129
223
|
);
|
|
@@ -137,41 +231,44 @@ var macosTarget = {
|
|
|
137
231
|
// src/signing.ts
|
|
138
232
|
import path3 from "path";
|
|
139
233
|
import { execFileSync } from "child_process";
|
|
140
|
-
import chalk2 from "chalk";
|
|
141
234
|
var signMacAppBundleIfPossible = (appBundle, options) => {
|
|
142
235
|
if (process.platform !== "darwin") return;
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
chalk2.yellow(
|
|
147
|
-
" No usable macOS signing identity found. The app will remain ad-hoc signed."
|
|
148
|
-
)
|
|
149
|
-
);
|
|
150
|
-
options.warn(
|
|
151
|
-
chalk2.yellow(
|
|
152
|
-
" Set VIDRA_MACOS_CODESIGN_KEY to override identity selection if needed."
|
|
153
|
-
)
|
|
154
|
-
);
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
236
|
+
const identity = resolveMacCodeSigningIdentity();
|
|
237
|
+
const signWith = identity ?? "-";
|
|
238
|
+
const label = path3.basename(appBundle);
|
|
157
239
|
try {
|
|
158
240
|
execFileSync(
|
|
159
241
|
"codesign",
|
|
160
|
-
["--force", "--deep", "--sign",
|
|
242
|
+
["--force", "--deep", "--sign", signWith, appBundle],
|
|
161
243
|
{
|
|
162
244
|
stdio: options.verbose ? "inherit" : "pipe"
|
|
163
245
|
}
|
|
164
246
|
);
|
|
165
247
|
options.log(
|
|
166
|
-
|
|
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
|
+
})
|
|
167
254
|
);
|
|
168
255
|
} catch (error) {
|
|
169
256
|
options.warn(
|
|
170
|
-
|
|
171
|
-
|
|
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
|
+
})
|
|
263
|
+
);
|
|
264
|
+
options.warn(
|
|
265
|
+
footer(
|
|
266
|
+
dim(
|
|
267
|
+
"install Xcode or the Command Line Tools (provides `codesign`), or set VIDRA_MACOS_CODESIGN_KEY."
|
|
268
|
+
)
|
|
172
269
|
)
|
|
173
270
|
);
|
|
174
|
-
options.warn(
|
|
271
|
+
options.warn(dim(formatExecError(error)));
|
|
175
272
|
}
|
|
176
273
|
};
|
|
177
274
|
var resolveMacCodeSigningIdentity = () => {
|
|
@@ -188,7 +285,7 @@ var resolveMacCodeSigningIdentity = () => {
|
|
|
188
285
|
encoding: "utf8"
|
|
189
286
|
}
|
|
190
287
|
);
|
|
191
|
-
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);
|
|
192
289
|
return identities.find((identity) => identity.startsWith("Apple Development:")) ?? identities.find((identity) => identity.startsWith("Developer ID Application:")) ?? null;
|
|
193
290
|
} catch {
|
|
194
291
|
return null;
|
|
@@ -239,7 +336,6 @@ var windowsTarget = {
|
|
|
239
336
|
// src/doctor.ts
|
|
240
337
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
241
338
|
import prompts from "prompts";
|
|
242
|
-
import chalk3 from "chalk";
|
|
243
339
|
var DOTNET = process.platform === "win32" ? "dotnet.exe" : "dotnet";
|
|
244
340
|
var MAUI_DOCS = "https://learn.microsoft.com/dotnet/maui/get-started/installation";
|
|
245
341
|
var bufToStr = (v) => v == null ? "" : Buffer.isBuffer(v) ? v.toString() : v;
|
|
@@ -272,6 +368,11 @@ var looksLikeMissingWorkload = (output) => [
|
|
|
272
368
|
/maui-windows/i,
|
|
273
369
|
/to\s+install\s+the\s+.*workload/i
|
|
274
370
|
].some((re) => re.test(output));
|
|
371
|
+
var looksLikeMissingXcode = (output) => [
|
|
372
|
+
/valid\s+Xcode\s+installation\s+was\s+not\s+found/i,
|
|
373
|
+
/could\s+not\s+find\s+a\s+valid\s+Xcode\s+app\s+bundle/i,
|
|
374
|
+
/macios-missing-xcode/i
|
|
375
|
+
].some((re) => re.test(output));
|
|
275
376
|
var checkDotnetSdk = () => {
|
|
276
377
|
const res = run(DOTNET, ["--list-sdks"]);
|
|
277
378
|
if (!res.found) {
|
|
@@ -361,19 +462,32 @@ var collectRequirements = (opts = {}) => {
|
|
|
361
462
|
}
|
|
362
463
|
return reqs;
|
|
363
464
|
};
|
|
465
|
+
var STATUS_GLYPH = {
|
|
466
|
+
ok: "done",
|
|
467
|
+
missing: "error",
|
|
468
|
+
unknown: "manual"
|
|
469
|
+
};
|
|
364
470
|
var printRequirements = (reqs) => {
|
|
471
|
+
const labelWidth = Math.max(0, ...reqs.map((r) => r.name.length)) + 2;
|
|
365
472
|
for (const r of reqs) {
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
473
|
+
console.log(
|
|
474
|
+
row({
|
|
475
|
+
glyph: STATUS_GLYPH[r.status],
|
|
476
|
+
label: r.name,
|
|
477
|
+
labelWidth,
|
|
478
|
+
detail: r.detail ? dim(r.detail) : void 0
|
|
479
|
+
})
|
|
480
|
+
);
|
|
369
481
|
if (r.status === "missing" && r.fix) {
|
|
370
|
-
console.log(
|
|
482
|
+
console.log(fixLine(r.fix));
|
|
371
483
|
}
|
|
372
484
|
}
|
|
373
485
|
};
|
|
374
486
|
var runDoctor = async () => {
|
|
375
487
|
console.log();
|
|
376
|
-
console.log(` ${
|
|
488
|
+
console.log(` ${lime("vidra")} ${value("doctor")}`);
|
|
489
|
+
console.log();
|
|
490
|
+
console.log(footer(dim("checking your environment\u2026")));
|
|
377
491
|
console.log();
|
|
378
492
|
const reqs = collectRequirements();
|
|
379
493
|
printRequirements(reqs);
|
|
@@ -381,17 +495,22 @@ var runDoctor = async () => {
|
|
|
381
495
|
const missing = reqs.filter((r) => r.status === "missing");
|
|
382
496
|
if (missing.length === 0) {
|
|
383
497
|
console.log(
|
|
384
|
-
|
|
385
|
-
"
|
|
386
|
-
|
|
498
|
+
footer(
|
|
499
|
+
`${dim("all checks passed \u2014 you're ready to run")} ${lime(
|
|
500
|
+
"vidra dev"
|
|
501
|
+
)}${dim(".")}`
|
|
502
|
+
)
|
|
387
503
|
);
|
|
388
504
|
console.log();
|
|
389
505
|
return 0;
|
|
390
506
|
}
|
|
507
|
+
const n = missing.length;
|
|
391
508
|
console.log(
|
|
392
|
-
|
|
393
|
-
`${
|
|
394
|
-
|
|
509
|
+
footer(
|
|
510
|
+
`${dim(
|
|
511
|
+
`${n} issue${n === 1 ? "" : "s"} found. apply the ${n === 1 ? "fix" : "fixes"} above, then re-run`
|
|
512
|
+
)} ${lime("vidra doctor")}${dim(".")}`
|
|
513
|
+
)
|
|
395
514
|
);
|
|
396
515
|
console.log();
|
|
397
516
|
return 1;
|
|
@@ -399,11 +518,16 @@ var runDoctor = async () => {
|
|
|
399
518
|
var installWorkload = (csprojPath) => {
|
|
400
519
|
const args = csprojPath ? ["workload", "restore", csprojPath] : ["workload", "install", "maui"];
|
|
401
520
|
console.log();
|
|
402
|
-
console.log(` ${chalk3.dim(`Running: ${DOTNET} ${args.join(" ")}`)}`);
|
|
403
521
|
console.log(
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
522
|
+
row({
|
|
523
|
+
glyph: "active",
|
|
524
|
+
detail: `${dim("running")} ${value(`${DOTNET} ${args.join(" ")}`)}`
|
|
525
|
+
})
|
|
526
|
+
);
|
|
527
|
+
console.log(
|
|
528
|
+
footer(
|
|
529
|
+
dim("this can download several hundred MB and take a few minutes.")
|
|
530
|
+
)
|
|
407
531
|
);
|
|
408
532
|
console.log();
|
|
409
533
|
try {
|
|
@@ -411,13 +535,15 @@ var installWorkload = (csprojPath) => {
|
|
|
411
535
|
return true;
|
|
412
536
|
} catch {
|
|
413
537
|
console.error();
|
|
414
|
-
console.error(
|
|
538
|
+
console.error(row({ glyph: "error", label: "workload install failed" }));
|
|
415
539
|
console.error(
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
540
|
+
footer(
|
|
541
|
+
dim(
|
|
542
|
+
"if this is a permissions error, your SDK is in a system location and needs elevation:"
|
|
543
|
+
)
|
|
544
|
+
)
|
|
419
545
|
);
|
|
420
|
-
console.error(
|
|
546
|
+
console.error(fixLine("sudo dotnet workload install maui"));
|
|
421
547
|
console.error();
|
|
422
548
|
return false;
|
|
423
549
|
}
|
|
@@ -426,9 +552,15 @@ var ensureMauiWorkload = async (opts = {}) => {
|
|
|
426
552
|
const dotnet = checkDotnetSdk();
|
|
427
553
|
if (dotnet.status === "missing") {
|
|
428
554
|
console.log();
|
|
429
|
-
console.log(
|
|
555
|
+
console.log(
|
|
556
|
+
row({
|
|
557
|
+
glyph: "error",
|
|
558
|
+
label: dotnet.name,
|
|
559
|
+
detail: dotnet.detail ? dim(dotnet.detail) : void 0
|
|
560
|
+
})
|
|
561
|
+
);
|
|
430
562
|
if (dotnet.fix) {
|
|
431
|
-
console.log(
|
|
563
|
+
console.log(fixLine(dotnet.fix));
|
|
432
564
|
}
|
|
433
565
|
return false;
|
|
434
566
|
}
|
|
@@ -436,7 +568,11 @@ var ensureMauiWorkload = async (opts = {}) => {
|
|
|
436
568
|
if (isMauiWorkloadInstalled()) return true;
|
|
437
569
|
console.log();
|
|
438
570
|
console.log(
|
|
439
|
-
|
|
571
|
+
row({
|
|
572
|
+
glyph: "error",
|
|
573
|
+
label: ".NET MAUI workload",
|
|
574
|
+
detail: dim("required but not installed")
|
|
575
|
+
})
|
|
440
576
|
);
|
|
441
577
|
const interactive = opts.interactive ?? isInteractive();
|
|
442
578
|
if (interactive) {
|
|
@@ -454,61 +590,91 @@ var ensureMauiWorkload = async (opts = {}) => {
|
|
|
454
590
|
}
|
|
455
591
|
if (install) {
|
|
456
592
|
if (installWorkload(opts.csprojPath) && isMauiWorkloadInstalled()) {
|
|
457
|
-
console.log(
|
|
593
|
+
console.log(
|
|
594
|
+
row({
|
|
595
|
+
glyph: "done",
|
|
596
|
+
label: ".NET MAUI workload",
|
|
597
|
+
detail: dim("installed")
|
|
598
|
+
})
|
|
599
|
+
);
|
|
458
600
|
return true;
|
|
459
601
|
}
|
|
460
602
|
return false;
|
|
461
603
|
}
|
|
462
604
|
}
|
|
463
|
-
console.log(
|
|
464
|
-
|
|
465
|
-
);
|
|
466
|
-
console.log(` ${chalk3.dim("docs:")} ${chalk3.cyan(MAUI_DOCS)}`);
|
|
605
|
+
console.log(fixLine("dotnet workload install maui", "run:"));
|
|
606
|
+
console.log(fixLine(MAUI_DOCS, "docs:"));
|
|
467
607
|
return false;
|
|
468
608
|
};
|
|
469
609
|
var printWorkloadHint = () => {
|
|
470
610
|
console.error();
|
|
471
611
|
console.error(
|
|
472
|
-
|
|
612
|
+
row({ glyph: "manual", label: "this looks like a missing .NET MAUI workload." })
|
|
473
613
|
);
|
|
614
|
+
console.error(fixLine("dotnet workload install maui"));
|
|
615
|
+
console.error(fixLine("vidra doctor", "check:"));
|
|
616
|
+
console.error();
|
|
617
|
+
};
|
|
618
|
+
var printXcodeHint = () => {
|
|
619
|
+
console.error();
|
|
474
620
|
console.error(
|
|
475
|
-
|
|
621
|
+
row({
|
|
622
|
+
glyph: "manual",
|
|
623
|
+
label: "Mac Catalyst needs the full Xcode app, not just the Command Line Tools."
|
|
624
|
+
})
|
|
476
625
|
);
|
|
626
|
+
console.error(` ${dim("1.")} ${value("install Xcode from the App Store")}`);
|
|
477
627
|
console.error(
|
|
478
|
-
` ${
|
|
628
|
+
` ${dim("2.")} ${lime(
|
|
629
|
+
"sudo xcode-select -s /Applications/Xcode.app/Contents/Developer"
|
|
630
|
+
)}`
|
|
479
631
|
);
|
|
632
|
+
console.error(` ${dim("3.")} ${lime("sudo xcodebuild -runFirstLaunch")}`);
|
|
633
|
+
console.error(fixLine("vidra doctor", "check:"));
|
|
480
634
|
console.error();
|
|
481
635
|
};
|
|
482
636
|
|
|
483
637
|
// src/commands/build.ts
|
|
484
|
-
var VERSION = "0.1.0";
|
|
485
638
|
var TARGETS = {
|
|
486
639
|
macos: macosTarget,
|
|
487
640
|
windows: windowsTarget
|
|
488
641
|
};
|
|
642
|
+
var packageLabel = (target) => target.name === "macos" ? "package DMG" : "package MSIX";
|
|
643
|
+
var artifactName = (project, target) => `${project.projectName}-${project.displayVersion}-${target.name}.${target.name === "macos" ? "dmg" : "msix"}`;
|
|
489
644
|
var buildCommand = async (argv) => {
|
|
490
645
|
const args = parseArgs(["_", "_", ...argv]);
|
|
491
646
|
const verbose = !!args["verbose"];
|
|
647
|
+
const plan = !!args["plan"] || !!args["dry-run"];
|
|
492
648
|
const targetName = args["target"] || detectPlatform();
|
|
493
|
-
console.log();
|
|
494
|
-
console.log(
|
|
495
|
-
` ${chalk4.bold.cyan("vidra build")} ${chalk4.dim(`v${VERSION}`)}`
|
|
496
|
-
);
|
|
497
|
-
console.log();
|
|
498
649
|
const target = TARGETS[targetName];
|
|
499
650
|
if (!target) {
|
|
500
651
|
const supported = Object.keys(TARGETS).join(", ");
|
|
652
|
+
console.error();
|
|
501
653
|
console.error(
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
654
|
+
row({
|
|
655
|
+
glyph: "error",
|
|
656
|
+
detail: dim(`unsupported target: ${targetName} \u2014 supported: ${supported}`)
|
|
657
|
+
})
|
|
505
658
|
);
|
|
506
659
|
process.exit(1);
|
|
507
660
|
}
|
|
508
661
|
const project = detectProject(process.cwd());
|
|
509
|
-
console.log(` ${chalk4.dim("Project:")} ${chalk4.cyan(project.projectName)}`);
|
|
510
|
-
console.log(` ${chalk4.dim("Target:")} ${chalk4.cyan(target.name)} (${target.framework})`);
|
|
511
662
|
console.log();
|
|
663
|
+
console.log(
|
|
664
|
+
header("build", `${target.name} \xB7 Release${plan ? " \xB7 plan" : ""}`)
|
|
665
|
+
);
|
|
666
|
+
console.log(kv("project", project.projectName));
|
|
667
|
+
console.log(kv("target", target.framework));
|
|
668
|
+
console.log();
|
|
669
|
+
if (plan) {
|
|
670
|
+
printBuildPlan(project, target);
|
|
671
|
+
console.log();
|
|
672
|
+
console.log(
|
|
673
|
+
footer(`${dim("nothing has run. re-run without")} ${lime("--plan")} ${dim("to apply.")}`)
|
|
674
|
+
);
|
|
675
|
+
console.log();
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
512
678
|
if (!await ensureMauiWorkload({ csprojPath: project.csprojPath })) {
|
|
513
679
|
process.exit(1);
|
|
514
680
|
}
|
|
@@ -518,13 +684,13 @@ var buildCommand = async (argv) => {
|
|
|
518
684
|
const bundlePath = target.findBundle(publishDir, project.projectName);
|
|
519
685
|
if (!bundlePath) {
|
|
520
686
|
console.error(
|
|
521
|
-
|
|
687
|
+
row({
|
|
688
|
+
glyph: "error",
|
|
689
|
+
detail: dim(`could not find build artifact in ${publishDir}`)
|
|
690
|
+
})
|
|
522
691
|
);
|
|
523
692
|
process.exit(1);
|
|
524
693
|
}
|
|
525
|
-
console.log(
|
|
526
|
-
` ${chalk4.dim("Bundle:")} ${chalk4.cyan(path5.basename(bundlePath))}`
|
|
527
|
-
);
|
|
528
694
|
if (target.name === "macos") {
|
|
529
695
|
signMacAppBundleIfPossible(bundlePath, {
|
|
530
696
|
verbose,
|
|
@@ -532,58 +698,116 @@ var buildCommand = async (argv) => {
|
|
|
532
698
|
warn: console.warn
|
|
533
699
|
});
|
|
534
700
|
}
|
|
535
|
-
const
|
|
536
|
-
fs4.ensureDirSync(outputDir);
|
|
701
|
+
const outputPath = await stepPackage(project, target, bundlePath);
|
|
537
702
|
console.log();
|
|
538
|
-
console.log(` ${chalk4.dim(`Packaging for ${target.name}...`)}`);
|
|
539
|
-
const startPkg = Date.now();
|
|
540
|
-
let outputPath;
|
|
541
|
-
try {
|
|
542
|
-
outputPath = await target.package(bundlePath, outputDir, {
|
|
543
|
-
projectName: project.projectName,
|
|
544
|
-
displayVersion: project.displayVersion
|
|
545
|
-
});
|
|
546
|
-
} catch (e) {
|
|
547
|
-
const err = e;
|
|
548
|
-
console.error(chalk4.red(` Packaging failed.`));
|
|
549
|
-
console.error(chalk4.dim(err.stderr?.toString() || err.message));
|
|
550
|
-
process.exit(1);
|
|
551
|
-
}
|
|
552
|
-
const pkgTime = ((Date.now() - startPkg) / 1e3).toFixed(1);
|
|
553
|
-
const sizeBytes = fs4.statSync(outputPath).size;
|
|
554
|
-
const sizeMB = (sizeBytes / (1024 * 1024)).toFixed(1);
|
|
555
703
|
console.log(
|
|
556
|
-
|
|
704
|
+
footer(
|
|
705
|
+
`${dim("done \u2014")} ${value(path5.relative(project.root, outputPath))}`
|
|
706
|
+
)
|
|
557
707
|
);
|
|
558
708
|
console.log();
|
|
709
|
+
};
|
|
710
|
+
var printBuildPlan = (project, target) => {
|
|
559
711
|
console.log(
|
|
560
|
-
|
|
712
|
+
row({
|
|
713
|
+
glyph: "done",
|
|
714
|
+
label: "build UI",
|
|
715
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
716
|
+
detail: `${dim("vite \u2192")} ${value("ui/dist")}`
|
|
717
|
+
})
|
|
561
718
|
);
|
|
562
|
-
console.log(
|
|
719
|
+
console.log(
|
|
720
|
+
row({
|
|
721
|
+
glyph: "done",
|
|
722
|
+
label: "copy assets",
|
|
723
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
724
|
+
detail: `${dim("\u2192")} ${value("Resources/Raw/wwwroot")}`
|
|
725
|
+
})
|
|
726
|
+
);
|
|
727
|
+
console.log(
|
|
728
|
+
row({
|
|
729
|
+
glyph: "done",
|
|
730
|
+
label: "publish .NET",
|
|
731
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
732
|
+
detail: `${dim("Release \xB7")} ${value(target.framework)}`
|
|
733
|
+
})
|
|
734
|
+
);
|
|
735
|
+
if (target.name === "macos") {
|
|
736
|
+
console.log(
|
|
737
|
+
row({
|
|
738
|
+
glyph: "done",
|
|
739
|
+
label: "codesign .app",
|
|
740
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
741
|
+
detail: dim("Apple Development, or ad-hoc (-)")
|
|
742
|
+
})
|
|
743
|
+
);
|
|
744
|
+
console.log(
|
|
745
|
+
row({
|
|
746
|
+
glyph: "plan",
|
|
747
|
+
label: "notarize",
|
|
748
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
749
|
+
detail: planBadge()
|
|
750
|
+
})
|
|
751
|
+
);
|
|
752
|
+
console.log(
|
|
753
|
+
row({
|
|
754
|
+
glyph: "active",
|
|
755
|
+
label: "package DMG",
|
|
756
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
757
|
+
detail: `${dim("hdiutil UDZO \u2192")} ${value(artifactName(project, target))}`
|
|
758
|
+
})
|
|
759
|
+
);
|
|
760
|
+
} else {
|
|
761
|
+
console.log(
|
|
762
|
+
row({
|
|
763
|
+
glyph: "active",
|
|
764
|
+
label: "package MSIX",
|
|
765
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
766
|
+
detail: `${dim("\u2192")} ${value(artifactName(project, target))}`
|
|
767
|
+
})
|
|
768
|
+
);
|
|
769
|
+
}
|
|
563
770
|
};
|
|
564
771
|
var stepBuildUi = (project, verbose) => {
|
|
565
|
-
console.log(` ${chalk4.dim("Building UI...")}`);
|
|
566
772
|
const start = Date.now();
|
|
567
773
|
try {
|
|
568
|
-
|
|
774
|
+
execSync3("npm run build", {
|
|
569
775
|
cwd: project.uiDir,
|
|
570
776
|
stdio: verbose ? "inherit" : "pipe"
|
|
571
777
|
});
|
|
572
778
|
} catch (e) {
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
779
|
+
console.error(
|
|
780
|
+
row({
|
|
781
|
+
glyph: "error",
|
|
782
|
+
label: "build UI",
|
|
783
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
784
|
+
detail: dim("vite build failed")
|
|
785
|
+
})
|
|
786
|
+
);
|
|
787
|
+
console.error(dim(formatBuildError(e)));
|
|
576
788
|
process.exit(1);
|
|
577
789
|
}
|
|
578
790
|
const elapsed = ((Date.now() - start) / 1e3).toFixed(1);
|
|
579
|
-
console.log(
|
|
580
|
-
|
|
791
|
+
console.log(
|
|
792
|
+
row({
|
|
793
|
+
glyph: "done",
|
|
794
|
+
label: "build UI",
|
|
795
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
796
|
+
detail: `${dim("vite \u2192")} ${value("ui/dist")} ${dim(`(${elapsed}s)`)}`
|
|
797
|
+
})
|
|
798
|
+
);
|
|
581
799
|
};
|
|
582
800
|
var stepCopyAssets = (project) => {
|
|
583
|
-
console.log(` ${chalk4.dim("Copying assets to host project...")}`);
|
|
584
801
|
const viteDist = path5.join(project.uiDir, "dist");
|
|
585
802
|
if (!fs4.existsSync(viteDist)) {
|
|
586
|
-
console.error(
|
|
803
|
+
console.error(
|
|
804
|
+
row({
|
|
805
|
+
glyph: "error",
|
|
806
|
+
label: "copy assets",
|
|
807
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
808
|
+
detail: dim("ui/dist not found \u2014 vite build may have failed")
|
|
809
|
+
})
|
|
810
|
+
);
|
|
587
811
|
process.exit(1);
|
|
588
812
|
}
|
|
589
813
|
const wwwroot = path5.join(project.hostDir, "Resources", "Raw", "wwwroot");
|
|
@@ -591,9 +815,13 @@ var stepCopyAssets = (project) => {
|
|
|
591
815
|
fs4.copySync(viteDist, wwwroot);
|
|
592
816
|
const fileCount = countFiles(wwwroot);
|
|
593
817
|
console.log(
|
|
594
|
-
|
|
818
|
+
row({
|
|
819
|
+
glyph: "done",
|
|
820
|
+
label: "copy assets",
|
|
821
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
822
|
+
detail: `${dim("\u2192")} ${value("Resources/Raw/wwwroot")} ${dim(`(${fileCount} files)`)}`
|
|
823
|
+
})
|
|
595
824
|
);
|
|
596
|
-
console.log();
|
|
597
825
|
};
|
|
598
826
|
var countFiles = (dir) => {
|
|
599
827
|
let count = 0;
|
|
@@ -607,13 +835,10 @@ var countFiles = (dir) => {
|
|
|
607
835
|
return count;
|
|
608
836
|
};
|
|
609
837
|
var stepDotnetPublish = (project, target, verbose) => {
|
|
610
|
-
console.log(
|
|
611
|
-
` ${chalk4.dim(`Publishing .NET host (${target.framework})...`)}`
|
|
612
|
-
);
|
|
613
838
|
const start = Date.now();
|
|
614
839
|
const extraArgs = target.extraPublishArgs ?? "-p:CreatePackage=false";
|
|
615
840
|
try {
|
|
616
|
-
|
|
841
|
+
execSync3(
|
|
617
842
|
`dotnet publish "${project.csprojPath}" -c Release -f ${target.framework} ${extraArgs}`,
|
|
618
843
|
{
|
|
619
844
|
cwd: project.root,
|
|
@@ -621,24 +846,67 @@ var stepDotnetPublish = (project, target, verbose) => {
|
|
|
621
846
|
}
|
|
622
847
|
);
|
|
623
848
|
} catch (e) {
|
|
624
|
-
const
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
849
|
+
const output = formatBuildError(e);
|
|
850
|
+
console.error(
|
|
851
|
+
row({
|
|
852
|
+
glyph: "error",
|
|
853
|
+
label: "publish .NET",
|
|
854
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
855
|
+
detail: dim("dotnet publish failed")
|
|
856
|
+
})
|
|
857
|
+
);
|
|
858
|
+
console.error(dim(output));
|
|
628
859
|
if (looksLikeMissingWorkload(output)) printWorkloadHint();
|
|
860
|
+
else if (looksLikeMissingXcode(output)) printXcodeHint();
|
|
861
|
+
if (!verbose) {
|
|
862
|
+
console.error(footer(dim("re-run with --verbose for the full build log.")));
|
|
863
|
+
}
|
|
629
864
|
process.exit(1);
|
|
630
865
|
}
|
|
631
866
|
const elapsed = ((Date.now() - start) / 1e3).toFixed(1);
|
|
632
867
|
console.log(
|
|
633
|
-
|
|
868
|
+
row({
|
|
869
|
+
glyph: "done",
|
|
870
|
+
label: "publish .NET",
|
|
871
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
872
|
+
detail: `${dim("Release \xB7")} ${value(target.framework)} ${dim(`(${elapsed}s)`)}`
|
|
873
|
+
})
|
|
634
874
|
);
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
875
|
+
return path5.join(project.hostDir, "bin", "Release", target.framework);
|
|
876
|
+
};
|
|
877
|
+
var stepPackage = async (project, target, bundlePath) => {
|
|
878
|
+
const outputDir = path5.join(project.root, "dist");
|
|
879
|
+
fs4.ensureDirSync(outputDir);
|
|
880
|
+
const start = Date.now();
|
|
881
|
+
let outputPath;
|
|
882
|
+
try {
|
|
883
|
+
outputPath = await target.package(bundlePath, outputDir, {
|
|
884
|
+
projectName: project.projectName,
|
|
885
|
+
displayVersion: project.displayVersion
|
|
886
|
+
});
|
|
887
|
+
} catch (e) {
|
|
888
|
+
console.error(
|
|
889
|
+
row({
|
|
890
|
+
glyph: "error",
|
|
891
|
+
label: packageLabel(target),
|
|
892
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
893
|
+
detail: dim("packaging failed")
|
|
894
|
+
})
|
|
895
|
+
);
|
|
896
|
+
console.error(dim(formatProcessError(e)));
|
|
897
|
+
process.exit(1);
|
|
898
|
+
}
|
|
899
|
+
const pkgTime = ((Date.now() - start) / 1e3).toFixed(1);
|
|
900
|
+
const sizeMB = (fs4.statSync(outputPath).size / (1024 * 1024)).toFixed(1);
|
|
901
|
+
console.log(
|
|
902
|
+
row({
|
|
903
|
+
glyph: "done",
|
|
904
|
+
label: packageLabel(target),
|
|
905
|
+
labelWidth: STEP_LABEL_WIDTH,
|
|
906
|
+
detail: `${value(path5.basename(outputPath))} ${dim(`(${sizeMB} MB, ${pkgTime}s)`)}`
|
|
907
|
+
})
|
|
640
908
|
);
|
|
641
|
-
return
|
|
909
|
+
return outputPath;
|
|
642
910
|
};
|
|
643
911
|
|
|
644
912
|
// src/commands/dev.ts
|
|
@@ -646,8 +914,6 @@ import path6 from "path";
|
|
|
646
914
|
import fs5 from "fs-extra";
|
|
647
915
|
import { execFileSync as execFileSync3, spawn } from "child_process";
|
|
648
916
|
import { request } from "http";
|
|
649
|
-
import chalk5 from "chalk";
|
|
650
|
-
var VERSION2 = "0.1.0";
|
|
651
917
|
var POLL_INTERVAL_MS = 500;
|
|
652
918
|
var POLL_TIMEOUT_MS = 3e4;
|
|
653
919
|
var NPM_COMMAND = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
@@ -662,7 +928,9 @@ var TARGETS2 = {
|
|
|
662
928
|
framework: "net10.0-windows10.0.19041.0"
|
|
663
929
|
}
|
|
664
930
|
};
|
|
665
|
-
var devCommand =
|
|
931
|
+
var devCommand = (argv) => startSession(argv, { vite: true });
|
|
932
|
+
var runCommand = (argv) => startSession(argv, { vite: false });
|
|
933
|
+
var startSession = async (argv, opts) => {
|
|
666
934
|
const args = parseArgs(["_", "_", ...argv]);
|
|
667
935
|
const targetName = args["target"] || detectPlatform();
|
|
668
936
|
const verbose = !!args["verbose"];
|
|
@@ -671,9 +939,10 @@ var devCommand = async (argv) => {
|
|
|
671
939
|
if (!target) {
|
|
672
940
|
const supported = Object.keys(TARGETS2).join(", ");
|
|
673
941
|
console.error(
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
942
|
+
row({
|
|
943
|
+
glyph: "error",
|
|
944
|
+
detail: dim(`unsupported target: ${targetName} \u2014 supported: ${supported}`)
|
|
945
|
+
})
|
|
677
946
|
);
|
|
678
947
|
process.exit(1);
|
|
679
948
|
}
|
|
@@ -682,15 +951,16 @@ var devCommand = async (argv) => {
|
|
|
682
951
|
if (!await ensureMauiWorkload({ csprojPath: project.csprojPath })) {
|
|
683
952
|
process.exit(1);
|
|
684
953
|
}
|
|
685
|
-
const session = new DevSession(project, target, viteUrl, verbose);
|
|
954
|
+
const session = new DevSession(project, target, viteUrl, verbose, opts);
|
|
686
955
|
await session.run();
|
|
687
956
|
};
|
|
688
957
|
var DevSession = class {
|
|
689
|
-
constructor(project, target, viteUrl, verbose) {
|
|
958
|
+
constructor(project, target, viteUrl, verbose, options = {}) {
|
|
690
959
|
this.project = project;
|
|
691
960
|
this.target = target;
|
|
692
961
|
this.viteUrl = viteUrl;
|
|
693
962
|
this.verbose = verbose;
|
|
963
|
+
this.vite = options.vite ?? true;
|
|
694
964
|
}
|
|
695
965
|
project;
|
|
696
966
|
target;
|
|
@@ -698,36 +968,65 @@ var DevSession = class {
|
|
|
698
968
|
verbose;
|
|
699
969
|
children = [];
|
|
700
970
|
buildConfig = process.env.VIDRA_BUILD_CONFIG || "Debug";
|
|
971
|
+
vite;
|
|
701
972
|
shuttingDown = false;
|
|
702
973
|
async run() {
|
|
703
974
|
this.installSignalHandlers();
|
|
704
975
|
console.log();
|
|
705
|
-
console.log(
|
|
706
|
-
console.log();
|
|
707
|
-
console.log(
|
|
708
|
-
console.log(
|
|
709
|
-
` ${chalk5.dim("Target:")} ${chalk5.cyan(this.target.name)} (${this.target.framework})`
|
|
710
|
-
);
|
|
976
|
+
console.log(header(this.vite ? "dev" : "run", this.target.name));
|
|
977
|
+
console.log(kv("project", this.project.projectName));
|
|
978
|
+
console.log(kv("target", this.target.framework));
|
|
711
979
|
console.log();
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
980
|
+
let vite;
|
|
981
|
+
if (this.vite) {
|
|
982
|
+
vite = this.startVite();
|
|
983
|
+
try {
|
|
984
|
+
await waitForServer(this.viteUrl, POLL_TIMEOUT_MS);
|
|
985
|
+
} catch (error) {
|
|
986
|
+
console.error(row({ glyph: "error", detail: dim(error.message) }));
|
|
987
|
+
this.shutdown(1);
|
|
988
|
+
}
|
|
989
|
+
console.log(
|
|
990
|
+
taggedRow("active", "ui", `${dim("vite ready \u2014")} ${value(this.viteUrl)}`)
|
|
991
|
+
);
|
|
992
|
+
} else {
|
|
993
|
+
console.log(
|
|
994
|
+
taggedRow(
|
|
995
|
+
"skip",
|
|
996
|
+
"ui",
|
|
997
|
+
`${dim("vite not started \u2014")} ${value("npm run dev:ui")}`
|
|
719
998
|
)
|
|
720
999
|
);
|
|
721
|
-
this.shutdown(1);
|
|
722
1000
|
}
|
|
723
|
-
console.log(` ${chalk5.dim("Vite:")} ${chalk5.cyan(this.viteUrl)}`);
|
|
724
|
-
console.log();
|
|
725
1001
|
const host = this.target.name === "macos" ? this.launchMacosHost() : this.launchWindowsHost();
|
|
726
|
-
|
|
1002
|
+
if (this.vite) {
|
|
1003
|
+
console.log(
|
|
1004
|
+
taggedRow(
|
|
1005
|
+
"active",
|
|
1006
|
+
null,
|
|
1007
|
+
`${lime("hot reload active")} ${dim("\u2014 edit ui/src and save")}`
|
|
1008
|
+
)
|
|
1009
|
+
);
|
|
1010
|
+
console.log();
|
|
1011
|
+
console.log(
|
|
1012
|
+
footer(
|
|
1013
|
+
`${dim("watching")} ${value("ui/")} ${dim(
|
|
1014
|
+
"\xB7 hot reload on save \xB7 ctrl-c to stop"
|
|
1015
|
+
)}`
|
|
1016
|
+
)
|
|
1017
|
+
);
|
|
1018
|
+
} else {
|
|
1019
|
+
console.log();
|
|
1020
|
+
console.log(
|
|
1021
|
+
footer(dim("host only \xB7 serve the UI separately \xB7 ctrl-c to stop"))
|
|
1022
|
+
);
|
|
1023
|
+
}
|
|
1024
|
+
console.log();
|
|
1025
|
+
await waitForExit(...vite ? [vite, host] : [host]);
|
|
727
1026
|
}
|
|
728
1027
|
installSignalHandlers() {
|
|
729
1028
|
process.on("SIGINT", () => {
|
|
730
|
-
console.log("\n
|
|
1029
|
+
console.log("\n" + footer(dim("shutting down\u2026")));
|
|
731
1030
|
this.shutdown(0);
|
|
732
1031
|
});
|
|
733
1032
|
process.on("SIGTERM", () => {
|
|
@@ -735,7 +1034,7 @@ var DevSession = class {
|
|
|
735
1034
|
});
|
|
736
1035
|
}
|
|
737
1036
|
startVite() {
|
|
738
|
-
console.log(
|
|
1037
|
+
console.log(taggedRow("active", "ui", dim("starting dev server\u2026")));
|
|
739
1038
|
const vite = spawn(NPM_COMMAND, ["run", "dev"], {
|
|
740
1039
|
cwd: this.project.uiDir,
|
|
741
1040
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -744,7 +1043,11 @@ var DevSession = class {
|
|
|
744
1043
|
}
|
|
745
1044
|
launchMacosHost() {
|
|
746
1045
|
console.log(
|
|
747
|
-
|
|
1046
|
+
taggedRow(
|
|
1047
|
+
"active",
|
|
1048
|
+
"host",
|
|
1049
|
+
`${dim("building")} ${value(this.target.framework)} ${dim("\u2026")}`
|
|
1050
|
+
)
|
|
748
1051
|
);
|
|
749
1052
|
try {
|
|
750
1053
|
execFileSync3(
|
|
@@ -763,10 +1066,14 @@ var DevSession = class {
|
|
|
763
1066
|
}
|
|
764
1067
|
);
|
|
765
1068
|
} catch (error) {
|
|
766
|
-
const output =
|
|
767
|
-
console.error(
|
|
768
|
-
console.error(
|
|
1069
|
+
const output = formatBuildError(error);
|
|
1070
|
+
console.error(taggedRow("error", "host", dim("MAUI build failed")));
|
|
1071
|
+
console.error(dim(output));
|
|
769
1072
|
if (looksLikeMissingWorkload(output)) printWorkloadHint();
|
|
1073
|
+
else if (looksLikeMissingXcode(output)) printXcodeHint();
|
|
1074
|
+
if (!this.verbose) {
|
|
1075
|
+
console.error(footer(dim("re-run with --verbose for the full build log.")));
|
|
1076
|
+
}
|
|
770
1077
|
process.exit(1);
|
|
771
1078
|
}
|
|
772
1079
|
const appBundle = findMacAppBundle(
|
|
@@ -776,9 +1083,12 @@ var DevSession = class {
|
|
|
776
1083
|
);
|
|
777
1084
|
if (!appBundle) {
|
|
778
1085
|
console.error(
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
1086
|
+
row({
|
|
1087
|
+
glyph: "error",
|
|
1088
|
+
detail: dim(
|
|
1089
|
+
`could not find .app bundle in ${path6.join(this.project.hostDir, "bin", this.buildConfig, this.target.framework)}`
|
|
1090
|
+
)
|
|
1091
|
+
})
|
|
782
1092
|
);
|
|
783
1093
|
process.exit(1);
|
|
784
1094
|
}
|
|
@@ -790,11 +1100,16 @@ var DevSession = class {
|
|
|
790
1100
|
const binary = findMacExecutable(appBundle);
|
|
791
1101
|
if (!binary) {
|
|
792
1102
|
console.error(
|
|
793
|
-
|
|
1103
|
+
row({
|
|
1104
|
+
glyph: "error",
|
|
1105
|
+
detail: dim(`could not find the app executable in ${appBundle}`)
|
|
1106
|
+
})
|
|
794
1107
|
);
|
|
795
1108
|
process.exit(1);
|
|
796
1109
|
}
|
|
797
|
-
console.log(
|
|
1110
|
+
console.log(
|
|
1111
|
+
taggedRow("done", "host", `${dim("launched")} ${value(path6.basename(appBundle))}`)
|
|
1112
|
+
);
|
|
798
1113
|
const host = spawn(binary, [], {
|
|
799
1114
|
cwd: this.project.root,
|
|
800
1115
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -803,7 +1118,7 @@ var DevSession = class {
|
|
|
803
1118
|
return this.registerChild(host, "host", path6.basename(binary));
|
|
804
1119
|
}
|
|
805
1120
|
launchWindowsHost() {
|
|
806
|
-
console.log(
|
|
1121
|
+
console.log(taggedRow("active", "host", dim("launching\u2026")));
|
|
807
1122
|
const host = spawn(
|
|
808
1123
|
DOTNET_COMMAND,
|
|
809
1124
|
[
|
|
@@ -823,31 +1138,44 @@ var DevSession = class {
|
|
|
823
1138
|
);
|
|
824
1139
|
return this.registerChild(host, "host", "MAUI host");
|
|
825
1140
|
}
|
|
826
|
-
registerChild(child,
|
|
1141
|
+
registerChild(child, tag2, label) {
|
|
827
1142
|
this.children.push(child);
|
|
828
|
-
prefixStream(child.stdout,
|
|
829
|
-
prefixStream(child.stderr,
|
|
830
|
-
child.on("exit", (code) => {
|
|
1143
|
+
prefixStream(child.stdout, tag2);
|
|
1144
|
+
prefixStream(child.stderr, tag2);
|
|
1145
|
+
child.on("exit", (code, signal) => {
|
|
831
1146
|
if (this.shuttingDown) return;
|
|
832
|
-
if (
|
|
1147
|
+
if (tag2 === "ui") {
|
|
833
1148
|
const exitCode = code ?? 1;
|
|
834
1149
|
console.error(
|
|
835
|
-
|
|
836
|
-
${label} exited with code ${exitCode}.`)
|
|
1150
|
+
"\n" + row({ glyph: "error", detail: dim(`${label} exited with code ${exitCode}`) })
|
|
837
1151
|
);
|
|
838
1152
|
this.shutdown(exitCode);
|
|
839
1153
|
return;
|
|
840
1154
|
}
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
1155
|
+
const failed = code !== null && code !== 0 || signal !== null;
|
|
1156
|
+
if (failed) {
|
|
1157
|
+
console.error(
|
|
1158
|
+
"\n" + row({
|
|
1159
|
+
glyph: "error",
|
|
1160
|
+
detail: dim(
|
|
1161
|
+
`${label} exited with ${signal ? `signal ${signal}` : `code ${code}`}`
|
|
1162
|
+
)
|
|
1163
|
+
})
|
|
1164
|
+
);
|
|
1165
|
+
if (tag2 === "host" && this.target.name === "macos") {
|
|
1166
|
+
printMacLaunchHint();
|
|
1167
|
+
}
|
|
844
1168
|
}
|
|
845
|
-
this.shutdown(code ?? 0);
|
|
1169
|
+
this.shutdown(code ?? (signal ? 1 : 0));
|
|
846
1170
|
});
|
|
847
1171
|
child.on("error", (error) => {
|
|
848
1172
|
if (this.shuttingDown) return;
|
|
849
|
-
console.error(
|
|
850
|
-
|
|
1173
|
+
console.error(
|
|
1174
|
+
"\n" + row({ glyph: "error", detail: dim(`failed to start ${label}: ${error.message}`) })
|
|
1175
|
+
);
|
|
1176
|
+
if (tag2 === "host" && this.target.name === "macos") {
|
|
1177
|
+
printMacLaunchHint();
|
|
1178
|
+
}
|
|
851
1179
|
this.shutdown(1);
|
|
852
1180
|
});
|
|
853
1181
|
return child;
|
|
@@ -863,23 +1191,26 @@ var DevSession = class {
|
|
|
863
1191
|
};
|
|
864
1192
|
var ensureTargetMatchesHostOs = (targetName) => {
|
|
865
1193
|
if (targetName === "macos" && process.platform !== "darwin") {
|
|
866
|
-
console.error(
|
|
1194
|
+
console.error(
|
|
1195
|
+
row({ glyph: "error", detail: dim("the macOS target can only run on macOS") })
|
|
1196
|
+
);
|
|
867
1197
|
process.exit(1);
|
|
868
1198
|
}
|
|
869
1199
|
if (targetName === "windows" && process.platform !== "win32") {
|
|
870
1200
|
console.error(
|
|
871
|
-
|
|
1201
|
+
row({ glyph: "error", detail: dim("the Windows target can only run on Windows") })
|
|
872
1202
|
);
|
|
873
1203
|
process.exit(1);
|
|
874
1204
|
}
|
|
875
1205
|
};
|
|
876
|
-
var prefixStream = (stream,
|
|
1206
|
+
var prefixStream = (stream, tag2) => {
|
|
877
1207
|
if (!stream) return;
|
|
1208
|
+
const prefix = streamPrefix(tag2);
|
|
878
1209
|
stream.on("data", (chunk) => {
|
|
879
1210
|
const lines = chunk.toString().split("\n");
|
|
880
1211
|
for (const line of lines) {
|
|
881
1212
|
if (line.length > 0) {
|
|
882
|
-
process.stdout.write(
|
|
1213
|
+
process.stdout.write(`${prefix} ${line}
|
|
883
1214
|
`);
|
|
884
1215
|
}
|
|
885
1216
|
}
|
|
@@ -916,11 +1247,12 @@ var waitForServer = (url, timeoutMs) => {
|
|
|
916
1247
|
poll();
|
|
917
1248
|
});
|
|
918
1249
|
};
|
|
919
|
-
var waitForExit = (
|
|
1250
|
+
var waitForExit = (...children) => {
|
|
920
1251
|
return new Promise((resolve) => {
|
|
921
1252
|
const resolveOnce = () => resolve();
|
|
922
|
-
|
|
923
|
-
|
|
1253
|
+
for (const child of children) {
|
|
1254
|
+
child.once("exit", resolveOnce);
|
|
1255
|
+
}
|
|
924
1256
|
});
|
|
925
1257
|
};
|
|
926
1258
|
var findMacAppBundle = (hostDir, framework, buildConfig) => {
|
|
@@ -965,39 +1297,52 @@ var killChild = (child) => {
|
|
|
965
1297
|
}
|
|
966
1298
|
child.kill("SIGTERM");
|
|
967
1299
|
};
|
|
968
|
-
var
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
1300
|
+
var printMacLaunchHint = () => {
|
|
1301
|
+
console.error();
|
|
1302
|
+
console.error(
|
|
1303
|
+
row({ glyph: "manual", label: "the host built but the app couldn't launch." })
|
|
1304
|
+
);
|
|
1305
|
+
console.error(
|
|
1306
|
+
footer(
|
|
1307
|
+
dim(
|
|
1308
|
+
"on macOS this is usually code signing / Gatekeeper for a locally built app:"
|
|
1309
|
+
)
|
|
1310
|
+
)
|
|
1311
|
+
);
|
|
1312
|
+
console.error(
|
|
1313
|
+
` ${dim("\u2022")} ${dim("install full Xcode, then run")} ${lime("vidra doctor")} ${dim("to verify")}`
|
|
1314
|
+
);
|
|
1315
|
+
console.error(
|
|
1316
|
+
` ${dim("\u2022")} ${dim("approve it once in Finder: right-click the")} ${value(".app")} ${dim("and choose")} ${value("Open")}`
|
|
1317
|
+
);
|
|
1318
|
+
console.error(
|
|
1319
|
+
` ${dim("\u2022")} ${dim("or provide a signing identity via")} ${value("VIDRA_MACOS_CODESIGN_KEY")}`
|
|
1320
|
+
);
|
|
1321
|
+
console.error();
|
|
977
1322
|
};
|
|
978
1323
|
|
|
979
1324
|
// src/cli.ts
|
|
980
|
-
var VERSION3 = "0.1.3";
|
|
981
1325
|
var printHelp = () => {
|
|
1326
|
+
const cmd = (name, desc) => ` ${value(name.padEnd(10))} ${dim(desc)}`;
|
|
1327
|
+
const ex = (args, comment) => ` ${lime("vidra")} ${value(args.padEnd(22))} ${dim(`# ${comment}`)}`;
|
|
982
1328
|
console.log(`
|
|
983
|
-
${
|
|
1329
|
+
${wordmark()} ${dim(`v${CLI_VERSION}`)}
|
|
984
1330
|
|
|
985
|
-
${
|
|
986
|
-
vidra <command> [options]
|
|
1331
|
+
${dim("usage")}
|
|
1332
|
+
${lime("vidra")} ${dim("<command> [options]")}
|
|
987
1333
|
|
|
988
|
-
${
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
1334
|
+
${dim("commands")}
|
|
1335
|
+
${cmd("dev", "start vite + the native host (hot reload)")}
|
|
1336
|
+
${cmd("run", "launch the native host only")}
|
|
1337
|
+
${cmd("build", "build & package for distribution")}
|
|
1338
|
+
${cmd("doctor", "check your environment")}
|
|
1339
|
+
${cmd("help", "show this message")}
|
|
993
1340
|
|
|
994
|
-
${
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
vidra build --verbose ${chalk6.dim("# show full build output")}
|
|
1000
|
-
vidra doctor ${chalk6.dim("# verify .NET SDK + MAUI workload")}
|
|
1341
|
+
${dim("examples")}
|
|
1342
|
+
${ex("dev --target windows", "run the windows host")}
|
|
1343
|
+
${ex("build --plan", "preview the build, run nothing")}
|
|
1344
|
+
${ex("build --target macos", "build & package a macOS DMG")}
|
|
1345
|
+
${ex("doctor", "verify .NET SDK + MAUI workload")}
|
|
1001
1346
|
`);
|
|
1002
1347
|
};
|
|
1003
1348
|
var main = async () => {
|
|
@@ -1007,6 +1352,9 @@ var main = async () => {
|
|
|
1007
1352
|
case "dev":
|
|
1008
1353
|
await devCommand(args.slice(1));
|
|
1009
1354
|
break;
|
|
1355
|
+
case "run":
|
|
1356
|
+
await runCommand(args.slice(1));
|
|
1357
|
+
break;
|
|
1010
1358
|
case "build":
|
|
1011
1359
|
await buildCommand(args.slice(1));
|
|
1012
1360
|
break;
|
|
@@ -1021,16 +1369,15 @@ var main = async () => {
|
|
|
1021
1369
|
break;
|
|
1022
1370
|
case "--version":
|
|
1023
1371
|
case "-v":
|
|
1024
|
-
console.log(
|
|
1372
|
+
console.log(CLI_VERSION);
|
|
1025
1373
|
break;
|
|
1026
1374
|
default:
|
|
1027
|
-
console.error(
|
|
1028
|
-
`));
|
|
1375
|
+
console.error(row({ glyph: "error", detail: dim(`unknown command: ${command}`) }));
|
|
1029
1376
|
printHelp();
|
|
1030
1377
|
process.exit(1);
|
|
1031
1378
|
}
|
|
1032
1379
|
};
|
|
1033
1380
|
main().catch((e) => {
|
|
1034
|
-
console.error(
|
|
1381
|
+
console.error(row({ glyph: "error", detail: dim(e.message) }));
|
|
1035
1382
|
process.exit(1);
|
|
1036
1383
|
});
|