vibeview 0.17.1 → 0.18.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.
- package/dist/{chunk-SYFMOPJW.js → chunk-BJEDH672.js} +38 -5
- package/dist/{chunk-3IMJ7FNN.js → chunk-MGP3UR7P.js} +17 -7
- package/dist/cli.js +238 -14
- package/dist/{server-AZLB25BY.js → server-TJQKNXDR.js} +3 -3
- package/dist/{upload-app-XRB7CKA3.js → upload-app-Y7MXT2PI.js} +1 -1
- package/package.json +1 -1
|
@@ -424,18 +424,51 @@ var ApiClient = class {
|
|
|
424
424
|
async deleteSigningCredential(id) {
|
|
425
425
|
await this.requestRaw("DELETE", `/signing-credentials/${id}`);
|
|
426
426
|
}
|
|
427
|
+
/** GET /api/v1/signing-credentials/asc-keys. Requires VIEWER role. Metadata
|
|
428
|
+
* only — the .p8 is never returned. */
|
|
429
|
+
async listAscKeys() {
|
|
430
|
+
return this.requestRaw("GET", "/signing-credentials/asc-keys");
|
|
431
|
+
}
|
|
432
|
+
/** POST /api/v1/signing-credentials/asc-keys (multipart). Requires ADMIN
|
|
433
|
+
* role. Same-name upload is a rotation upsert server-side. Field names are
|
|
434
|
+
* converted to the route's snake_case here, at the client boundary, like
|
|
435
|
+
* addSigningCredential. */
|
|
436
|
+
async addAscKey(body) {
|
|
437
|
+
const formData = new FormData();
|
|
438
|
+
if (body.name !== void 0) formData.append("name", body.name);
|
|
439
|
+
formData.append("issuer_id", body.issuerId);
|
|
440
|
+
formData.append("key_id", body.keyId);
|
|
441
|
+
formData.append("file", new Blob([new Uint8Array(body.file)]), body.filename);
|
|
442
|
+
return this.requestFormData("POST", "/signing-credentials/asc-keys", formData);
|
|
443
|
+
}
|
|
444
|
+
/** DELETE /api/v1/signing-credentials/asc-keys/{id}. Requires ADMIN role. */
|
|
445
|
+
async deleteAscKey(id) {
|
|
446
|
+
await this.requestRaw("DELETE", `/signing-credentials/asc-keys/${id}`);
|
|
447
|
+
}
|
|
448
|
+
/** GET /api/v1/signing-credentials/{id}/material. Requires ADMIN role;
|
|
449
|
+
* audited server-side. 404s (NotFoundError) for non-generated rows —
|
|
450
|
+
* uploaded material is never readable back. */
|
|
451
|
+
async getSigningCredentialMaterial(id) {
|
|
452
|
+
return this.requestRaw("GET", `/signing-credentials/${id}/material`);
|
|
453
|
+
}
|
|
427
454
|
/**
|
|
428
|
-
* POST /api/v1/signing-credentials/generate. Requires ADMIN role. Generates
|
|
429
|
-
*
|
|
430
|
-
*
|
|
431
|
-
*
|
|
432
|
-
*
|
|
455
|
+
* POST /api/v1/signing-credentials/generate. Requires ADMIN role. Generates a signing
|
|
456
|
+
* credential server-side and stores it. `platform` omitted means android
|
|
457
|
+
* (the server default); for android the response carries the keystore
|
|
458
|
+
* bytes and passwords inline, for ios/tvos it is a plain credential (no
|
|
459
|
+
* inline material — see getSigningCredentialMaterial). As with
|
|
460
|
+
* addSigningCredential, the CLI's camelCase (`keyAlias`, `bundleId`,
|
|
461
|
+
* `ascKey`) is converted to the route's snake_case at this boundary and
|
|
462
|
+
* nowhere else.
|
|
433
463
|
*/
|
|
434
464
|
async generateSigningCredential(body) {
|
|
435
465
|
return this.requestRaw("POST", "/signing-credentials/generate", {
|
|
436
466
|
name: body.name,
|
|
467
|
+
...body.platform !== void 0 ? { platform: body.platform } : {},
|
|
437
468
|
...body.app !== void 0 ? { app: body.app } : {},
|
|
438
469
|
...body.keyAlias !== void 0 ? { key_alias: body.keyAlias } : {},
|
|
470
|
+
...body.bundleId !== void 0 ? { bundle_id: body.bundleId } : {},
|
|
471
|
+
...body.ascKey !== void 0 ? { asc_key: body.ascKey } : {},
|
|
439
472
|
...body.overwrite !== void 0 ? { overwrite: body.overwrite } : {}
|
|
440
473
|
});
|
|
441
474
|
}
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
loadConfig,
|
|
6
6
|
resolveAuth,
|
|
7
7
|
uploadAppBuild
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-BJEDH672.js";
|
|
9
9
|
|
|
10
10
|
// src/lib/dev-state.ts
|
|
11
11
|
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "fs";
|
|
@@ -1000,8 +1000,13 @@ function persistPickedAppId(cwd, cfg, platform, appId) {
|
|
|
1000
1000
|
saveDevConfig(cwd, next);
|
|
1001
1001
|
return next;
|
|
1002
1002
|
}
|
|
1003
|
-
var
|
|
1004
|
-
|
|
1003
|
+
var APP_PICKER_SENTINEL = {
|
|
1004
|
+
CREATE_NEW_APP: "__vibeview_create_new_app__",
|
|
1005
|
+
DONT_LINK_APP: "__vibeview_dont_link_app__"
|
|
1006
|
+
};
|
|
1007
|
+
function isAppPickerSentinel(value) {
|
|
1008
|
+
return Object.values(APP_PICKER_SENTINEL).includes(value);
|
|
1009
|
+
}
|
|
1005
1010
|
async function resolveCloudAppIds(cwd, cfgRef, platforms, opts, listApps) {
|
|
1006
1011
|
const createFromArtifact = /* @__PURE__ */ new Set();
|
|
1007
1012
|
const missing = platforms.filter((p) => !cfgRef.current?.platforms?.[p]?.appId);
|
|
@@ -1041,18 +1046,23 @@ async function resolveCloudAppIds(cwd, cfgRef, platforms, opts, listApps) {
|
|
|
1041
1046
|
// Under --production a "Don't link an app" row leads the list (the
|
|
1042
1047
|
// neutral default, since the create-from-artifact escape hatch below
|
|
1043
1048
|
// is suppressed there): production builds aren't linked to an app
|
|
1044
|
-
// unless the user explicitly wants the link — see
|
|
1045
|
-
...opts.production ? [{ value: DONT_LINK_APP, name: "Don't link an app" }] : [],
|
|
1049
|
+
// unless the user explicitly wants the link — see APP_PICKER_SENTINEL.
|
|
1050
|
+
...opts.production ? [{ value: APP_PICKER_SENTINEL.DONT_LINK_APP, name: "Don't link an app" }] : [],
|
|
1046
1051
|
...apps.map((a) => ({ value: a.public_id, name: a.name })),
|
|
1047
1052
|
// No create-from-artifact row under --production: a production build
|
|
1048
1053
|
// never creates an app (internal_builds returns before app creation),
|
|
1049
1054
|
// so offering it would promise something that can't happen. Picking
|
|
1050
1055
|
// an EXISTING app is still meaningful — app-scoped signing
|
|
1051
1056
|
// credentials resolve by app.
|
|
1052
|
-
...opts.production ? [] : [
|
|
1057
|
+
...opts.production ? [] : [
|
|
1058
|
+
{
|
|
1059
|
+
value: APP_PICKER_SENTINEL.CREATE_NEW_APP,
|
|
1060
|
+
name: "Create a new app from this build"
|
|
1061
|
+
}
|
|
1062
|
+
]
|
|
1053
1063
|
]
|
|
1054
1064
|
});
|
|
1055
|
-
if (appId
|
|
1065
|
+
if (isAppPickerSentinel(appId)) {
|
|
1056
1066
|
createFromArtifact.add(platform);
|
|
1057
1067
|
continue;
|
|
1058
1068
|
}
|
package/dist/cli.js
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
readDevState,
|
|
14
14
|
readMetroState,
|
|
15
15
|
runAgentVerb
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-MGP3UR7P.js";
|
|
17
17
|
import {
|
|
18
18
|
ApiClient,
|
|
19
19
|
EXIT_INFRA_ERROR,
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
resolveAuth,
|
|
27
27
|
saveConfig,
|
|
28
28
|
uploadApp
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-BJEDH672.js";
|
|
30
30
|
|
|
31
31
|
// src/cli.ts
|
|
32
32
|
import { createRequire } from "module";
|
|
@@ -1710,6 +1710,17 @@ function defaultDeps4(client) {
|
|
|
1710
1710
|
await client.deleteSigningCredential(match.id);
|
|
1711
1711
|
},
|
|
1712
1712
|
generateCredential: (body) => client.generateSigningCredential(body),
|
|
1713
|
+
getMaterial: (id) => client.getSigningCredentialMaterial(id),
|
|
1714
|
+
addAscKey: (body) => client.addAscKey(body),
|
|
1715
|
+
listAscKeys: () => client.listAscKeys(),
|
|
1716
|
+
deleteAscKey: async (name) => {
|
|
1717
|
+
const { keys } = await client.listAscKeys();
|
|
1718
|
+
const match = keys.find((k) => k.name === name);
|
|
1719
|
+
if (!match) {
|
|
1720
|
+
throw new Error(`No App Store Connect key named "${name}" found.`);
|
|
1721
|
+
}
|
|
1722
|
+
await client.deleteAscKey(match.id);
|
|
1723
|
+
},
|
|
1713
1724
|
prompt: ({ message, hidden }) => hidden ? password2({ message }) : input({ message }),
|
|
1714
1725
|
isTTY: Boolean(process.stdin.isTTY),
|
|
1715
1726
|
readFile: (path) => readFileAsync2(path),
|
|
@@ -1802,16 +1813,18 @@ async function credentialsAdd(opts, deps) {
|
|
|
1802
1813
|
async function credentialsGenerate(opts, deps) {
|
|
1803
1814
|
const d = deps ?? defaultDeps4(clientFor2(opts));
|
|
1804
1815
|
if (!opts.platform) {
|
|
1805
|
-
throw new UsageError('--platform is required
|
|
1816
|
+
throw new UsageError('--platform is required and must be "android", "ios", or "tvos"');
|
|
1806
1817
|
}
|
|
1807
|
-
if (opts.platform
|
|
1808
|
-
throw new UsageError(
|
|
1809
|
-
"iOS/tvOS generation isn't available yet because it requires an Apple Developer account; upload an exported certificate with `vibeview credentials add` instead"
|
|
1810
|
-
);
|
|
1818
|
+
if (!isCredentialPlatform(opts.platform)) {
|
|
1819
|
+
throw new UsageError(`--platform must be "android", "ios", or "tvos" \u2014 got "${opts.platform}"`);
|
|
1811
1820
|
}
|
|
1812
1821
|
if (!opts.name) {
|
|
1813
1822
|
throw new UsageError("--name is required");
|
|
1814
1823
|
}
|
|
1824
|
+
if (opts.platform !== "android") {
|
|
1825
|
+
await generateAppleCredential(opts.platform, opts, d);
|
|
1826
|
+
return;
|
|
1827
|
+
}
|
|
1815
1828
|
const outDir = opts.out ?? process.cwd();
|
|
1816
1829
|
try {
|
|
1817
1830
|
d.mkdir(outDir);
|
|
@@ -1871,6 +1884,200 @@ async function credentialsGenerate(opts, deps) {
|
|
|
1871
1884
|
process.exitCode = 1;
|
|
1872
1885
|
}
|
|
1873
1886
|
}
|
|
1887
|
+
async function generateAppleCredential(platform, opts, d) {
|
|
1888
|
+
try {
|
|
1889
|
+
const result = await d.generateCredential({
|
|
1890
|
+
name: opts.name,
|
|
1891
|
+
platform,
|
|
1892
|
+
...opts.app !== void 0 ? { app: opts.app } : {},
|
|
1893
|
+
...opts.bundleId !== void 0 ? { bundleId: opts.bundleId } : {},
|
|
1894
|
+
...opts.ascKey !== void 0 ? { ascKey: opts.ascKey } : {},
|
|
1895
|
+
// Same rule as the android path: only ever `overwrite: true`, otherwise
|
|
1896
|
+
// the field is omitted and the server's 409-on-collision stays in charge.
|
|
1897
|
+
...opts.force ? { overwrite: true } : {}
|
|
1898
|
+
});
|
|
1899
|
+
if (opts.json) {
|
|
1900
|
+
console.log(JSON.stringify(result));
|
|
1901
|
+
} else {
|
|
1902
|
+
console.log(chalk14.green(`\u2713 generated ${result.name} (${result.platform})`));
|
|
1903
|
+
console.log("");
|
|
1904
|
+
console.log(` Scope: ${chalk14.bold(result.app_public_id ?? "org-wide")}`);
|
|
1905
|
+
const expires = formatExpires(result);
|
|
1906
|
+
if (expires) {
|
|
1907
|
+
console.log(` Expires: ${chalk14.bold(expires)}`);
|
|
1908
|
+
}
|
|
1909
|
+
console.log("");
|
|
1910
|
+
console.log(
|
|
1911
|
+
` The certificate and provisioning profile are stored with VibeView and already active for ${result.platform} production builds.`
|
|
1912
|
+
);
|
|
1913
|
+
console.log(
|
|
1914
|
+
` Run ${chalk14.bold(`vibeview credentials download ${result.name}`)} if you need the files locally.`
|
|
1915
|
+
);
|
|
1916
|
+
}
|
|
1917
|
+
process.exitCode = 0;
|
|
1918
|
+
} catch (err) {
|
|
1919
|
+
printError3(opts, err);
|
|
1920
|
+
process.exitCode = 1;
|
|
1921
|
+
}
|
|
1922
|
+
}
|
|
1923
|
+
async function credentialsDownload(name, opts, deps) {
|
|
1924
|
+
const d = deps ?? defaultDeps4(clientFor2(opts));
|
|
1925
|
+
const outDir = opts.out ?? process.cwd();
|
|
1926
|
+
try {
|
|
1927
|
+
const { credentials: credentials2 } = await d.listCredentials(opts.app);
|
|
1928
|
+
const wantApp = opts.app ?? null;
|
|
1929
|
+
const matches = credentials2.filter(
|
|
1930
|
+
(c) => c.name === name && (c.app_public_id ?? null) === wantApp
|
|
1931
|
+
);
|
|
1932
|
+
if (matches.length === 0) {
|
|
1933
|
+
throw new Error(
|
|
1934
|
+
`No credential named "${name}" found${opts.app ? ` for app "${opts.app}"` : ""}.`
|
|
1935
|
+
);
|
|
1936
|
+
}
|
|
1937
|
+
if (matches.length > 1) {
|
|
1938
|
+
throw new Error(
|
|
1939
|
+
`Multiple credentials named "${name}" match (platforms: ${matches.map((c) => c.platform).join(", ")}) \u2014 narrow the lookup with --app.`
|
|
1940
|
+
);
|
|
1941
|
+
}
|
|
1942
|
+
const cred = matches[0];
|
|
1943
|
+
d.mkdir(outDir);
|
|
1944
|
+
let material;
|
|
1945
|
+
try {
|
|
1946
|
+
material = await d.getMaterial(cred.id);
|
|
1947
|
+
} catch (err) {
|
|
1948
|
+
if (err instanceof NotFoundError) {
|
|
1949
|
+
throw new Error(
|
|
1950
|
+
`"${name}" was uploaded, not generated by VibeView \u2014 uploaded credential material is never readable back. Only credentials created by \`vibeview credentials generate\` can be downloaded.`
|
|
1951
|
+
);
|
|
1952
|
+
}
|
|
1953
|
+
throw err;
|
|
1954
|
+
}
|
|
1955
|
+
const savedTo = join(outDir, basename2(material.filename));
|
|
1956
|
+
const profileSavedTo = material.profile_base64 != null ? join(outDir, `${basename2(material.filename, extname(material.filename))}.mobileprovision`) : null;
|
|
1957
|
+
if (opts.json) {
|
|
1958
|
+
console.log(
|
|
1959
|
+
JSON.stringify({
|
|
1960
|
+
...material,
|
|
1961
|
+
saved_to: savedTo,
|
|
1962
|
+
...profileSavedTo !== null ? { profile_saved_to: profileSavedTo } : {}
|
|
1963
|
+
})
|
|
1964
|
+
);
|
|
1965
|
+
}
|
|
1966
|
+
const targets = [[savedTo, material.file_base64]];
|
|
1967
|
+
if (profileSavedTo !== null) targets.push([profileSavedTo, material.profile_base64]);
|
|
1968
|
+
for (const [path] of targets) {
|
|
1969
|
+
if (await d.fileExists(path)) {
|
|
1970
|
+
throw new Error(
|
|
1971
|
+
`${path} already exists \u2014 refusing to overwrite it. Move it away or pass a different --out.`
|
|
1972
|
+
);
|
|
1973
|
+
}
|
|
1974
|
+
}
|
|
1975
|
+
for (const [path, base64] of targets) {
|
|
1976
|
+
await d.writeFile(path, Buffer.from(base64, "base64"), 384);
|
|
1977
|
+
await d.chmod(path, 384);
|
|
1978
|
+
}
|
|
1979
|
+
if (!opts.json) {
|
|
1980
|
+
console.log(chalk14.green(`\u2713 downloaded ${material.name} (${material.platform})`));
|
|
1981
|
+
console.log("");
|
|
1982
|
+
console.log(` Saved to: ${chalk14.bold(savedTo)}`);
|
|
1983
|
+
if (profileSavedTo !== null) {
|
|
1984
|
+
console.log(` Profile: ${chalk14.bold(profileSavedTo)}`);
|
|
1985
|
+
}
|
|
1986
|
+
for (const [key, value] of Object.entries(material.passwords)) {
|
|
1987
|
+
console.log(` ${key}: ${chalk14.bold(value)}`);
|
|
1988
|
+
}
|
|
1989
|
+
console.log("");
|
|
1990
|
+
console.log(chalk14.yellow(" This download is recorded in your organization's audit log."));
|
|
1991
|
+
}
|
|
1992
|
+
process.exitCode = 0;
|
|
1993
|
+
} catch (err) {
|
|
1994
|
+
printError3(opts, err);
|
|
1995
|
+
process.exitCode = 1;
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
async function ascKeyAdd(opts, deps) {
|
|
1999
|
+
const d = deps ?? defaultDeps4(clientFor2(opts));
|
|
2000
|
+
if (!opts.keyId) {
|
|
2001
|
+
throw new UsageError("--key-id is required (the 10-character App Store Connect key id)");
|
|
2002
|
+
}
|
|
2003
|
+
if (!opts.issuerId) {
|
|
2004
|
+
throw new UsageError("--issuer-id is required (the UUID shown above the keys table)");
|
|
2005
|
+
}
|
|
2006
|
+
if (!opts.file) {
|
|
2007
|
+
throw new UsageError("--file is required (the AuthKey_<KEYID>.p8 file Apple let you download)");
|
|
2008
|
+
}
|
|
2009
|
+
try {
|
|
2010
|
+
const file = await d.readFile(opts.file);
|
|
2011
|
+
const result = await d.addAscKey({
|
|
2012
|
+
...opts.name !== void 0 ? { name: opts.name } : {},
|
|
2013
|
+
keyId: opts.keyId,
|
|
2014
|
+
issuerId: opts.issuerId,
|
|
2015
|
+
file,
|
|
2016
|
+
filename: basename2(opts.file)
|
|
2017
|
+
});
|
|
2018
|
+
if (opts.json) {
|
|
2019
|
+
console.log(JSON.stringify(result));
|
|
2020
|
+
} else {
|
|
2021
|
+
console.log(chalk14.green(`\u2713 added App Store Connect key ${result.name}`));
|
|
2022
|
+
console.log("");
|
|
2023
|
+
console.log(` Key ID: ${chalk14.bold(result.key_id)}`);
|
|
2024
|
+
console.log(` Issuer ID: ${chalk14.bold(result.issuer_id)}`);
|
|
2025
|
+
console.log("");
|
|
2026
|
+
console.log(
|
|
2027
|
+
chalk14.yellow(
|
|
2028
|
+
" The .p8 is stored encrypted and will never be shown again \u2014 keep your own copy somewhere safe."
|
|
2029
|
+
)
|
|
2030
|
+
);
|
|
2031
|
+
}
|
|
2032
|
+
process.exitCode = 0;
|
|
2033
|
+
} catch (err) {
|
|
2034
|
+
printError3(opts, err);
|
|
2035
|
+
process.exitCode = 1;
|
|
2036
|
+
}
|
|
2037
|
+
}
|
|
2038
|
+
async function ascKeyList(opts, deps) {
|
|
2039
|
+
const d = deps ?? defaultDeps4(clientFor2(opts));
|
|
2040
|
+
try {
|
|
2041
|
+
const { keys } = await d.listAscKeys();
|
|
2042
|
+
if (opts.json) {
|
|
2043
|
+
console.log(JSON.stringify(keys, null, 2));
|
|
2044
|
+
} else {
|
|
2045
|
+
process.stdout.write(formatAscKeysHuman(keys));
|
|
2046
|
+
}
|
|
2047
|
+
process.exitCode = 0;
|
|
2048
|
+
} catch (err) {
|
|
2049
|
+
printError3(opts, err);
|
|
2050
|
+
process.exitCode = 1;
|
|
2051
|
+
}
|
|
2052
|
+
}
|
|
2053
|
+
function formatAscKeysHuman(keys) {
|
|
2054
|
+
if (keys.length === 0) {
|
|
2055
|
+
return "No App Store Connect keys found.\n";
|
|
2056
|
+
}
|
|
2057
|
+
const HEADERS3 = ["NAME", "KEY ID", "ISSUER ID", "CREATED"];
|
|
2058
|
+
const rows = keys.map((k) => [k.name, k.key_id, k.issuer_id, k.created_at ?? ""]);
|
|
2059
|
+
const widths = HEADERS3.map((h, i) => Math.max(h.length, ...rows.map((r) => r[i].length)));
|
|
2060
|
+
const padCells = (cells) => cells.map((c, i) => c.padEnd(widths[i]));
|
|
2061
|
+
const join3 = (cells) => cells.join(" ").trimEnd();
|
|
2062
|
+
const lines = [chalk14.bold(join3(padCells(HEADERS3)))];
|
|
2063
|
+
for (const row of rows) lines.push(join3(padCells(row)));
|
|
2064
|
+
return lines.join("\n") + "\n";
|
|
2065
|
+
}
|
|
2066
|
+
async function ascKeyRm(name, opts, deps) {
|
|
2067
|
+
const d = deps ?? defaultDeps4(clientFor2(opts));
|
|
2068
|
+
try {
|
|
2069
|
+
await d.deleteAscKey(name);
|
|
2070
|
+
if (opts.json) {
|
|
2071
|
+
console.log(JSON.stringify({ event: "deleted", name }));
|
|
2072
|
+
} else {
|
|
2073
|
+
console.log(chalk14.green(`\u2713 removed App Store Connect key ${name}`));
|
|
2074
|
+
}
|
|
2075
|
+
process.exitCode = 0;
|
|
2076
|
+
} catch (err) {
|
|
2077
|
+
printError3(opts, err);
|
|
2078
|
+
process.exitCode = 1;
|
|
2079
|
+
}
|
|
2080
|
+
}
|
|
1874
2081
|
async function credentialsList(opts, deps) {
|
|
1875
2082
|
const d = deps ?? defaultDeps4(clientFor2(opts));
|
|
1876
2083
|
try {
|
|
@@ -2528,19 +2735,36 @@ credentials.command("add").description(
|
|
|
2528
2735
|
"ios/tvos: the .mobileprovision file (required; tvOS profiles are distinct from iOS ones)"
|
|
2529
2736
|
).option("--app <id>", "Scope to a single app (default: org-wide)").option("--name <name>", "Credential name (default: the file basename without extension)").action((opts) => credentialsAdd(opts));
|
|
2530
2737
|
credentials.command("generate").description(
|
|
2531
|
-
"Generate
|
|
2532
|
-
).option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").option(
|
|
2533
|
-
"--
|
|
2534
|
-
"
|
|
2535
|
-
).option(
|
|
2738
|
+
"Generate a signing credential server-side. android: saves the keystore file locally and prints its passwords ONCE. ios/tvos: creates the distribution certificate and provisioning profile through the App Store Connect API (requires a stored key \u2014 see `vibeview credentials asc-key add`); fetch the files later with `vibeview credentials download`."
|
|
2739
|
+
).option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").option("--platform <platform>", "android, ios, or tvos").option("--name <name>", "Credential name").option("--app <id>", "Scope to a single app (default: org-wide)").option("--alias <alias>", "android: key alias (default: server-chosen)").option(
|
|
2740
|
+
"--bundle-id <id>",
|
|
2741
|
+
"ios/tvos: bundle id for the provisioning profile (default: the --app's package id)"
|
|
2742
|
+
).option(
|
|
2743
|
+
"--asc-key <name>",
|
|
2744
|
+
"ios/tvos: which stored App Store Connect key to use (default when exactly one)"
|
|
2745
|
+
).option(
|
|
2746
|
+
"--out <dir>",
|
|
2747
|
+
"android: directory to save the keystore file into (default: current directory)"
|
|
2748
|
+
).option(
|
|
2536
2749
|
"--force",
|
|
2537
2750
|
"Replace an existing credential of the same name \u2014 irreversible; breaks Play Store updates signed with the old key",
|
|
2538
2751
|
false
|
|
2539
2752
|
).option(
|
|
2540
2753
|
"--json",
|
|
2541
|
-
"Print the raw generation response (including the one-time secrets) as JSON",
|
|
2754
|
+
"Print the raw generation response (android: including the one-time secrets) as JSON",
|
|
2542
2755
|
false
|
|
2543
2756
|
).action((opts) => credentialsGenerate(opts));
|
|
2757
|
+
credentials.command("download <name>").description(
|
|
2758
|
+
"Download the files of a credential VibeView GENERATED (uploaded credentials are never readable back). Admin-only; the download is recorded in the audit log."
|
|
2759
|
+
).option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").option("--app <id>", "Scope to a single app (default: org-wide)").option("--out <dir>", "Directory to save the files into (default: current directory)").option("--json", "Print the material (including passwords) and saved paths as JSON", false).action((name, opts) => credentialsDownload(name, opts));
|
|
2760
|
+
var ascKey = credentials.command("asc-key").description(
|
|
2761
|
+
"Manage App Store Connect API keys (create one in App Store Connect \u2192 Users and Access \u2192 Integrations) \u2014 they power `credentials generate --platform ios|tvos`"
|
|
2762
|
+
);
|
|
2763
|
+
ascKey.command("add").description(
|
|
2764
|
+
"Store an App Store Connect API key. The .p8 is stored encrypted and never shown again; uploading the same name again rotates the key."
|
|
2765
|
+
).option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").option("--key-id <id>", "The 10-character key id (shown next to the key in App Store Connect)").option("--issuer-id <id>", "The issuer id (UUID shown above the keys table)").option("--file <path>", "The AuthKey_<KEYID>.p8 file Apple let you download once").option("--name <name>", "Key name (default: server-chosen)").option("--json", "Print the raw response as one JSON line", false).action((opts) => ascKeyAdd(opts));
|
|
2766
|
+
ascKey.command("list").description("List stored App Store Connect keys (metadata only \u2014 never the .p8)").option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").option("--json", "Print the raw key list as a JSON array", false).action((opts) => ascKeyList(opts));
|
|
2767
|
+
ascKey.command("rm <name>").description("Remove a stored App Store Connect key").option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").option("--json", "Print the result as one JSON line", false).action((name, opts) => ascKeyRm(name, opts));
|
|
2544
2768
|
credentials.command("list").description("List signing credentials (never prints key material)").option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").option("--app <id>", "Scope to a single app (default: org-wide credentials only)").option("--json", "Print the raw credential list as a JSON array", false).action((opts) => credentialsList(opts));
|
|
2545
2769
|
credentials.command("rm <name>").description("Remove a signing credential (replace by rm then add)").option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").option("--app <id>", "Scope to a single app (default: org-wide)").option("--json", "Print the result as one JSON line", false).action((name, opts) => credentialsRm(name, opts));
|
|
2546
2770
|
var webhooks = program.command("webhooks").description("Manage build-completion webhook endpoints");
|
|
@@ -2555,7 +2779,7 @@ program.command("dev-stop").description("Stop a `vibeview dev --detach` session
|
|
|
2555
2779
|
program.command("mcp").description(
|
|
2556
2780
|
"Run an MCP stdio server exposing the agent verbs (tap, swipe, type, ...) plus dev_start/dev_stop as tools"
|
|
2557
2781
|
).option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").action(async (opts) => {
|
|
2558
|
-
const { runMcpServer } = await import("./server-
|
|
2782
|
+
const { runMcpServer } = await import("./server-TJQKNXDR.js");
|
|
2559
2783
|
await runMcpServer(opts);
|
|
2560
2784
|
});
|
|
2561
2785
|
program.command("agent-setup").description(
|
|
@@ -11,11 +11,11 @@ import {
|
|
|
11
11
|
readDevState,
|
|
12
12
|
renderEnvelope,
|
|
13
13
|
startDevSession
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-MGP3UR7P.js";
|
|
15
15
|
import {
|
|
16
16
|
ApiClient,
|
|
17
17
|
resolveAuth
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-BJEDH672.js";
|
|
19
19
|
|
|
20
20
|
// src/mcp/server.ts
|
|
21
21
|
import { writeFileSync } from "fs";
|
|
@@ -239,7 +239,7 @@ async function handleUploadApp(args, deps) {
|
|
|
239
239
|
}
|
|
240
240
|
const name = typeof args.name === "string" && args.name ? args.name : void 0;
|
|
241
241
|
const upload = deps.uploadApp ?? (async (f, n) => {
|
|
242
|
-
const { uploadAppBuild } = await import("./upload-app-
|
|
242
|
+
const { uploadAppBuild } = await import("./upload-app-Y7MXT2PI.js");
|
|
243
243
|
const { result: result2 } = await uploadAppBuild(f, { ...deps.auth, name: n });
|
|
244
244
|
return result2;
|
|
245
245
|
});
|