@capgo/cli 4.12.14 → 4.13.2

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,18 +1,19 @@
1
1
  import { randomUUID } from 'node:crypto'
2
2
  import { existsSync, readFileSync } from 'node:fs'
3
+ import { exit } from 'node:process'
3
4
  import type { Buffer } from 'node:buffer'
4
- import process from 'node:process'
5
- import * as p from '@clack/prompts'
6
5
  import { program } from 'commander'
7
6
  import { checksum as getChecksum } from '@tomasklaen/checksum'
8
7
  import ciDetect from 'ci-info'
9
8
  import type LogSnag from 'logsnag'
10
9
  import { S3Client } from '@bradenmacdonald/s3-lite-client'
11
10
  import ky, { HTTPError } from 'ky'
11
+ import { confirm as confirmC, intro, log, outro, spinner as spinnerC } from '@clack/prompts'
12
12
  import { encryptSource } from '../api/crypto'
13
- import { type OptionsBase, OrganizationPerm, baseKeyPub, checkChecksum, checkCompatibility, checkPlanValid, convertAppName, createSupabaseClient, deletedFailedVersion, findSavedKey, formatError, getConfig, getLocalConfig, getLocalDepenencies, getOrganizationId, getPMAndCommand, hasOrganizationPerm, regexSemver, updateOrCreateChannel, updateOrCreateVersion, uploadMultipart, uploadUrl, useLogSnag, verifyUser, zipFile } from '../utils'
13
+ import { type OptionsBase, OrganizationPerm, baseKeyPub, checkChecksum, checkCompatibility, checkPlanValid, convertAppName, createSupabaseClient, deletedFailedVersion, findSavedKey, formatError, getConfig, getLocalConfig, getLocalDepenencies, getOrganizationId, getPMAndCommand, hasOrganizationPerm, readPackageJson, regexSemver, updateOrCreateChannel, updateOrCreateVersion, uploadMultipart, uploadUrl, useLogSnag, verifyUser, zipFile } from '../utils'
14
14
  import { checkAppExistsAndHasPermissionOrgErr } from '../api/app'
15
15
  import { checkLatest } from '../api/update'
16
+ import type { CapacitorConfig } from '../config'
16
17
  import { checkIndexPosition, searchInDirectory } from './check'
17
18
 
18
19
  interface Options extends OptionsBase {
@@ -44,20 +45,20 @@ interface Options extends OptionsBase {
44
45
  const alertMb = 20
45
46
  const UPLOAD_TIMEOUT = 120000
46
47
 
47
- type ConfigType = Awaited<ReturnType<typeof getConfig>>
48
48
  type SupabaseType = Awaited<ReturnType<typeof createSupabaseClient>>
49
49
  type pmType = ReturnType<typeof getPMAndCommand>
50
50
  type localConfigType = Awaited<ReturnType<typeof getLocalConfig>>
51
51
 
52
- function getBundle(config: ConfigType, options: Options) {
52
+ async function getBundle(config: CapacitorConfig, options: Options) {
53
+ const pkg = await readPackageJson()
53
54
  // create bundle name format : 1.0.0-beta.x where x is a uuid
54
55
  const bundle = options.bundle
55
- || config?.app?.extConfig?.plugins?.CapacitorUpdater?.version
56
- || config?.app?.package?.version
56
+ || config?.plugins?.CapacitorUpdater?.version
57
+ || pkg?.version
57
58
  || `0.0.1-beta.${randomUUID().split('-')[0]}`
58
59
 
59
60
  if (!regexSemver.test(bundle)) {
60
- p.log.error(`Your bundle name ${bundle}, is not valid it should follow semver convention : https://semver.org/`)
61
+ log.error(`Your bundle name ${bundle}, is not valid it should follow semver convention : https://semver.org/`)
61
62
  program.error('')
62
63
  }
63
64
 
@@ -67,24 +68,24 @@ function getBundle(config: ConfigType, options: Options) {
67
68
  function getApikey(options: Options) {
68
69
  const apikey = options.apikey || findSavedKey()
69
70
  if (!apikey) {
70
- p.log.error(`Missing API key, you need to provide a API key to upload your bundle`)
71
+ log.error(`Missing API key, you need to provide a API key to upload your bundle`)
71
72
  program.error('')
72
73
  }
73
74
 
74
75
  return apikey
75
76
  }
76
77
 
77
- function getAppIdAndPath(appId: string | undefined, options: Options, config: ConfigType) {
78
- const finalAppId = appId || config?.app?.appId
79
- const path = options.path || config?.app?.webDir
78
+ function getAppIdAndPath(appId: string | undefined, options: Options, config: CapacitorConfig) {
79
+ const finalAppId = appId || config?.appId
80
+ const path = options.path || config?.webDir
80
81
 
81
82
  if (!finalAppId || !path) {
82
- p.log.error('Missing argument, you need to provide a appid and a path (--path), or be in a capacitor project')
83
+ log.error('Missing argument, you need to provide a appid and a path (--path), or be in a capacitor project')
83
84
  program.error('')
84
85
  }
85
86
 
86
87
  if (!existsSync(path)) {
87
- p.log.error(`Path ${path} does not exist, build your app first, or provide a valid path`)
88
+ log.error(`Path ${path} does not exist, build your app first, or provide a valid path`)
88
89
  program.error('')
89
90
  }
90
91
 
@@ -97,12 +98,12 @@ function checkNotifyAppReady(options: Options, path: string) {
97
98
  if (typeof checkNotifyAppReady === 'undefined' || checkNotifyAppReady) {
98
99
  const isPluginConfigured = searchInDirectory(path, 'notifyAppReady')
99
100
  if (!isPluginConfigured) {
100
- p.log.error(`notifyAppReady() is missing in the source code. see: https://capgo.app/docs/plugin/api/#notifyappready`)
101
+ log.error(`notifyAppReady() is missing in the source code. see: https://capgo.app/docs/plugin/api/#notifyappready`)
101
102
  program.error('')
102
103
  }
103
104
  const foundIndex = checkIndexPosition(path)
104
105
  if (!foundIndex) {
105
- p.log.error(`index.html is missing in the root folder or in the only folder in the root folder`)
106
+ log.error(`index.html is missing in the root folder or in the only folder in the root folder`)
106
107
  program.error('')
107
108
  }
108
109
  }
@@ -129,7 +130,7 @@ async function verifyCompatibility(supabase: SupabaseType, pm: pmType, options:
129
130
 
130
131
  // We only check compatibility IF the channel exists
131
132
  if (!channelError && channelData && channelData.version && (channelData.version as any).native_packages && !ignoreMetadataCheck) {
132
- const spinner = p.spinner()
133
+ const spinner = spinnerC()
133
134
  spinner.start(`Checking bundle compatibility with channel ${channel}`)
134
135
  const {
135
136
  finalCompatibility: finalCompatibilityWithChannel,
@@ -141,18 +142,18 @@ async function verifyCompatibility(supabase: SupabaseType, pm: pmType, options:
141
142
 
142
143
  if (finalCompatibility.find(x => x.localVersion !== x.remoteVersion)) {
143
144
  spinner.stop(`Bundle NOT compatible with ${channel} channel`)
144
- p.log.warn(`You can check compatibility with "${pm.runner} @capgo/cli bundle compatibility"`)
145
+ log.warn(`You can check compatibility with "${pm.runner} @capgo/cli bundle compatibility"`)
145
146
 
146
147
  if (autoMinUpdateVersion) {
147
148
  minUpdateVersion = bundle
148
- p.log.info(`Auto set min-update-version to ${minUpdateVersion}`)
149
+ log.info(`Auto set min-update-version to ${minUpdateVersion}`)
149
150
  }
150
151
  }
151
152
  else if (autoMinUpdateVersion) {
152
153
  try {
153
154
  const { minUpdateVersion: lastMinUpdateVersion } = channelData.version as any
154
155
  if (!lastMinUpdateVersion || !regexSemver.test(lastMinUpdateVersion)) {
155
- p.log.error('Invalid remote min update version, skipping auto setting compatibility')
156
+ log.error('Invalid remote min update version, skipping auto setting compatibility')
156
157
  program.error('')
157
158
  }
158
159
 
@@ -160,7 +161,7 @@ async function verifyCompatibility(supabase: SupabaseType, pm: pmType, options:
160
161
  spinner.stop(`Auto set min-update-version to ${minUpdateVersion}`)
161
162
  }
162
163
  catch (error) {
163
- p.log.error(`Cannot auto set compatibility, invalid data ${channelData}`)
164
+ log.error(`Cannot auto set compatibility, invalid data ${channelData}`)
164
165
  program.error('')
165
166
  }
166
167
  }
@@ -169,23 +170,23 @@ async function verifyCompatibility(supabase: SupabaseType, pm: pmType, options:
169
170
  }
170
171
  }
171
172
  else if (!ignoreMetadataCheck) {
172
- p.log.warn(`Channel ${channel} is new or it's your first upload with compatibility check, it will be ignored this time`)
173
+ log.warn(`Channel ${channel} is new or it's your first upload with compatibility check, it will be ignored this time`)
173
174
  localDependencies = await getLocalDepenencies()
174
175
 
175
176
  if (autoMinUpdateVersion) {
176
177
  minUpdateVersion = bundle
177
- p.log.info(`Auto set min-update-version to ${minUpdateVersion}`)
178
+ log.info(`Auto set min-update-version to ${minUpdateVersion}`)
178
179
  }
179
180
  }
180
181
 
181
182
  if (updateMetadataRequired && !minUpdateVersion && !ignoreMetadataCheck) {
182
- p.log.error(`You need to provide a min-update-version to upload a bundle to this channel`)
183
+ log.error(`You need to provide a min-update-version to upload a bundle to this channel`)
183
184
  program.error('')
184
185
  }
185
186
 
186
187
  if (minUpdateVersion) {
187
188
  if (!regexSemver.test(minUpdateVersion)) {
188
- p.log.error(`Your minimal version update ${minUpdateVersion}, is not valid it should follow semver convention : https://semver.org/`)
189
+ log.error(`Your minimal version update ${minUpdateVersion}, is not valid it should follow semver convention : https://semver.org/`)
189
190
  program.error('')
190
191
  }
191
192
  }
@@ -207,8 +208,8 @@ async function checkTrial(supabase: SupabaseType, orgId: string, localConfig: lo
207
208
  .single()
208
209
  if ((isTrial && isTrial > 0) || isTrialsError) {
209
210
  // TODO: Come back to this to fix for orgs v3
210
- p.log.warn(`WARNING !!\nTrial expires in ${isTrial} days`)
211
- p.log.warn(`Upgrade here: ${localConfig.hostWeb}/dashboard/settings/plans?oid=${orgId}`)
211
+ log.warn(`WARNING !!\nTrial expires in ${isTrial} days`)
212
+ log.warn(`Upgrade here: ${localConfig.hostWeb}/dashboard/settings/plans?oid=${orgId}`)
212
213
  }
213
214
  }
214
215
 
@@ -221,7 +222,7 @@ async function checkVersionExists(supabase: SupabaseType, appid: string, bundle:
221
222
  .single()
222
223
 
223
224
  if (appVersion || appVersionError) {
224
- p.log.error(`Version already exists ${formatError(appVersionError)}`)
225
+ log.error(`Version already exists ${formatError(appVersionError)}`)
225
226
  program.error('')
226
227
  }
227
228
  }
@@ -233,28 +234,28 @@ async function prepareBundleFile(path: string, options: Options, localConfig: lo
233
234
  const key = options.key
234
235
 
235
236
  zipped = await zipFile(path)
236
- const s = p.spinner()
237
+ const s = spinnerC()
237
238
  s.start(`Calculating checksum`)
238
239
  checksum = await getChecksum(zipped, 'crc32')
239
240
  s.stop(`Checksum: ${checksum}`)
240
241
  // key should be undefined or a string if false it should ingore encryption
241
242
  if (!key) {
242
- p.log.info(`Encryption ignored`)
243
+ log.info(`Encryption ignored`)
243
244
  }
244
245
  else if (key || existsSync(baseKeyPub)) {
245
246
  const publicKey = typeof key === 'string' ? key : baseKeyPub
246
247
  let keyData = options.keyData || ''
247
248
  // check if publicKey exist
248
249
  if (!keyData && !existsSync(publicKey)) {
249
- p.log.error(`Cannot find public key ${publicKey}`)
250
+ log.error(`Cannot find public key ${publicKey}`)
250
251
  if (ciDetect.isCI) {
251
- p.log.error('Cannot ask if user wants to use capgo public key on the cli')
252
+ log.error('Cannot ask if user wants to use capgo public key on the cli')
252
253
  program.error('')
253
254
  }
254
255
 
255
- const res = await p.confirm({ message: 'Do you want to use our public key ?' })
256
+ const res = await confirmC({ message: 'Do you want to use our public key ?' })
256
257
  if (!res) {
257
- p.log.error(`Error: Missing public key`)
258
+ log.error(`Error: Missing public key`)
258
259
  program.error('')
259
260
  }
260
261
  keyData = localConfig.signKey || ''
@@ -275,11 +276,11 @@ async function prepareBundleFile(path: string, options: Options, localConfig: lo
275
276
  keyData = keyFile.toString()
276
277
  }
277
278
  // encrypt
278
- p.log.info(`Encrypting your bundle`)
279
+ log.info(`Encrypting your bundle`)
279
280
  const res = encryptSource(zipped, keyData)
280
281
  sessionKey = res.ivSessionKey
281
282
  if (options.displayIvSession) {
282
- p.log.info(`Your Iv Session key is ${sessionKey},
283
+ log.info(`Your Iv Session key is ${sessionKey},
283
284
  keep it safe, you will need it to decrypt your bundle.
284
285
  It will be also visible in your dashboard\n`)
285
286
  }
@@ -287,8 +288,8 @@ It will be also visible in your dashboard\n`)
287
288
  }
288
289
  const mbSize = Math.floor((zipped?.byteLength ?? 0) / 1024 / 1024)
289
290
  if (mbSize > alertMb) {
290
- p.log.warn(`WARNING !!\nThe app size is ${mbSize} Mb, this may take a while to download for users\n`)
291
- p.log.info(`Learn how to optimize your assets https://capgo.app/blog/optimise-your-images-for-updates/\n`)
291
+ log.warn(`WARNING !!\nThe app size is ${mbSize} Mb, this may take a while to download for users\n`)
292
+ log.info(`Learn how to optimize your assets https://capgo.app/blog/optimise-your-images-for-updates/\n`)
292
293
  await snag.track({
293
294
  channel: 'app-error',
294
295
  event: 'App Too Large',
@@ -305,19 +306,19 @@ It will be also visible in your dashboard\n`)
305
306
  }
306
307
 
307
308
  async function uploadBundleToCapgoCloud(supabase: SupabaseType, appid: string, bundle: string, orgId: string, zipped: Buffer, options: Options) {
308
- const spinner = p.spinner()
309
+ const spinner = spinnerC()
309
310
  spinner.start(`Uploading Bundle`)
310
311
  const startTime = performance.now()
311
312
 
312
313
  try {
313
314
  if (options.multipart !== undefined && options.multipart) {
314
- p.log.info(`Uploading bundle as multipart`)
315
+ log.info(`Uploading bundle as multipart`)
315
316
  await uploadMultipart(supabase, appid, bundle, zipped, orgId)
316
317
  }
317
318
  else {
318
319
  const url = await uploadUrl(supabase, appid, bundle)
319
320
  if (!url) {
320
- p.log.error(`Cannot get upload url`)
321
+ log.error(`Cannot get upload url`)
321
322
  program.error('')
322
323
  }
323
324
  await ky.put(url, {
@@ -331,10 +332,10 @@ async function uploadBundleToCapgoCloud(supabase: SupabaseType, appid: string, b
331
332
  const endTime = performance.now()
332
333
  const uploadTime = ((endTime - startTime) / 1000).toFixed(2)
333
334
  spinner.stop(`Failed to upload bundle ( after ${uploadTime} seconds)`)
334
- p.log.error(`Cannot upload bundle ( try again with --multipart option) ${formatError(errorUpload)}`)
335
+ log.error(`Cannot upload bundle ( try again with --multipart option) ${formatError(errorUpload)}`)
335
336
  if (errorUpload instanceof HTTPError) {
336
337
  const body = await errorUpload.response.text()
337
- p.log.error(`Response: ${formatError(body)}`)
338
+ log.error(`Response: ${formatError(body)}`)
338
339
  }
339
340
  // call delete version on path /delete_failed_version to delete the version
340
341
  await deletedFailedVersion(supabase, appid, bundle)
@@ -371,46 +372,46 @@ async function setVersionInChannel(
371
372
  owner_org: orgId,
372
373
  })
373
374
  if (dbError3) {
374
- p.log.error(`Cannot set channel, the upload key is not allowed to do that, use the "all" for this. ${formatError(dbError3)}`)
375
+ log.error(`Cannot set channel, the upload key is not allowed to do that, use the "all" for this. ${formatError(dbError3)}`)
375
376
  program.error('')
376
377
  }
377
378
  const appidWeb = convertAppName(appid)
378
379
  const bundleUrl = `${localConfig.hostWeb}/app/p/${appidWeb}/channel/${data.id}`
379
380
  if (data?.public)
380
- p.log.info('Your update is now available in your public channel 🎉')
381
+ log.info('Your update is now available in your public channel 🎉')
381
382
  else if (data?.id)
382
- p.log.info(`Link device to this bundle to try it: ${bundleUrl}`)
383
+ log.info(`Link device to this bundle to try it: ${bundleUrl}`)
383
384
 
384
385
  if (displayBundleUrl) {
385
- p.log.info(`Bundle url: ${bundleUrl}`)
386
+ log.info(`Bundle url: ${bundleUrl}`)
386
387
  }
387
388
  else if (!versionId) {
388
- p.log.warn('Cannot set bundle with upload key, use key with more rights for that')
389
+ log.warn('Cannot set bundle with upload key, use key with more rights for that')
389
390
  program.error('')
390
391
  }
391
392
  else if (!hasOrganizationPerm(permissions, OrganizationPerm.write)) {
392
- p.log.warn('Cannot set channel as a upload organization member')
393
+ log.warn('Cannot set channel as a upload organization member')
393
394
  }
394
395
  }
395
396
  }
396
397
 
397
398
  export async function uploadBundle(preAppid: string, options: Options, shouldExit = true) {
398
- p.intro(`Uploading`)
399
+ intro(`Uploading`)
399
400
  const pm = getPMAndCommand()
400
401
  await checkLatest()
401
402
 
402
403
  const { s3Region, s3Apikey, s3Apisecret, s3BucketName, s3Endpoint, s3Port, s3SSL } = options
403
404
 
404
405
  const apikey = getApikey(options)
405
- const config = await getConfig()
406
- const { appid, path } = getAppIdAndPath(preAppid, options, config)
407
- const bundle = getBundle(config, options)
406
+ const extConfig = await getConfig()
407
+ const { appid, path } = getAppIdAndPath(preAppid, options, extConfig.config)
408
+ const bundle = await getBundle(extConfig.config, options)
408
409
  const channel = options.channel || 'dev'
409
410
  const snag = useLogSnag()
410
411
 
411
412
  checkNotifyAppReady(options, path)
412
413
 
413
- p.log.info(`Upload ${appid}@${bundle} started from path "${path}" to Capgo cloud`)
414
+ log.info(`Upload ${appid}@${bundle} started from path "${path}" to Capgo cloud`)
414
415
 
415
416
  const localConfig = await getLocalConfig()
416
417
  const supabase = await createSupabaseClient(apikey)
@@ -426,7 +427,7 @@ export async function uploadBundle(preAppid: string, options: Options, shouldExi
426
427
  await checkVersionExists(supabase, appid, bundle)
427
428
 
428
429
  if (options.external && !options.external.startsWith('https://')) {
429
- p.log.error(`External link should should start with "https://" current is "${external}"`)
430
+ log.error(`External link should should start with "https://" current is "${external}"`)
430
431
  program.error('')
431
432
  }
432
433
 
@@ -470,17 +471,17 @@ export async function uploadBundle(preAppid: string, options: Options, shouldExi
470
471
 
471
472
  const { error: dbError } = await updateOrCreateVersion(supabase, versionData)
472
473
  if (dbError) {
473
- p.log.error(`Cannot add bundle ${formatError(dbError)}`)
474
+ log.error(`Cannot add bundle ${formatError(dbError)}`)
474
475
  program.error('')
475
476
  }
476
477
 
477
478
  if (zipped && (s3BucketName || s3Endpoint || s3Region || s3Apikey || s3Apisecret || s3Port || s3SSL)) {
478
479
  if (!s3BucketName || !s3Endpoint || !s3Region || !s3Apikey || !s3Apisecret || !s3Port) {
479
- p.log.error('Missing argument, for S3 upload you need to provide a bucket name, endpoint, region, port, API key, and API secret')
480
+ log.error('Missing argument, for S3 upload you need to provide a bucket name, endpoint, region, port, API key, and API secret')
480
481
  program.error('')
481
482
  }
482
483
 
483
- p.log.info('Uploading to S3')
484
+ log.info('Uploading to S3')
484
485
  const s3Client = new S3Client({
485
486
  endPoint: s3Endpoint,
486
487
  region: s3Region,
@@ -504,7 +505,7 @@ export async function uploadBundle(preAppid: string, options: Options, shouldExi
504
505
  versionData.storage_provider = 'r2'
505
506
  const { error: dbError2 } = await updateOrCreateVersion(supabase, versionData)
506
507
  if (dbError2) {
507
- p.log.error(`Cannot update bundle ${formatError(dbError2)}`)
508
+ log.error(`Cannot update bundle ${formatError(dbError2)}`)
508
509
  program.error('')
509
510
  }
510
511
  }
@@ -522,8 +523,8 @@ export async function uploadBundle(preAppid: string, options: Options, shouldExi
522
523
  notify: false,
523
524
  }).catch()
524
525
  if (shouldExit) {
525
- p.outro('Time to share your update to the world 🌍')
526
- process.exit()
526
+ outro('Time to share your update to the world 🌍')
527
+ exit()
527
528
  }
528
529
  return true
529
530
  }
@@ -533,19 +534,19 @@ export async function uploadCommand(appid: string, options: Options) {
533
534
  await uploadBundle(appid, options, true)
534
535
  }
535
536
  catch (error) {
536
- p.log.error(formatError(error))
537
+ log.error(formatError(error))
537
538
  program.error('')
538
539
  }
539
540
  }
540
541
 
541
542
  export async function uploadDeprecatedCommand(appid: string, options: Options) {
542
543
  const pm = getPMAndCommand()
543
- p.log.warn(`⚠️ This command is deprecated, use "${pm.runner} @capgo/cli bundle upload" instead ⚠️`)
544
+ log.warn(`⚠️ This command is deprecated, use "${pm.runner} @capgo/cli bundle upload" instead ⚠️`)
544
545
  try {
545
546
  await uploadBundle(appid, options, true)
546
547
  }
547
548
  catch (error) {
548
- p.log.error(formatError(error))
549
+ log.error(formatError(error))
549
550
  program.error('')
550
551
  }
551
552
  }
package/src/bundle/zip.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { randomUUID } from 'node:crypto'
2
2
  import { writeFileSync } from 'node:fs'
3
- import process from 'node:process'
3
+ import { exit } from 'node:process'
4
4
  import { program } from 'commander'
5
- import * as p from '@clack/prompts'
6
5
  import { checksum as getChecksum } from '@tomasklaen/checksum'
6
+ import { intro, log, outro, spinner } from '@clack/prompts'
7
7
  import { checkLatest } from '../api/update'
8
8
  import type {
9
9
  OptionsBase,
@@ -11,6 +11,7 @@ import type {
11
11
  import {
12
12
  formatError,
13
13
  getConfig,
14
+ readPackageJson,
14
15
  regexSemver,
15
16
  useLogSnag,
16
17
  zipFile,
@@ -35,37 +36,38 @@ export async function zipBundle(appId: string, options: Options) {
35
36
  if (!json)
36
37
  await checkLatest()
37
38
 
38
- const config = await getConfig()
39
- appId = appId || config?.app?.appId
39
+ const extConfig = await getConfig()
40
+ appId = appId || extConfig?.config?.appId
40
41
  // create bundle name format : 1.0.0-beta.x where x is a uuid
41
42
  const uuid = randomUUID().split('-')[0]
42
- bundle = bundle || config?.app?.package?.version || `0.0.1-beta.${uuid}`
43
+ const pack = await readPackageJson()
44
+ bundle = bundle || pack?.version || `0.0.1-beta.${uuid}`
43
45
  if (!json)
44
- p.intro(`Zipping ${appId}@${bundle}`)
46
+ intro(`Zipping ${appId}@${bundle}`)
45
47
  // check if bundle is valid
46
- if (!regexSemver.test(bundle)) {
48
+ if (bundle && !regexSemver.test(bundle)) {
47
49
  if (!json)
48
- p.log.error(`Your bundle name ${bundle}, is not valid it should follow semver convention : https://semver.org/`)
50
+ log.error(`Your bundle name ${bundle}, is not valid it should follow semver convention : https://semver.org/`)
49
51
  else
50
52
  console.error(formatError({ error: 'invalid_semver' }))
51
53
  program.error('')
52
54
  }
53
- path = path || config?.app?.webDir
55
+ path = path || extConfig?.config?.webDir
54
56
  if (!appId || !bundle || !path) {
55
57
  if (!json)
56
- p.log.error('Missing argument, you need to provide a appId and a bundle and a path, or be in a capacitor project')
58
+ log.error('Missing argument, you need to provide a appId and a bundle and a path, or be in a capacitor project')
57
59
  else
58
60
  console.error(formatError({ error: 'missing_argument' }))
59
61
  program.error('')
60
62
  }
61
63
  if (!json)
62
- p.log.info(`Started from path "${path}"`)
64
+ log.info(`Started from path "${path}"`)
63
65
  const checkNotifyAppReady = options.codeCheck
64
66
  if (typeof checkNotifyAppReady === 'undefined' || checkNotifyAppReady) {
65
67
  const isPluginConfigured = searchInDirectory(path, 'notifyAppReady')
66
68
  if (!isPluginConfigured) {
67
69
  if (!json)
68
- p.log.error(`notifyAppReady() is missing in the source code. see: https://capgo.app/docs/plugin/api/#notifyappready`)
70
+ log.error(`notifyAppReady() is missing in the source code. see: https://capgo.app/docs/plugin/api/#notifyappready`)
69
71
  else
70
72
  console.error(formatError({ error: 'notifyAppReady_not_in_source_code' }))
71
73
  program.error('')
@@ -73,7 +75,7 @@ export async function zipBundle(appId: string, options: Options) {
73
75
  const foundIndex = checkIndexPosition(path)
74
76
  if (!foundIndex) {
75
77
  if (!json)
76
- p.log.error(`index.html is missing in the root folder or in the only folder in the root folder`)
78
+ log.error(`index.html is missing in the root folder or in the only folder in the root folder`)
77
79
  else
78
80
  console.error(formatError({ error: 'index_html_not_found' }))
79
81
  program.error('')
@@ -81,8 +83,8 @@ export async function zipBundle(appId: string, options: Options) {
81
83
  }
82
84
  const zipped = await zipFile(path)
83
85
  if (!json)
84
- p.log.info(`Zipped ${zipped.byteLength} bytes`)
85
- const s = p.spinner()
86
+ log.info(`Zipped ${zipped.byteLength} bytes`)
87
+ const s = spinner()
86
88
  if (!json)
87
89
  s.start(`Calculating checksum`)
88
90
  const checksum = await getChecksum(zipped, 'crc32')
@@ -91,8 +93,8 @@ export async function zipBundle(appId: string, options: Options) {
91
93
  const mbSize = Math.floor(zipped.byteLength / 1024 / 1024)
92
94
  // We do not issue this warning for json
93
95
  if (mbSize > alertMb && !json) {
94
- p.log.warn(`WARNING !!\nThe app size is ${mbSize} Mb, this may take a while to download for users\n`)
95
- p.log.warn(`Learn how to optimize your assets https://capgo.app/blog/optimise-your-images-for-updates/\n`)
96
+ log.warn(`WARNING !!\nThe app size is ${mbSize} Mb, this may take a while to download for users\n`)
97
+ log.warn(`Learn how to optimize your assets https://capgo.app/blog/optimise-your-images-for-updates/\n`)
96
98
  await snag.track({
97
99
  channel: 'app-error',
98
100
  event: 'App Too Large',
@@ -103,7 +105,7 @@ export async function zipBundle(appId: string, options: Options) {
103
105
  notify: false,
104
106
  }).catch()
105
107
  }
106
- const s2 = p.spinner()
108
+ const s2 = spinner()
107
109
  const name = options.name || `${appId}_${bundle}.zip`
108
110
  if (!json)
109
111
  s2.start(`Saving to ${name}`)
@@ -122,7 +124,7 @@ export async function zipBundle(appId: string, options: Options) {
122
124
  }).catch()
123
125
 
124
126
  if (!json)
125
- p.outro(`Done ✅`)
127
+ outro(`Done ✅`)
126
128
 
127
129
  if (json) {
128
130
  const output = {
@@ -134,10 +136,10 @@ export async function zipBundle(appId: string, options: Options) {
134
136
  // eslint-disable-next-line no-console
135
137
  console.log(JSON.stringify(output, null, 2))
136
138
  }
137
- process.exit()
139
+ exit()
138
140
  }
139
141
  catch (error) {
140
- p.log.error(formatError(error))
142
+ log.error(formatError(error))
141
143
  program.error('')
142
144
  }
143
145
  }
@@ -1,6 +1,6 @@
1
- import process from 'node:process'
1
+ import { exit } from 'node:process'
2
2
  import { program } from 'commander'
3
- import * as p from '@clack/prompts'
3
+ import { intro, log, outro } from '@clack/prompts'
4
4
  import { checkAppExistsAndHasPermissionOrgErr } from '../api/app'
5
5
  import { createChannel, findUnknownVersion } from '../api/channels'
6
6
  import type { OptionsBase } from '../utils'
@@ -11,18 +11,18 @@ interface Options extends OptionsBase {
11
11
  }
12
12
 
13
13
  export async function addChannel(channelId: string, appId: string, options: Options, shouldExit = true) {
14
- p.intro(`Create channel`)
14
+ intro(`Create channel`)
15
15
  options.apikey = options.apikey || findSavedKey()
16
- const config = await getConfig()
17
- appId = appId || config?.app?.appId
16
+ const extConfig = await getConfig()
17
+ appId = appId || extConfig?.config?.appId
18
18
  const snag = useLogSnag()
19
19
 
20
20
  if (!options.apikey) {
21
- p.log.error('Missing API key, you need to provide a API key to upload your bundle')
21
+ log.error('Missing API key, you need to provide a API key to upload your bundle')
22
22
  program.error('')
23
23
  }
24
24
  if (!appId) {
25
- p.log.error('Missing argument, you need to provide a appId, or be in a capacitor project')
25
+ log.error('Missing argument, you need to provide a appId, or be in a capacitor project')
26
26
  program.error('')
27
27
  }
28
28
  const supabase = await createSupabaseClient(options.apikey)
@@ -31,12 +31,12 @@ export async function addChannel(channelId: string, appId: string, options: Opti
31
31
  // Check we have app access to this appId
32
32
  await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, OrganizationPerm.admin)
33
33
 
34
- p.log.info(`Creating channel ${appId}#${channelId} to Capgo`)
34
+ log.info(`Creating channel ${appId}#${channelId} to Capgo`)
35
35
  try {
36
36
  const data = await findUnknownVersion(supabase, appId)
37
37
  const orgId = await getOrganizationId(supabase, appId)
38
38
  if (!data) {
39
- p.log.error(`Cannot find default version for channel creation, please contact Capgo support 🤨`)
39
+ log.error(`Cannot find default version for channel creation, please contact Capgo support 🤨`)
40
40
  program.error('')
41
41
  }
42
42
  const res = await createChannel(supabase, {
@@ -47,11 +47,11 @@ export async function addChannel(channelId: string, appId: string, options: Opti
47
47
  })
48
48
 
49
49
  if (res.error) {
50
- p.log.error(`Cannot create Channel 🙀\n${formatError(res.error)}`)
50
+ log.error(`Cannot create Channel 🙀\n${formatError(res.error)}`)
51
51
  program.error('')
52
52
  }
53
53
 
54
- p.log.success(`Channel created ✅`)
54
+ log.success(`Channel created ✅`)
55
55
  await snag.track({
56
56
  channel: 'channel',
57
57
  event: 'Create channel',
@@ -65,12 +65,12 @@ export async function addChannel(channelId: string, appId: string, options: Opti
65
65
  }).catch()
66
66
  }
67
67
  catch (error) {
68
- p.log.error(`Cannot create Channel 🙀`)
68
+ log.error(`Cannot create Channel 🙀`)
69
69
  return false
70
70
  }
71
71
  if (shouldExit) {
72
- p.outro(`Done ✅`)
73
- process.exit()
72
+ outro(`Done ✅`)
73
+ exit()
74
74
  }
75
75
  return true
76
76
  }