vibeview 0.12.3 → 0.14.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.
@@ -56,6 +56,10 @@ function extractDetail(text) {
56
56
  }
57
57
  return void 0;
58
58
  }
59
+ async function parseJsonBody(resp) {
60
+ if (resp.status === 204 || resp.status === 205) return void 0;
61
+ return resp.json();
62
+ }
59
63
  var ApiClient = class {
60
64
  constructor(baseUrl, token) {
61
65
  this.baseUrl = baseUrl;
@@ -96,7 +100,7 @@ var ApiClient = class {
96
100
  if (resp.status === 404) throw new NotFoundError(`Not found: ${extractDetail(text) ?? path}`);
97
101
  throw new Error(extractDetail(text) ?? `API error ${resp.status}: ${text}`);
98
102
  }
99
- return resp.json();
103
+ return parseJsonBody(resp);
100
104
  }
101
105
  async listSuites(opts) {
102
106
  const params = new URLSearchParams();
@@ -168,7 +172,7 @@ var ApiClient = class {
168
172
  if (resp.status === 404) throw new NotFoundError(`Not found: ${extractDetail(text) ?? path}`);
169
173
  throw new Error(extractDetail(text) ?? `API error ${resp.status}: ${text}`);
170
174
  }
171
- return resp.json();
175
+ return parseJsonBody(resp);
172
176
  }
173
177
  /** FormData request without /ci prefix — for file uploads */
174
178
  async requestFormData(method, path, formData) {
@@ -188,7 +192,7 @@ var ApiClient = class {
188
192
  if (resp.status === 404) throw new NotFoundError(`Not found: ${extractDetail(text) ?? path}`);
189
193
  throw new Error(extractDetail(text) ?? `API error ${resp.status}: ${text}`);
190
194
  }
191
- return resp.json();
195
+ return parseJsonBody(resp);
192
196
  }
193
197
  async listApps() {
194
198
  return this.requestRaw("GET", "/apps/");
@@ -293,6 +297,13 @@ var ApiClient = class {
293
297
  async cancelCloudBuild(id) {
294
298
  return this.requestRaw("POST", `/builds/${id}/cancel`);
295
299
  }
300
+ /** DELETE /api/v1/builds/{id}/artifact — deletes a production build's
301
+ * stored artifact file. The build record, its logs, and its cost stay
302
+ * intact; this only removes the downloadable file. 409 if the build has
303
+ * no artifact (never had one, or already deleted). */
304
+ async deleteCloudBuildArtifact(id) {
305
+ return this.requestRaw("DELETE", `/builds/${id}/artifact`);
306
+ }
296
307
  /**
297
308
  * Download a finished build's artifact (GET /api/v1/builds/{id}/artifact),
298
309
  * streaming the response body straight to a file in destDir. The filename
@@ -335,6 +346,83 @@ var ApiClient = class {
335
346
  }
336
347
  return { filename, path };
337
348
  }
349
+ /** GET /api/v1/build-env/[?app=]. Requires VIEWER role. Never returns a
350
+ * value — see BuildEnvVar. */
351
+ async listBuildEnvVars(app) {
352
+ const qs = app ? `?app=${encodeURIComponent(app)}` : "";
353
+ return this.requestRaw("GET", `/build-env/${qs}`);
354
+ }
355
+ /** POST /api/v1/build-env/ (JSON body) for a plain/sensitive/secret value.
356
+ * Requires ADMIN role. Upserts by (org, app, name). */
357
+ async setBuildEnvVar(body) {
358
+ return this.requestRaw("POST", "/build-env/", body);
359
+ }
360
+ /** POST /api/v1/build-env/ (multipart) for a file variable. `content` is
361
+ * sent as the raw bytes read from disk — the server does its own
362
+ * base64-encoding internally, so encoding here too would double-encode
363
+ * and corrupt the file. Requires ADMIN role. */
364
+ async setBuildEnvFileVar(body) {
365
+ const formData = new FormData();
366
+ formData.append("name", body.name);
367
+ formData.append("visibility", body.visibility);
368
+ if (body.app) formData.append("app", body.app);
369
+ const blob = new Blob([new Uint8Array(body.content)]);
370
+ formData.append("file", blob, body.filename);
371
+ return this.requestFormData("POST", "/build-env/", formData);
372
+ }
373
+ /** GET /api/v1/users/me — identity + roles for `vibeview whoami`. */
374
+ async whoAmI() {
375
+ return this.requestRaw("GET", "/users/me");
376
+ }
377
+ /** DELETE /api/v1/build-env/{id}. Requires ADMIN role. */
378
+ async deleteBuildEnvVar(id) {
379
+ await this.requestRaw("DELETE", `/build-env/${id}`);
380
+ }
381
+ /** GET /api/v1/build-env/pull[?app=]. Requires DEVELOPER role. The only
382
+ * endpoint that returns values — already excludes secret/file variables
383
+ * server-side. */
384
+ async pullBuildEnvVars(app) {
385
+ const qs = app ? `?app=${encodeURIComponent(app)}` : "";
386
+ return this.requestRaw("GET", `/build-env/pull${qs}`);
387
+ }
388
+ /** GET /api/v1/signing-credentials/[?app=]. Requires VIEWER role. Never
389
+ * returns file bytes, profile bytes, or a password — see
390
+ * routes/signing.py's module docstring. */
391
+ async listSigningCredentials(app) {
392
+ const qs = app ? `?app=${encodeURIComponent(app)}` : "";
393
+ return this.requestRaw("GET", `/signing-credentials/${qs}`);
394
+ }
395
+ /**
396
+ * POST /api/v1/signing-credentials/ (multipart). Requires ADMIN role.
397
+ * `passwords` carries the route's own snake_case form field names
398
+ * (store_password, key_password, key_alias, p12_password) — the CLI's own
399
+ * camelCase objects are converted to this shape ONLY at this boundary
400
+ * (see credentials.ts), never anywhere else, so there is exactly one place
401
+ * the two naming conventions meet.
402
+ */
403
+ async addSigningCredential(body) {
404
+ const formData = new FormData();
405
+ formData.append("platform", body.platform);
406
+ formData.append("kind", body.kind);
407
+ formData.append("name", body.name);
408
+ if (body.app) formData.append("app", body.app);
409
+ for (const [key, value] of Object.entries(body.passwords)) {
410
+ formData.append(key, value);
411
+ }
412
+ formData.append("file", new Blob([new Uint8Array(body.file)]), body.filename);
413
+ if (body.profile) {
414
+ formData.append(
415
+ "profile",
416
+ new Blob([new Uint8Array(body.profile)]),
417
+ body.profileFilename ?? "profile"
418
+ );
419
+ }
420
+ return this.requestFormData("POST", "/signing-credentials/", formData);
421
+ }
422
+ /** DELETE /api/v1/signing-credentials/{id}. Requires ADMIN role. */
423
+ async deleteSigningCredential(id) {
424
+ await this.requestRaw("DELETE", `/signing-credentials/${id}`);
425
+ }
338
426
  };
339
427
  function parseContentDispositionFilename(header) {
340
428
  if (!header) return void 0;
@@ -371,6 +459,12 @@ function createSpinner(text) {
371
459
  var EXIT_PASS = 0;
372
460
  var EXIT_TEST_FAIL = 1;
373
461
  var EXIT_INFRA_ERROR = 2;
462
+ var UsageError = class extends Error {
463
+ constructor(message) {
464
+ super(message);
465
+ this.name = "UsageError";
466
+ }
467
+ };
374
468
 
375
469
  // src/commands/upload-app.ts
376
470
  async function uploadAppBuild(filePath, options) {
@@ -441,6 +535,7 @@ export {
441
535
  EXIT_PASS,
442
536
  EXIT_TEST_FAIL,
443
537
  EXIT_INFRA_ERROR,
538
+ UsageError,
444
539
  uploadAppBuild,
445
540
  uploadApp
446
541
  };