@capgo/cli 7.18.11 → 7.18.13

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/cli",
3
- "version": "7.18.11",
3
+ "version": "7.18.13",
4
4
  "description": "A CLI to upload to capgo servers",
5
5
  "author": "Martin martin@capgo.app",
6
6
  "license": "Apache 2.0",
@@ -1 +1 @@
1
- {"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../../src/bundle/upload.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAgBvD,OAAO,EAA8F,oBAAoB,EAAmb,MAAM,UAAU,CAAA;AAI5jB,KAAK,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC,CAAA;AAIpE,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAA;IACtC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AA+cD,wBAAsB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,0BAalG;AAED,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,UAAU,UAAO,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAkQ3H;AA2CD,wBAAsB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,iBASxE"}
1
+ {"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../../src/bundle/upload.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAgBvD,OAAO,EAA8F,oBAAoB,EAAmb,MAAM,UAAU,CAAA;AAI5jB,KAAK,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC,CAAA;AAIpE,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAA;IACtC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAijBD,wBAAsB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,0BAalG;AAED,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,UAAU,UAAO,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAyc3H;AA2CD,wBAAsB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,iBASxE"}
@@ -244,6 +244,13 @@ async function prepareBundleFile(path, options, apikey, orgId, appid, maxUploadL
244
244
  else if (zipped?.byteLength > alertUploadSize) {
245
245
  log.warn(`WARNING !!\nThe bundle size is ${mbSize} Mb, this may take a while to download for users\n`);
246
246
  log.info(`Learn how to optimize your assets https://capgo.app/blog/optimise-your-images-for-updates/\n`);
247
+ if (options.verbose) {
248
+ log.info(`[Verbose] Bundle size details:`);
249
+ log.info(` - Actual size: ${mbSize} MB (${zipped?.byteLength} bytes)`);
250
+ log.info(` - Alert threshold: ${Math.floor(alertUploadSize / 1024 / 1024)} MB`);
251
+ log.info(` - Maximum allowed: ${mbSizeMax} MB`);
252
+ log.info(`[Verbose] Sending 'App Too Large' event to analytics...`);
253
+ }
247
254
  await sendEvent(apikey, {
248
255
  channel: 'app-error',
249
256
  event: 'App Too Large',
@@ -254,7 +261,14 @@ async function prepareBundleFile(path, options, apikey, orgId, appid, maxUploadL
254
261
  },
255
262
  notify: false,
256
263
  });
264
+ if (options.verbose)
265
+ log.info(`[Verbose] Event sent successfully`);
266
+ }
267
+ else if (options.verbose) {
268
+ log.info(`[Verbose] Bundle size OK: ${mbSize} MB (under ${Math.floor(alertUploadSize / 1024 / 1024)} MB alert threshold)`);
257
269
  }
270
+ if (options.verbose)
271
+ log.info(`[Verbose] Bundle preparation complete, returning bundle data`);
258
272
  return { zipped, ivSessionKey, sessionKey, checksum, encryptionMethod, finalKeyData };
259
273
  }
260
274
  async function uploadBundleToCapgoCloud(apikey, supabase, appid, bundle, orgId, zipped, options, tusChunkSize) {
@@ -262,12 +276,23 @@ async function uploadBundleToCapgoCloud(apikey, supabase, appid, bundle, orgId,
262
276
  spinner.start(`Uploading Bundle`);
263
277
  const startTime = performance.now();
264
278
  let isTus = false;
279
+ if (options.verbose) {
280
+ log.info(`[Verbose] uploadBundleToCapgoCloud called:`);
281
+ log.info(` - Bundle size: ${Math.floor(zipped.byteLength / 1024)} KB`);
282
+ log.info(` - App ID: ${appid}`);
283
+ log.info(` - Bundle version: ${bundle}`);
284
+ log.info(` - Chunk size: ${Math.floor(tusChunkSize / 1024 / 1024)} MB`);
285
+ }
265
286
  if (options.dryUpload) {
266
287
  spinner.stop(`Dry run, bundle not uploaded\nBundle uploaded 💪 in 0 seconds`);
288
+ if (options.verbose)
289
+ log.info(`[Verbose] Dry upload mode - skipping actual upload`);
267
290
  return;
268
291
  }
269
292
  try {
270
293
  const localConfig = await getLocalConfig();
294
+ if (options.verbose)
295
+ log.info(`[Verbose] Local config retrieved for upload`);
271
296
  if ((options.multipart !== undefined && options.multipart) || (options.tus !== undefined && options.tus)) {
272
297
  if (options.multipart) {
273
298
  log.info(`Uploading bundle with multipart is deprecated, we upload with TUS instead`);
@@ -275,8 +300,15 @@ async function uploadBundleToCapgoCloud(apikey, supabase, appid, bundle, orgId,
275
300
  else {
276
301
  log.info(`Uploading bundle with TUS protocol`);
277
302
  }
303
+ if (options.verbose) {
304
+ log.info(`[Verbose] Starting TUS resumable upload...`);
305
+ log.info(` - Host: ${localConfig.hostWeb}`);
306
+ log.info(` - Chunk size: ${Math.floor(tusChunkSize / 1024 / 1024)} MB`);
307
+ }
278
308
  await uploadTUS(apikey, zipped, orgId, appid, bundle, spinner, localConfig, tusChunkSize);
279
309
  isTus = true;
310
+ if (options.verbose)
311
+ log.info(`[Verbose] TUS upload completed, updating database with R2 path...`);
280
312
  const filePath = `orgs/${orgId}/apps/${appid}/${bundle}.zip`;
281
313
  const { error: changeError } = await supabase
282
314
  .from('app_versions')
@@ -285,15 +317,29 @@ async function uploadBundleToCapgoCloud(apikey, supabase, appid, bundle, orgId,
285
317
  .eq('app_id', appid);
286
318
  if (changeError) {
287
319
  log.error(`Cannot finish TUS upload ${formatError(changeError)}`);
320
+ if (options.verbose)
321
+ log.info(`[Verbose] Database update failed: ${formatError(changeError)}`);
288
322
  return Promise.reject(new Error('Cannot finish TUS upload'));
289
323
  }
324
+ if (options.verbose)
325
+ log.info(`[Verbose] Database updated with R2 path: ${filePath}`);
290
326
  }
291
327
  else {
328
+ if (options.verbose)
329
+ log.info(`[Verbose] Using standard upload (non-TUS), getting presigned URL...`);
292
330
  const url = await uploadUrl(supabase, appid, bundle);
293
331
  if (!url) {
294
332
  log.error(`Cannot get upload url`);
333
+ if (options.verbose)
334
+ log.info(`[Verbose] Failed to retrieve presigned upload URL from database`);
295
335
  return Promise.reject(new Error('Cannot get upload url'));
296
336
  }
337
+ if (options.verbose) {
338
+ log.info(`[Verbose] Presigned URL obtained, uploading via HTTP PUT...`);
339
+ log.info(` - Timeout: ${options.timeout || UPLOAD_TIMEOUT}ms`);
340
+ log.info(` - Retry attempts: 5`);
341
+ log.info(` - Content-Type: application/zip`);
342
+ }
297
343
  await ky.put(url, {
298
344
  timeout: options.timeout || UPLOAD_TIMEOUT,
299
345
  retry: 5,
@@ -302,15 +348,23 @@ async function uploadBundleToCapgoCloud(apikey, supabase, appid, bundle, orgId,
302
348
  'Content-Type': 'application/zip',
303
349
  },
304
350
  });
351
+ if (options.verbose)
352
+ log.info(`[Verbose] HTTP PUT upload completed successfully`);
305
353
  }
306
354
  }
307
355
  catch (errorUpload) {
308
356
  const endTime = performance.now();
309
357
  const uploadTime = ((endTime - startTime) / 1000).toFixed(2);
310
358
  spinner.stop(`Failed to upload bundle ( after ${uploadTime} seconds)`);
359
+ if (options.verbose) {
360
+ log.info(`[Verbose] Upload failed after ${uploadTime} seconds`);
361
+ log.info(`[Verbose] Error type: ${errorUpload instanceof HTTPError ? 'HTTPError' : typeof errorUpload}`);
362
+ }
311
363
  if (errorUpload instanceof HTTPError) {
312
364
  try {
313
365
  const text = await errorUpload.response.text();
366
+ if (options.verbose)
367
+ log.info(`[Verbose] HTTP error response body: ${text.substring(0, 500)}`);
314
368
  if (text.startsWith('<?xml')) {
315
369
  // Parse XML error message
316
370
  const matches = text.match(/<Message>(.*?)<\/Message>/s);
@@ -327,6 +381,8 @@ async function uploadBundleToCapgoCloud(apikey, supabase, appid, bundle, orgId,
327
381
  }
328
382
  }
329
383
  else {
384
+ if (options.verbose)
385
+ log.info(`[Verbose] Non-HTTP error: ${formatError(errorUpload)}`);
330
386
  if (!options.tus) {
331
387
  log.error(`Cannot upload bundle ( try again with --tus option) ${formatError(errorUpload)}`);
332
388
  }
@@ -334,13 +390,24 @@ async function uploadBundleToCapgoCloud(apikey, supabase, appid, bundle, orgId,
334
390
  log.error(`Cannot upload bundle please contact support if the issue persists ${formatError(errorUpload)}`);
335
391
  }
336
392
  }
393
+ if (options.verbose)
394
+ log.info(`[Verbose] Cleaning up failed version from database...`);
337
395
  // call delete version on path /delete_failed_version to delete the version
338
396
  await deletedFailedVersion(supabase, appid, bundle);
397
+ if (options.verbose)
398
+ log.info(`[Verbose] Failed version cleaned up`);
339
399
  throw errorUpload instanceof Error ? errorUpload : new Error(String(errorUpload));
340
400
  }
341
401
  const endTime = performance.now();
342
402
  const uploadTime = ((endTime - startTime) / 1000).toFixed(2);
343
403
  spinner.stop(`Bundle uploaded 💪 in (${uploadTime} seconds)`);
404
+ if (options.verbose) {
405
+ log.info(`[Verbose] Upload successful:`);
406
+ log.info(` - Upload time: ${uploadTime} seconds`);
407
+ log.info(` - Upload method: ${isTus ? 'TUS (resumable)' : 'Standard HTTP PUT'}`);
408
+ log.info(` - Bundle size: ${Math.floor(zipped.byteLength / 1024)} KB`);
409
+ log.info(`[Verbose] Sending performance event...`);
410
+ }
344
411
  await sendEvent(apikey, {
345
412
  channel: 'performance',
346
413
  event: isTus ? 'TUS upload zip performance' : 'Upload zip performance',
@@ -352,6 +419,8 @@ async function uploadBundleToCapgoCloud(apikey, supabase, appid, bundle, orgId,
352
419
  },
353
420
  notify: false,
354
421
  });
422
+ if (options.verbose)
423
+ log.info(`[Verbose] Performance event sent successfully`);
355
424
  }
356
425
  // It is really important that his function never terminates the program, it should always return, even if it fails
357
426
  async function deleteLinkedBundleOnUpload(supabase, appid, channel) {
@@ -434,34 +503,95 @@ export async function uploadBundle(preAppid, options, shouldExit = true) {
434
503
  const pm = getPMAndCommand();
435
504
  await checkAlerts();
436
505
  const { s3Region, s3Apikey, s3Apisecret, s3BucketName, s3Endpoint, s3Port, s3SSL } = options;
506
+ if (options.verbose) {
507
+ log.info(`[Verbose] Starting upload process with options:`);
508
+ log.info(` - API key: ${options.apikey ? 'provided' : 'from saved key'}`);
509
+ log.info(` - Path: ${options.path || 'from capacitor config'}`);
510
+ log.info(` - Channel: ${options.channel || 'from default upload channel'}`);
511
+ log.info(` - Bundle: ${options.bundle || 'auto-detected'}`);
512
+ log.info(` - External: ${options.external || 'false'}`);
513
+ log.info(` - Encryption: ${options.keyV2 || options.keyDataV2 ? 'v2' : options.key === false ? 'disabled' : 'auto'}`);
514
+ log.info(` - Upload method: ${options.tus ? 'TUS' : options.zip ? 'ZIP' : 'auto'}`);
515
+ log.info(` - Delta updates: ${options.delta || options.partial ? 'enabled' : 'disabled'}`);
516
+ }
437
517
  const apikey = getApikey(options);
518
+ if (options.verbose)
519
+ log.info(`[Verbose] API key retrieved successfully`);
438
520
  const extConfig = await getConfig();
521
+ if (options.verbose)
522
+ log.info(`[Verbose] Capacitor config loaded successfully`);
439
523
  const fileConfig = await getRemoteFileConfig();
524
+ if (options.verbose) {
525
+ log.info(`[Verbose] Remote file config retrieved:`);
526
+ log.info(` - Max upload length: ${Math.floor(fileConfig.maxUploadLength / 1024 / 1024)} MB`);
527
+ log.info(` - Alert upload size: ${Math.floor(fileConfig.alertUploadSize / 1024 / 1024)} MB`);
528
+ log.info(` - TUS upload: ${fileConfig.TUSUpload ? 'enabled' : 'disabled'}`);
529
+ log.info(` - TUS upload forced: ${fileConfig.TUSUploadForced ? 'yes' : 'no'}`);
530
+ log.info(` - Partial upload: ${fileConfig.partialUpload ? 'enabled' : 'disabled'}`);
531
+ log.info(` - Max chunk size: ${Math.floor(fileConfig.maxChunkSize / 1024 / 1024)} MB`);
532
+ }
440
533
  const { appid, path } = getAppIdAndPath(preAppid, options, extConfig.config);
534
+ if (options.verbose)
535
+ log.info(`[Verbose] App ID: ${appid}, Build path: ${path}`);
441
536
  const bundle = await getBundle(extConfig.config, options);
537
+ if (options.verbose)
538
+ log.info(`[Verbose] Bundle version: ${bundle}`);
442
539
  const defaultStorageProvider = options.external ? 'external' : 'r2-direct';
443
540
  let encryptionMethod = 'none';
444
541
  if (options.autoSetBundle) {
445
542
  await updateConfigUpdater({ version: bundle });
543
+ if (options.verbose)
544
+ log.info(`[Verbose] Auto-set bundle version in capacitor.config.json`);
446
545
  }
447
546
  checkNotifyAppReady(options, path);
547
+ if (options.verbose)
548
+ log.info(`[Verbose] Code check passed (notifyAppReady found and index.html present)`);
448
549
  log.info(`Upload ${appid}@${bundle} started from path "${path}" to Capgo cloud`);
449
550
  const localConfig = await getLocalConfig();
551
+ if (options.verbose)
552
+ log.info(`[Verbose] Local config loaded: host=${localConfig.hostWeb}`);
450
553
  if (options.supaHost && options.supaAnon) {
451
554
  log.info('Using custom supabase instance from provided options');
452
555
  localConfig.supaHost = options.supaHost;
453
556
  localConfig.supaKey = options.supaAnon;
557
+ if (options.verbose)
558
+ log.info(`[Verbose] Custom Supabase host: ${options.supaHost}`);
454
559
  }
455
560
  const supabase = await createSupabaseClient(apikey, options.supaHost, options.supaAnon);
561
+ if (options.verbose)
562
+ log.info(`[Verbose] Supabase client created successfully`);
456
563
  const userId = await verifyUser(supabase, apikey, ['write', 'all', 'upload']);
564
+ if (options.verbose)
565
+ log.info(`[Verbose] User verified successfully, user_id: ${userId}`);
457
566
  const channel = options.channel || await getDefaulUploadChannel(appid, supabase, localConfig.hostWeb) || 'dev';
567
+ if (options.verbose)
568
+ log.info(`[Verbose] Target channel: ${channel}`);
458
569
  // Now if it does exist we will fetch the org id
459
570
  const orgId = await getOrganizationId(supabase, appid);
571
+ if (options.verbose)
572
+ log.info(`[Verbose] Organization ID: ${orgId}`);
460
573
  await checkRemoteCliMessages(supabase, orgId, pack.version);
574
+ if (options.verbose)
575
+ log.info(`[Verbose] Remote CLI messages checked`);
461
576
  await checkPlanValidUpload(supabase, orgId, apikey, appid, true);
577
+ if (options.verbose)
578
+ log.info(`[Verbose] Plan validation passed`);
462
579
  await checkTrial(supabase, orgId, localConfig);
580
+ if (options.verbose)
581
+ log.info(`[Verbose] Trial check completed`);
582
+ if (options.verbose)
583
+ log.info(`[Verbose] Checking compatibility with channel ${channel}...`);
463
584
  const { nativePackages, minUpdateVersion } = await verifyCompatibility(supabase, pm, options, channel, appid, bundle);
585
+ if (options.verbose) {
586
+ log.info(`[Verbose] Compatibility check completed:`);
587
+ log.info(` - Native packages: ${nativePackages ? nativePackages.length : 0}`);
588
+ log.info(` - Min update version: ${minUpdateVersion || 'none'}`);
589
+ }
590
+ if (options.verbose)
591
+ log.info(`[Verbose] Checking if version ${bundle} already exists...`);
464
592
  const versionAlreadyExists = await checkVersionExists(supabase, appid, bundle, options.versionExistsOk);
593
+ if (options.verbose)
594
+ log.info(`[Verbose] Version exists check: ${versionAlreadyExists ? 'yes (skipping)' : 'no (continuing)'}`);
465
595
  if (versionAlreadyExists) {
466
596
  return {
467
597
  success: true,
@@ -497,6 +627,8 @@ export async function uploadBundle(preAppid, options, shouldExit = true) {
497
627
  let zipped = null;
498
628
  let finalKeyData = '';
499
629
  if (!options.external) {
630
+ if (options.verbose)
631
+ log.info(`[Verbose] Preparing bundle file from path: ${path}`);
500
632
  const { zipped: _zipped, ivSessionKey, checksum, sessionKey: sk, encryptionMethod: em, finalKeyData: fkd } = await prepareBundleFile(path, options, apikey, orgId, appid, fileConfig.maxUploadLength, fileConfig.alertUploadSize);
501
633
  versionData.session_key = ivSessionKey;
502
634
  versionData.checksum = checksum;
@@ -504,11 +636,24 @@ export async function uploadBundle(preAppid, options, shouldExit = true) {
504
636
  zipped = _zipped;
505
637
  encryptionMethod = em;
506
638
  finalKeyData = fkd;
639
+ if (options.verbose) {
640
+ log.info(`[Verbose] Bundle prepared:`);
641
+ log.info(` - Size: ${Math.floor((_zipped?.byteLength ?? 0) / 1024)} KB`);
642
+ log.info(` - Checksum: ${checksum}`);
643
+ log.info(` - Encryption: ${em}`);
644
+ log.info(` - IV Session Key: ${ivSessionKey ? 'present' : 'none'}`);
645
+ }
507
646
  if (!options.ignoreChecksumCheck) {
647
+ if (options.verbose)
648
+ log.info(`[Verbose] Checking for duplicate checksum...`);
508
649
  await checkChecksum(supabase, appid, channel, checksum);
650
+ if (options.verbose)
651
+ log.info(`[Verbose] Checksum is unique`);
509
652
  }
510
653
  }
511
654
  else {
655
+ if (options.verbose)
656
+ log.info(`[Verbose] Using external URL: ${options.external}`);
512
657
  await sendEvent(apikey, {
513
658
  channel: 'app',
514
659
  event: 'App external',
@@ -521,22 +666,38 @@ export async function uploadBundle(preAppid, options, shouldExit = true) {
521
666
  });
522
667
  versionData.session_key = options.ivSessionKey;
523
668
  versionData.checksum = options.encryptedChecksum;
669
+ if (options.verbose) {
670
+ log.info(`[Verbose] External bundle configured:`);
671
+ log.info(` - URL: ${options.external}`);
672
+ log.info(` - IV Session Key: ${options.ivSessionKey ? 'provided' : 'none'}`);
673
+ log.info(` - Encrypted Checksum: ${options.encryptedChecksum ? 'provided' : 'none'}`);
674
+ }
524
675
  }
525
676
  if (options.zip) {
526
677
  options.tus = false;
678
+ if (options.verbose)
679
+ log.info(`[Verbose] Upload method: ZIP (explicitly set via --zip)`);
527
680
  }
528
681
  // ALLOW TO OVERRIDE THE FILE CONFIG WITH THE OPTIONS IF THE FILE CONFIG IS FORCED
529
682
  else if (!fileConfig.TUSUpload || options.external) {
530
683
  options.tus = false;
684
+ if (options.verbose)
685
+ log.info(`[Verbose] Upload method: Standard (TUS not available or external URL)`);
531
686
  }
532
687
  else {
533
688
  options.tus = options.tus || fileConfig.TUSUploadForced;
689
+ if (options.verbose)
690
+ log.info(`[Verbose] Upload method: ${options.tus ? 'TUS (resumable)' : 'Standard'}`);
534
691
  }
535
692
  if (!fileConfig.partialUpload || options.external) {
536
693
  options.delta = false;
694
+ if (options.verbose && options.external)
695
+ log.info(`[Verbose] Delta updates disabled (not available with external URLs)`);
537
696
  }
538
697
  else {
539
698
  options.delta = options.delta || options.partial || options.deltaOnly || options.partialOnly || fileConfig.partialUploadForced;
699
+ if (options.verbose)
700
+ log.info(`[Verbose] Delta updates: ${options.delta ? 'enabled' : 'disabled'}`);
540
701
  }
541
702
  if (options.encryptPartial && encryptionMethod === 'v1')
542
703
  uploadFail('You cannot encrypt the partial update if you are not using the v2 encryption method');
@@ -549,13 +710,23 @@ export async function uploadBundle(preAppid, options, shouldExit = true) {
549
710
  const coerced = coerceVersion(updaterVersion);
550
711
  if (updaterVersion && coerced && semverGte(coerced.version, '6.14.4')) {
551
712
  log.info(`Auto-enabling partial update encryption for updater version ${coerced.version} (> 6.14.4)`);
713
+ if (options.verbose)
714
+ log.info(`[Verbose] Partial encryption auto-enabled for updater >= 6.14.4`);
552
715
  options.encryptPartial = true;
553
716
  }
554
717
  }
718
+ if (options.verbose && options.delta)
719
+ log.info(`[Verbose] Preparing delta/partial update manifest...`);
555
720
  const manifest = options.delta ? await prepareBundlePartialFiles(path, apikey, orgId, appid, options.encryptPartial ? encryptionMethod : 'none', finalKeyData) : [];
721
+ if (options.verbose && options.delta)
722
+ log.info(`[Verbose] Delta manifest prepared with ${manifest.length} files`);
723
+ if (options.verbose)
724
+ log.info(`[Verbose] Creating version record in database...`);
556
725
  const { error: dbError } = await updateOrCreateVersion(supabase, versionData);
557
726
  if (dbError)
558
727
  uploadFail(`Cannot add bundle ${formatError(dbError)}`);
728
+ if (options.verbose)
729
+ log.info(`[Verbose] Version record created successfully`);
559
730
  if (options.tusChunkSize && options.tusChunkSize > fileConfig.maxChunkSize) {
560
731
  log.error(`Chunk size ${options.tusChunkSize} is greater than the maximum chunk size ${fileConfig.maxChunkSize}, using the maximum chunk size`);
561
732
  options.tusChunkSize = fileConfig.maxChunkSize;
@@ -563,10 +734,20 @@ export async function uploadBundle(preAppid, options, shouldExit = true) {
563
734
  else if (!options.tusChunkSize) {
564
735
  options.tusChunkSize = fileConfig.maxChunkSize;
565
736
  }
737
+ if (options.verbose)
738
+ log.info(`[Verbose] TUS chunk size: ${Math.floor(options.tusChunkSize / 1024 / 1024)} MB`);
566
739
  if (zipped && (s3BucketName || s3Endpoint || s3Region || s3Apikey || s3Apisecret || s3Port || s3SSL)) {
567
740
  if (!s3BucketName || !s3Endpoint || !s3Region || !s3Apikey || !s3Apisecret || !s3Port)
568
741
  uploadFail('Missing argument, for S3 upload you need to provide a bucket name, endpoint, region, port, API key, and API secret');
569
742
  log.info('Uploading to S3');
743
+ if (options.verbose) {
744
+ log.info(`[Verbose] S3 configuration:`);
745
+ log.info(` - Endpoint: ${s3Endpoint}`);
746
+ log.info(` - Region: ${s3Region}`);
747
+ log.info(` - Bucket: ${s3BucketName}`);
748
+ log.info(` - Port: ${s3Port}`);
749
+ log.info(` - SSL: ${s3SSL ? 'enabled' : 'disabled'}`);
750
+ }
570
751
  const endPoint = s3SSL ? `https://${s3Endpoint}` : `http://${s3Endpoint}`;
571
752
  const s3Client = new S3Client({
572
753
  endPoint: s3Endpoint,
@@ -579,18 +760,29 @@ export async function uploadBundle(preAppid, options, shouldExit = true) {
579
760
  });
580
761
  const fileName = `${appid}-${bundle}`;
581
762
  const encodeFileName = encodeURIComponent(fileName);
763
+ if (options.verbose)
764
+ log.info(`[Verbose] Uploading to S3 as: ${fileName}`);
582
765
  await s3Client.putObject(fileName, Uint8Array.from(zipped));
583
766
  versionData.external_url = `${endPoint}/${encodeFileName}`;
584
767
  versionData.storage_provider = 'external';
768
+ if (options.verbose)
769
+ log.info(`[Verbose] S3 upload complete, external URL: ${versionData.external_url}`);
585
770
  }
586
771
  else if (zipped) {
587
772
  if (!options.partialOnly && !options.deltaOnly) {
773
+ if (options.verbose)
774
+ log.info(`[Verbose] Starting full bundle upload to Capgo Cloud...`);
588
775
  await uploadBundleToCapgoCloud(apikey, supabase, appid, bundle, orgId, zipped, options, options.tusChunkSize);
589
776
  }
777
+ else if (options.verbose) {
778
+ log.info(`[Verbose] Skipping full bundle upload (delta-only mode)`);
779
+ }
590
780
  let finalManifest = null;
591
781
  try {
592
782
  if (options.dryUpload) {
593
783
  options.delta = false;
784
+ if (options.verbose)
785
+ log.info(`[Verbose] Dry upload mode: skipping delta upload`);
594
786
  }
595
787
  const encryptionData = versionData.session_key && options.encryptPartial && sessionKey
596
788
  ? {
@@ -598,33 +790,62 @@ export async function uploadBundle(preAppid, options, shouldExit = true) {
598
790
  ivSessionKey: versionData.session_key,
599
791
  }
600
792
  : undefined;
793
+ if (options.verbose && options.delta) {
794
+ log.info(`[Verbose] Starting delta/partial file upload...`);
795
+ log.info(` - Manifest entries: ${manifest.length}`);
796
+ log.info(` - Encryption: ${encryptionData ? 'enabled' : 'disabled'}`);
797
+ }
601
798
  finalManifest = options.delta
602
799
  ? await uploadPartial(apikey, manifest, path, appid, bundle, orgId, encryptionData, options)
603
800
  : null;
801
+ if (options.verbose && finalManifest)
802
+ log.info(`[Verbose] Delta upload complete with ${finalManifest.length} files`);
604
803
  }
605
804
  catch (err) {
606
805
  log.info(`Failed to upload partial files to capgo cloud. Error: ${formatError(err)}. This is not a critical error, the bundle has been uploaded without the partial files`);
806
+ if (options.verbose)
807
+ log.info(`[Verbose] Delta upload error details: ${formatError(err)}`);
607
808
  }
608
809
  versionData.storage_provider = 'r2';
609
810
  versionData.manifest = finalManifest;
811
+ if (options.verbose)
812
+ log.info(`[Verbose] Updating version record with storage provider and manifest...`);
610
813
  const { error: dbError2 } = await updateOrCreateVersion(supabase, versionData);
611
814
  if (dbError2)
612
815
  uploadFail(`Cannot update bundle ${formatError(dbError2)}`);
816
+ if (options.verbose)
817
+ log.info(`[Verbose] Version record updated successfully`);
613
818
  }
614
819
  // Check we have app access to this appId
820
+ if (options.verbose)
821
+ log.info(`[Verbose] Checking app permissions...`);
615
822
  const permissions = await checkAppExistsAndHasPermissionOrgErr(supabase, apikey, appid, OrganizationPerm.upload);
823
+ if (options.verbose) {
824
+ log.info(`[Verbose] Permissions:`);
825
+ log.info(` - Upload: ${hasOrganizationPerm(permissions, OrganizationPerm.upload) ? 'yes' : 'no'}`);
826
+ log.info(` - Write: ${hasOrganizationPerm(permissions, OrganizationPerm.write) ? 'yes' : 'no'}`);
827
+ log.info(` - Admin: ${hasOrganizationPerm(permissions, OrganizationPerm.admin) ? 'yes' : 'no'}`);
828
+ }
616
829
  if (options.deleteLinkedBundleOnUpload && hasOrganizationPerm(permissions, OrganizationPerm.write)) {
830
+ if (options.verbose)
831
+ log.info(`[Verbose] Deleting linked bundle in channel ${channel}...`);
617
832
  await deleteLinkedBundleOnUpload(supabase, appid, channel);
618
833
  }
619
834
  else if (options.deleteLinkedBundleOnUpload) {
620
835
  log.warn('Cannot delete linked bundle on upload as a upload organization member');
621
836
  }
622
837
  if (hasOrganizationPerm(permissions, OrganizationPerm.write)) {
838
+ if (options.verbose)
839
+ log.info(`[Verbose] Setting bundle ${bundle} to channel ${channel}...`);
623
840
  await setVersionInChannel(supabase, apikey, !!options.bundleUrl, bundle, channel, userId, orgId, appid, localConfig, options.selfAssign);
841
+ if (options.verbose)
842
+ log.info(`[Verbose] Channel updated successfully`);
624
843
  }
625
844
  else {
626
845
  log.warn('Cannot set channel as a upload organization member');
627
846
  }
847
+ if (options.verbose)
848
+ log.info(`[Verbose] Sending upload event...`);
628
849
  await sendEvent(apikey, {
629
850
  channel: 'app',
630
851
  event: 'App Uploaded',
@@ -644,6 +865,13 @@ export async function uploadBundle(preAppid, options, shouldExit = true) {
644
865
  ivSessionKey: typeof versionData.session_key === 'string' ? versionData.session_key : undefined,
645
866
  storageProvider: versionData.storage_provider,
646
867
  };
868
+ if (options.verbose) {
869
+ log.info(`[Verbose] Upload completed successfully:`);
870
+ log.info(` - Bundle: ${result.bundle}`);
871
+ log.info(` - Checksum: ${result.checksum}`);
872
+ log.info(` - Encryption: ${result.encryptionMethod}`);
873
+ log.info(` - Storage: ${result.storageProvider}`);
874
+ }
647
875
  if (shouldExit && !result.skipped)
648
876
  outro('Time to share your update to the world 🌍');
649
877
  return result;