@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.
package/src/app/debug.ts CHANGED
@@ -1,82 +1,83 @@
1
- import * as p from '@clack/prompts';
2
- import { SupabaseClient } from '@supabase/supabase-js';
3
- import { program } from 'commander';
4
- import LogSnag from 'logsnag';
5
- import { Database } from '../types/supabase.types';
6
- import { checkAppExistsAndHasPermissionErr } from '../api/app';
7
- import { checkLatest } from '../api/update';
8
- import { convertAppName, createSupabaseClient, findSavedKey, getLocalConfig, useLogSnag, verifyUser, getConfig } from '../utils';
9
-
10
- const wait = (ms: number) => new Promise(resolve => { setTimeout(resolve, ms) })
11
-
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 } from '../utils'
10
+
11
+ function wait(ms: number) {
12
+ return new Promise((resolve) => {
13
+ setTimeout(resolve, ms)
14
+ })
15
+ }
12
16
 
13
17
  export interface OptionsBaseDebug {
14
- apikey: string;
15
- device?: string;
18
+ apikey: string
19
+ device?: string
16
20
  }
17
21
 
18
- export const markSnag = async (channel: string, userId: string, snag: LogSnag, event: string, icon = '✅') => {
22
+ export async function markSnag(channel: string, userId: string, snag: LogSnag, event: string, icon = '✅') {
19
23
  await snag.track({
20
- channel,
21
- event,
22
- icon,
23
- user_id: userId,
24
- notify: false,
24
+ channel,
25
+ event,
26
+ icon,
27
+ user_id: userId,
28
+ notify: false,
25
29
  }).catch()
26
30
  }
27
31
 
28
- export const cancelCommand = async (channel: string, command: boolean | symbol, userId: string, snag: LogSnag) => {
32
+ export async function cancelCommand(channel: string, command: boolean | symbol, userId: string, snag: LogSnag) {
29
33
  if (p.isCancel(command)) {
30
- await markSnag(channel, userId, snag, 'canceled', '🤷')
31
- process.exit()
34
+ await markSnag(channel, userId, snag, 'canceled', '🤷')
35
+ process.exit()
32
36
  }
33
37
  }
34
38
 
35
39
  interface Order {
36
- key: string
37
- sortable?: 'asc' | 'desc'
40
+ key: string
41
+ sortable?: 'asc' | 'desc'
38
42
  }
39
43
 
40
44
  interface QueryStats {
41
- appId: string
42
- devicesId?: string[]
43
- search?: string
44
- order?: Order[]
45
- rangeStart?: number
46
- rangeEnd?: number
47
- after?: string
45
+ appId: string
46
+ devicesId?: string[]
47
+ search?: string
48
+ order?: Order[]
49
+ rangeStart?: number
50
+ rangeEnd?: number
51
+ after?: string
48
52
  }
49
53
 
50
- export async function getStats(supabase: SupabaseClient<Database>, query: QueryStats)
51
- : Promise<Database['public']['Tables']['stats']['Row'] | null> {
52
- try {
53
- const pathStats = 'private/stats'
54
- const res = await supabase.functions.invoke(pathStats, { body: JSON.stringify(query) })
55
- const listData = res.data.data as Database['public']['Tables']['stats']['Row'][]
56
- if (listData?.length > 0) {
57
- return listData[0]
58
- }
59
- } catch (error) {
60
- p.log.error(`Cannot get stats ${JSON.stringify(error)}`);
61
- }
62
- return null;
54
+ export async function getStats(supabase: SupabaseClient<Database>, query: QueryStats): Promise<Database['public']['Tables']['stats']['Row'] | null> {
55
+ try {
56
+ const pathStats = 'private/stats'
57
+ const res = await supabase.functions.invoke(pathStats, { body: JSON.stringify(query) })
58
+ const listData = res.data.data as Database['public']['Tables']['stats']['Row'][]
59
+ if (listData?.length > 0)
60
+ return listData[0]
61
+ }
62
+ catch (error) {
63
+ p.log.error(`Cannot get stats ${formatError(error)}`)
64
+ }
65
+ return null
63
66
  }
64
67
 
65
-
66
- export const waitLog = async (channel: string, supabase: SupabaseClient<Database>,
67
- appId: string, snag: LogSnag, userId: string, deviceId?: string) => {
68
+ export async function waitLog(channel: string, supabase: SupabaseClient<Database>, appId: string, snag: LogSnag, userId: string, deviceId?: string) {
68
69
  let loop = true
69
70
  let now = new Date().toISOString()
70
71
  const appIdUrl = convertAppName(appId)
71
- const config = await getLocalConfig();
72
+ const config = await getLocalConfig()
72
73
  const baseUrl = `${config.hostWeb}/app/p/${appIdUrl}`
73
74
  await markSnag(channel, userId, snag, 'Use waitlog')
74
75
  const query: QueryStats = {
75
76
  appId,
76
77
  devicesId: deviceId ? [deviceId] : undefined,
77
78
  order: [{
78
- key: 'created_at',
79
- sortable: 'desc',
79
+ key: 'created_at',
80
+ sortable: 'desc',
80
81
  }],
81
82
  rangeStart: 0,
82
83
  rangeEnd: 1,
@@ -86,133 +87,134 @@ export const waitLog = async (channel: string, supabase: SupabaseClient<Database
86
87
  const data = await getStats(supabase, query)
87
88
  // console.log('data', data)
88
89
  if (data) {
89
- p.log.info(`Log from Device: ${data.device_id}`)
90
- if (data.action === 'get') {
91
- p.log.info('Update Sent your your device, wait until event download complete')
92
- await markSnag(channel, userId, snag, 'done')
93
- }
94
- else if (data.action.startsWith('download_')) {
95
- const action = data.action.split('_')[1]
96
- if (action === 'complete') {
97
- p.log.info('Your bundle has been downloaded on your device, background the app now and open it again to see the update')
98
- await markSnag(channel, userId, snag, 'downloaded')
99
- }
100
- else if (action === 'fail') {
101
- p.log.error('Your bundle has failed to download on your device.')
102
- p.log.error('Please check if you have network connection and try again')
103
- }
104
- else {
105
- p.log.info(`Your bundle is downloading ${action}% ...`)
106
- }
107
- }
108
- else if (data.action === 'set') {
109
- p.log.info('Your bundle has been set on your device ❤️')
110
- loop = false
111
- await markSnag(channel, userId, snag, 'set')
112
- return Promise.resolve(data)
113
- }
114
- else if (data.action === 'NoChannelOrOverride') {
115
- p.log.error(`No default channel or override (channel/device) found, please create it here ${baseUrl}`)
116
- }
117
- else if (data.action === 'needPlanUpgrade') {
118
- p.log.error('Your are out of quota, please upgrade your plan here https://web.capgo.app/dashboard/settings/plans')
119
- }
120
- else if (data.action === 'missingBundle') {
121
- p.log.error('Your bundle is missing, please check how you build your app ')
122
- }
123
- else if (data.action === 'noNew') {
124
- p.log.error(`Your version in ${data.platform} is the same as your version uploaded, change it to see the update`)
125
- }
126
- else if (data.action === 'disablePlatformIos') {
127
- p.log.error(`iOS is disabled in the default channel and your device is an iOS device ${baseUrl}`)
128
- }
129
- else if (data.action === 'disablePlatformAndroid') {
130
- p.log.error(`Android is disabled in the default channel and your device is an Android device ${baseUrl}`)
131
- }
132
- else if (data.action === 'disableAutoUpdateToMajor') {
133
- p.log.error('Auto update to major version is disabled in the default channel.')
134
- p.log.error('Set your app to the same major version as the default channel')
135
- }
136
- else if (data.action === 'disableAutoUpdateUnderNative') {
137
- p.log.error('Auto update under native version is disabled in the default channel.')
138
- p.log.error('Set your app to the same native version as the default channel.')
139
- }
140
- else if (data.action === 'disableDevBuild') {
141
- p.log.error(`Dev build is disabled in the default channel. ${baseUrl}`)
142
- p.log.error('Set your channel to allow it if you wanna test your app')
143
- }
144
- else if (data.action === 'disableEmulator') {
145
- p.log.error(`Emulator is disabled in the default channel. ${baseUrl}`)
146
- p.log.error('Set your channel to allow it if you wanna test your app')
147
- }
148
- else if (data.action === 'cannotGetBundle') {
149
- p.log.error(`We cannot get your bundle from the default channel. ${baseUrl}`)
150
- p.log.error('Are you sure your default channel has a bundle set?')
151
- }
152
- else if (data.action === 'set_fail') {
153
- p.log.error(`Your bundle seems to be corrupted, try to download from ${baseUrl} to identify the issue`)
154
- }
155
- else if (data.action === 'reset') {
156
- p.log.error('Your device has been reset to the builtin bundle, did you added notifyAppReady in your code?')
157
- }
158
- else if (data.action === 'update_fail') {
159
- p.log.error('Your bundle has been installed but failed to call notifyAppReady')
160
- p.log.error('Please check if you have network connection and try again')
161
- }
162
- else if (data.action === 'checksum_fail') {
163
- p.log.error('Your bundle has failed to validate checksum, please check your code and send it again to Capgo')
90
+ p.log.info(`Log from Device: ${data.device_id}`)
91
+ if (data.action === 'get') {
92
+ p.log.info('Update Sent your your device, wait until event download complete')
93
+ await markSnag(channel, userId, snag, 'done')
94
+ }
95
+ else if (data.action.startsWith('download_')) {
96
+ const action = data.action.split('_')[1]
97
+ if (action === 'complete') {
98
+ p.log.info('Your bundle has been downloaded on your device, background the app now and open it again to see the update')
99
+ await markSnag(channel, userId, snag, 'downloaded')
100
+ }
101
+ else if (action === 'fail') {
102
+ p.log.error('Your bundle has failed to download on your device.')
103
+ p.log.error('Please check if you have network connection and try again')
164
104
  }
165
105
  else {
166
- p.log.error(`Log from Capgo ${data.action}`)
167
- }
168
- now = new Date().toISOString()
169
- query.after = now
106
+ p.log.info(`Your bundle is downloading ${action}% ...`)
107
+ }
108
+ }
109
+ else if (data.action === 'set') {
110
+ p.log.info('Your bundle has been set on your device ❤️')
111
+ loop = false
112
+ await markSnag(channel, userId, snag, 'set')
113
+ return Promise.resolve(data)
114
+ }
115
+ else if (data.action === 'NoChannelOrOverride') {
116
+ p.log.error(`No default channel or override (channel/device) found, please create it here ${baseUrl}`)
117
+ }
118
+ else if (data.action === 'needPlanUpgrade') {
119
+ p.log.error('Your are out of quota, please upgrade your plan here https://web.capgo.app/dashboard/settings/plans')
120
+ }
121
+ else if (data.action === 'missingBundle') {
122
+ p.log.error('Your bundle is missing, please check how you build your app ')
123
+ }
124
+ else if (data.action === 'noNew') {
125
+ p.log.error(`Your version in ${data.platform} is the same as your version uploaded, change it to see the update`)
126
+ }
127
+ else if (data.action === 'disablePlatformIos') {
128
+ p.log.error(`iOS is disabled in the default channel and your device is an iOS device ${baseUrl}`)
129
+ }
130
+ else if (data.action === 'disablePlatformAndroid') {
131
+ p.log.error(`Android is disabled in the default channel and your device is an Android device ${baseUrl}`)
132
+ }
133
+ else if (data.action === 'disableAutoUpdateToMajor') {
134
+ p.log.error('Auto update to major version is disabled in the default channel.')
135
+ p.log.error('Set your app to the same major version as the default channel')
136
+ }
137
+ else if (data.action === 'disableAutoUpdateUnderNative') {
138
+ p.log.error('Auto update under native version is disabled in the default channel.')
139
+ p.log.error('Set your app to the same native version as the default channel.')
140
+ }
141
+ else if (data.action === 'disableDevBuild') {
142
+ p.log.error(`Dev build is disabled in the default channel. ${baseUrl}`)
143
+ p.log.error('Set your channel to allow it if you wanna test your app')
144
+ }
145
+ else if (data.action === 'disableEmulator') {
146
+ p.log.error(`Emulator is disabled in the default channel. ${baseUrl}`)
147
+ p.log.error('Set your channel to allow it if you wanna test your app')
148
+ }
149
+ else if (data.action === 'cannotGetBundle') {
150
+ p.log.error(`We cannot get your bundle from the default channel. ${baseUrl}`)
151
+ p.log.error('Are you sure your default channel has a bundle set?')
152
+ }
153
+ else if (data.action === 'set_fail') {
154
+ p.log.error(`Your bundle seems to be corrupted, try to download from ${baseUrl} to identify the issue`)
155
+ }
156
+ else if (data.action === 'reset') {
157
+ p.log.error('Your device has been reset to the builtin bundle, did you added notifyAppReady in your code?')
158
+ }
159
+ else if (data.action === 'update_fail') {
160
+ p.log.error('Your bundle has been installed but failed to call notifyAppReady')
161
+ p.log.error('Please check if you have network connection and try again')
162
+ }
163
+ else if (data.action === 'checksum_fail') {
164
+ p.log.error('Your bundle has failed to validate checksum, please check your code and send it again to Capgo')
165
+ }
166
+ else {
167
+ p.log.error(`Log from Capgo ${data.action}`)
168
+ }
169
+ now = new Date().toISOString()
170
+ query.after = now
170
171
  }
171
172
  await wait(1000)
172
173
  }
173
174
  return Promise.resolve()
174
175
  }
175
176
 
176
- export const debugApp = async (appId: string, options: OptionsBaseDebug) => {
177
- p.intro(`Debug Live update in Capgo`);
177
+ export async function debugApp(appId: string, options: OptionsBaseDebug) {
178
+ p.intro(`Debug Live update in Capgo`)
178
179
 
179
- await checkLatest();
180
+ await checkLatest()
180
181
  options.apikey = options.apikey || findSavedKey()
181
- const config = await getConfig();
182
+ const config = await getConfig()
182
183
 
183
184
  appId = appId || config?.app?.appId
184
185
  const deviceId = options.device
185
186
  if (!options.apikey) {
186
- p.log.error(`Missing API key, you need to provide an API key to delete your app`);
187
- program.error('');
187
+ p.log.error(`Missing API key, you need to provide an API key to delete your app`)
188
+ program.error('')
188
189
  }
189
190
  if (!appId) {
190
- p.log.error("Missing argument, you need to provide a appId, or be in a capacitor project");
191
- program.error('');
191
+ p.log.error('Missing argument, you need to provide a appId, or be in a capacitor project')
192
+ program.error('')
192
193
  }
193
194
 
194
195
  const supabase = await createSupabaseClient(options.apikey)
195
196
  const snag = useLogSnag()
196
197
 
197
- const userId = await verifyUser(supabase, options.apikey);
198
+ const userId = await verifyUser(supabase, options.apikey)
198
199
 
199
- p.log.info(`Getting active bundle in Capgo`);
200
+ p.log.info(`Getting active bundle in Capgo`)
200
201
 
201
202
  // Check we have app access to this appId
202
- await checkAppExistsAndHasPermissionErr(supabase, options.apikey, appId);
203
+ await checkAppExistsAndHasPermissionErr(supabase, options.apikey, appId)
203
204
 
204
- const doRun = await p.confirm({ message: `Automatic check if update working in device ?` });
205
- await cancelCommand('debug', doRun, userId, snag);
205
+ const doRun = await p.confirm({ message: `Automatic check if update working in device ?` })
206
+ await cancelCommand('debug', doRun, userId, snag)
206
207
  if (doRun) {
207
- p.log.info(`Wait logs sent to Capgo from ${appId} device, Put the app in background and open it again.`)
208
- p.log.info('Waiting...');
209
- await waitLog('debug', supabase, appId, snag, userId, deviceId);
210
- p.outro(`Done ✅`);
211
- } else {
212
- // const appIdUrl = convertAppName(appId)
213
- // p.log.info(`Check logs in https://web.capgo.app/app/p/${appIdUrl}/logs to see if update works.`)
214
- p.outro(`Canceled ❌`);
208
+ p.log.info(`Wait logs sent to Capgo from ${appId} device, Put the app in background and open it again.`)
209
+ p.log.info('Waiting...')
210
+ await waitLog('debug', supabase, appId, snag, userId, deviceId)
211
+ p.outro(`Done ✅`)
212
+ }
213
+ else {
214
+ // const appIdUrl = convertAppName(appId)
215
+ // p.log.info(`Check logs in https://web.capgo.app/app/p/${appIdUrl}/logs to see if update works.`)
216
+ p.outro(`Canceled ❌`)
215
217
  }
216
- p.outro(`Done ✅`);
218
+ p.outro(`Done ✅`)
217
219
  process.exit()
218
220
  }
package/src/app/delete.ts CHANGED
@@ -1,66 +1,68 @@
1
- import { program } from "commander";
2
- import * as p from '@clack/prompts';
3
- import { checkAppExistsAndHasPermissionErr } from '../api/app';
4
- import { createSupabaseClient, findSavedKey, getConfig, useLogSnag, verifyUser, OptionsBase } from "../utils";
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'
5
7
 
6
- export const deleteApp = async (appId: string, options: OptionsBase) => {
7
- p.intro(`Deleting`);
8
- options.apikey = options.apikey || findSavedKey()
9
- const config = await getConfig();
10
- appId = appId || config?.app?.appId
11
- const snag = useLogSnag()
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()
12
14
 
13
- if (!options.apikey) {
14
- p.log.error('Missing API key, you need to provide a API key to upload your bundle');
15
- program.error('');
16
- }
17
- if (!appId) {
18
- p.log.error('Missing argument, you need to provide a appId, or be in a capacitor project');
19
- program.error('');
20
- }
21
- const supabase = await createSupabaseClient(options.apikey)
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)
22
24
 
23
- const userId = await verifyUser(supabase, options.apikey, ['write', 'all']);
24
- // Check we have app access to this appId
25
- await checkAppExistsAndHasPermissionErr(supabase, options.apikey, appId);
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)
26
28
 
27
- const { error } = await supabase
28
- .storage
29
- .from(`images/${userId}`)
30
- .remove([appId])
31
- if (error) {
32
- p.log.error('Could not delete app logo');
33
- }
34
- const { error: delError } = await supabase
35
- .storage
36
- .from(`apps/${appId}/${userId}`)
37
- .remove(['versions'])
38
- if (delError) {
39
- p.log.error('Could not delete app version');
40
- program.error('');
41
- }
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')
42
35
 
43
- const { error: dbError } = await supabase
44
- .from('apps')
45
- .delete()
46
- .eq('app_id', appId)
47
- .eq('user_id', userId)
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
+ }
48
44
 
49
- if (dbError) {
50
- p.log.error('Could not delete app');
51
- program.error('');
52
- }
53
- await snag.track({
54
- channel: 'app',
55
- event: 'App Deleted',
56
- icon: '🗑️',
57
- user_id: userId,
58
- tags: {
59
- 'app-id': appId,
60
- },
61
- notify: false,
62
- }).catch()
63
- p.log.success(`App deleted in Capgo`);
64
- p.outro('Done ✅');
65
- process.exit()
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()
66
68
  }