@capgo/cli 4.0.11 → 4.0.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.
@@ -1,30 +1,44 @@
1
- import { randomUUID } from 'node:crypto';
2
- import { existsSync, readFileSync } from 'node:fs';
3
- import AdmZip from 'adm-zip';
4
- import { program } from 'commander';
5
- import * as p from '@clack/prompts';
6
- import { checksum as getChecksum } from '@tomasklaen/checksum';
7
- import ciDetect from 'ci-info';
8
- import ky from 'ky';
9
- import { checkLatest } from '../api/update';
10
- import { checkAppExistsAndHasPermissionOrgErr } from "../api/app";
11
- import { encryptSource } from '../api/crypto';
12
- import {
1
+ import { randomUUID } from 'node:crypto'
2
+ import { existsSync, readFileSync } from 'node:fs'
3
+ import process from 'node:process'
4
+ import type { Buffer } from 'node:buffer'
5
+ import AdmZip from 'adm-zip'
6
+ import { program } from 'commander'
7
+ import * as p from '@clack/prompts'
8
+ import { checksum as getChecksum } from '@tomasklaen/checksum'
9
+ import ciDetect from 'ci-info'
10
+ import ky from 'ky'
11
+ import { checkLatest } from '../api/update'
12
+ import { checkAppExistsAndHasPermissionOrgErr } from '../api/app'
13
+ import { encryptSource } from '../api/crypto'
14
+ import type {
13
15
  OptionsBase,
14
- getConfig, createSupabaseClient,
15
- uploadUrl,
16
- updateOrCreateChannel, updateOrCreateVersion,
17
- formatError, findSavedKey, checkPlanValid,
18
- useLogSnag, regexSemver, baseKeyPub, convertAppName, getLocalConfig, checkCompatibility, requireUpdateMetadata,
19
- getLocalDepenencies,
20
- verifyUser,
16
+ } from '../utils'
17
+ import {
21
18
  OrganizationPerm,
19
+ baseKeyPub,
20
+ checkCompatibility,
21
+ checkPlanValid,
22
+ convertAppName,
23
+ createSupabaseClient,
24
+ findSavedKey,
25
+ formatError,
26
+ getAppOwner,
27
+ getConfig,
28
+ getLocalConfig,
29
+ getLocalDepenencies,
22
30
  hasOrganizationPerm,
23
- getAppOwner
24
- } from '../utils';
25
- import { checkIndexPosition, searchInDirectory } from './check';
31
+ regexSemver,
32
+ requireUpdateMetadata,
33
+ updateOrCreateChannel,
34
+ updateOrCreateVersion,
35
+ uploadUrl,
36
+ useLogSnag,
37
+ verifyUser,
38
+ } from '../utils'
39
+ import { checkIndexPosition, searchInDirectory } from './check'
26
40
 
27
- const alertMb = 20;
41
+ const alertMb = 20
28
42
 
29
43
  interface Options extends OptionsBase {
30
44
  bundle?: string
@@ -32,75 +46,74 @@ interface Options extends OptionsBase {
32
46
  channel?: string
33
47
  displayIvSession?: boolean
34
48
  external?: string
35
- key?: boolean | string,
36
- keyData?: string,
37
- ivSessionKey?: string,
49
+ key?: boolean | string
50
+ keyData?: string
51
+ ivSessionKey?: string
38
52
  bundleUrl?: boolean
39
- codeCheck?: boolean,
40
- minUpdateVersion?: string,
41
- autoMinUpdateVersion?: boolean,
53
+ codeCheck?: boolean
54
+ minUpdateVersion?: string
55
+ autoMinUpdateVersion?: boolean
42
56
  ignoreMetadataCheck?: boolean
43
57
  }
44
58
 
45
- export const uploadBundle = async (appid: string, options: Options, shouldExit = true) => {
46
-
47
- p.intro(`Uploading`);
48
- await checkLatest();
49
- let { bundle, path, channel } = options;
50
- const { external, key = false, displayIvSession, autoMinUpdateVersion, ignoreMetadataCheck } = options;
59
+ export async function uploadBundle(appid: string, options: Options, shouldExit = true) {
60
+ p.intro(`Uploading`)
61
+ await checkLatest()
62
+ let { bundle, path, channel } = options
63
+ const { external, key = false, displayIvSession, autoMinUpdateVersion, ignoreMetadataCheck } = options
51
64
  let { minUpdateVersion } = options
52
65
  options.apikey = options.apikey || findSavedKey()
53
66
  const snag = useLogSnag()
54
67
 
55
- channel = channel || 'dev';
68
+ channel = channel || 'dev'
56
69
 
57
- const config = await getConfig();
70
+ const config = await getConfig()
58
71
  const localS3: boolean = (config.app.extConfig.plugins && config.app.extConfig.plugins.CapacitorUpdater
59
- && config.app.extConfig.plugins.CapacitorUpdater.localS3) === true;
72
+ && config.app.extConfig.plugins.CapacitorUpdater.localS3) === true
60
73
 
61
74
  const checkNotifyAppReady = options.codeCheck
62
75
  appid = appid || config?.app?.appId
63
76
  // create bundle name format : 1.0.0-beta.x where x is a uuid
64
- const uuid = randomUUID().split('-')[0];
77
+ const uuid = randomUUID().split('-')[0]
65
78
  bundle = bundle || config?.app?.package?.version || `0.0.1-beta.${uuid}`
66
- // check if bundle is valid
79
+ // check if bundle is valid
67
80
  if (!regexSemver.test(bundle)) {
68
- p.log.error(`Your bundle name ${bundle}, is not valid it should follow semver convention : https://semver.org/`);
69
- program.error('');
81
+ p.log.error(`Your bundle name ${bundle}, is not valid it should follow semver convention : https://semver.org/`)
82
+ program.error('')
70
83
  }
71
84
  path = path || config?.app?.webDir
72
85
  if (!options.apikey) {
73
- p.log.error(`Missing API key, you need to provide a API key to upload your bundle`);
74
- program.error('');
86
+ p.log.error(`Missing API key, you need to provide a API key to upload your bundle`)
87
+ program.error('')
75
88
  }
76
89
  if (!appid || !bundle || !path) {
77
- p.log.error("Missing argument, you need to provide a appid and a bundle and a path, or be in a capacitor project");
78
- program.error('');
90
+ p.log.error('Missing argument, you need to provide a appid and a bundle and a path, or be in a capacitor project')
91
+ program.error('')
79
92
  }
80
93
  // check if path exist
81
94
  if (!existsSync(path)) {
82
- p.log.error(`Path ${path} does not exist, build your app first, or provide a valid path`);
83
- program.error('');
95
+ p.log.error(`Path ${path} does not exist, build your app first, or provide a valid path`)
96
+ program.error('')
84
97
  }
85
98
 
86
99
  if (typeof checkNotifyAppReady === 'undefined' || checkNotifyAppReady) {
87
100
  const isPluginConfigured = searchInDirectory(path, 'notifyAppReady')
88
101
  if (!isPluginConfigured) {
89
- p.log.error(`notifyAppReady() is missing in the source code. see: https://capgo.app/docs/plugin/api/#notifyappready`);
90
- program.error('');
102
+ p.log.error(`notifyAppReady() is missing in the source code. see: https://capgo.app/docs/plugin/api/#notifyappready`)
103
+ program.error('')
91
104
  }
92
- const foundIndex = checkIndexPosition(path);
105
+ const foundIndex = checkIndexPosition(path)
93
106
  if (!foundIndex) {
94
- p.log.error(`index.html is missing in the root folder or in the only folder in the root folder`);
95
- program.error('');
107
+ p.log.error(`index.html is missing in the root folder or in the only folder in the root folder`)
108
+ program.error('')
96
109
  }
97
110
  }
98
111
 
99
- p.log.info(`Upload ${appid}@${bundle} started from path "${path}" to Capgo cloud`);
112
+ p.log.info(`Upload ${appid}@${bundle} started from path "${path}" to Capgo cloud`)
100
113
 
101
114
  const localConfig = await getLocalConfig()
102
115
  const supabase = await createSupabaseClient(options.apikey)
103
- const userId = await verifyUser(supabase, options.apikey, ['write', 'all', 'upload']);
116
+ const userId = await verifyUser(supabase, options.apikey, ['write', 'all', 'upload'])
104
117
  // Check we have app access to this appId
105
118
  // await checkAppExistsAndHasPermissionErr(supabase, options.apikey, appid);
106
119
 
@@ -118,73 +131,76 @@ export const uploadBundle = async (appid: string, options: Options, shouldExit =
118
131
  .single()
119
132
 
120
133
  // eslint-disable-next-line no-undef-init
121
- let localDependencies: Awaited<ReturnType<typeof getLocalDepenencies>> | undefined = undefined;
122
- let finalCompatibility: Awaited<ReturnType<typeof checkCompatibility>>['finalCompatibility'];
134
+ let localDependencies: Awaited<ReturnType<typeof getLocalDepenencies>> | undefined = undefined
135
+ let finalCompatibility: Awaited<ReturnType<typeof checkCompatibility>>['finalCompatibility']
123
136
 
124
137
  // We only check compatibility IF the channel exists
125
138
  if (!channelError && channelData && channelData.version && (channelData.version as any).native_packages && !ignoreMetadataCheck) {
126
- const spinner = p.spinner();
127
- spinner.start(`Checking bundle compatibility with channel ${channel}`);
139
+ const spinner = p.spinner()
140
+ spinner.start(`Checking bundle compatibility with channel ${channel}`)
128
141
  const {
129
142
  finalCompatibility: finalCompatibilityWithChannel,
130
- localDependencies: localDependenciesWithChannel
143
+ localDependencies: localDependenciesWithChannel,
131
144
  } = await checkCompatibility(supabase, appid, channel)
132
145
 
133
146
  finalCompatibility = finalCompatibilityWithChannel
134
147
  localDependencies = localDependenciesWithChannel
135
148
 
136
- if (finalCompatibility.find((x) => x.localVersion !== x.remoteVersion)) {
137
- p.log.error(`Your bundle is not compatible with the channel ${channel}`);
138
- p.log.warn(`You can check compatibility with "npx @capgo/cli bundle compatibility"`);
149
+ if (finalCompatibility.find(x => x.localVersion !== x.remoteVersion)) {
150
+ p.log.error(`Your bundle is not compatible with the channel ${channel}`)
151
+ p.log.warn(`You can check compatibility with "npx @capgo/cli bundle compatibility"`)
139
152
 
140
153
  if (autoMinUpdateVersion) {
141
154
  minUpdateVersion = bundle
142
- p.log.info(`Auto set min-update-version to ${minUpdateVersion}`);
155
+ p.log.info(`Auto set min-update-version to ${minUpdateVersion}`)
143
156
  }
144
- } else if (autoMinUpdateVersion) {
157
+ }
158
+ else if (autoMinUpdateVersion) {
145
159
  try {
146
160
  const { minUpdateVersion: lastMinUpdateVersion } = channelData.version as any
147
161
  if (!lastMinUpdateVersion || !regexSemver.test(lastMinUpdateVersion)) {
148
- p.log.error('Invalid remote min update version, skipping auto setting compatibility');
149
- program.error('');
162
+ p.log.error('Invalid remote min update version, skipping auto setting compatibility')
163
+ program.error('')
150
164
  }
151
165
 
152
166
  minUpdateVersion = lastMinUpdateVersion
153
- p.log.info(`Auto set min-update-version to ${minUpdateVersion}`);
154
- } catch (error) {
155
- p.log.error(`Cannot auto set compatibility, invalid data ${channelData}`);
156
- program.error('');
167
+ p.log.info(`Auto set min-update-version to ${minUpdateVersion}`)
168
+ }
169
+ catch (error) {
170
+ p.log.error(`Cannot auto set compatibility, invalid data ${channelData}`)
171
+ program.error('')
157
172
  }
158
173
  }
159
- spinner.stop(`Bundle compatible with ${channel} channel`);
160
- } else if (!ignoreMetadataCheck) {
161
- p.log.warn(`Channel ${channel} is new or it's your first upload with compatibility check, it will be ignored this time`);
174
+ spinner.stop(`Bundle compatible with ${channel} channel`)
175
+ }
176
+ else if (!ignoreMetadataCheck) {
177
+ p.log.warn(`Channel ${channel} is new or it's your first upload with compatibility check, it will be ignored this time`)
162
178
  localDependencies = await getLocalDepenencies()
163
179
 
164
180
  if (autoMinUpdateVersion) {
165
181
  minUpdateVersion = bundle
166
- p.log.info(`Auto set min-update-version to ${minUpdateVersion}`);
182
+ p.log.info(`Auto set min-update-version to ${minUpdateVersion}`)
167
183
  }
168
184
  }
169
185
 
170
186
  if (updateMetadataRequired && !minUpdateVersion && !ignoreMetadataCheck) {
171
- p.log.error(`You need to provide a min-update-version to upload a bundle to this channel`);
172
- program.error('');
187
+ p.log.error(`You need to provide a min-update-version to upload a bundle to this channel`)
188
+ program.error('')
173
189
  }
174
190
 
175
191
  if (minUpdateVersion) {
176
192
  if (!regexSemver.test(minUpdateVersion)) {
177
- p.log.error(`Your minimal version update ${minUpdateVersion}, is not valid it should follow semver convention : https://semver.org/`);
178
- program.error('');
193
+ p.log.error(`Your minimal version update ${minUpdateVersion}, is not valid it should follow semver convention : https://semver.org/`)
194
+ program.error('')
179
195
  }
180
196
  }
181
197
 
182
198
  const { data: isTrial, error: isTrialsError } = await supabase
183
199
  .rpc('is_trial', { userid: userId })
184
200
  .single()
185
- if (isTrial && isTrial > 0 || isTrialsError) {
186
- p.log.warn(`WARNING !!\nTrial expires in ${isTrial} days`);
187
- p.log.warn(`Upgrade here: ${localConfig.hostWeb}/dashboard/settings/plans`);
201
+ if ((isTrial && isTrial > 0) || isTrialsError) {
202
+ p.log.warn(`WARNING !!\nTrial expires in ${isTrial} days`)
203
+ p.log.warn(`Upgrade here: ${localConfig.hostWeb}/dashboard/settings/plans`)
188
204
  }
189
205
 
190
206
  // check if app already exist
@@ -193,37 +209,37 @@ export const uploadBundle = async (appid: string, options: Options, shouldExit =
193
209
  .single()
194
210
 
195
211
  if (appVersion || appVersionError) {
196
- p.log.error(`Version already exists ${formatError(appVersionError)}`);
197
- program.error('');
212
+ p.log.error(`Version already exists ${formatError(appVersionError)}`)
213
+ program.error('')
198
214
  }
199
215
  // make bundle safe for s3 name https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-keys.html
200
- const safeBundle = bundle.replace(/[^a-zA-Z0-9-_.!*'()]/g, '__');
201
- const fileName = `${safeBundle}.zip`;
216
+ const safeBundle = bundle.replace(/[^a-zA-Z0-9-_.!*'()]/g, '__')
217
+ const fileName = `${safeBundle}.zip`
202
218
 
203
- let sessionKey;
219
+ let sessionKey
204
220
  let checksum = ''
205
- let zipped: Buffer | null = null;
221
+ let zipped: Buffer | null = null
206
222
  if (!external) {
207
- const zip = new AdmZip();
208
- zip.addLocalFolder(path);
209
- zipped = zip.toBuffer();
223
+ const zip = new AdmZip()
224
+ zip.addLocalFolder(path)
225
+ zipped = zip.toBuffer()
210
226
  const s = p.spinner()
211
- s.start(`Calculating checksum`);
212
- checksum = await getChecksum(zipped, 'crc32');
213
- s.stop(`Checksum: ${checksum}`);
227
+ s.start(`Calculating checksum`)
228
+ checksum = await getChecksum(zipped, 'crc32')
229
+ s.stop(`Checksum: ${checksum}`)
214
230
  if (key || existsSync(baseKeyPub)) {
215
231
  const publicKey = typeof key === 'string' ? key : baseKeyPub
216
232
  let keyData = options.keyData || ''
217
233
  // check if publicKey exist
218
234
  if (!keyData && !existsSync(publicKey)) {
219
- p.log.error(`Cannot find public key ${publicKey}`);
220
- if (ciDetect.isCI) {
221
- program.error('');
222
- }
235
+ p.log.error(`Cannot find public key ${publicKey}`)
236
+ if (ciDetect.isCI)
237
+ program.error('')
238
+
223
239
  const res = await p.confirm({ message: 'Do you want to use our public key ?' })
224
240
  if (!res) {
225
- p.log.error(`Error: Missing public key`);
226
- program.error('');
241
+ p.log.error(`Error: Missing public key`)
242
+ program.error('')
227
243
  }
228
244
  keyData = localConfig.signKey || ''
229
245
  }
@@ -243,20 +259,20 @@ export const uploadBundle = async (appid: string, options: Options, shouldExit =
243
259
  keyData = keyFile.toString()
244
260
  }
245
261
  // encrypt
246
- p.log.info(`Encrypting your bundle`);
262
+ p.log.info(`Encrypting your bundle`)
247
263
  const res = encryptSource(zipped, keyData)
248
264
  sessionKey = res.ivSessionKey
249
265
  if (displayIvSession) {
250
266
  p.log.info(`Your Iv Session key is ${sessionKey},
251
267
  keep it safe, you will need it to decrypt your bundle.
252
- It will be also visible in your dashboard\n`);
268
+ It will be also visible in your dashboard\n`)
253
269
  }
254
270
  zipped = res.encryptedData
255
271
  }
256
- const mbSize = Math.floor(zipped.byteLength / 1024 / 1024);
272
+ const mbSize = Math.floor(zipped.byteLength / 1024 / 1024)
257
273
  if (mbSize > alertMb) {
258
- p.log.warn(`WARNING !!\nThe app size is ${mbSize} Mb, this may take a while to download for users\n`);
259
- p.log.info(`Learn how to optimize your assets https://capgo.app/blog/optimise-your-images-for-updates/\n`);
274
+ p.log.warn(`WARNING !!\nThe app size is ${mbSize} Mb, this may take a while to download for users\n`)
275
+ p.log.info(`Learn how to optimize your assets https://capgo.app/blog/optimise-your-images-for-updates/\n`)
260
276
  await snag.track({
261
277
  channel: 'app-error',
262
278
  event: 'App Too Large',
@@ -268,10 +284,12 @@ It will be also visible in your dashboard\n`);
268
284
  notify: false,
269
285
  }).catch()
270
286
  }
271
- } else if (external && !external.startsWith('https://')) {
272
- p.log.error(`External link should should start with "https://" current is "${external}"`);
273
- program.error('');
274
- } else {
287
+ }
288
+ else if (external && !external.startsWith('https://')) {
289
+ p.log.error(`External link should should start with "https://" current is "${external}"`)
290
+ program.error('')
291
+ }
292
+ else {
275
293
  await snag.track({
276
294
  channel: 'app',
277
295
  event: 'App external',
@@ -285,11 +303,12 @@ It will be also visible in your dashboard\n`);
285
303
  sessionKey = options.ivSessionKey
286
304
  }
287
305
 
288
- const hashedLocalDependencies = localDependencies ? new Map(localDependencies
289
- .filter((a) => !!a.native && a.native !== undefined)
290
- .map((a) => [a.name, a])) : new Map()
306
+ const hashedLocalDependencies = localDependencies
307
+ ? new Map(localDependencies
308
+ .filter(a => !!a.native && a.native !== undefined)
309
+ .map(a => [a.name, a]))
310
+ : new Map()
291
311
 
292
- // eslint-disable-next-line max-len
293
312
  const nativePackages = (hashedLocalDependencies.size > 0 || !options.ignoreMetadataCheck) ? Array.from(hashedLocalDependencies, ([name, value]) => ({ name, version: value.version })) : undefined
294
313
 
295
314
  const appOwner = await getAppOwner(supabase, appid)
@@ -306,35 +325,36 @@ It will be also visible in your dashboard\n`);
306
325
  native_packages: nativePackages,
307
326
  checksum,
308
327
  }
309
- const { error: dbError } = await updateOrCreateVersion(supabase, versionData, options.apikey)
328
+ const { error: dbError } = await updateOrCreateVersion(supabase, versionData)
310
329
  if (dbError) {
311
- p.log.error(`Cannot add bundle ${formatError(dbError)}`);
312
- program.error('');
330
+ p.log.error(`Cannot add bundle ${formatError(dbError)}`)
331
+ program.error('')
313
332
  }
314
333
  if (!external && zipped) {
315
- const spinner = p.spinner();
316
- spinner.start(`Uploading Bundle`);
334
+ const spinner = p.spinner()
335
+ spinner.start(`Uploading Bundle`)
317
336
 
318
337
  const url = await uploadUrl(supabase, appid, fileName)
319
338
  if (!url) {
320
- p.log.error(`Cannot get upload url`);
321
- program.error('');
339
+ p.log.error(`Cannot get upload url`)
340
+ program.error('')
322
341
  }
323
342
  await ky.put(url, {
324
343
  timeout: 60000,
325
344
  body: zipped,
326
- headers: (!localS3 ? {
327
- "Content-Type": "application/octet-stream",
328
- "Cache-Control": "public, max-age=456789, immutable",
329
- "x-amz-meta-crc32": checksum,
330
- } : undefined)
345
+ headers: (!localS3
346
+ ? {
347
+ 'Content-Type': 'application/octet-stream',
348
+ 'Cache-Control': 'public, max-age=456789, immutable',
349
+ 'x-amz-meta-crc32': checksum,
350
+ }
351
+ : undefined),
331
352
  })
332
353
  versionData.storage_provider = 'r2'
333
- const { error: dbError2 } = await updateOrCreateVersion(supabase, versionData, options.apikey)
354
+ const { error: dbError2 } = await updateOrCreateVersion(supabase, versionData)
334
355
  if (dbError2) {
335
- console.log(dbError2)
336
- p.log.error(`Cannot update bundle ${formatError(dbError)}`);
337
- program.error('');
356
+ p.log.error(`Cannot update bundle ${formatError(dbError2)}`)
357
+ program.error('')
338
358
  }
339
359
  spinner.stop('Bundle Uploaded 💪')
340
360
  }
@@ -350,25 +370,24 @@ It will be also visible in your dashboard\n`);
350
370
  version: versionId,
351
371
  })
352
372
  if (dbError3) {
353
- p.log.error(`Cannot set channel, the upload key is not allowed to do that, use the "all" for this.`);
354
- console.log(dbError3)
355
- program.error('');
373
+ p.log.error(`Cannot set channel, the upload key is not allowed to do that, use the "all" for this. ${formatError(dbError3)}`)
374
+ program.error('')
356
375
  }
357
376
  const appidWeb = convertAppName(appid)
358
377
  const bundleUrl = `${localConfig.hostWeb}/app/p/${appidWeb}/channel/${data.id}`
359
- if (data?.public) {
378
+ if (data?.public)
360
379
  p.log.info('Your update is now available in your public channel 🎉')
361
- } else if (data?.id) {
362
- p.log.info(`Link device to this bundle to try it: ${bundleUrl}`);
363
- }
380
+ else if (data?.id)
381
+ p.log.info(`Link device to this bundle to try it: ${bundleUrl}`)
364
382
 
365
- if (options.bundleUrl) {
366
- p.log.info(`Bundle url: ${bundleUrl}`);
367
- }
368
- } else if (!versionId) {
369
- p.log.warn('Cannot set bundle with upload key, use key with more rights for that');
370
- program.error('');
371
- } else if (!hasOrganizationPerm(permissions, OrganizationPerm.write)) {
383
+ if (options.bundleUrl)
384
+ p.log.info(`Bundle url: ${bundleUrl}`)
385
+ }
386
+ else if (!versionId) {
387
+ p.log.warn('Cannot set bundle with upload key, use key with more rights for that')
388
+ program.error('')
389
+ }
390
+ else if (!hasOrganizationPerm(permissions, OrganizationPerm.write)) {
372
391
  p.log.warn('Cannot set channel as a upload organization member')
373
392
  }
374
393
  await snag.track({
@@ -388,21 +407,23 @@ It will be also visible in your dashboard\n`);
388
407
  return true
389
408
  }
390
409
 
391
- export const uploadCommand = async (apikey: string, options: Options) => {
410
+ export async function uploadCommand(apikey: string, options: Options) {
392
411
  try {
393
412
  await uploadBundle(apikey, options, true)
394
- } catch (error) {
395
- p.log.error(JSON.stringify(error))
413
+ }
414
+ catch (error) {
415
+ p.log.error(formatError(error))
396
416
  program.error('')
397
417
  }
398
418
  }
399
419
 
400
- export const uploadDeprecatedCommand = async (apikey: string, options: Options) => {
420
+ export async function uploadDeprecatedCommand(apikey: string, options: Options) {
401
421
  p.log.warn('⚠️ This command is deprecated, use "npx @capgo/cli bundle upload" instead ⚠️')
402
422
  try {
403
423
  await uploadBundle(apikey, options, true)
404
- } catch (error) {
405
- p.log.error(JSON.stringify(error))
424
+ }
425
+ catch (error) {
426
+ p.log.error(formatError(error))
406
427
  program.error('')
407
428
  }
408
429
  }