vibeview 0.23.0 → 0.25.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.
@@ -197,7 +197,12 @@ var ApiClient = class {
197
197
  async listApps() {
198
198
  return this.requestRaw("GET", "/apps/");
199
199
  }
200
- async uploadApp(filePath, name) {
200
+ /** GET /api/v1/apps/{appPublicId} — the app with its uploaded builds,
201
+ * newest first. */
202
+ async getApp(appId) {
203
+ return this.requestRaw("GET", `/apps/${encodeURIComponent(appId)}`);
204
+ }
205
+ async uploadApp(filePath, name, note) {
201
206
  const fileBuffer = readFileSync2(filePath);
202
207
  const blob = new Blob([fileBuffer]);
203
208
  const formData = new FormData();
@@ -205,8 +210,15 @@ var ApiClient = class {
205
210
  if (name) {
206
211
  formData.append("name", name);
207
212
  }
213
+ if (note) {
214
+ formData.append("note", note);
215
+ }
208
216
  return this.requestFormData("POST", "/apps/upload", formData);
209
217
  }
218
+ /** PATCH a build's note (null clears it). */
219
+ async updateBuildNote(appPublicId, buildId, note) {
220
+ return this.requestRaw("PATCH", `/apps/${appPublicId}/builds/${buildId}`, { note });
221
+ }
210
222
  async uploadBuild(appPublicId, filePath, version) {
211
223
  const fileBuffer = readFileSync2(filePath);
212
224
  const blob = new Blob([fileBuffer]);
@@ -613,9 +625,15 @@ function sanitizeDownloadFilename(raw) {
613
625
 
614
626
  // src/lib/spinner.ts
615
627
  import ora from "ora";
616
- function createSpinner(text) {
628
+ function createSpinner(text, opts = {}) {
617
629
  const isCI = process.env.CI === "true" || process.env.CI === "1" || !process.stdout.isTTY;
618
- return ora({ text, isEnabled: !isCI, stream: process.stderr, discardStdin: false });
630
+ return ora({
631
+ text,
632
+ isEnabled: !isCI,
633
+ stream: process.stderr,
634
+ discardStdin: false,
635
+ isSilent: opts.silent === true
636
+ });
619
637
  }
620
638
 
621
639
  // src/lib/types.ts
@@ -636,16 +654,26 @@ async function uploadAppBuild(filePath, options) {
636
654
  }
637
655
  const { token, baseUrl } = resolveAuth(options);
638
656
  const client = new ApiClient(baseUrl, token);
639
- const result = await client.uploadApp(filePath, options.name);
657
+ const note = options.note?.trim() || void 0;
658
+ const result = await client.uploadApp(filePath, options.name, note);
659
+ if (note && result.deduplicated && result.build_id != null) {
660
+ await client.updateBuildNote(result.public_id, result.build_id, note);
661
+ }
640
662
  return { result, baseUrl };
641
663
  }
664
+ function describeBuild(result) {
665
+ if (result.build_id == null) return null;
666
+ const version = result.version ? `v${result.version}${result.build_number ? ` (${result.build_number})` : ""}` : "";
667
+ const dedup = result.deduplicated ? chalk.dim(" identical build already uploaded") : "";
668
+ return `Build ${chalk.cyan(String(result.build_id))}${version ? ` ${version}` : ""}${dedup}`;
669
+ }
642
670
  async function uploadApp(filePath, options) {
643
671
  if (!existsSync(filePath)) {
644
672
  console.error(chalk.red(`Error: File not found: ${filePath}`));
645
673
  process.exit(EXIT_INFRA_ERROR);
646
674
  }
647
675
  const { baseUrl } = resolveAuth(options);
648
- const spinner = createSpinner("Uploading app...");
676
+ const spinner = createSpinner("Uploading app...", { silent: options.output === "json" });
649
677
  spinner.start();
650
678
  try {
651
679
  const { result } = await uploadAppBuild(filePath, options);
@@ -662,6 +690,11 @@ async function uploadApp(filePath, options) {
662
690
  package_name: result.package_name,
663
691
  platform: result.platform,
664
692
  is_new: isNew,
693
+ build_id: result.build_id ?? null,
694
+ version: result.version ?? null,
695
+ build_number: result.build_number ?? null,
696
+ deduplicated: result.deduplicated === true,
697
+ note: options.note?.trim() || null,
665
698
  url: `${baseUrl}/apps/${result.public_id}`,
666
699
  warnings: result.warnings ?? []
667
700
  },
@@ -675,6 +708,8 @@ async function uploadApp(filePath, options) {
675
708
  ${chalk.cyan(result.public_id)} ${result.name} ${chalk.dim(`[${result.platform}]`)}`
676
709
  );
677
710
  console.log(` ${chalk.dim(result.package_name)}`);
711
+ const build = describeBuild(result);
712
+ if (build) console.log(` ${build}`);
678
713
  console.log(chalk.dim(` ${baseUrl}/apps/${result.public_id}
679
714
  `));
680
715
  }
@@ -683,7 +718,9 @@ async function uploadApp(filePath, options) {
683
718
  \u26A0 ${w}`));
684
719
  }
685
720
  } catch (err) {
686
- spinner.fail(err instanceof Error ? err.message : "Upload failed");
721
+ const message = err instanceof Error ? err.message : "Upload failed";
722
+ spinner.fail(message);
723
+ if (options.output === "json") console.error(chalk.red(`Error: ${message}`));
687
724
  process.exit(EXIT_INFRA_ERROR);
688
725
  }
689
726
  }
@@ -700,5 +737,6 @@ export {
700
737
  EXIT_INFRA_ERROR,
701
738
  UsageError,
702
739
  uploadAppBuild,
740
+ describeBuild,
703
741
  uploadApp
704
742
  };