@capgo/cli 5.0.0-alpha.3 → 5.0.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.
Files changed (59) hide show
  1. package/README.md +197 -37
  2. package/dist/index.js +327 -65172
  3. package/dist/package.json +83 -0
  4. package/package.json +48 -61
  5. package/.eslintignore +0 -4
  6. package/.github/FUNDING.yml +0 -1
  7. package/.github/workflows/build.yml +0 -46
  8. package/.github/workflows/bump_version.yml +0 -56
  9. package/.github/workflows/test.yml +0 -30
  10. package/.prettierignore +0 -6
  11. package/.vscode/launch.json +0 -23
  12. package/.vscode/settings.json +0 -5
  13. package/.vscode/tasks.json +0 -42
  14. package/CHANGELOG.md +0 -2727
  15. package/build.mjs +0 -23
  16. package/bun.lockb +0 -0
  17. package/capacitor.config.ts +0 -33
  18. package/crypto_explained.png +0 -0
  19. package/eslint.config.js +0 -3
  20. package/renovate.json +0 -23
  21. package/src/api/app.ts +0 -75
  22. package/src/api/channels.ts +0 -142
  23. package/src/api/crypto.ts +0 -121
  24. package/src/api/devices_override.ts +0 -41
  25. package/src/api/update.ts +0 -12
  26. package/src/api/versions.ts +0 -98
  27. package/src/app/add.ts +0 -154
  28. package/src/app/debug.ts +0 -214
  29. package/src/app/delete.ts +0 -68
  30. package/src/app/info.ts +0 -87
  31. package/src/app/list.ts +0 -63
  32. package/src/app/set.ts +0 -94
  33. package/src/bundle/check.ts +0 -42
  34. package/src/bundle/cleanup.ts +0 -128
  35. package/src/bundle/compatibility.ts +0 -70
  36. package/src/bundle/decrypt.ts +0 -65
  37. package/src/bundle/delete.ts +0 -53
  38. package/src/bundle/encrypt.ts +0 -69
  39. package/src/bundle/list.ts +0 -43
  40. package/src/bundle/unlink.ts +0 -80
  41. package/src/bundle/upload.ts +0 -434
  42. package/src/bundle/zip.ts +0 -137
  43. package/src/channel/add.ts +0 -73
  44. package/src/channel/currentBundle.ts +0 -73
  45. package/src/channel/delete.ts +0 -51
  46. package/src/channel/list.ts +0 -49
  47. package/src/channel/set.ts +0 -171
  48. package/src/index.ts +0 -285
  49. package/src/init.ts +0 -301
  50. package/src/key.ts +0 -158
  51. package/src/login.ts +0 -66
  52. package/src/types/capacitor__cli.d.ts +0 -6
  53. package/src/types/supabase.types.ts +0 -2065
  54. package/src/utils.ts +0 -719
  55. package/test/chunk_convert.ts +0 -28
  56. package/test/data.ts +0 -18769
  57. package/test/test_headers_rls.ts +0 -24
  58. package/test/test_semver.ts +0 -13
  59. package/tsconfig.json +0 -39
package/src/app/add.ts DELETED
@@ -1,154 +0,0 @@
1
- import { randomUUID } from 'node:crypto'
2
- import { existsSync, readFileSync } from 'node:fs'
3
- import process from 'node:process'
4
- import mime from 'mime'
5
- import { program } from 'commander'
6
- import * as p from '@clack/prompts'
7
- import { checkLatest } from '../api/update'
8
- import type { Options } from '../api/app'
9
- import { checkAppExists, newIconPath } from '../api/app'
10
- import {
11
- checkPlanValid,
12
- createSupabaseClient,
13
- findSavedKey,
14
- formatError,
15
- getConfig,
16
- useLogSnag,
17
- verifyUser,
18
- } from '../utils'
19
-
20
- export async function addApp(appId: string, options: Options, throwErr = true) {
21
- if (throwErr)
22
- p.intro(`Adding`)
23
-
24
- await checkLatest()
25
- options.apikey = options.apikey || findSavedKey()
26
- const config = await getConfig()
27
- appId = appId || config?.app?.appId
28
- const snag = useLogSnag()
29
-
30
- if (!options.apikey) {
31
- p.log.error(`Missing API key, you need to provide a API key to upload your bundle`)
32
- program.error('')
33
- }
34
- if (!appId) {
35
- p.log.error('Missing argument, you need to provide a appId, or be in a capacitor project')
36
- program.error('')
37
- }
38
- const supabase = await createSupabaseClient(options.apikey)
39
-
40
- const userId = await verifyUser(supabase, options.apikey, ['write', 'all'])
41
-
42
- await checkPlanValid(supabase, userId, options.apikey, undefined, false)
43
-
44
- // Check we have app access to this appId
45
- const appExist = await checkAppExists(supabase, appId)
46
- if (throwErr && appExist) {
47
- p.log.error(`App ${appId} already exist`)
48
- program.error('')
49
- }
50
- else if (appExist) {
51
- return true
52
- }
53
-
54
- let { name, icon } = options
55
- appId = appId || config?.app?.appId
56
- name = name || config?.app?.appName || 'Unknown'
57
- icon = icon || 'resources/icon.png' // default path for capacitor app
58
- if (!icon || !name) {
59
- p.log.error('Missing argument, you need to provide a appId and a name, or be in a capacitor project')
60
- program.error('')
61
- }
62
- if (throwErr)
63
- p.log.info(`Adding ${appId} to Capgo`)
64
-
65
- let iconBuff
66
- let iconType
67
-
68
- if (icon && existsSync(icon)) {
69
- iconBuff = readFileSync(icon)
70
- const contentType = mime.getType(icon)
71
- iconType = contentType || 'image/png'
72
- p.log.warn(`Found app icon ${icon}`)
73
- }
74
- else if (existsSync(newIconPath)) {
75
- iconBuff = readFileSync(newIconPath)
76
- const contentType = mime.getType(newIconPath)
77
- iconType = contentType || 'image/png'
78
- p.log.warn(`Found app icon ${newIconPath}`)
79
- }
80
- else {
81
- p.log.warn(`Cannot find app icon in any of the following locations: ${icon}, ${newIconPath}`)
82
- }
83
-
84
- const fileName = `icon_${randomUUID()}`
85
- let signedURL = 'https://xvwzpoazmxkqosrdewyv.supabase.co/storage/v1/object/public/images/capgo.png'
86
-
87
- // upload image if available
88
- if (iconBuff && iconType) {
89
- const { error } = await supabase.storage
90
- .from(`images/${userId}/${appId}`)
91
- .upload(fileName, iconBuff, {
92
- contentType: iconType,
93
- })
94
- if (error) {
95
- p.log.error(`Could not add app ${formatError(error)}`)
96
- program.error('')
97
- }
98
- const { data: signedURLData } = await supabase
99
- .storage
100
- .from(`images/${userId}/${appId}`)
101
- .getPublicUrl(fileName)
102
- signedURL = signedURLData?.publicUrl || signedURL
103
- }
104
- // add app to db
105
- const { error: dbError } = await supabase
106
- .from('apps')
107
- .insert({
108
- icon_url: signedURL,
109
- user_id: userId,
110
- name,
111
- app_id: appId,
112
- })
113
- if (dbError) {
114
- p.log.error(`Could not add app ${formatError(dbError)}`)
115
- program.error('')
116
- }
117
- const { error: dbVersionError } = await supabase
118
- .from('app_versions')
119
- .insert([{
120
- user_id: userId,
121
- deleted: true,
122
- name: 'unknown',
123
- app_id: appId,
124
- }, {
125
- user_id: userId,
126
- deleted: true,
127
- name: 'builtin',
128
- app_id: appId,
129
- }])
130
- if (dbVersionError) {
131
- p.log.error(`Could not add app ${formatError(dbVersionError)}`)
132
- program.error('')
133
- }
134
- await snag.track({
135
- channel: 'app',
136
- event: 'App Added',
137
- icon: '🎉',
138
- user_id: userId,
139
- tags: {
140
- 'app-id': appId,
141
- },
142
- notify: false,
143
- }).catch()
144
- p.log.success(`App ${appId} added to Capgo. ${throwErr ? 'You can upload a bundle now' : ''}`)
145
- if (throwErr) {
146
- p.outro(`Done ✅`)
147
- process.exit()
148
- }
149
- return true
150
- }
151
-
152
- export async function addCommand(apikey: string, options: Options) {
153
- addApp(apikey, options, true)
154
- }
package/src/app/debug.ts DELETED
@@ -1,214 +0,0 @@
1
- import process from 'node:process'
2
- import * as p from '@clack/prompts'
3
- import type { SupabaseClient } from '@supabase/supabase-js'
4
- import { program } from 'commander'
5
- import type LogSnag from 'logsnag'
6
- import type { Database } from '../types/supabase.types'
7
- import { checkAppExistsAndHasPermissionErr } from '../api/app'
8
- import { checkLatest } from '../api/update'
9
- import { convertAppName, createSupabaseClient, findSavedKey, formatError, getConfig, getLocalConfig, useLogSnag, verifyUser, wait } from '../utils'
10
-
11
- export interface OptionsBaseDebug {
12
- apikey: string
13
- device?: string
14
- }
15
-
16
- export async function markSnag(channel: string, userId: string, snag: LogSnag, event: string, icon = '✅') {
17
- await snag.track({
18
- channel,
19
- event,
20
- icon,
21
- user_id: userId,
22
- notify: false,
23
- }).catch()
24
- }
25
-
26
- export async function cancelCommand(channel: string, command: boolean | symbol, userId: string, snag: LogSnag) {
27
- if (p.isCancel(command)) {
28
- await markSnag(channel, userId, snag, 'canceled', '🤷')
29
- process.exit()
30
- }
31
- }
32
-
33
- interface Order {
34
- key: string
35
- sortable?: 'asc' | 'desc'
36
- }
37
-
38
- interface QueryStats {
39
- appId: string
40
- devicesId?: string[]
41
- search?: string
42
- order?: Order[]
43
- rangeStart?: number
44
- rangeEnd?: number
45
- after?: string
46
- }
47
-
48
- export async function getStats(supabase: SupabaseClient<Database>, query: QueryStats): Promise<Database['public']['Tables']['stats']['Row'] | null> {
49
- try {
50
- const pathStats = 'private/stats'
51
- const res = await supabase.functions.invoke(pathStats, { body: JSON.stringify(query) })
52
- const listData = res.data.data as Database['public']['Tables']['stats']['Row'][]
53
- if (listData?.length > 0)
54
- return listData[0]
55
- }
56
- catch (error) {
57
- p.log.error(`Cannot get stats ${formatError(error)}`)
58
- }
59
- return null
60
- }
61
-
62
- export async function waitLog(channel: string, supabase: SupabaseClient<Database>, appId: string, snag: LogSnag, userId: string, deviceId?: string) {
63
- let loop = true
64
- let now = new Date().toISOString()
65
- const appIdUrl = convertAppName(appId)
66
- const config = await getLocalConfig()
67
- const baseUrl = `${config.hostWeb}/app/p/${appIdUrl}`
68
- await markSnag(channel, userId, snag, 'Use waitlog')
69
- const query: QueryStats = {
70
- appId,
71
- devicesId: deviceId ? [deviceId] : undefined,
72
- order: [{
73
- key: 'created_at',
74
- sortable: 'desc',
75
- }],
76
- rangeStart: 0,
77
- rangeEnd: 1,
78
- after: now,
79
- }
80
- while (loop) {
81
- const data = await getStats(supabase, query)
82
- // console.log('data', data)
83
- if (data) {
84
- p.log.info(`Log from Device: ${data.device_id}`)
85
- if (data.action === 'get') {
86
- p.log.info('Update Sent your your device, wait until event download complete')
87
- await markSnag(channel, userId, snag, 'done')
88
- }
89
- else if (data.action.startsWith('download_')) {
90
- const action = data.action.split('_')[1]
91
- if (action === 'complete') {
92
- p.log.info('Your bundle has been downloaded on your device, background the app now and open it again to see the update')
93
- await markSnag(channel, userId, snag, 'downloaded')
94
- }
95
- else if (action === 'fail') {
96
- p.log.error('Your bundle has failed to download on your device.')
97
- p.log.error('Please check if you have network connection and try again')
98
- }
99
- else {
100
- p.log.info(`Your bundle is downloading ${action}% ...`)
101
- }
102
- }
103
- else if (data.action === 'set') {
104
- p.log.info('Your bundle has been set on your device ❤️')
105
- loop = false
106
- await markSnag(channel, userId, snag, 'set')
107
- return Promise.resolve(data)
108
- }
109
- else if (data.action === 'NoChannelOrOverride') {
110
- p.log.error(`No default channel or override (channel/device) found, please create it here ${baseUrl}`)
111
- }
112
- else if (data.action === 'needPlanUpgrade') {
113
- p.log.error('Your are out of quota, please upgrade your plan here https://web.capgo.app/dashboard/settings/plans')
114
- }
115
- else if (data.action === 'missingBundle') {
116
- p.log.error('Your bundle is missing, please check how you build your app ')
117
- }
118
- else if (data.action === 'noNew') {
119
- p.log.error(`Your version in ${data.platform} is the same as your version uploaded, change it to see the update`)
120
- }
121
- else if (data.action === 'disablePlatformIos') {
122
- p.log.error(`iOS is disabled in the default channel and your device is an iOS device ${baseUrl}`)
123
- }
124
- else if (data.action === 'disablePlatformAndroid') {
125
- p.log.error(`Android is disabled in the default channel and your device is an Android device ${baseUrl}`)
126
- }
127
- else if (data.action === 'disableAutoUpdateToMajor') {
128
- p.log.error('Auto update to major version is disabled in the default channel.')
129
- p.log.error('Set your app to the same major version as the default channel')
130
- }
131
- else if (data.action === 'disableAutoUpdateUnderNative') {
132
- p.log.error('Auto update under native version is disabled in the default channel.')
133
- p.log.error('Set your app to the same native version as the default channel.')
134
- }
135
- else if (data.action === 'disableDevBuild') {
136
- p.log.error(`Dev build is disabled in the default channel. ${baseUrl}`)
137
- p.log.error('Set your channel to allow it if you wanna test your app')
138
- }
139
- else if (data.action === 'disableEmulator') {
140
- p.log.error(`Emulator is disabled in the default channel. ${baseUrl}`)
141
- p.log.error('Set your channel to allow it if you wanna test your app')
142
- }
143
- else if (data.action === 'cannotGetBundle') {
144
- p.log.error(`We cannot get your bundle from the default channel. ${baseUrl}`)
145
- p.log.error('Are you sure your default channel has a bundle set?')
146
- }
147
- else if (data.action === 'set_fail') {
148
- p.log.error(`Your bundle seems to be corrupted, try to download from ${baseUrl} to identify the issue`)
149
- }
150
- else if (data.action === 'reset') {
151
- p.log.error('Your device has been reset to the builtin bundle, did you added notifyAppReady in your code?')
152
- }
153
- else if (data.action === 'update_fail') {
154
- p.log.error('Your bundle has been installed but failed to call notifyAppReady')
155
- p.log.error('Please check if you have network connection and try again')
156
- }
157
- else if (data.action === 'checksum_fail') {
158
- p.log.error('Your bundle has failed to validate checksum, please check your code and send it again to Capgo')
159
- }
160
- else {
161
- p.log.error(`Log from Capgo ${data.action}`)
162
- }
163
- now = new Date().toISOString()
164
- query.after = now
165
- }
166
- await wait(1000)
167
- }
168
- return Promise.resolve()
169
- }
170
-
171
- export async function debugApp(appId: string, options: OptionsBaseDebug) {
172
- p.intro(`Debug Live update in Capgo`)
173
-
174
- await checkLatest()
175
- options.apikey = options.apikey || findSavedKey()
176
- const config = await getConfig()
177
-
178
- appId = appId || config?.app?.appId
179
- const deviceId = options.device
180
- if (!options.apikey) {
181
- p.log.error(`Missing API key, you need to provide an API key to delete your app`)
182
- program.error('')
183
- }
184
- if (!appId) {
185
- p.log.error('Missing argument, you need to provide a appId, or be in a capacitor project')
186
- program.error('')
187
- }
188
-
189
- const supabase = await createSupabaseClient(options.apikey)
190
- const snag = useLogSnag()
191
-
192
- const userId = await verifyUser(supabase, options.apikey)
193
-
194
- p.log.info(`Getting active bundle in Capgo`)
195
-
196
- // Check we have app access to this appId
197
- await checkAppExistsAndHasPermissionErr(supabase, options.apikey, appId)
198
-
199
- const doRun = await p.confirm({ message: `Automatic check if update working in device ?` })
200
- await cancelCommand('debug', doRun, userId, snag)
201
- if (doRun) {
202
- p.log.info(`Wait logs sent to Capgo from ${appId} device, Put the app in background and open it again.`)
203
- p.log.info('Waiting...')
204
- await waitLog('debug', supabase, appId, snag, userId, deviceId)
205
- p.outro(`Done ✅`)
206
- }
207
- else {
208
- // const appIdUrl = convertAppName(appId)
209
- // p.log.info(`Check logs in https://web.capgo.app/app/p/${appIdUrl}/logs to see if update works.`)
210
- p.outro(`Canceled ❌`)
211
- }
212
- p.outro(`Done ✅`)
213
- process.exit()
214
- }
package/src/app/delete.ts DELETED
@@ -1,68 +0,0 @@
1
- import process from 'node:process'
2
- import { program } from 'commander'
3
- import * as p from '@clack/prompts'
4
- import { checkAppExistsAndHasPermissionErr } from '../api/app'
5
- import type { OptionsBase } from '../utils'
6
- import { createSupabaseClient, findSavedKey, getConfig, useLogSnag, verifyUser } from '../utils'
7
-
8
- export async function deleteApp(appId: string, options: OptionsBase) {
9
- p.intro(`Deleting`)
10
- options.apikey = options.apikey || findSavedKey()
11
- const config = await getConfig()
12
- appId = appId || config?.app?.appId
13
- const snag = useLogSnag()
14
-
15
- if (!options.apikey) {
16
- p.log.error('Missing API key, you need to provide a API key to upload your bundle')
17
- program.error('')
18
- }
19
- if (!appId) {
20
- p.log.error('Missing argument, you need to provide a appId, or be in a capacitor project')
21
- program.error('')
22
- }
23
- const supabase = await createSupabaseClient(options.apikey)
24
-
25
- const userId = await verifyUser(supabase, options.apikey, ['write', 'all'])
26
- // Check we have app access to this appId
27
- await checkAppExistsAndHasPermissionErr(supabase, options.apikey, appId)
28
-
29
- const { error } = await supabase
30
- .storage
31
- .from(`images/${userId}`)
32
- .remove([appId])
33
- if (error)
34
- p.log.error('Could not delete app logo')
35
-
36
- const { error: delError } = await supabase
37
- .storage
38
- .from(`apps/${appId}/${userId}`)
39
- .remove(['versions'])
40
- if (delError) {
41
- p.log.error('Could not delete app version')
42
- program.error('')
43
- }
44
-
45
- const { error: dbError } = await supabase
46
- .from('apps')
47
- .delete()
48
- .eq('app_id', appId)
49
- .eq('user_id', userId)
50
-
51
- if (dbError) {
52
- p.log.error('Could not delete app')
53
- program.error('')
54
- }
55
- await snag.track({
56
- channel: 'app',
57
- event: 'App Deleted',
58
- icon: '🗑️',
59
- user_id: userId,
60
- tags: {
61
- 'app-id': appId,
62
- },
63
- notify: false,
64
- }).catch()
65
- p.log.success(`App deleted in Capgo`)
66
- p.outro('Done ✅')
67
- process.exit()
68
- }
package/src/app/info.ts DELETED
@@ -1,87 +0,0 @@
1
- import { readFileSync } from 'node:fs'
2
- import { join } from 'node:path'
3
- import os from 'node:os'
4
- import process from 'node:process'
5
- import getLatest from 'get-latest-version'
6
- import Spinnies from '@trufflesuite/spinnies'
7
- import * as p from '@clack/prompts'
8
- import pack from '../../package.json'
9
-
10
- async function getLatestDependencies(installedDependencies: { [key: string]: string }) {
11
- const latestDependencies: { [key: string]: string } = {}
12
- const all = []
13
- for (const dependency in installedDependencies) {
14
- if (Object.prototype.hasOwnProperty.call(installedDependencies, dependency)) {
15
- // get in npm the last version of the dependency
16
- all.push(getLatest(dependency))
17
- }
18
- }
19
- await Promise.all(all)
20
- .then((values) => {
21
- const keys = Object.keys(installedDependencies)
22
- for (let i = 0; i < values.length; i += 1) {
23
- const v = values[i]
24
- if (v)
25
- latestDependencies[keys[i]] = v
26
- }
27
- })
28
- return latestDependencies
29
- }
30
-
31
- async function readPackageJson() {
32
- const packageJson = readFileSync(join(process.cwd(), 'package.json'))
33
- return JSON.parse(packageJson as any)
34
- }
35
-
36
- async function getInstalledDependencies() {
37
- const { dependencies } = await readPackageJson()
38
- const installedDependencies: { [key: string]: string } = {
39
- '@capgo/cli': pack.version,
40
- }
41
- for (const dependency in dependencies) {
42
- if (Object.prototype.hasOwnProperty.call(dependencies, dependency) && dependency.startsWith('@capgo/')) {
43
- // remove ^ or ~ from version
44
- const version = dependencies[dependency].replace('^', '').replace('~', '')
45
- installedDependencies[dependency] = version
46
- }
47
- }
48
- return installedDependencies
49
- }
50
-
51
- export async function getInfo() {
52
- p.log.info(' 💊 Capgo Doctor 💊\n')
53
- p.log.info(` OS: ${os.platform()} ${os.version()}\n`)
54
- p.log.info(` Node: ${process.version}\n`)
55
- p.log.info(' Installed Dependencies:\n')
56
- const installedDependencies = await getInstalledDependencies()
57
- if (Object.keys(installedDependencies).length === 0) {
58
- // display in red color in shell with console log
59
- p.log.warning('\x1B[31m%s\x1B[0m 🚨 No dependencies found')
60
- process.exit(1)
61
- }
62
- for (const dependency in installedDependencies) {
63
- if (Object.prototype.hasOwnProperty.call(installedDependencies, dependency)) {
64
- const installedVersion = (installedDependencies as any)[dependency]
65
- p.log.info(` ${dependency}: ${installedVersion}`)
66
- }
67
- }
68
- p.log.info('\n')
69
- const spinnies = new Spinnies()
70
- spinnies.add('loading', { text: ' Loading latest dependencies' })
71
- const latestDependencies = await getLatestDependencies(installedDependencies)
72
- spinnies.succeed('loading', { text: ' Latest Dependencies:' })
73
- for (const dependency in latestDependencies) {
74
- if (Object.prototype.hasOwnProperty.call(latestDependencies, dependency)) {
75
- const latestVersion = (latestDependencies as any)[dependency]
76
- p.log.info(` ${dependency}: ${latestVersion}`)
77
- }
78
- }
79
- if (JSON.stringify(installedDependencies) !== JSON.stringify(latestDependencies)) {
80
- // display in red color in shell with console log
81
- p.log.warn('\x1B[31m🚨 Some dependencies are not up to date\x1B[0m')
82
- process.exit(1)
83
- }
84
- // display in green color in shell with console log
85
- p.log.success('\x1B[32m✅ All dependencies are up to date\x1B[0m')
86
- process.exit()
87
- }
package/src/app/list.ts DELETED
@@ -1,63 +0,0 @@
1
- import process from 'node:process'
2
- import { program } from 'commander'
3
- import { Table } from 'console-table-printer'
4
- import type { SupabaseClient } from '@supabase/supabase-js'
5
- import * as p from '@clack/prompts'
6
- import type { Database } from '../types/supabase.types'
7
- import type { OptionsBase } from '../utils'
8
- import { createSupabaseClient, findSavedKey, getHumanDate, verifyUser } from '../utils'
9
- import { checkLatest } from '../api/update'
10
-
11
- function displayApp(data: Database['public']['Tables']['apps']['Row'][]) {
12
- const t = new Table({
13
- title: 'Apps',
14
- charLength: { '❌': 2, '✅': 2 },
15
- })
16
-
17
- // add rows with color
18
- data.reverse().forEach((row) => {
19
- t.addRow({
20
- Name: row.name,
21
- id: row.app_id,
22
- Created: getHumanDate(row.created_at),
23
- })
24
- })
25
-
26
- p.log.success(t.render())
27
- }
28
-
29
- export async function getActiveApps(supabase: SupabaseClient<Database>) {
30
- const { data, error: vError } = await supabase
31
- .from('apps')
32
- .select()
33
- // .eq('user_id', userId)
34
- .order('created_at', { ascending: false })
35
-
36
- if (vError) {
37
- p.log.error('Apps not found')
38
- program.error('')
39
- }
40
- return data
41
- }
42
-
43
- export async function listApp(options: OptionsBase) {
44
- p.intro(`List apps in Capgo`)
45
-
46
- await checkLatest()
47
- options.apikey = options.apikey || findSavedKey()
48
-
49
- const supabase = await createSupabaseClient(options.apikey)
50
-
51
- await verifyUser(supabase, options.apikey, ['write', 'all', 'read', 'upload'])
52
-
53
- p.log.info(`Getting active bundle in Capgo`)
54
-
55
- // Get all active app versions we might possibly be able to cleanup
56
- const allApps = await getActiveApps(supabase)
57
-
58
- p.log.info(`Active app in Capgo: ${allApps?.length}`)
59
-
60
- displayApp(allApps)
61
- p.outro(`Done ✅`)
62
- process.exit()
63
- }
package/src/app/set.ts DELETED
@@ -1,94 +0,0 @@
1
- import { randomUUID } from 'node:crypto'
2
- import { existsSync, readFileSync } from 'node:fs'
3
- import process from 'node:process'
4
- import mime from 'mime'
5
- import { program } from 'commander'
6
- import * as p from '@clack/prompts'
7
- import type { Options } from '../api/app'
8
- import { checkAppExistsAndHasPermissionErr, newIconPath } from '../api/app'
9
- import { createSupabaseClient, findSavedKey, formatError, getConfig, verifyUser } from '../utils'
10
-
11
- export async function setApp(appId: string, options: Options) {
12
- p.intro(`Set app`)
13
- options.apikey = options.apikey || findSavedKey()
14
- const config = await getConfig()
15
- appId = appId || config?.app?.appId
16
-
17
- if (!options.apikey) {
18
- p.log.error(`Missing API key, you need to provide a API key to upload your bundle`)
19
- program.error(``)
20
- }
21
- if (!appId) {
22
- p.log.error('Missing argument, you need to provide a appId, or be in a capacitor project')
23
- program.error(``)
24
- }
25
- const supabase = await createSupabaseClient(options.apikey)
26
-
27
- const userId = await verifyUser(supabase, options.apikey, ['write', 'all'])
28
- // Check we have app access to this appId
29
- await checkAppExistsAndHasPermissionErr(supabase, options.apikey, appId)
30
-
31
- const { name, icon, retention } = options
32
-
33
- if (retention && !Number.isNaN(Number(retention))) {
34
- p.log.error(`retention value must be a number`)
35
- program.error(``)
36
- }
37
- else if (retention && retention < 0) {
38
- p.log.error(`retention value cannot be less than 0`)
39
- program.error(``)
40
- }
41
-
42
- let iconBuff
43
- let iconType
44
- const fileName = `icon_${randomUUID()}`
45
- let signedURL = 'https://xvwzpoazmxkqosrdewyv.supabase.co/storage/v1/object/public/images/capgo.png'
46
-
47
- if (icon && existsSync(icon)) {
48
- iconBuff = readFileSync(icon)
49
- const contentType = mime.getType(icon)
50
- iconType = contentType || 'image/png'
51
- p.log.warn(`Found app icon ${icon}`)
52
- }
53
- else if (existsSync(newIconPath)) {
54
- iconBuff = readFileSync(newIconPath)
55
- const contentType = mime.getType(newIconPath)
56
- iconType = contentType || 'image/png'
57
- p.log.warn(`Found app icon ${newIconPath}`)
58
- }
59
- else {
60
- p.log.warn(`Cannot find app icon in any of the following locations: ${icon}, ${newIconPath}`)
61
- }
62
- if (iconBuff && iconType) {
63
- const { error } = await supabase.storage
64
- .from(`images/${userId}/${appId}`)
65
- .upload(fileName, iconBuff, {
66
- contentType: iconType,
67
- })
68
- if (error) {
69
- p.log.error(`Could not set app ${formatError(error)}`)
70
- program.error(``)
71
- }
72
- const { data: signedURLData } = await supabase
73
- .storage
74
- .from(`images/${userId}/${appId}`)
75
- .getPublicUrl(fileName)
76
- signedURL = signedURLData?.publicUrl || signedURL
77
- }
78
- // retention is in seconds in the database but received as days here
79
- const { error: dbError } = await supabase
80
- .from('apps')
81
- .update({
82
- icon_url: signedURL,
83
- name,
84
- retention: !retention ? undefined : retention * 24 * 60 * 60,
85
- })
86
- .eq('app_id', appId)
87
- .eq('user_id', userId)
88
- if (dbError) {
89
- p.log.error(`Could not set app ${formatError(dbError)}`)
90
- program.error(``)
91
- }
92
- p.outro(`Done ✅`)
93
- process.exit()
94
- }