@capgo/cli 4.12.12 → 4.12.14-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/autofix.yml +25 -0
- package/CHANGELOG.md +9 -0
- package/bun.lockb +0 -0
- package/bunfig.toml +2 -0
- package/dist/index.js +40559 -50832
- package/package.json +22 -24
- package/src/api/app.ts +5 -5
- package/src/api/channels.ts +12 -12
- package/src/api/devices_override.ts +8 -8
- package/src/api/update.ts +2 -2
- package/src/api/versions.ts +10 -9
- package/src/app/add.ts +21 -22
- package/src/app/debug.ts +53 -54
- package/src/app/delete.ts +20 -20
- package/src/app/info.ts +34 -24
- package/src/app/list.ts +11 -11
- package/src/app/set.ts +16 -16
- package/src/bundle/check.ts +10 -10
- package/src/bundle/cleanup.ts +27 -27
- package/src/bundle/compatibility.ts +8 -8
- package/src/bundle/decrypt.ts +8 -8
- package/src/bundle/delete.ts +14 -15
- package/src/bundle/encrypt.ts +13 -13
- package/src/bundle/list.ts +11 -12
- package/src/bundle/unlink.ts +15 -13
- package/src/bundle/upload.ts +93 -86
- package/src/bundle/zip.ts +23 -21
- package/src/channel/add.ts +14 -14
- package/src/channel/currentBundle.ts +13 -13
- package/src/channel/delete.ts +13 -13
- package/src/channel/list.ts +11 -11
- package/src/channel/set.ts +28 -26
- package/src/config/index.ts +156 -0
- package/src/index.ts +6 -3
- package/src/init.ts +22 -22
- package/src/key.ts +45 -46
- package/src/login.ts +10 -10
- package/src/user/account.ts +3 -3
- package/src/utils.ts +119 -150
- package/tsconfig.json +1 -1
- package/vercel-ncc.js +18 -0
package/src/app/debug.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { exit } from 'node:process'
|
|
2
2
|
import ky from 'ky'
|
|
3
|
-
import * as p from '@clack/prompts'
|
|
4
3
|
import { program } from 'commander'
|
|
5
4
|
import type LogSnag from 'logsnag'
|
|
5
|
+
import { confirm as confirmC, intro, isCancel, log, outro, spinner } from '@clack/prompts'
|
|
6
6
|
import type { Database } from '../types/supabase.types'
|
|
7
7
|
import { checkAppExistsAndHasPermissionOrgErr } from '../api/app'
|
|
8
8
|
import { checkLatest } from '../api/update'
|
|
@@ -30,9 +30,9 @@ export async function markSnag(channel: string, orgId: string, snag: LogSnag, ev
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
export async function cancelCommand(channel: string, command: boolean | symbol, orgId: string, snag: LogSnag) {
|
|
33
|
-
if (
|
|
33
|
+
if (isCancel(command)) {
|
|
34
34
|
await markSnag(channel, orgId, snag, 'canceled', '🤷')
|
|
35
|
-
|
|
35
|
+
exit()
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
@@ -77,103 +77,103 @@ export async function getStats(apikey: string, query: QueryStats, after: string
|
|
|
77
77
|
return dataD
|
|
78
78
|
}
|
|
79
79
|
catch (error) {
|
|
80
|
-
|
|
80
|
+
log.error(`Cannot get stats ${formatError(error)}`)
|
|
81
81
|
}
|
|
82
82
|
return []
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
async function displayError(data: LogData, channel: string, orgId: string, snag: LogSnag, baseUrl: string) {
|
|
86
|
-
|
|
86
|
+
log.info(`Log from Device: ${data.device_id}`)
|
|
87
87
|
if (data.action === 'get') {
|
|
88
|
-
|
|
88
|
+
log.info('Update Sent your your device, wait until event download complete')
|
|
89
89
|
await markSnag(channel, orgId, snag, 'done')
|
|
90
90
|
}
|
|
91
91
|
else if (data.action.startsWith('download_')) {
|
|
92
92
|
const action = data.action.split('_')[1]
|
|
93
93
|
if (action === 'complete') {
|
|
94
|
-
|
|
94
|
+
log.info('Your bundle has been downloaded on your device, background the app now and open it again to see the update')
|
|
95
95
|
await markSnag(channel, orgId, snag, 'downloaded')
|
|
96
96
|
}
|
|
97
97
|
else if (action === 'fail') {
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
log.error('Your bundle has failed to download on your device.')
|
|
99
|
+
log.error('Please check if you have network connection and try again')
|
|
100
100
|
}
|
|
101
101
|
else {
|
|
102
|
-
|
|
102
|
+
log.info(`Your bundle is downloading ${action}% ...`)
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
else if (data.action === 'set') {
|
|
106
|
-
|
|
106
|
+
log.info('Your bundle has been set on your device ❤️')
|
|
107
107
|
await markSnag(channel, orgId, snag, 'set')
|
|
108
108
|
return false
|
|
109
109
|
}
|
|
110
110
|
else if (data.action === 'NoChannelOrOverride') {
|
|
111
|
-
|
|
111
|
+
log.error(`No default channel or override (channel/device) found, please create it here ${baseUrl}`)
|
|
112
112
|
}
|
|
113
113
|
else if (data.action === 'needPlanUpgrade') {
|
|
114
|
-
|
|
114
|
+
log.error('Your are out of quota, please upgrade your plan here https://web.capgo.app/dashboard/settings/plans')
|
|
115
115
|
}
|
|
116
116
|
else if (data.action === 'missingBundle') {
|
|
117
|
-
|
|
117
|
+
log.error('Your bundle is missing, please check how you build your app')
|
|
118
118
|
}
|
|
119
119
|
else if (data.action === 'noNew') {
|
|
120
|
-
|
|
121
|
-
|
|
120
|
+
log.error(`The version number you uploaded to your default channel in Capgo, is the same as the present in the device ${data.device_id}.`)
|
|
121
|
+
log.error(`To fix it, ensure the variable:
|
|
122
122
|
- iOS: keyCFBundleShortVersionString or MARKETING_VERSION
|
|
123
123
|
- Android: versionName
|
|
124
124
|
Are lower than the version number you uploaded to Capgo.`)
|
|
125
|
-
|
|
125
|
+
log.error('More info here: https://capgo.app/blog/how-version-work-in-capgo/#versioning-system')
|
|
126
126
|
}
|
|
127
127
|
else if (data.action === 'disablePlatformIos') {
|
|
128
|
-
|
|
128
|
+
log.error(`iOS is disabled in the default channel and your device ${data.device_id} is an iOS device ${baseUrl}`)
|
|
129
129
|
}
|
|
130
130
|
else if (data.action === 'disablePlatformAndroid') {
|
|
131
|
-
|
|
131
|
+
log.error(`Android is disabled in the default channel and your device ${data.device_id} is an Android device ${baseUrl}`)
|
|
132
132
|
}
|
|
133
133
|
else if (data.action === 'disableAutoUpdateToMajor') {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
134
|
+
log.error(`The version number you uploaded to your default channel in Capgo, is a major version higher (ex: 1.0.0 in device to 2.0.0 in Capgo) than the present in the device ${data.device_id}.`)
|
|
135
|
+
log.error('Capgo is set by default to protect you from this, and avoid sending breaking changes incompatible with the native code present in the device.')
|
|
136
|
+
log.error(`To fix it, ensure the variable:
|
|
137
137
|
- iOS: keyCFBundleShortVersionString or MARKETING_VERSION
|
|
138
138
|
- Android: versionName
|
|
139
139
|
Are lower than the version number you uploaded to Capgo.`)
|
|
140
|
-
|
|
140
|
+
log.error('More info here: https://capgo.app/blog/how-version-work-in-capgo/#versioning-system')
|
|
141
141
|
}
|
|
142
142
|
else if (data.action === 'disableAutoUpdateUnderNative') {
|
|
143
|
-
|
|
144
|
-
|
|
143
|
+
log.error(`The version number you uploaded to your default channel in Capgo, is lower than the present in the device ${data.device_id}.`)
|
|
144
|
+
log.error(`To fix it, ensure the variable:
|
|
145
145
|
- iOS: keyCFBundleShortVersionString or MARKETING_VERSION
|
|
146
146
|
- Android: versionName
|
|
147
147
|
Are lower than the version number you uploaded to Capgo.`)
|
|
148
|
-
|
|
148
|
+
log.error('More info here: https://capgo.app/blog/how-version-work-in-capgo/#versioning-system')
|
|
149
149
|
}
|
|
150
150
|
else if (data.action === 'disableDevBuild') {
|
|
151
|
-
|
|
152
|
-
|
|
151
|
+
log.error(`Dev build is disabled in the default channel. ${baseUrl}`)
|
|
152
|
+
log.error('Set your channel to allow it if you wanna test your app')
|
|
153
153
|
}
|
|
154
154
|
else if (data.action === 'disableEmulator') {
|
|
155
|
-
|
|
156
|
-
|
|
155
|
+
log.error(`Emulator is disabled in the default channel. ${baseUrl}`)
|
|
156
|
+
log.error('Set your channel to allow it if you wanna test your app')
|
|
157
157
|
}
|
|
158
158
|
else if (data.action === 'cannotGetBundle') {
|
|
159
|
-
|
|
160
|
-
|
|
159
|
+
log.error(`We cannot get your bundle from the default channel. ${baseUrl}`)
|
|
160
|
+
log.error('Are you sure your default channel has a bundle set?')
|
|
161
161
|
}
|
|
162
162
|
else if (data.action === 'set_fail') {
|
|
163
|
-
|
|
163
|
+
log.error(`Your bundle seems to be corrupted, try to download from ${baseUrl} to identify the issue`)
|
|
164
164
|
}
|
|
165
165
|
else if (data.action === 'reset') {
|
|
166
|
-
|
|
166
|
+
log.error('Your device has been reset to the builtin bundle, did notifyAppReady() is present in the code builded and uploaded to Capgo ?')
|
|
167
167
|
}
|
|
168
168
|
else if (data.action === 'update_fail') {
|
|
169
|
-
|
|
170
|
-
|
|
169
|
+
log.error('Your bundle has been installed but failed to call notifyAppReady()')
|
|
170
|
+
log.error('Please check if you have network connection and try again')
|
|
171
171
|
}
|
|
172
172
|
else if (data.action === 'checksum_fail') {
|
|
173
|
-
|
|
173
|
+
log.error('Your bundle has failed to validate checksum, please check your code and send it again to Capgo')
|
|
174
174
|
}
|
|
175
175
|
else {
|
|
176
|
-
|
|
176
|
+
log.error(`Log from Capgo ${data.action}`)
|
|
177
177
|
}
|
|
178
178
|
return true
|
|
179
179
|
}
|
|
@@ -194,7 +194,7 @@ export async function waitLog(channel: string, apikey: string, appId: string, sn
|
|
|
194
194
|
rangeStart: new Date().toISOString(),
|
|
195
195
|
}
|
|
196
196
|
let after: string | null = null
|
|
197
|
-
const s =
|
|
197
|
+
const s = spinner()
|
|
198
198
|
s.start(`Waiting for logs (Expect delay of 30 sec)`)
|
|
199
199
|
while (loop) {
|
|
200
200
|
await wait(5000)
|
|
@@ -213,20 +213,19 @@ export async function waitLog(channel: string, apikey: string, appId: string, sn
|
|
|
213
213
|
}
|
|
214
214
|
|
|
215
215
|
export async function debugApp(appId: string, options: OptionsBaseDebug) {
|
|
216
|
-
|
|
216
|
+
intro(`Debug Live update in Capgo`)
|
|
217
217
|
|
|
218
218
|
await checkLatest()
|
|
219
219
|
options.apikey = options.apikey || findSavedKey()
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
appId = appId || config?.app?.appId
|
|
220
|
+
const extConfig = await getConfig()
|
|
221
|
+
appId = appId || extConfig?.config?.appId
|
|
223
222
|
const deviceId = options.device
|
|
224
223
|
if (!options.apikey) {
|
|
225
|
-
|
|
224
|
+
log.error(`Missing API key, you need to provide an API key to delete your app`)
|
|
226
225
|
program.error('')
|
|
227
226
|
}
|
|
228
227
|
if (!appId) {
|
|
229
|
-
|
|
228
|
+
log.error('Missing argument, you need to provide a appId, or be in a capacitor project')
|
|
230
229
|
program.error('')
|
|
231
230
|
}
|
|
232
231
|
|
|
@@ -235,25 +234,25 @@ export async function debugApp(appId: string, options: OptionsBaseDebug) {
|
|
|
235
234
|
|
|
236
235
|
const userId = await verifyUser(supabase, options.apikey)
|
|
237
236
|
|
|
238
|
-
|
|
237
|
+
log.info(`Getting active bundle in Capgo`)
|
|
239
238
|
|
|
240
239
|
// Check we have app access to this appId
|
|
241
240
|
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, OrganizationPerm.admin)
|
|
242
241
|
|
|
243
242
|
const orgId = await getOrganizationId(supabase, appId)
|
|
244
243
|
|
|
245
|
-
const doRun = await
|
|
244
|
+
const doRun = await confirmC({ message: `Automatic check if update working in device ?` })
|
|
246
245
|
await cancelCommand('debug', doRun, userId, snag)
|
|
247
246
|
if (doRun) {
|
|
248
|
-
|
|
247
|
+
log.info(`Wait logs sent to Capgo from ${appId} device, Please open your app 💪`)
|
|
249
248
|
await waitLog('debug', options.apikey, appId, snag, orgId, deviceId)
|
|
250
|
-
|
|
249
|
+
outro(`Done ✅`)
|
|
251
250
|
}
|
|
252
251
|
else {
|
|
253
252
|
// const appIdUrl = convertAppName(appId)
|
|
254
|
-
//
|
|
255
|
-
|
|
253
|
+
// log.info(`Check logs in https://web.capgo.app/app/p/${appIdUrl}/logs to see if update works.`)
|
|
254
|
+
outro(`Canceled ❌`)
|
|
256
255
|
}
|
|
257
|
-
|
|
258
|
-
|
|
256
|
+
outro(`Done ✅`)
|
|
257
|
+
exit()
|
|
259
258
|
}
|
package/src/app/delete.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { exit } from 'node:process'
|
|
2
2
|
import { program } from 'commander'
|
|
3
|
-
import
|
|
3
|
+
import { intro, isCancel, log, outro, select } from '@clack/prompts'
|
|
4
4
|
import { checkAppExistsAndHasPermissionOrgErr } from '../api/app'
|
|
5
5
|
import type { OptionsBase } from '../utils'
|
|
6
6
|
import { OrganizationPerm, createSupabaseClient, findSavedKey, formatError, getConfig, getOrganizationId, useLogSnag, verifyUser } from '../utils'
|
|
7
7
|
|
|
8
8
|
export async function deleteApp(appId: string, options: OptionsBase) {
|
|
9
|
-
|
|
9
|
+
intro(`Deleting`)
|
|
10
10
|
options.apikey = options.apikey || findSavedKey()
|
|
11
|
-
const
|
|
12
|
-
appId = appId || config?.
|
|
11
|
+
const extConfig = await getConfig()
|
|
12
|
+
appId = appId || extConfig?.config?.appId
|
|
13
13
|
const snag = useLogSnag()
|
|
14
14
|
|
|
15
15
|
if (!options.apikey) {
|
|
16
|
-
|
|
16
|
+
log.error('Missing API key, you need to provide a API key to upload your bundle')
|
|
17
17
|
program.error('')
|
|
18
18
|
}
|
|
19
19
|
if (!appId) {
|
|
20
|
-
|
|
20
|
+
log.error('Missing argument, you need to provide a appId, or be in a capacitor project')
|
|
21
21
|
program.error('')
|
|
22
22
|
}
|
|
23
23
|
const supabase = await createSupabaseClient(options.apikey)
|
|
@@ -37,11 +37,11 @@ export async function deleteApp(appId: string, options: OptionsBase) {
|
|
|
37
37
|
// We are dealing with a member user that is not the owner
|
|
38
38
|
// Deleting the app is not recomended at this stage
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
log.warn('Deleting the app is not recomended for users that are not the organization owner')
|
|
41
|
+
log.warn('You are invited as a super_admin but your are not the owner')
|
|
42
|
+
log.warn('It\'s strongly recomended that you do not continue!')
|
|
43
43
|
|
|
44
|
-
const shouldContinue = await
|
|
44
|
+
const shouldContinue = await select({
|
|
45
45
|
message: 'Do you want to continue?',
|
|
46
46
|
options: [
|
|
47
47
|
{
|
|
@@ -55,13 +55,13 @@ export async function deleteApp(appId: string, options: OptionsBase) {
|
|
|
55
55
|
],
|
|
56
56
|
})
|
|
57
57
|
|
|
58
|
-
if (
|
|
59
|
-
|
|
58
|
+
if (isCancel(shouldContinue) || shouldContinue === 'no') {
|
|
59
|
+
log.error('Canceled deleting the app, exiting')
|
|
60
60
|
program.error('')
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
else if (appOwnerError) {
|
|
64
|
-
|
|
64
|
+
log.warn(`Cannot get the app owner ${formatError(appOwnerError)}`)
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
const { error } = await supabase
|
|
@@ -70,7 +70,7 @@ export async function deleteApp(appId: string, options: OptionsBase) {
|
|
|
70
70
|
.remove([`org/${appOwner?.owner_org.id}/${appId}/icon`])
|
|
71
71
|
if (error) {
|
|
72
72
|
console.error(error, `images/org/${appOwner?.owner_org.id}/${appId}`)
|
|
73
|
-
|
|
73
|
+
log.error('Could not delete app logo')
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
// TODO: make the version delete in R2 too
|
|
@@ -79,7 +79,7 @@ export async function deleteApp(appId: string, options: OptionsBase) {
|
|
|
79
79
|
.from(`apps/${appId}/${userId}`)
|
|
80
80
|
.remove(['versions'])
|
|
81
81
|
if (delError)
|
|
82
|
-
|
|
82
|
+
log.error('Could not delete app version')
|
|
83
83
|
// We should not care too much, most is in r2 anyways :/
|
|
84
84
|
// program.error('')
|
|
85
85
|
|
|
@@ -90,7 +90,7 @@ export async function deleteApp(appId: string, options: OptionsBase) {
|
|
|
90
90
|
// .eq('user_id', userId)
|
|
91
91
|
|
|
92
92
|
if (dbError) {
|
|
93
|
-
|
|
93
|
+
log.error('Could not delete app')
|
|
94
94
|
program.error('')
|
|
95
95
|
}
|
|
96
96
|
const orgId = await getOrganizationId(supabase, appId)
|
|
@@ -104,7 +104,7 @@ export async function deleteApp(appId: string, options: OptionsBase) {
|
|
|
104
104
|
},
|
|
105
105
|
notify: false,
|
|
106
106
|
}).catch()
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
107
|
+
log.success(`App deleted in Capgo`)
|
|
108
|
+
outro('Done ✅')
|
|
109
|
+
exit()
|
|
110
110
|
}
|
package/src/app/info.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import os from 'node:os'
|
|
4
|
-
import process from 'node:process'
|
|
1
|
+
import { exit, version as nodeVersion } from 'node:process'
|
|
2
|
+
import { platform, version } from 'node:os'
|
|
5
3
|
import getLatest from 'get-latest-version'
|
|
6
|
-
import
|
|
4
|
+
import { log, spinner } from '@clack/prompts'
|
|
5
|
+
import { getConfig, readPackageJson } from '../utils'
|
|
7
6
|
import pack from '../../package.json'
|
|
8
7
|
|
|
9
8
|
async function getLatestDependencies(installedDependencies: { [key: string]: string }) {
|
|
@@ -27,11 +26,6 @@ async function getLatestDependencies(installedDependencies: { [key: string]: str
|
|
|
27
26
|
return latestDependencies
|
|
28
27
|
}
|
|
29
28
|
|
|
30
|
-
async function readPackageJson() {
|
|
31
|
-
const packageJson = readFileSync(join(process.cwd(), 'package.json'))
|
|
32
|
-
return JSON.parse(packageJson as any)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
29
|
async function getInstalledDependencies() {
|
|
36
30
|
const { dependencies } = await readPackageJson()
|
|
37
31
|
const installedDependencies: { [key: string]: string } = {
|
|
@@ -51,39 +45,55 @@ async function getInstalledDependencies() {
|
|
|
51
45
|
}
|
|
52
46
|
|
|
53
47
|
export async function getInfo() {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
48
|
+
log.warn(' 💊 Capgo Doctor 💊')
|
|
49
|
+
// app name
|
|
50
|
+
const extConfig = await getConfig()
|
|
51
|
+
const pkg = await readPackageJson()
|
|
52
|
+
// create bundle name format : 1.0.0-beta.x where x is a uuid
|
|
53
|
+
const appVersion = extConfig?.config?.plugins?.CapacitorUpdater?.version
|
|
54
|
+
|| pkg?.version
|
|
55
|
+
const appName = extConfig?.config?.appName || ''
|
|
56
|
+
log.info(` App Name: ${appName}`)
|
|
57
|
+
// app id
|
|
58
|
+
const appId = extConfig?.config?.appId || ''
|
|
59
|
+
log.info(` App ID: ${appId}`)
|
|
60
|
+
// app version
|
|
61
|
+
log.info(` App Version: ${appVersion}`)
|
|
62
|
+
// webdir
|
|
63
|
+
const webDir = extConfig?.config?.webDir || ''
|
|
64
|
+
log.info(` Web Dir: ${webDir}`)
|
|
65
|
+
// os
|
|
66
|
+
log.info(` OS: ${platform()} ${version()}`)
|
|
67
|
+
log.info(` Node: ${nodeVersion}`)
|
|
68
|
+
log.info(' Installed Dependencies:')
|
|
58
69
|
const installedDependencies = await getInstalledDependencies()
|
|
59
70
|
if (Object.keys(installedDependencies).length === 0) {
|
|
60
71
|
// display in red color in shell with console log
|
|
61
|
-
|
|
62
|
-
|
|
72
|
+
log.warning('\x1B[31m%s\x1B[0m 🚨 No dependencies found')
|
|
73
|
+
exit(1)
|
|
63
74
|
}
|
|
64
75
|
for (const dependency in installedDependencies) {
|
|
65
76
|
if (Object.prototype.hasOwnProperty.call(installedDependencies, dependency)) {
|
|
66
77
|
const installedVersion = (installedDependencies as any)[dependency]
|
|
67
|
-
|
|
78
|
+
log.info(` ${dependency}: ${installedVersion}`)
|
|
68
79
|
}
|
|
69
80
|
}
|
|
70
|
-
|
|
71
|
-
const s = p.spinner()
|
|
81
|
+
const s = spinner()
|
|
72
82
|
s.start(`Running: Loading latest dependencies`)
|
|
73
83
|
const latestDependencies = await getLatestDependencies(installedDependencies)
|
|
74
84
|
s.stop(`Latest Dependencies:`)
|
|
75
85
|
for (const dependency in latestDependencies) {
|
|
76
86
|
if (Object.prototype.hasOwnProperty.call(latestDependencies, dependency)) {
|
|
77
87
|
const latestVersion = (latestDependencies as any)[dependency]
|
|
78
|
-
|
|
88
|
+
log.info(` ${dependency}: ${latestVersion}`)
|
|
79
89
|
}
|
|
80
90
|
}
|
|
81
91
|
if (JSON.stringify(installedDependencies) !== JSON.stringify(latestDependencies)) {
|
|
82
92
|
// display in red color in shell with console log
|
|
83
|
-
|
|
84
|
-
|
|
93
|
+
log.warn('\x1B[31m🚨 Some dependencies are not up to date\x1B[0m')
|
|
94
|
+
exit(1)
|
|
85
95
|
}
|
|
86
96
|
// display in green color in shell with console log
|
|
87
|
-
|
|
88
|
-
|
|
97
|
+
log.success('\x1B[32m✅ All dependencies are up to date\x1B[0m')
|
|
98
|
+
exit()
|
|
89
99
|
}
|
package/src/app/list.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { exit } from 'node:process'
|
|
2
2
|
import { program } from 'commander'
|
|
3
3
|
import { Table } from 'console-table-printer'
|
|
4
4
|
import type { SupabaseClient } from '@supabase/supabase-js'
|
|
5
|
-
import
|
|
5
|
+
import { intro, log, outro } from '@clack/prompts'
|
|
6
6
|
import type { Database } from '../types/supabase.types'
|
|
7
7
|
import type { OptionsBase } from '../utils'
|
|
8
8
|
import { createSupabaseClient, findSavedKey, getHumanDate, verifyUser } from '../utils'
|
|
@@ -10,8 +10,8 @@ import { checkLatest } from '../api/update'
|
|
|
10
10
|
|
|
11
11
|
function displayApp(data: Database['public']['Tables']['apps']['Row'][]) {
|
|
12
12
|
if (!data.length) {
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
log.error('No apps found')
|
|
14
|
+
exit(1)
|
|
15
15
|
}
|
|
16
16
|
const t = new Table({
|
|
17
17
|
title: 'Apps',
|
|
@@ -27,7 +27,7 @@ function displayApp(data: Database['public']['Tables']['apps']['Row'][]) {
|
|
|
27
27
|
})
|
|
28
28
|
})
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
log.success(t.render())
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
export async function getActiveApps(supabase: SupabaseClient<Database>) {
|
|
@@ -38,14 +38,14 @@ export async function getActiveApps(supabase: SupabaseClient<Database>) {
|
|
|
38
38
|
.order('created_at', { ascending: false })
|
|
39
39
|
|
|
40
40
|
if (vError) {
|
|
41
|
-
|
|
41
|
+
log.error('Apps not found')
|
|
42
42
|
program.error('')
|
|
43
43
|
}
|
|
44
44
|
return data
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
export async function listApp(options: OptionsBase) {
|
|
48
|
-
|
|
48
|
+
intro(`List apps in Capgo`)
|
|
49
49
|
|
|
50
50
|
await checkLatest()
|
|
51
51
|
options.apikey = options.apikey || findSavedKey()
|
|
@@ -54,14 +54,14 @@ export async function listApp(options: OptionsBase) {
|
|
|
54
54
|
|
|
55
55
|
await verifyUser(supabase, options.apikey, ['write', 'all', 'read', 'upload'])
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
log.info(`Getting active bundle in Capgo`)
|
|
58
58
|
|
|
59
59
|
// Get all active app versions we might possibly be able to cleanup
|
|
60
60
|
const allApps = await getActiveApps(supabase)
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
log.info(`Active app in Capgo: ${allApps?.length}`)
|
|
63
63
|
|
|
64
64
|
displayApp(allApps)
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
outro(`Done ✅`)
|
|
66
|
+
exit()
|
|
67
67
|
}
|
package/src/app/set.ts
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto'
|
|
2
2
|
import { existsSync, readFileSync } from 'node:fs'
|
|
3
|
-
import
|
|
3
|
+
import { exit } from 'node:process'
|
|
4
4
|
import mime from 'mime'
|
|
5
5
|
import { program } from 'commander'
|
|
6
|
-
import
|
|
6
|
+
import { intro, log, outro } from '@clack/prompts'
|
|
7
7
|
import type { Options } from '../api/app'
|
|
8
8
|
import { checkAppExistsAndHasPermissionOrgErr, newIconPath } from '../api/app'
|
|
9
9
|
import { OrganizationPerm, createSupabaseClient, findSavedKey, formatError, getConfig, getOrganization, verifyUser } from '../utils'
|
|
10
10
|
|
|
11
11
|
export async function setApp(appId: string, options: Options) {
|
|
12
|
-
|
|
12
|
+
intro(`Set app`)
|
|
13
13
|
options.apikey = options.apikey || findSavedKey()
|
|
14
|
-
const
|
|
15
|
-
appId = appId || config?.
|
|
14
|
+
const extConfig = await getConfig()
|
|
15
|
+
appId = appId || extConfig?.config?.appId
|
|
16
16
|
|
|
17
17
|
if (!options.apikey) {
|
|
18
|
-
|
|
18
|
+
log.error(`Missing API key, you need to provide a API key to upload your bundle`)
|
|
19
19
|
program.error(``)
|
|
20
20
|
}
|
|
21
21
|
if (!appId) {
|
|
22
|
-
|
|
22
|
+
log.error('Missing argument, you need to provide a appId, or be in a capacitor project')
|
|
23
23
|
program.error(``)
|
|
24
24
|
}
|
|
25
25
|
const supabase = await createSupabaseClient(options.apikey)
|
|
@@ -33,11 +33,11 @@ export async function setApp(appId: string, options: Options) {
|
|
|
33
33
|
const { name, icon, retention } = options
|
|
34
34
|
|
|
35
35
|
if (retention && Number.isNaN(Number(retention))) {
|
|
36
|
-
|
|
36
|
+
log.error(`retention value must be a number`)
|
|
37
37
|
program.error(``)
|
|
38
38
|
}
|
|
39
39
|
else if (retention && retention < 0) {
|
|
40
|
-
|
|
40
|
+
log.error(`retention value cannot be less than 0`)
|
|
41
41
|
program.error(``)
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -50,16 +50,16 @@ export async function setApp(appId: string, options: Options) {
|
|
|
50
50
|
iconBuff = readFileSync(icon)
|
|
51
51
|
const contentType = mime.getType(icon)
|
|
52
52
|
iconType = contentType || 'image/png'
|
|
53
|
-
|
|
53
|
+
log.warn(`Found app icon ${icon}`)
|
|
54
54
|
}
|
|
55
55
|
else if (existsSync(newIconPath)) {
|
|
56
56
|
iconBuff = readFileSync(newIconPath)
|
|
57
57
|
const contentType = mime.getType(newIconPath)
|
|
58
58
|
iconType = contentType || 'image/png'
|
|
59
|
-
|
|
59
|
+
log.warn(`Found app icon ${newIconPath}`)
|
|
60
60
|
}
|
|
61
61
|
else {
|
|
62
|
-
|
|
62
|
+
log.warn(`Cannot find app icon in any of the following locations: ${icon}, ${newIconPath}`)
|
|
63
63
|
}
|
|
64
64
|
if (iconBuff && iconType) {
|
|
65
65
|
const { error } = await supabase.storage
|
|
@@ -68,7 +68,7 @@ export async function setApp(appId: string, options: Options) {
|
|
|
68
68
|
contentType: iconType,
|
|
69
69
|
})
|
|
70
70
|
if (error) {
|
|
71
|
-
|
|
71
|
+
log.error(`Could not set app ${formatError(error)}`)
|
|
72
72
|
program.error(``)
|
|
73
73
|
}
|
|
74
74
|
const { data: signedURLData } = await supabase
|
|
@@ -88,9 +88,9 @@ export async function setApp(appId: string, options: Options) {
|
|
|
88
88
|
.eq('app_id', appId)
|
|
89
89
|
.eq('user_id', userId)
|
|
90
90
|
if (dbError) {
|
|
91
|
-
|
|
91
|
+
log.error(`Could not set app ${formatError(dbError)}`)
|
|
92
92
|
program.error(``)
|
|
93
93
|
}
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
outro(`Done ✅`)
|
|
95
|
+
exit()
|
|
96
96
|
}
|
package/src/bundle/check.ts
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { readFileSync, readdirSync, statSync } from 'node:fs'
|
|
2
|
+
import { extname, join } from 'node:path'
|
|
3
3
|
|
|
4
4
|
function searchInFile(filePath: string, searchString: string) {
|
|
5
|
-
const content =
|
|
5
|
+
const content = readFileSync(filePath, 'utf8')
|
|
6
6
|
return content.includes(searchString)
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export function searchInDirectory(dirPath: string, searchString: string) {
|
|
10
|
-
const files =
|
|
10
|
+
const files = readdirSync(dirPath)
|
|
11
11
|
for (const file of files) {
|
|
12
|
-
const filePath =
|
|
13
|
-
const stats =
|
|
12
|
+
const filePath = join(dirPath, file)
|
|
13
|
+
const stats = statSync(filePath)
|
|
14
14
|
|
|
15
15
|
if (stats.isDirectory()) {
|
|
16
16
|
if (searchInDirectory(filePath, searchString))
|
|
17
17
|
return true
|
|
18
18
|
}
|
|
19
|
-
else if (stats.isFile() &&
|
|
19
|
+
else if (stats.isFile() && extname(filePath) === '.js') {
|
|
20
20
|
if (searchInFile(filePath, searchString))
|
|
21
21
|
return true
|
|
22
22
|
}
|
|
@@ -27,10 +27,10 @@ export function searchInDirectory(dirPath: string, searchString: string) {
|
|
|
27
27
|
|
|
28
28
|
export function checkIndexPosition(dirPath: string): boolean {
|
|
29
29
|
// look for index.html in the root folder or if there only one folder in the root folder look for index.html in this folder
|
|
30
|
-
const files =
|
|
30
|
+
const files = readdirSync(dirPath)
|
|
31
31
|
if (files.length === 1) {
|
|
32
|
-
const filePath =
|
|
33
|
-
const stats =
|
|
32
|
+
const filePath = join(dirPath, files[0])
|
|
33
|
+
const stats = statSync(filePath)
|
|
34
34
|
if (stats.isDirectory())
|
|
35
35
|
return checkIndexPosition(filePath)
|
|
36
36
|
}
|