@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/index.js +217 -217
- package/dist/package.json +1 -1
- package/dist/src/bundle/upload.d.ts.map +1 -1
- package/dist/src/bundle/upload.js +228 -0
- package/dist/src/bundle/upload.js.map +1 -1
- package/dist/src/bundle/upload_interface.d.ts +1 -0
- package/dist/src/bundle/upload_interface.d.ts.map +1 -1
- package/dist/src/index.js +5 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/sdk.js +186 -186
- package/package.json +1 -1
package/dist/package.json
CHANGED
|
@@ -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;
|
|
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;
|