vibeview 0.13.0 → 0.14.1
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/{chunk-YFXMXO5T.js → chunk-2VNBRBST.js} +235 -82
- package/dist/{chunk-J7V3GYOI.js → chunk-2WTLJ66O.js} +58 -1
- package/dist/cli.js +309 -34
- package/dist/{server-JA5A5PY6.js → server-KG7CEBEY.js} +3 -3
- package/dist/{upload-app-ZAWCZFQE.js → upload-app-NVPQ7KRO.js} +1 -1
- package/package.json +1 -1
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
loadConfig,
|
|
6
6
|
resolveAuth,
|
|
7
7
|
uploadAppBuild
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-2WTLJ66O.js";
|
|
9
9
|
|
|
10
10
|
// src/lib/dev-state.ts
|
|
11
11
|
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "fs";
|
|
@@ -148,6 +148,20 @@ function loadDevConfig(cwd) {
|
|
|
148
148
|
`vibeview.json: platforms.${key}.build.artifact must be a non-empty string`
|
|
149
149
|
);
|
|
150
150
|
}
|
|
151
|
+
if (entry.build.productionCommand !== void 0) {
|
|
152
|
+
if (typeof entry.build.productionCommand !== "string" || !entry.build.productionCommand) {
|
|
153
|
+
throw new Error(
|
|
154
|
+
`vibeview.json: platforms.${key}.build.productionCommand must be a non-empty string`
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if (entry.build.productionArtifact !== void 0) {
|
|
159
|
+
if (typeof entry.build.productionArtifact !== "string" || !entry.build.productionArtifact) {
|
|
160
|
+
throw new Error(
|
|
161
|
+
`vibeview.json: platforms.${key}.build.productionArtifact must be a non-empty string`
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
151
165
|
}
|
|
152
166
|
if (entry.watchIgnore !== void 0) {
|
|
153
167
|
if (!Array.isArray(entry.watchIgnore)) {
|
|
@@ -252,7 +266,7 @@ async function checkMetro(port, timeoutMs = 1500) {
|
|
|
252
266
|
import { spawn as spawn2 } from "child_process";
|
|
253
267
|
import { createInterface } from "readline";
|
|
254
268
|
import { select as select2 } from "@inquirer/prompts";
|
|
255
|
-
import
|
|
269
|
+
import chalk2 from "chalk";
|
|
256
270
|
|
|
257
271
|
// src/lib/artifact.ts
|
|
258
272
|
import { existsSync as existsSync2, mkdtempSync, readdirSync, rmSync as rmSync2, statSync } from "fs";
|
|
@@ -312,6 +326,7 @@ function prepareUploadArtifact(path) {
|
|
|
312
326
|
}
|
|
313
327
|
|
|
314
328
|
// src/lib/dev-setup.ts
|
|
329
|
+
import chalk from "chalk";
|
|
315
330
|
import { input, select } from "@inquirer/prompts";
|
|
316
331
|
|
|
317
332
|
// src/lib/project-detect.ts
|
|
@@ -402,6 +417,26 @@ function defaultsFor(cwd, platform) {
|
|
|
402
417
|
metroCommand
|
|
403
418
|
};
|
|
404
419
|
}
|
|
420
|
+
var ANDROID_PRODUCTION_ARTIFACT = "android/app/build/outputs/bundle/release/*.aab";
|
|
421
|
+
var ANDROID_PRODUCTION_COMMAND = "yarn install --immutable && cd android && ./gradlew bundleRelease";
|
|
422
|
+
var IOS_PRODUCTION_ARTIFACT = "ios/build/*.ipa";
|
|
423
|
+
function productionDefaultsFor(cwd, platform) {
|
|
424
|
+
if (platform === "android") {
|
|
425
|
+
return { buildCommand: ANDROID_PRODUCTION_COMMAND, artifact: ANDROID_PRODUCTION_ARTIFACT };
|
|
426
|
+
}
|
|
427
|
+
if (platform === "ios") {
|
|
428
|
+
const ws = iosWorkspaceName(cwd);
|
|
429
|
+
if (!ws) return { artifact: IOS_PRODUCTION_ARTIFACT };
|
|
430
|
+
const archivePath = `ios/build/${ws}.xcarchive`;
|
|
431
|
+
const archiveCmd = `xcodebuild archive -workspace ios/${ws}.xcworkspace -scheme ${ws} -configuration Release -archivePath ${archivePath} CODE_SIGN_STYLE=Manual \${VIBEVIEW_DEVELOPMENT_TEAM:+"DEVELOPMENT_TEAM=$VIBEVIEW_DEVELOPMENT_TEAM"} \${VIBEVIEW_PROVISIONING_PROFILE:+"PROVISIONING_PROFILE_SPECIFIER=$VIBEVIEW_PROVISIONING_PROFILE"} \${VIBEVIEW_CODE_SIGN_IDENTITY:+"CODE_SIGN_IDENTITY=$VIBEVIEW_CODE_SIGN_IDENTITY"}`;
|
|
432
|
+
const exportCmd = `xcodebuild -exportArchive -archivePath ${archivePath} -exportPath ios/build -exportOptionsPlist "$VIBEVIEW_EXPORT_OPTIONS_PLIST"`;
|
|
433
|
+
return {
|
|
434
|
+
buildCommand: `yarn install --immutable && ${archiveCmd} && ${exportCmd}`,
|
|
435
|
+
artifact: IOS_PRODUCTION_ARTIFACT
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
return {};
|
|
439
|
+
}
|
|
405
440
|
|
|
406
441
|
// src/lib/dev-setup.ts
|
|
407
442
|
function platformChoices(cwd) {
|
|
@@ -454,6 +489,11 @@ async function promptBuildConfig(cwd, platform) {
|
|
|
454
489
|
if (choice === "default") {
|
|
455
490
|
return { command: defaults.buildCommand, artifact: defaults.artifact };
|
|
456
491
|
}
|
|
492
|
+
console.log(
|
|
493
|
+
chalk.dim(
|
|
494
|
+
" Tip: include your install step \u2014 dependencies are not uploaded.\n e.g. `yarn install --immutable && yarn build:android`"
|
|
495
|
+
)
|
|
496
|
+
);
|
|
457
497
|
const command = await input({ message: `Build command for ${platform}`, required: true });
|
|
458
498
|
const artifact = await input({
|
|
459
499
|
message: platform === "roku" ? "Path to the channel zip it produces (* allowed)" : "Path to the built app it produces (.apk, or .app dir; * allowed)",
|
|
@@ -462,6 +502,35 @@ async function promptBuildConfig(cwd, platform) {
|
|
|
462
502
|
});
|
|
463
503
|
return { command, artifact };
|
|
464
504
|
}
|
|
505
|
+
async function promptProductionBuildConfig(cwd, platform) {
|
|
506
|
+
const defaults = productionDefaultsFor(cwd, platform);
|
|
507
|
+
const choice = await commandSelect(
|
|
508
|
+
`Production build command for ${platform}`,
|
|
509
|
+
defaults.buildCommand
|
|
510
|
+
);
|
|
511
|
+
if (choice === "skip") return null;
|
|
512
|
+
if (choice === "default") {
|
|
513
|
+
return {
|
|
514
|
+
productionCommand: defaults.buildCommand,
|
|
515
|
+
productionArtifact: defaults.artifact
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
console.log(
|
|
519
|
+
chalk.dim(
|
|
520
|
+
" Tip: include your install step \u2014 dependencies are not uploaded.\n e.g. `yarn install --immutable && cd android && ./gradlew bundleRelease`"
|
|
521
|
+
)
|
|
522
|
+
);
|
|
523
|
+
const productionCommand = await input({
|
|
524
|
+
message: `Production build command for ${platform}`,
|
|
525
|
+
required: true
|
|
526
|
+
});
|
|
527
|
+
const productionArtifact = await input({
|
|
528
|
+
message: "Path to the signed production artifact it produces (.aab/.ipa; * allowed)",
|
|
529
|
+
default: defaults.artifact,
|
|
530
|
+
required: true
|
|
531
|
+
});
|
|
532
|
+
return { productionCommand, productionArtifact };
|
|
533
|
+
}
|
|
465
534
|
async function promptMetroCommand(cwd, platform) {
|
|
466
535
|
const defaults = defaultsFor(cwd, platform);
|
|
467
536
|
const choice = await commandSelect("Command that starts Metro", defaults.metroCommand);
|
|
@@ -642,6 +711,7 @@ function runTar(args) {
|
|
|
642
711
|
|
|
643
712
|
// src/commands/build.ts
|
|
644
713
|
var CLOUD_PLATFORMS = ["ios", "android", "tvos", "androidtv"];
|
|
714
|
+
var PRODUCTION_SIGNING_PLATFORMS = ["ios", "android"];
|
|
645
715
|
function isCloudPlatform(p) {
|
|
646
716
|
return CLOUD_PLATFORMS.includes(p);
|
|
647
717
|
}
|
|
@@ -692,7 +762,7 @@ function runShell(command, cwd, log) {
|
|
|
692
762
|
}
|
|
693
763
|
async function resolveBarePlatform(cwd, cfg, opts) {
|
|
694
764
|
if (opts.platform && !isDevPlatform(opts.platform)) {
|
|
695
|
-
console.error(
|
|
765
|
+
console.error(chalk2.red(`error: --platform must be one of ${DEV_PLATFORMS.join(", ")}`));
|
|
696
766
|
process.exit(2);
|
|
697
767
|
}
|
|
698
768
|
let platform = opts.platform || cfg?.defaultPlatform;
|
|
@@ -753,6 +823,37 @@ async function resolveBuildConfig(cwd, cfgRef, platform, opts) {
|
|
|
753
823
|
cfgRef.current = persistPromptedBuild(cwd, cfgRef.current, platform, answered);
|
|
754
824
|
return answered;
|
|
755
825
|
}
|
|
826
|
+
function persistPromptedProductionBuild(cwd, cfg, platform, production) {
|
|
827
|
+
const next = cfg ?? { defaultPlatform: platform, platforms: {} };
|
|
828
|
+
const existingBuild = next.platforms[platform]?.build;
|
|
829
|
+
if (!existingBuild?.command || !existingBuild?.artifact) {
|
|
830
|
+
throw new Error(
|
|
831
|
+
`internal: cannot persist a production build config for ${platform} before its debug command/artifact are resolved`
|
|
832
|
+
);
|
|
833
|
+
}
|
|
834
|
+
next.platforms[platform].build = { ...existingBuild, ...production };
|
|
835
|
+
saveDevConfig(cwd, next);
|
|
836
|
+
return next;
|
|
837
|
+
}
|
|
838
|
+
async function resolveProductionBuildConfig(cwd, cfgRef, platform, opts) {
|
|
839
|
+
const entry = cfgRef.current?.platforms?.[platform]?.build;
|
|
840
|
+
if (entry?.productionCommand && entry?.productionArtifact) {
|
|
841
|
+
return { command: entry.productionCommand, artifact: entry.productionArtifact };
|
|
842
|
+
}
|
|
843
|
+
if (opts.json || !process.stdin.isTTY) {
|
|
844
|
+
fail(
|
|
845
|
+
opts,
|
|
846
|
+
`no production build config for ${platform}: add platforms.${platform}.build.productionCommand/productionArtifact to vibeview.json`,
|
|
847
|
+
"config_required"
|
|
848
|
+
);
|
|
849
|
+
}
|
|
850
|
+
const answered = await promptProductionBuildConfig(cwd, platform);
|
|
851
|
+
if (!answered) {
|
|
852
|
+
fail(opts, "a production build config is required for --production", "config_required");
|
|
853
|
+
}
|
|
854
|
+
cfgRef.current = persistPromptedProductionBuild(cwd, cfgRef.current, platform, answered);
|
|
855
|
+
return { command: answered.productionCommand, artifact: answered.productionArtifact };
|
|
856
|
+
}
|
|
756
857
|
async function buildCommand(opts, cloudDeps) {
|
|
757
858
|
const cwd = process.cwd();
|
|
758
859
|
const cfgRef = { current: loadDevConfig(cwd) };
|
|
@@ -761,6 +862,13 @@ async function buildCommand(opts, cloudDeps) {
|
|
|
761
862
|
await runCloudBuildCommand(cwd, cfgRef, opts, cloudDeps);
|
|
762
863
|
return;
|
|
763
864
|
}
|
|
865
|
+
if (opts.production) {
|
|
866
|
+
fail(
|
|
867
|
+
opts,
|
|
868
|
+
"--production requires --cloud: signed release builds run in the cloud (vibeview build --cloud --production)",
|
|
869
|
+
"usage"
|
|
870
|
+
);
|
|
871
|
+
}
|
|
764
872
|
const platform = await resolveBarePlatform(cwd, cfgRef.current, opts);
|
|
765
873
|
const build = await resolveBuildConfig(cwd, cfgRef, platform, opts);
|
|
766
874
|
const cfg = cfgRef.current;
|
|
@@ -769,9 +877,9 @@ async function buildCommand(opts, cloudDeps) {
|
|
|
769
877
|
platform,
|
|
770
878
|
build,
|
|
771
879
|
opts,
|
|
772
|
-
(l) => console.error(
|
|
880
|
+
(l) => console.error(chalk2.dim(l))
|
|
773
881
|
);
|
|
774
|
-
for (const w of result.warnings ?? []) console.error(
|
|
882
|
+
for (const w of result.warnings ?? []) console.error(chalk2.yellow(`\u26A0 ${w}`));
|
|
775
883
|
persistUploadedAppId(cwd, cfg, platform, build, result.public_id);
|
|
776
884
|
if (opts.json) {
|
|
777
885
|
console.log(
|
|
@@ -779,8 +887,8 @@ async function buildCommand(opts, cloudDeps) {
|
|
|
779
887
|
);
|
|
780
888
|
} else {
|
|
781
889
|
console.error(
|
|
782
|
-
|
|
783
|
-
${
|
|
890
|
+
chalk2.green(`\u2713 built and uploaded ${result.name}`) + `
|
|
891
|
+
${chalk2.cyan(result.public_id)} ${chalk2.dim(`[${result.platform}]`)}`
|
|
784
892
|
);
|
|
785
893
|
}
|
|
786
894
|
} catch (err) {
|
|
@@ -792,7 +900,7 @@ async function buildCommand(opts, cloudDeps) {
|
|
|
792
900
|
}
|
|
793
901
|
function printFailure(opts, message, code) {
|
|
794
902
|
if (opts.json) console.log(JSON.stringify({ event: "error", code, message }));
|
|
795
|
-
console.error(
|
|
903
|
+
console.error(chalk2.red(`error: ${message}`));
|
|
796
904
|
}
|
|
797
905
|
function fail(opts, message, code) {
|
|
798
906
|
printFailure(opts, message, code);
|
|
@@ -805,7 +913,32 @@ async function resolveCloudPlatforms(cwd, cfgRef, opts) {
|
|
|
805
913
|
if (opts.platform === "all") {
|
|
806
914
|
const configured = Object.entries(cfgRef.current?.platforms ?? {});
|
|
807
915
|
const withBuild = configured.filter(([p, entry]) => isCloudPlatform(p) && entry?.build);
|
|
808
|
-
if (withBuild.length > 0)
|
|
916
|
+
if (withBuild.length > 0) {
|
|
917
|
+
let chosenPlatforms = withBuild.map(([p]) => p);
|
|
918
|
+
if (opts.production) {
|
|
919
|
+
const unsupported = chosenPlatforms.filter(
|
|
920
|
+
(p) => !PRODUCTION_SIGNING_PLATFORMS.includes(p)
|
|
921
|
+
);
|
|
922
|
+
if (unsupported.length > 0) {
|
|
923
|
+
for (const p of unsupported) {
|
|
924
|
+
const reason = `--production doesn't support ${p} \u2014 production signing supports ${PRODUCTION_SIGNING_PLATFORMS.join(" and ")}`;
|
|
925
|
+
emitCloud(opts.json, { event: "skipped", platform: p, reason });
|
|
926
|
+
if (!opts.json) console.error(chalk2.yellow(`\u26A0 skipping ${p}: ${reason}`));
|
|
927
|
+
}
|
|
928
|
+
chosenPlatforms = chosenPlatforms.filter((p) => !unsupported.includes(p));
|
|
929
|
+
}
|
|
930
|
+
if (chosenPlatforms.length === 0) {
|
|
931
|
+
const exclusions = describeAllExclusions(configured);
|
|
932
|
+
const prefix = exclusions ? `${exclusions}; ` : "";
|
|
933
|
+
fail(
|
|
934
|
+
opts,
|
|
935
|
+
`--platform all --production: ${prefix}none of the configured platforms support production signing (${PRODUCTION_SIGNING_PLATFORMS.join(" and ")} only)`,
|
|
936
|
+
"config_required"
|
|
937
|
+
);
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
return chosenPlatforms;
|
|
941
|
+
}
|
|
809
942
|
if (opts.json || !process.stdin.isTTY) {
|
|
810
943
|
fail(
|
|
811
944
|
opts,
|
|
@@ -818,18 +951,20 @@ async function resolveCloudPlatforms(cwd, cfgRef, opts) {
|
|
|
818
951
|
platform: void 0
|
|
819
952
|
});
|
|
820
953
|
requireCloudCapable(opts, chosen);
|
|
954
|
+
requireProductionCapable(opts, chosen);
|
|
821
955
|
await resolveBuildConfig(cwd, cfgRef, chosen, opts);
|
|
822
956
|
return [chosen];
|
|
823
957
|
}
|
|
824
958
|
const platform = opts.platform ? validateExplicitPlatform(opts.platform) : await resolveBarePlatform(cwd, cfgRef.current, opts);
|
|
825
959
|
requireCloudCapable(opts, platform);
|
|
960
|
+
requireProductionCapable(opts, platform);
|
|
826
961
|
await resolveBuildConfig(cwd, cfgRef, platform, opts);
|
|
827
962
|
return [platform];
|
|
828
963
|
}
|
|
829
964
|
function validateExplicitPlatform(raw) {
|
|
830
965
|
if (!isDevPlatform(raw)) {
|
|
831
966
|
console.error(
|
|
832
|
-
|
|
967
|
+
chalk2.red(`error: --platform must be one of ${DEV_PLATFORMS.join(", ")}, or "all"`)
|
|
833
968
|
);
|
|
834
969
|
process.exit(2);
|
|
835
970
|
}
|
|
@@ -843,6 +978,14 @@ function requireCloudCapable(opts, platform) {
|
|
|
843
978
|
);
|
|
844
979
|
}
|
|
845
980
|
}
|
|
981
|
+
function requireProductionCapable(opts, platform) {
|
|
982
|
+
if (opts.production && !PRODUCTION_SIGNING_PLATFORMS.includes(platform)) {
|
|
983
|
+
fail(
|
|
984
|
+
opts,
|
|
985
|
+
`--production doesn't support ${platform} \u2014 production signing supports ${PRODUCTION_SIGNING_PLATFORMS.join(" and ")}`
|
|
986
|
+
);
|
|
987
|
+
}
|
|
988
|
+
}
|
|
846
989
|
function persistPickedAppId(cwd, cfg, platform, appId) {
|
|
847
990
|
const next = cfg ?? { defaultPlatform: platform, platforms: {} };
|
|
848
991
|
const entry = next.platforms[platform];
|
|
@@ -878,7 +1021,7 @@ async function resolveCloudAppIds(cwd, cfgRef, platforms, opts, listApps) {
|
|
|
878
1021
|
createFromArtifact.add(platform);
|
|
879
1022
|
if (!opts.json) {
|
|
880
1023
|
console.error(
|
|
881
|
-
|
|
1024
|
+
chalk2.dim(`no ${platform} apps yet \u2014 this build will create one from the artifact`)
|
|
882
1025
|
);
|
|
883
1026
|
}
|
|
884
1027
|
continue;
|
|
@@ -976,6 +1119,12 @@ async function runCloudBuildCommand(cwd, cfgRef, opts, deps) {
|
|
|
976
1119
|
const client = new ApiClient(baseUrl, token);
|
|
977
1120
|
const d = deps ?? defaultCloudBuildDeps(client);
|
|
978
1121
|
const createFromArtifact = await resolveCloudAppIds(cwd, cfgRef, platforms, opts, d.listApps);
|
|
1122
|
+
const productionBuilds = /* @__PURE__ */ new Map();
|
|
1123
|
+
if (opts.production) {
|
|
1124
|
+
for (const p of platforms) {
|
|
1125
|
+
productionBuilds.set(p, await resolveProductionBuildConfig(cwd, cfgRef, p, opts));
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
979
1128
|
const cfg = cfgRef.current;
|
|
980
1129
|
for (const p of platforms) {
|
|
981
1130
|
try {
|
|
@@ -1021,6 +1170,9 @@ ${offenders}`);
|
|
|
1021
1170
|
const manifestEntries = platforms.map((p) => {
|
|
1022
1171
|
const entry = cfg.platforms[p];
|
|
1023
1172
|
const build = entry.build;
|
|
1173
|
+
const production = productionBuilds.get(p);
|
|
1174
|
+
const command = production ? production.command : build.command;
|
|
1175
|
+
const artifactPath = production ? production.artifact : build.artifact;
|
|
1024
1176
|
return {
|
|
1025
1177
|
platform: p,
|
|
1026
1178
|
// OMITTED, never invented, for a platform whose app the artifact will
|
|
@@ -1029,8 +1181,9 @@ ${offenders}`);
|
|
|
1029
1181
|
// it either persisted a picked appId onto the entry, marked the
|
|
1030
1182
|
// platform create-from-artifact, or failed the whole command.
|
|
1031
1183
|
...createFromArtifact.has(p) ? {} : { app_public_id: entry.appId },
|
|
1032
|
-
command
|
|
1033
|
-
artifact_path:
|
|
1184
|
+
command,
|
|
1185
|
+
artifact_path: artifactPath,
|
|
1186
|
+
distribution: production ? "production" : "simulator",
|
|
1034
1187
|
...build.env ? { env: build.env } : {}
|
|
1035
1188
|
};
|
|
1036
1189
|
});
|
|
@@ -1051,7 +1204,7 @@ ${offenders}`);
|
|
|
1051
1204
|
}
|
|
1052
1205
|
if (!opts.json) {
|
|
1053
1206
|
for (const b of created) {
|
|
1054
|
-
console.error(` ${
|
|
1207
|
+
console.error(` ${chalk2.cyan(b.id)} ${chalk2.dim(`[${b.platform}]`)}`);
|
|
1055
1208
|
}
|
|
1056
1209
|
}
|
|
1057
1210
|
const shouldWait = opts.wait !== false || opts.download;
|
|
@@ -1074,7 +1227,7 @@ ${offenders}`);
|
|
|
1074
1227
|
path: result.path
|
|
1075
1228
|
});
|
|
1076
1229
|
if (!opts.json) {
|
|
1077
|
-
console.error(
|
|
1230
|
+
console.error(chalk2.green(`\u2713 saved ${result.filename}`));
|
|
1078
1231
|
}
|
|
1079
1232
|
} catch (err) {
|
|
1080
1233
|
downloadFailed = true;
|
|
@@ -1083,7 +1236,7 @@ ${offenders}`);
|
|
|
1083
1236
|
event: "error",
|
|
1084
1237
|
message: `error downloading ${b.id}: ${message}`
|
|
1085
1238
|
});
|
|
1086
|
-
if (!opts.json) console.error(
|
|
1239
|
+
if (!opts.json) console.error(chalk2.red(`error downloading ${b.id}: ${message}`));
|
|
1087
1240
|
}
|
|
1088
1241
|
}
|
|
1089
1242
|
}
|
|
@@ -1140,7 +1293,7 @@ async function waitForCloudBuilds(builds, opts, deps) {
|
|
|
1140
1293
|
const giveUpLocally = (id, message) => {
|
|
1141
1294
|
abandoned.add(id);
|
|
1142
1295
|
emitCloud(opts.json, { event: "error", message });
|
|
1143
|
-
if (!opts.json) console.error(
|
|
1296
|
+
if (!opts.json) console.error(chalk2.red(message));
|
|
1144
1297
|
};
|
|
1145
1298
|
const pollAndProcess = async (build) => {
|
|
1146
1299
|
const offset = offsets.get(build.id) ?? 0;
|
|
@@ -1301,21 +1454,21 @@ function printTransition(id, platform, status, state, json, printLine) {
|
|
|
1301
1454
|
if (json) {
|
|
1302
1455
|
emitCloud(json, { event: "status", id, status: "queued" });
|
|
1303
1456
|
} else {
|
|
1304
|
-
printLine(id, platform,
|
|
1457
|
+
printLine(id, platform, chalk2.dim("\u23F3 queued \u2014 waiting for a build slot"));
|
|
1305
1458
|
}
|
|
1306
1459
|
} else if (status === "running" && !state.printedRunning) {
|
|
1307
1460
|
state.printedRunning = true;
|
|
1308
1461
|
if (json) {
|
|
1309
1462
|
emitCloud(json, { event: "status", id, status: "running" });
|
|
1310
1463
|
} else {
|
|
1311
|
-
printLine(id, platform, `${
|
|
1464
|
+
printLine(id, platform, `${chalk2.cyan("\u25B6")} building`);
|
|
1312
1465
|
}
|
|
1313
1466
|
}
|
|
1314
1467
|
}
|
|
1315
1468
|
function printOutcomeLine(build, multi) {
|
|
1316
1469
|
const prefix = multi ? `[${build.platform}] ` : "";
|
|
1317
1470
|
const ok = build.status === "succeeded";
|
|
1318
|
-
const mark = ok ?
|
|
1471
|
+
const mark = ok ? chalk2.green("\u2713") : chalk2.red("\u2717");
|
|
1319
1472
|
const duration = formatDuration(build.started_at, build.finished_at);
|
|
1320
1473
|
let line = `${prefix}${mark} ${build.status}`;
|
|
1321
1474
|
if (duration) line += ` (${duration})`;
|
|
@@ -1330,7 +1483,7 @@ import { createWriteStream, mkdirSync as mkdirSync3 } from "fs";
|
|
|
1330
1483
|
import { dirname as dirname5 } from "path";
|
|
1331
1484
|
import { createInterface as createInterface3 } from "readline";
|
|
1332
1485
|
import { select as select3 } from "@inquirer/prompts";
|
|
1333
|
-
import
|
|
1486
|
+
import chalk3 from "chalk";
|
|
1334
1487
|
import openBrowser from "open";
|
|
1335
1488
|
|
|
1336
1489
|
// src/lib/tunnel-client.ts
|
|
@@ -1964,7 +2117,7 @@ function requireNonInteractive(json) {
|
|
|
1964
2117
|
async function ensureConfig(api, opts) {
|
|
1965
2118
|
const existing = loadDevConfig(process.cwd());
|
|
1966
2119
|
if (opts.platform && !isDevPlatform(opts.platform)) {
|
|
1967
|
-
console.error(
|
|
2120
|
+
console.error(chalk3.red(`error: --platform must be one of ${DEV_PLATFORMS.join(", ")}`));
|
|
1968
2121
|
process.exit(2);
|
|
1969
2122
|
}
|
|
1970
2123
|
if (!opts.platform && !existing?.defaultPlatform) {
|
|
@@ -1977,12 +2130,12 @@ async function ensureConfig(api, opts) {
|
|
|
1977
2130
|
const isTv = PLATFORM_DEVICE[platform].tv;
|
|
1978
2131
|
if (isTv && opts.deviceCategory) {
|
|
1979
2132
|
console.error(
|
|
1980
|
-
|
|
2133
|
+
chalk3.red(`error: --device-category does not apply to ${platform} (always a tv device)`)
|
|
1981
2134
|
);
|
|
1982
2135
|
process.exit(2);
|
|
1983
2136
|
}
|
|
1984
2137
|
if (!isTv && opts.deviceCategory === "tv") {
|
|
1985
|
-
console.error(
|
|
2138
|
+
console.error(chalk3.red(`error: use --platform tvos or --platform androidtv for TV devices`));
|
|
1986
2139
|
process.exit(2);
|
|
1987
2140
|
}
|
|
1988
2141
|
let firstRunBuild = null;
|
|
@@ -2005,7 +2158,7 @@ async function ensureConfig(api, opts) {
|
|
|
2005
2158
|
allApps = await api.listApps();
|
|
2006
2159
|
} catch (err) {
|
|
2007
2160
|
const message = `could not fetch your app list \u2014 ${err instanceof Error ? err.message : String(err)}`;
|
|
2008
|
-
console.error(
|
|
2161
|
+
console.error(chalk3.red(`error: ${message}`));
|
|
2009
2162
|
emit(opts.json, { event: "error", message });
|
|
2010
2163
|
process.exit(1);
|
|
2011
2164
|
}
|
|
@@ -2014,7 +2167,7 @@ async function ensureConfig(api, opts) {
|
|
|
2014
2167
|
if (choice.staleFlag) {
|
|
2015
2168
|
const message = `app "${choice.staleFlag}" not found \u2014 it may have been deleted.`;
|
|
2016
2169
|
console.error(
|
|
2017
|
-
|
|
2170
|
+
chalk3.red(`error: ${message}`) + `
|
|
2018
2171
|
Run \`vibeview dev\` without --app to pick from the list.`
|
|
2019
2172
|
);
|
|
2020
2173
|
emit(opts.json, { event: "error", message });
|
|
@@ -2024,7 +2177,7 @@ Run \`vibeview dev\` without --app to pick from the list.`
|
|
|
2024
2177
|
let builtThisRun = false;
|
|
2025
2178
|
if (choice.staleCached) {
|
|
2026
2179
|
console.error(
|
|
2027
|
-
|
|
2180
|
+
chalk3.yellow(`\u26A0 app "${choice.staleCached}" no longer exists \u2014 pick your debug build again`)
|
|
2028
2181
|
);
|
|
2029
2182
|
}
|
|
2030
2183
|
if (isFirstRun && !appId) {
|
|
@@ -2040,20 +2193,20 @@ Run \`vibeview dev\` without --app to pick from the list.`
|
|
|
2040
2193
|
});
|
|
2041
2194
|
}
|
|
2042
2195
|
if (action === "build") {
|
|
2043
|
-
console.error(
|
|
2196
|
+
console.error(chalk3.dim(`Building ${platform}...`));
|
|
2044
2197
|
try {
|
|
2045
2198
|
const result = await runBuildForPlatform(
|
|
2046
2199
|
process.cwd(),
|
|
2047
2200
|
platform,
|
|
2048
2201
|
firstRunBuild,
|
|
2049
2202
|
opts,
|
|
2050
|
-
(l) => console.error(
|
|
2203
|
+
(l) => console.error(chalk3.dim(l))
|
|
2051
2204
|
);
|
|
2052
2205
|
appId = result.public_id;
|
|
2053
2206
|
builtThisRun = true;
|
|
2054
2207
|
} catch (err) {
|
|
2055
2208
|
const message = err.message;
|
|
2056
|
-
console.error(
|
|
2209
|
+
console.error(chalk3.red(`error: ${message}`));
|
|
2057
2210
|
process.exit(1);
|
|
2058
2211
|
}
|
|
2059
2212
|
}
|
|
@@ -2061,20 +2214,20 @@ Run \`vibeview dev\` without --app to pick from the list.`
|
|
|
2061
2214
|
if (!appId) {
|
|
2062
2215
|
if (apps.length === 0) {
|
|
2063
2216
|
const message = noAppsMessage(platform, entry?.build !== void 0);
|
|
2064
|
-
console.error(
|
|
2217
|
+
console.error(chalk3.red(message));
|
|
2065
2218
|
emit(opts.json, { event: "error", code: "no_apps", message });
|
|
2066
2219
|
process.exit(1);
|
|
2067
2220
|
}
|
|
2068
2221
|
if (choice.staleCached) {
|
|
2069
2222
|
const message = `app "${choice.staleCached}" for ${platform} no longer exists \u2014 pass --app <id> (see \`vibeview list-apps\`) or run interactively to pick one.`;
|
|
2070
|
-
console.error(
|
|
2223
|
+
console.error(chalk3.red(`error: ${message}`));
|
|
2071
2224
|
emit(opts.json, { event: "error", code: "app_deleted", message });
|
|
2072
2225
|
process.exit(1);
|
|
2073
2226
|
}
|
|
2074
2227
|
requireNonInteractive(opts.json);
|
|
2075
2228
|
if (!process.stdin.isTTY) {
|
|
2076
2229
|
console.error(
|
|
2077
|
-
|
|
2230
|
+
chalk3.red(
|
|
2078
2231
|
`error: no valid app configured for ${platform} \u2014 run interactively to pick one, or pass --app <id>`
|
|
2079
2232
|
)
|
|
2080
2233
|
);
|
|
@@ -2110,7 +2263,7 @@ Run \`vibeview dev\` without --app to pick from the list.`
|
|
|
2110
2263
|
{ build: !firstRunBuild, metro: PLATFORM_NEEDS_METRO[platform] && !firstRunMetro },
|
|
2111
2264
|
platform
|
|
2112
2265
|
);
|
|
2113
|
-
if (hint) console.error(
|
|
2266
|
+
if (hint) console.error(chalk3.dim(hint));
|
|
2114
2267
|
}
|
|
2115
2268
|
const finalMetro = isFirstRun ? resolveMetro(cfg, platform, opts.metroPort ? parseInt(opts.metroPort, 10) : void 0) : metroResolved;
|
|
2116
2269
|
return {
|
|
@@ -2129,7 +2282,7 @@ async function runDevInProcess(opts) {
|
|
|
2129
2282
|
watchSeconds = parseWatchSeconds(opts.watch);
|
|
2130
2283
|
} catch (err) {
|
|
2131
2284
|
const message = err.message;
|
|
2132
|
-
console.error(
|
|
2285
|
+
console.error(chalk3.red(`error: ${message}`));
|
|
2133
2286
|
emit(opts.json, { event: "error", code: "invalid_flag", message });
|
|
2134
2287
|
process.exit(2);
|
|
2135
2288
|
}
|
|
@@ -2145,7 +2298,7 @@ async function runDevInProcess(opts) {
|
|
|
2145
2298
|
}
|
|
2146
2299
|
}
|
|
2147
2300
|
const { token, baseUrl } = resolveAuth(opts);
|
|
2148
|
-
console.error(
|
|
2301
|
+
console.error(chalk3.dim(`Using ${baseUrl}`));
|
|
2149
2302
|
const api = new ApiClient(baseUrl, token);
|
|
2150
2303
|
const cfg = await ensureConfig(api, opts);
|
|
2151
2304
|
if (opts.build && !cfg.builtThisRun) {
|
|
@@ -2153,18 +2306,18 @@ async function runDevInProcess(opts) {
|
|
|
2153
2306
|
const build = reloaded?.platforms?.[cfg.platform]?.build;
|
|
2154
2307
|
if (!build) {
|
|
2155
2308
|
const message = `no build config for ${cfg.platform} \u2014 run vibeview build once to set it up`;
|
|
2156
|
-
console.error(
|
|
2309
|
+
console.error(chalk3.red(`error: ${message}`));
|
|
2157
2310
|
emit(opts.json, { event: "error", code: "config_required", message });
|
|
2158
2311
|
process.exit(1);
|
|
2159
2312
|
}
|
|
2160
|
-
console.error(
|
|
2313
|
+
console.error(chalk3.dim(`Building ${cfg.platform}...`));
|
|
2161
2314
|
try {
|
|
2162
2315
|
const result = await runBuildForPlatform(
|
|
2163
2316
|
process.cwd(),
|
|
2164
2317
|
cfg.platform,
|
|
2165
2318
|
build,
|
|
2166
2319
|
{ token, baseUrl },
|
|
2167
|
-
(l) => console.error(
|
|
2320
|
+
(l) => console.error(chalk3.dim(l))
|
|
2168
2321
|
);
|
|
2169
2322
|
cfg.appId = result.public_id;
|
|
2170
2323
|
if (reloaded && reloaded.platforms[cfg.platform] && reloaded.platforms[cfg.platform].appId !== result.public_id) {
|
|
@@ -2173,7 +2326,7 @@ async function runDevInProcess(opts) {
|
|
|
2173
2326
|
}
|
|
2174
2327
|
} catch (err) {
|
|
2175
2328
|
const message = err.message;
|
|
2176
|
-
console.error(
|
|
2329
|
+
console.error(chalk3.red(`error: ${message}`));
|
|
2177
2330
|
emit(opts.json, { event: "error", message });
|
|
2178
2331
|
process.exit(1);
|
|
2179
2332
|
}
|
|
@@ -2195,7 +2348,7 @@ async function runDevInProcess(opts) {
|
|
|
2195
2348
|
metroLogStream.write(line.replace(/^\[metro\] /, "") + "\n");
|
|
2196
2349
|
} catch {
|
|
2197
2350
|
}
|
|
2198
|
-
if (shouldEchoMetroLine(line, opts.debug === true)) console.error(
|
|
2351
|
+
if (shouldEchoMetroLine(line, opts.debug === true)) console.error(chalk3.dim(line));
|
|
2199
2352
|
};
|
|
2200
2353
|
metroResult = await ensureMetro(
|
|
2201
2354
|
process.cwd(),
|
|
@@ -2208,15 +2361,15 @@ async function runDevInProcess(opts) {
|
|
|
2208
2361
|
);
|
|
2209
2362
|
} catch (err) {
|
|
2210
2363
|
const message = err.message;
|
|
2211
|
-
console.error(
|
|
2364
|
+
console.error(chalk3.red(`error: ${message}`));
|
|
2212
2365
|
emit(opts.json, { event: "error", code: "metro_down", message });
|
|
2213
2366
|
process.exit(1);
|
|
2214
2367
|
}
|
|
2215
|
-
for (const w of metroResult.warnings) console.error(
|
|
2368
|
+
for (const w of metroResult.warnings) console.error(chalk3.yellow(`\u26A0 ${w}`));
|
|
2216
2369
|
if (metroResult.status === "spawned" || metroResult.status === "respawned") {
|
|
2217
|
-
console.error(
|
|
2370
|
+
console.error(chalk3.green(`\u2713 started Metro (${cfg.metroCommand})`));
|
|
2218
2371
|
console.error(
|
|
2219
|
-
|
|
2372
|
+
chalk3.dim(` full Metro output: ${metroLogPath(process.cwd())} (--debug echoes it here)`)
|
|
2220
2373
|
);
|
|
2221
2374
|
}
|
|
2222
2375
|
metroOwnedThisRun = metroResult.status === "spawned" || metroResult.status === "respawned";
|
|
@@ -2226,19 +2379,19 @@ async function runDevInProcess(opts) {
|
|
|
2226
2379
|
watchIgnore = rokuEntry?.watchIgnore ?? [];
|
|
2227
2380
|
if (!rokuBuild) {
|
|
2228
2381
|
const message = `no build config for ${cfg.platform} \u2014 run \`vibeview build --platform ${cfg.platform}\` once to set it up`;
|
|
2229
|
-
console.error(
|
|
2382
|
+
console.error(chalk3.red(`error: ${message}`));
|
|
2230
2383
|
emit(opts.json, { event: "error", code: "config_required", message });
|
|
2231
2384
|
process.exit(1);
|
|
2232
2385
|
}
|
|
2233
2386
|
}
|
|
2234
|
-
console.error(
|
|
2387
|
+
console.error(chalk3.dim(`Starting a ${cfg.platform} dev session for ${cfg.appId}...`));
|
|
2235
2388
|
let stopping = false;
|
|
2236
2389
|
let handle = null;
|
|
2237
2390
|
let reloadLoop = null;
|
|
2238
2391
|
const stopSession = async (code) => {
|
|
2239
2392
|
if (stopping) return;
|
|
2240
2393
|
stopping = true;
|
|
2241
|
-
console.error(
|
|
2394
|
+
console.error(chalk3.dim("\nStopping session..."));
|
|
2242
2395
|
reloadLoop?.stop();
|
|
2243
2396
|
await handle?.stop();
|
|
2244
2397
|
if (metroOwnedThisRun) killOwnedMetro(process.cwd());
|
|
@@ -2271,15 +2424,15 @@ async function runDevInProcess(opts) {
|
|
|
2271
2424
|
if (evt.event === "warning") {
|
|
2272
2425
|
if (nextWarningIsMetroUnreachable) {
|
|
2273
2426
|
nextWarningIsMetroUnreachable = false;
|
|
2274
|
-
console.error(
|
|
2427
|
+
console.error(chalk3.red(`\u2717 ${evt.message}`));
|
|
2275
2428
|
} else {
|
|
2276
|
-
console.error(
|
|
2429
|
+
console.error(chalk3.yellow(`\u26A0 ${evt.message}`));
|
|
2277
2430
|
}
|
|
2278
2431
|
} else if (evt.event === "tunnel_connected") {
|
|
2279
2432
|
everConnected = true;
|
|
2280
|
-
console.error(
|
|
2433
|
+
console.error(chalk3.green("\u2713 tunnel connected \u2014 edit away, Fast Refresh is live"));
|
|
2281
2434
|
} else if (evt.event === "session_ended" && !stopping && handle) {
|
|
2282
|
-
console.error(
|
|
2435
|
+
console.error(chalk3.red("tunnel closed by server \u2014 session ended"));
|
|
2283
2436
|
stopping = true;
|
|
2284
2437
|
endedEmitted = true;
|
|
2285
2438
|
emit(opts.json, evt);
|
|
@@ -2298,20 +2451,20 @@ async function runDevInProcess(opts) {
|
|
|
2298
2451
|
if (!waitingPrinted) {
|
|
2299
2452
|
waitingPrinted = true;
|
|
2300
2453
|
console.error(
|
|
2301
|
-
|
|
2454
|
+
chalk3.dim("\u2026 waiting for the device to come up (tunnel not ready yet)")
|
|
2302
2455
|
);
|
|
2303
2456
|
}
|
|
2304
2457
|
return;
|
|
2305
2458
|
}
|
|
2306
|
-
console.error(
|
|
2459
|
+
console.error(chalk3.yellow("\u2026 tunnel dropped, reconnecting"));
|
|
2307
2460
|
} else if (s === "metro-unreachable") {
|
|
2308
2461
|
nextWarningIsMetroUnreachable = true;
|
|
2309
2462
|
}
|
|
2310
2463
|
}
|
|
2311
2464
|
);
|
|
2312
|
-
const keysLine = rokuBuild ? `Press ${
|
|
2465
|
+
const keysLine = rokuBuild ? `Press ${chalk3.bold("r")} to reload the channel, ${chalk3.bold("q")} or Ctrl-C to end the session.` : "Ctrl-C to end the session.";
|
|
2313
2466
|
console.error(`
|
|
2314
|
-
Watch and interact: ${
|
|
2467
|
+
Watch and interact: ${chalk3.cyan(handle.pageUrl)}
|
|
2315
2468
|
${keysLine}
|
|
2316
2469
|
`);
|
|
2317
2470
|
writeDevState(process.cwd(), {
|
|
@@ -2343,13 +2496,13 @@ async function runDevInProcess(opts) {
|
|
|
2343
2496
|
// Build output and loop notices are human output, so they go to
|
|
2344
2497
|
// stderr like every other line this command prints — stdout stays
|
|
2345
2498
|
// reserved for the `--json` event stream.
|
|
2346
|
-
log: (line) => console.error(
|
|
2499
|
+
log: (line) => console.error(chalk3.dim(line))
|
|
2347
2500
|
}),
|
|
2348
|
-
log: (line) => console.error(
|
|
2501
|
+
log: (line) => console.error(chalk3.yellow(line)),
|
|
2349
2502
|
// A failed reload is an error, not a notice — same red as every other
|
|
2350
2503
|
// failure this command prints, so it doesn't read like the yellow
|
|
2351
2504
|
// "already reloading" line.
|
|
2352
|
-
logError: (line) => console.error(
|
|
2505
|
+
logError: (line) => console.error(chalk3.red(`\u2717 ${line}`)),
|
|
2353
2506
|
...watchSeconds !== void 0 ? {
|
|
2354
2507
|
watchSeconds,
|
|
2355
2508
|
watch: watchProjectFiles(process.cwd(), rokuBuild.artifact, watchIgnore)
|
|
@@ -2357,7 +2510,7 @@ async function runDevInProcess(opts) {
|
|
|
2357
2510
|
});
|
|
2358
2511
|
if (watchSeconds !== void 0) {
|
|
2359
2512
|
console.error(
|
|
2360
|
-
|
|
2513
|
+
chalk3.dim(` Watching for changes \u2014 reloading after ${watchSeconds}s of quiet.`)
|
|
2361
2514
|
);
|
|
2362
2515
|
}
|
|
2363
2516
|
if (process.stdin.isTTY) {
|
|
@@ -2392,7 +2545,7 @@ async function runDevInProcess(opts) {
|
|
|
2392
2545
|
}
|
|
2393
2546
|
const verdict = sessionLivenessVerdict(info);
|
|
2394
2547
|
if (verdict.end && !stopping) {
|
|
2395
|
-
console.error(
|
|
2548
|
+
console.error(chalk3.red(verdict.message));
|
|
2396
2549
|
emit(opts.json, { event: "session_ended", session_id: sessionId, code: 1 });
|
|
2397
2550
|
endedEmitted = true;
|
|
2398
2551
|
await stopSession(1);
|
|
@@ -2401,7 +2554,7 @@ async function runDevInProcess(opts) {
|
|
|
2401
2554
|
const warningVerdict = lateWarningVerdict(info, reportedWarnings);
|
|
2402
2555
|
for (const w of warningVerdict.toReport) {
|
|
2403
2556
|
reportedWarnings.add(w);
|
|
2404
|
-
console.error(
|
|
2557
|
+
console.error(chalk3.yellow(`\u26A0 ${w}`));
|
|
2405
2558
|
emit(opts.json, { event: "warning", message: w });
|
|
2406
2559
|
}
|
|
2407
2560
|
if (warningVerdict.blocking && !stopping) {
|
|
@@ -2419,7 +2572,7 @@ async function runDevInProcess(opts) {
|
|
|
2419
2572
|
}
|
|
2420
2573
|
} catch (err) {
|
|
2421
2574
|
const message = err.message;
|
|
2422
|
-
console.error(
|
|
2575
|
+
console.error(chalk3.red(`error: ${message}`));
|
|
2423
2576
|
emit(opts.json, { event: "error", message });
|
|
2424
2577
|
await stopSession(1);
|
|
2425
2578
|
}
|
|
@@ -2449,12 +2602,12 @@ async function dev(opts) {
|
|
|
2449
2602
|
if (opts.json) {
|
|
2450
2603
|
console.log(JSON.stringify(parsed));
|
|
2451
2604
|
} else {
|
|
2452
|
-
console.error(
|
|
2453
|
-
console.error(
|
|
2605
|
+
console.error(chalk3.dim(`Using ${resolveAuth(opts).baseUrl}`));
|
|
2606
|
+
console.error(chalk3.green(`\u2713 dev session started in the background (pid ${parsed.pid})`));
|
|
2454
2607
|
console.error(`
|
|
2455
|
-
Watch and interact: ${
|
|
2456
|
-
console.error(
|
|
2457
|
-
console.error(
|
|
2608
|
+
Watch and interact: ${chalk3.cyan(parsed.url)}`);
|
|
2609
|
+
console.error(chalk3.dim(` vibeview dev-status \u2014 check on it`));
|
|
2610
|
+
console.error(chalk3.dim(` vibeview dev-stop \u2014 end it
|
|
2458
2611
|
`));
|
|
2459
2612
|
}
|
|
2460
2613
|
child.unref();
|
|
@@ -2464,13 +2617,13 @@ async function dev(opts) {
|
|
|
2464
2617
|
settled = true;
|
|
2465
2618
|
rl.close();
|
|
2466
2619
|
emit(opts.json, parsed);
|
|
2467
|
-
if (!opts.json) console.error(
|
|
2620
|
+
if (!opts.json) console.error(chalk3.red(`error: ${parsed.message}`));
|
|
2468
2621
|
reject(new Error(parsed.message));
|
|
2469
2622
|
} else if (parsed.event === "warning") {
|
|
2470
2623
|
if (opts.json) {
|
|
2471
2624
|
console.log(JSON.stringify(parsed));
|
|
2472
2625
|
} else {
|
|
2473
|
-
console.error(
|
|
2626
|
+
console.error(chalk3.yellow(`\u26A0 ${parsed.message}`));
|
|
2474
2627
|
}
|
|
2475
2628
|
}
|
|
2476
2629
|
});
|
|
@@ -2479,14 +2632,14 @@ async function dev(opts) {
|
|
|
2479
2632
|
rl.close();
|
|
2480
2633
|
const message = `dev session exited before starting (code ${code ?? "unknown"})`;
|
|
2481
2634
|
emit(opts.json, { event: "error", message });
|
|
2482
|
-
if (!opts.json) console.error(
|
|
2635
|
+
if (!opts.json) console.error(chalk3.red(`error: ${message}`));
|
|
2483
2636
|
reject(new Error(message));
|
|
2484
2637
|
});
|
|
2485
2638
|
child.on("error", (err) => {
|
|
2486
2639
|
if (settled) return;
|
|
2487
2640
|
rl.close();
|
|
2488
2641
|
emit(opts.json, { event: "error", message: err.message });
|
|
2489
|
-
if (!opts.json) console.error(
|
|
2642
|
+
if (!opts.json) console.error(chalk3.red(`error: ${err.message}`));
|
|
2490
2643
|
reject(err);
|
|
2491
2644
|
});
|
|
2492
2645
|
}).catch(() => {
|
|
@@ -2902,18 +3055,18 @@ var AGENT_COMMANDS = [
|
|
|
2902
3055
|
];
|
|
2903
3056
|
|
|
2904
3057
|
// src/agent/render.ts
|
|
2905
|
-
import
|
|
3058
|
+
import chalk4 from "chalk";
|
|
2906
3059
|
function renderEnvelope(env) {
|
|
2907
3060
|
const lines = [];
|
|
2908
3061
|
if (env.ok) {
|
|
2909
|
-
lines.push(
|
|
3062
|
+
lines.push(chalk4.green(`ok`) + chalk4.dim(` (${env.tool})`));
|
|
2910
3063
|
} else {
|
|
2911
|
-
lines.push(
|
|
3064
|
+
lines.push(chalk4.red(`error`) + chalk4.dim(` (${env.tool})`));
|
|
2912
3065
|
}
|
|
2913
3066
|
lines.push(...resultLines(env.result));
|
|
2914
3067
|
if (env.observation) {
|
|
2915
3068
|
if (env.observation.kind === "unavailable") {
|
|
2916
|
-
lines.push(
|
|
3069
|
+
lines.push(chalk4.yellow(`warning: ${env.observation.text}`));
|
|
2917
3070
|
} else {
|
|
2918
3071
|
lines.push(env.observation.text);
|
|
2919
3072
|
}
|
|
@@ -2926,17 +3079,17 @@ function resultLines(result) {
|
|
|
2926
3079
|
const lines = [];
|
|
2927
3080
|
if (Array.isArray(r.entries) && typeof r.cursor === "number") {
|
|
2928
3081
|
if (r.entries.length === 0) {
|
|
2929
|
-
lines.push(
|
|
3082
|
+
lines.push(chalk4.dim("(no log lines)"));
|
|
2930
3083
|
}
|
|
2931
3084
|
for (const e of r.entries) {
|
|
2932
3085
|
if (!e || typeof e !== "object") continue;
|
|
2933
3086
|
const entry = e;
|
|
2934
3087
|
const ts = typeof entry.timestamp === "number" ? new Date(entry.timestamp).toISOString().slice(11, 23) : "??:??:??.???";
|
|
2935
3088
|
const level = typeof entry.level === "string" ? entry.level : "info";
|
|
2936
|
-
const levelTag = level === "error" ?
|
|
2937
|
-
lines.push(`${
|
|
3089
|
+
const levelTag = level === "error" ? chalk4.red(level) : level === "warn" ? chalk4.yellow(level) : chalk4.dim(level);
|
|
3090
|
+
lines.push(`${chalk4.dim(ts)} ${levelTag} ${String(entry.message ?? "")}`);
|
|
2938
3091
|
}
|
|
2939
|
-
lines.push(
|
|
3092
|
+
lines.push(chalk4.dim(`cursor: ${r.cursor}`));
|
|
2940
3093
|
}
|
|
2941
3094
|
if (r.found === true && typeof r.ref === "string" && r.ref) {
|
|
2942
3095
|
let found = `found: @${r.ref}`;
|
|
@@ -2948,10 +3101,10 @@ function resultLines(result) {
|
|
|
2948
3101
|
const text = typeof a.text === "string" && a.text ? ` ${JSON.stringify(a.text)}` : "";
|
|
2949
3102
|
return `${ref}${text}`;
|
|
2950
3103
|
});
|
|
2951
|
-
if (alts.length > 0) lines.push(
|
|
3104
|
+
if (alts.length > 0) lines.push(chalk4.dim(`alternatives: ${alts.join(", ")}`));
|
|
2952
3105
|
}
|
|
2953
3106
|
}
|
|
2954
|
-
if (typeof r.note === "string" && r.note) lines.push(
|
|
3107
|
+
if (typeof r.note === "string" && r.note) lines.push(chalk4.dim(r.note));
|
|
2955
3108
|
if (typeof r.message === "string" && r.message) lines.push(r.message);
|
|
2956
3109
|
if (typeof r.warning === "string" && r.warning) lines.push(r.warning);
|
|
2957
3110
|
return lines;
|