vibeview 0.51.0 → 0.52.0
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.
|
@@ -60,6 +60,14 @@ function rawProfile(build, name) {
|
|
|
60
60
|
}
|
|
61
61
|
return null;
|
|
62
62
|
}
|
|
63
|
+
function profileNames(build) {
|
|
64
|
+
if (!build) return [];
|
|
65
|
+
const names = /* @__PURE__ */ new Set();
|
|
66
|
+
for (const n of [DEVELOPMENT, PREVIEW, PRODUCTION, ...Object.keys(build.profiles ?? {})]) {
|
|
67
|
+
if (rawProfile(build, n)) names.add(n);
|
|
68
|
+
}
|
|
69
|
+
return [...names];
|
|
70
|
+
}
|
|
63
71
|
function hasProfile(build, name) {
|
|
64
72
|
return !!build && rawProfile(build, name) !== null;
|
|
65
73
|
}
|
|
@@ -1756,16 +1764,78 @@ async function commandSelect(message, detected) {
|
|
|
1756
1764
|
choices.push({ value: "skip", name: "Skip for now" });
|
|
1757
1765
|
return select({ message, choices });
|
|
1758
1766
|
}
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1767
|
+
var PROFILES_DOCS_URL = "https://vibeview.io/docs/cloud-builds#build-profiles";
|
|
1768
|
+
var SIGNING_DOCS_URL = "https://vibeview.io/docs/app-signing";
|
|
1769
|
+
function usesMetroBuild(cwd, platform) {
|
|
1770
|
+
const flavor = detectFlavor(cwd);
|
|
1771
|
+
return (flavor === "expo" || flavor === "bare-rn") && (platform === "ios" || platform === "android");
|
|
1772
|
+
}
|
|
1773
|
+
function profileIntro(cwd, platform, profile, defaults) {
|
|
1774
|
+
const label = platformLabel(platform);
|
|
1775
|
+
const metro = usesMetroBuild(cwd, platform);
|
|
1776
|
+
if (profile === DEVELOPMENT) {
|
|
1777
|
+
return [
|
|
1778
|
+
`No development build profile for ${label} in vibeview.json yet.`,
|
|
1779
|
+
metro ? " development is the debug build VibeView devices run while you code: it loads your JavaScript from Metro (vibeview dev)." : " development is the build VibeView devices run while you work: vibeview build and vibeview dev use it.",
|
|
1780
|
+
" The answer is saved to vibeview.json. Commit it so your team and CI build the same way.",
|
|
1781
|
+
` Build profiles: ${PROFILES_DOCS_URL}`
|
|
1782
|
+
];
|
|
1783
|
+
}
|
|
1784
|
+
if (profile === PREVIEW) {
|
|
1785
|
+
const lines = [
|
|
1786
|
+
`No preview build profile for ${label} in vibeview.json yet.`,
|
|
1787
|
+
" preview is a standalone build that runs without a dev server: for share links, tests, teammates and GitHub pull requests."
|
|
1788
|
+
];
|
|
1789
|
+
if (!defaults.buildCommand && metro && platform === "android") {
|
|
1790
|
+
lines.push(
|
|
1791
|
+
" No suggestion: your release build doesn't use the debug key, and cloud builds don't have your own keystore.",
|
|
1792
|
+
" Enter a command that makes an APK a device can install (signed with the debug key), or skip."
|
|
1793
|
+
);
|
|
1794
|
+
} else if (defaults.buildCommand && !metro) {
|
|
1795
|
+
lines.push(
|
|
1796
|
+
" Your development build already runs by itself, so the suggestion is the same command."
|
|
1797
|
+
);
|
|
1798
|
+
}
|
|
1799
|
+
lines.push(` Build profiles: ${PROFILES_DOCS_URL}`);
|
|
1800
|
+
return lines;
|
|
1801
|
+
}
|
|
1802
|
+
if (profile === PRODUCTION) {
|
|
1803
|
+
return [
|
|
1804
|
+
`No production build profile for ${label} in vibeview.json yet.`,
|
|
1805
|
+
" production is the signed build for the stores (.ipa for TestFlight, .aab for Google Play).",
|
|
1806
|
+
` It builds in the cloud with the signing you set up in VibeView: ${SIGNING_DOCS_URL}`
|
|
1807
|
+
];
|
|
1808
|
+
}
|
|
1809
|
+
return [
|
|
1810
|
+
`No "${profile}" build profile for ${label} in vibeview.json yet.`,
|
|
1811
|
+
" A profile of your own makes a build that runs on VibeView devices, like development.",
|
|
1812
|
+
` To make it a signed store build, add "distribution": "production" to it in vibeview.json: ${PROFILES_DOCS_URL}`
|
|
1813
|
+
];
|
|
1814
|
+
}
|
|
1815
|
+
function previewSkippedNote(cwd, platform) {
|
|
1816
|
+
if (!usesMetroBuild(cwd, platform)) return [];
|
|
1817
|
+
const why = platform === "android" && !hasSeparatePreview(cwd, platform) ? "your release build doesn't use the debug key" : "you entered your own build command, so there's no Release version of it to suggest";
|
|
1818
|
+
return [
|
|
1819
|
+
` No preview profile saved (${why}). For a build that runs without Metro (share links, tests,`,
|
|
1820
|
+
" GitHub pull requests), add one with `vibeview build --cloud --profile preview`."
|
|
1821
|
+
];
|
|
1822
|
+
}
|
|
1823
|
+
function previewSavedNote() {
|
|
1824
|
+
return [
|
|
1825
|
+
" preview is the same build in Release, which runs without Metro: for share links, tests and",
|
|
1826
|
+
" GitHub pull requests. Build it with `vibeview build --cloud --profile preview`."
|
|
1827
|
+
];
|
|
1828
|
+
}
|
|
1829
|
+
function commandLabel(profile, platform) {
|
|
1830
|
+
return `Build command for ${platformLabel(platform)} (${profile} profile)`;
|
|
1762
1831
|
}
|
|
1763
1832
|
async function promptProfileConfig(cwd, platform, profile) {
|
|
1764
1833
|
const production = profile === PRODUCTION;
|
|
1765
1834
|
const defaults = await promptDefaults(cwd, platform, { profile });
|
|
1835
|
+
console.log(chalk2.dim(profileIntro(cwd, platform, profile, defaults).join("\n")));
|
|
1766
1836
|
evaluatedConfigNote(cwd, defaults);
|
|
1767
|
-
const label = commandLabel(profile);
|
|
1768
|
-
const choice = await commandSelect(
|
|
1837
|
+
const label = commandLabel(profile, platform);
|
|
1838
|
+
const choice = await commandSelect(label, defaults.buildCommand);
|
|
1769
1839
|
if (choice === "skip") return null;
|
|
1770
1840
|
if (choice === "default") {
|
|
1771
1841
|
return { command: defaults.buildCommand, artifact: defaults.artifact };
|
|
@@ -1775,7 +1845,7 @@ async function promptProfileConfig(cwd, platform, profile) {
|
|
|
1775
1845
|
" Tip: include your install step \u2014 dependencies are not uploaded.\n" + (production ? " e.g. `yarn install --immutable && cd android && ./gradlew bundleRelease`" : " e.g. `yarn install --immutable && yarn build:android`")
|
|
1776
1846
|
)
|
|
1777
1847
|
);
|
|
1778
|
-
const command = await input({ message:
|
|
1848
|
+
const command = await input({ message: label, required: true });
|
|
1779
1849
|
const artifact = await input({
|
|
1780
1850
|
message: production ? "Path to the signed production artifact it produces (.aab/.ipa; * allowed)" : platform === "roku" ? "Path to the channel zip it produces (* allowed)" : "Path to the built app it produces (.apk, or .app dir; * allowed)",
|
|
1781
1851
|
default: defaults.artifact,
|
|
@@ -2320,19 +2390,17 @@ async function resolveBuildProfile(cwd, cfgRef, platform, opts) {
|
|
|
2320
2390
|
);
|
|
2321
2391
|
}
|
|
2322
2392
|
const save = { [name]: answered };
|
|
2393
|
+
let note = [];
|
|
2323
2394
|
if (name === DEVELOPMENT && !hasProfile(build, PREVIEW)) {
|
|
2324
2395
|
const preview = await companionPreview(cwd, platform, answered);
|
|
2325
|
-
if (preview)
|
|
2326
|
-
|
|
2327
|
-
console.error(
|
|
2328
|
-
chalk3.dim(
|
|
2329
|
-
` Also saved a preview profile for ${platform}: the same build in Release, which runs without Metro
|
|
2330
|
-
(share links, tests, GitHub pull requests). Build it with \`vibeview build --cloud --profile preview\`.`
|
|
2331
|
-
)
|
|
2332
|
-
);
|
|
2333
|
-
}
|
|
2396
|
+
if (preview) save[PREVIEW] = preview;
|
|
2397
|
+
note = preview ? previewSavedNote() : previewSkippedNote(cwd, platform);
|
|
2334
2398
|
}
|
|
2335
2399
|
cfgRef.current = persistPromptedProfiles(cwd, platform, save);
|
|
2400
|
+
console.error(
|
|
2401
|
+
chalk3.green("\u2713") + ` Saved the ${Object.keys(save).join(" and ")} build profile${Object.keys(save).length > 1 ? "s" : ""} for ${platformLabel(platform)} to vibeview.json`
|
|
2402
|
+
);
|
|
2403
|
+
if (note.length) console.error(chalk3.dim(note.join("\n")));
|
|
2336
2404
|
return resolveProfile(cfgRef.current.platforms[platform]?.build, name);
|
|
2337
2405
|
}
|
|
2338
2406
|
async function buildCommand(opts, cloudDeps) {
|
|
@@ -2420,6 +2488,10 @@ async function buildCommand(opts, cloudDeps) {
|
|
|
2420
2488
|
);
|
|
2421
2489
|
}
|
|
2422
2490
|
} catch (err) {
|
|
2491
|
+
if (err instanceof Error && err.name === "ExitPromptError") {
|
|
2492
|
+
process.exitCode = 130;
|
|
2493
|
+
return;
|
|
2494
|
+
}
|
|
2423
2495
|
if (!(err instanceof BuildFailError)) {
|
|
2424
2496
|
printFailure(opts, err instanceof Error ? err.message : String(err));
|
|
2425
2497
|
}
|
|
@@ -2942,6 +3014,8 @@ async function waitForCloudBuilds(builds, opts, deps) {
|
|
|
2942
3014
|
id: final.id,
|
|
2943
3015
|
status: final.status,
|
|
2944
3016
|
cost_micro: final.cost_micro,
|
|
3017
|
+
included_minutes: final.included_minutes ?? null,
|
|
3018
|
+
billed_minutes: final.billed_minutes ?? null,
|
|
2945
3019
|
error_summary: final.error_summary,
|
|
2946
3020
|
app_build_id: final.app_build_id ?? null,
|
|
2947
3021
|
app_public_id: final.app_public_id ?? null,
|
|
@@ -3094,9 +3168,22 @@ function printOutcomeLine(build, multi) {
|
|
|
3094
3168
|
let line = `${prefix}${mark} ${build.status}`;
|
|
3095
3169
|
if (duration) line += ` (${duration})`;
|
|
3096
3170
|
if (build.error_summary) line += ` \u2014 ${build.error_summary}`;
|
|
3097
|
-
|
|
3171
|
+
const minutes = buildMinutesSuffix(build);
|
|
3172
|
+
if (minutes) line += ` \u2014 ${minutes}`;
|
|
3173
|
+
else if (build.cost_micro > 0) line += ` \u2014 cost: ${formatCost(build.cost_micro)} usage credit`;
|
|
3098
3174
|
console.error(line);
|
|
3099
3175
|
}
|
|
3176
|
+
function buildMinutesSuffix(build) {
|
|
3177
|
+
const included = build.included_minutes ?? 0;
|
|
3178
|
+
const billed = build.billed_minutes ?? 0;
|
|
3179
|
+
if (build.included_minutes == null && build.billed_minutes == null) return null;
|
|
3180
|
+
const plural = (n) => n === 1 ? "minute" : "minutes";
|
|
3181
|
+
if (billed === 0) return included > 0 ? `${included} included build ${plural(included)}` : null;
|
|
3182
|
+
const cost = `${formatCost(build.cost_micro)} usage credit`;
|
|
3183
|
+
if (included === 0) return `${billed} billed build ${plural(billed)} (${cost})`;
|
|
3184
|
+
const total = included + billed;
|
|
3185
|
+
return `${total} build ${plural(total)}: ${included} included, ${billed} billed (${cost})`;
|
|
3186
|
+
}
|
|
3100
3187
|
|
|
3101
3188
|
// src/lib/roku-push.ts
|
|
3102
3189
|
function createRokuPush(opts) {
|
|
@@ -4157,15 +4244,9 @@ async function ensureConfig(api, opts) {
|
|
|
4157
4244
|
if (answered) {
|
|
4158
4245
|
firstRunBuild = withProfile(void 0, DEVELOPMENT, answered);
|
|
4159
4246
|
const preview = await companionPreview(process.cwd(), platform, answered);
|
|
4160
|
-
if (preview)
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
chalk4.dim(
|
|
4164
|
-
` Also saved a preview profile for ${platform}: the same build in Release, which runs without Metro
|
|
4165
|
-
(share links, tests, GitHub pull requests). Build it with \`vibeview build --cloud --profile preview\`.`
|
|
4166
|
-
)
|
|
4167
|
-
);
|
|
4168
|
-
}
|
|
4247
|
+
if (preview) firstRunBuild = withProfile(firstRunBuild, PREVIEW, preview);
|
|
4248
|
+
const note = preview ? previewSavedNote() : previewSkippedNote(process.cwd(), platform);
|
|
4249
|
+
if (note.length) console.error(chalk4.dim(note.join("\n")));
|
|
4169
4250
|
}
|
|
4170
4251
|
if (PLATFORM_NEEDS_METRO[platform]) {
|
|
4171
4252
|
firstRunMetro = await promptMetroCommand(process.cwd(), platform);
|
|
@@ -4331,7 +4412,13 @@ ${hint}`);
|
|
|
4331
4412
|
);
|
|
4332
4413
|
}
|
|
4333
4414
|
if (isFirstRun) {
|
|
4334
|
-
|
|
4415
|
+
const saved = profileNames(firstRunBuild ?? void 0);
|
|
4416
|
+
console.error(
|
|
4417
|
+
chalk4.dim(
|
|
4418
|
+
`Created vibeview.json (platform: ${platform}, app: ${appId}` + (saved.length ? `, build profiles: ${saved.join(", ")}` : "") + ")." + // The development prompt's intro already said to commit it.
|
|
4419
|
+
(firstRunBuild ? "" : " Commit it so your team and CI use the same setup.")
|
|
4420
|
+
)
|
|
4421
|
+
);
|
|
4335
4422
|
const hint = fillLaterHint(
|
|
4336
4423
|
{ build: !firstRunBuild, metro: PLATFORM_NEEDS_METRO[platform] && !firstRunMetro },
|
|
4337
4424
|
platform
|
package/dist/cli.js
CHANGED
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
runAgentVerb,
|
|
36
36
|
runStepsNotChecked,
|
|
37
37
|
stepsNotCheckedLabel
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-AQCZ3UOE.js";
|
|
39
39
|
import {
|
|
40
40
|
ApiClient,
|
|
41
41
|
ApiStatusError,
|
|
@@ -2291,6 +2291,8 @@ The build may still be running server-side \u2014 resume watching it with \`vibe
|
|
|
2291
2291
|
id: final.id,
|
|
2292
2292
|
status: final.status,
|
|
2293
2293
|
cost_micro: final.cost_micro,
|
|
2294
|
+
included_minutes: final.included_minutes ?? null,
|
|
2295
|
+
billed_minutes: final.billed_minutes ?? null,
|
|
2294
2296
|
error_summary: final.error_summary
|
|
2295
2297
|
})
|
|
2296
2298
|
);
|
|
@@ -4518,7 +4520,7 @@ program.command("dev-reload").description(
|
|
|
4518
4520
|
program.command("mcp").description(
|
|
4519
4521
|
"Run an MCP stdio server exposing the agent verbs (tap, swipe, type, ...) plus dev_start/dev_stop/dev_reload as tools"
|
|
4520
4522
|
).option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").action(async (opts) => {
|
|
4521
|
-
const { runMcpServer } = await import("./server-
|
|
4523
|
+
const { runMcpServer } = await import("./server-3D436M2S.js");
|
|
4522
4524
|
await runMcpServer({ ...opts, version: pkg.version });
|
|
4523
4525
|
});
|
|
4524
4526
|
program.command("agent-setup").description(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibeview",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.52.0",
|
|
4
4
|
"description": "VibeView CLI -- run your app on cloud iOS simulators, Android emulators, Apple TV, Android TV and Roku devices: a React Native dev loop, device control for you or your coding agent (CLI or MCP), and tests from CI",
|
|
5
5
|
"mcpName": "io.github.vibeview/vibeview",
|
|
6
6
|
"type": "module",
|