@capgo/cli 4.2.3 → 4.2.7
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/CHANGELOG.md +29 -0
- package/dist/index.js +113 -83
- package/package.json +1 -1
- package/src/api/channels.ts +2 -4
- package/src/api/versions.ts +9 -11
- package/src/app/add.ts +35 -4
- package/src/app/debug.ts +9 -3
- package/src/app/delete.ts +44 -6
- package/src/app/set.ts +4 -4
- package/src/bundle/cleanup.ts +5 -6
- package/src/bundle/compatibility.ts +3 -3
- package/src/bundle/delete.ts +3 -3
- package/src/bundle/list.ts +3 -3
- package/src/bundle/unlink.ts +7 -6
- package/src/bundle/upload.ts +12 -8
- package/src/bundle/zip.ts +11 -9
- package/src/channel/add.ts +4 -4
- package/src/channel/currentBundle.ts +4 -5
- package/src/channel/delete.ts +3 -3
- package/src/channel/list.ts +3 -3
- package/src/channel/set.ts +3 -2
- package/src/index.ts +7 -6
- package/src/types/supabase.types.ts +57 -29
- package/src/utils.ts +7 -6
package/src/app/add.ts
CHANGED
|
@@ -37,7 +37,7 @@ export async function addApp(appId: string, options: Options, throwErr = true) {
|
|
|
37
37
|
}
|
|
38
38
|
const supabase = await createSupabaseClient(options.apikey)
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
let userId = await verifyUser(supabase, options.apikey, ['write', 'all'])
|
|
41
41
|
|
|
42
42
|
await checkPlanValid(supabase, userId, options.apikey, undefined, false)
|
|
43
43
|
|
|
@@ -51,6 +51,37 @@ export async function addApp(appId: string, options: Options, throwErr = true) {
|
|
|
51
51
|
return true
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
const { error: orgError, data: allOrganizations } = await supabase
|
|
55
|
+
.rpc('get_orgs_v4')
|
|
56
|
+
|
|
57
|
+
if (orgError) {
|
|
58
|
+
p.log.error('Cannot get the list of organizations - exiting')
|
|
59
|
+
p.log.error(`Error ${JSON.stringify(orgError)}`)
|
|
60
|
+
program.error('')
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const adminOrgs = allOrganizations.filter(org => org.role === 'admin' || org.role === 'super_admin')
|
|
64
|
+
|
|
65
|
+
const organizationUidRaw = (adminOrgs.length > 1)
|
|
66
|
+
? await p.select({
|
|
67
|
+
message: 'Please pick the organization that you want to insert to',
|
|
68
|
+
options: adminOrgs.map((org) => {
|
|
69
|
+
return { value: org.gid, label: org.name }
|
|
70
|
+
}),
|
|
71
|
+
})
|
|
72
|
+
: adminOrgs[0].gid
|
|
73
|
+
|
|
74
|
+
if (p.isCancel(organizationUidRaw)) {
|
|
75
|
+
p.log.error('Canceled organization selection, exiting')
|
|
76
|
+
program.error('')
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const organizationUid = organizationUidRaw as string
|
|
80
|
+
const organization = allOrganizations.find(org => org.gid === organizationUid)!
|
|
81
|
+
userId = organization.created_by
|
|
82
|
+
|
|
83
|
+
p.log.info(`Using the organization "${organization.name}" as the app owner`)
|
|
84
|
+
|
|
54
85
|
let { name, icon } = options
|
|
55
86
|
appId = appId || config?.app?.appId
|
|
56
87
|
name = name || config?.app?.appName || 'Unknown'
|
|
@@ -106,7 +137,7 @@ export async function addApp(appId: string, options: Options, throwErr = true) {
|
|
|
106
137
|
.from('apps')
|
|
107
138
|
.insert({
|
|
108
139
|
icon_url: signedURL,
|
|
109
|
-
|
|
140
|
+
owner_org: organizationUid,
|
|
110
141
|
name,
|
|
111
142
|
app_id: appId,
|
|
112
143
|
})
|
|
@@ -117,12 +148,12 @@ export async function addApp(appId: string, options: Options, throwErr = true) {
|
|
|
117
148
|
const { error: dbVersionError } = await supabase
|
|
118
149
|
.from('app_versions')
|
|
119
150
|
.insert([{
|
|
120
|
-
|
|
151
|
+
owner_org: organizationUid,
|
|
121
152
|
deleted: true,
|
|
122
153
|
name: 'unknown',
|
|
123
154
|
app_id: appId,
|
|
124
155
|
}, {
|
|
125
|
-
|
|
156
|
+
owner_org: organizationUid,
|
|
126
157
|
deleted: true,
|
|
127
158
|
name: 'builtin',
|
|
128
159
|
app_id: appId,
|
package/src/app/debug.ts
CHANGED
|
@@ -4,9 +4,15 @@ import type { SupabaseClient } from '@supabase/supabase-js'
|
|
|
4
4
|
import { program } from 'commander'
|
|
5
5
|
import type LogSnag from 'logsnag'
|
|
6
6
|
import type { Database } from '../types/supabase.types'
|
|
7
|
-
import {
|
|
7
|
+
import { checkAppExistsAndHasPermissionOrgErr } from '../api/app'
|
|
8
8
|
import { checkLatest } from '../api/update'
|
|
9
|
-
import { convertAppName, createSupabaseClient, findSavedKey, formatError, getConfig, getLocalConfig, useLogSnag, verifyUser
|
|
9
|
+
import { OrganizationPerm, 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
|
+
}
|
|
10
16
|
|
|
11
17
|
export interface OptionsBaseDebug {
|
|
12
18
|
apikey: string
|
|
@@ -194,7 +200,7 @@ export async function debugApp(appId: string, options: OptionsBaseDebug) {
|
|
|
194
200
|
p.log.info(`Getting active bundle in Capgo`)
|
|
195
201
|
|
|
196
202
|
// Check we have app access to this appId
|
|
197
|
-
await
|
|
203
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, OrganizationPerm.admin)
|
|
198
204
|
|
|
199
205
|
const doRun = await p.confirm({ message: `Automatic check if update working in device ?` })
|
|
200
206
|
await cancelCommand('debug', doRun, userId, snag)
|
package/src/app/delete.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import process from 'node:process'
|
|
2
2
|
import { program } from 'commander'
|
|
3
3
|
import * as p from '@clack/prompts'
|
|
4
|
-
import {
|
|
4
|
+
import { checkAppExistsAndHasPermissionOrgErr } from '../api/app'
|
|
5
5
|
import type { OptionsBase } from '../utils'
|
|
6
|
-
import { createSupabaseClient, findSavedKey, getConfig, useLogSnag, verifyUser } from '../utils'
|
|
6
|
+
import { OrganizationPerm, createSupabaseClient, findSavedKey, formatError, getConfig, useLogSnag, verifyUser } from '../utils'
|
|
7
7
|
|
|
8
8
|
export async function deleteApp(appId: string, options: OptionsBase) {
|
|
9
9
|
p.intro(`Deleting`)
|
|
@@ -24,7 +24,45 @@ export async function deleteApp(appId: string, options: OptionsBase) {
|
|
|
24
24
|
|
|
25
25
|
const userId = await verifyUser(supabase, options.apikey, ['write', 'all'])
|
|
26
26
|
// Check we have app access to this appId
|
|
27
|
-
await
|
|
27
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, OrganizationPerm.super_admin)
|
|
28
|
+
|
|
29
|
+
const { data: appOwnerRaw, error: appOwnerError } = await supabase.from('apps')
|
|
30
|
+
.select(`owner_org ( created_by )`)
|
|
31
|
+
.eq('app_id', appId)
|
|
32
|
+
.single()
|
|
33
|
+
|
|
34
|
+
const appOwner = appOwnerRaw as { owner_org: { created_by: string } } | null
|
|
35
|
+
|
|
36
|
+
if (!appOwnerError && (appOwner?.owner_org.created_by ?? '') !== userId) {
|
|
37
|
+
// We are dealing with a member user that is not the owner
|
|
38
|
+
// Deleting the app is not recomended at this stage
|
|
39
|
+
|
|
40
|
+
p.log.warn('Deleting the app is not recomended for users that are not the organization owner')
|
|
41
|
+
p.log.warn('You are invited as a super_admin but your are not the owner')
|
|
42
|
+
p.log.warn('It\'s strongly recomended that you do not continue!')
|
|
43
|
+
|
|
44
|
+
const shouldContinue = await p.select({
|
|
45
|
+
message: 'Do you want to continue?',
|
|
46
|
+
options: [
|
|
47
|
+
{
|
|
48
|
+
label: 'Yes',
|
|
49
|
+
value: 'yes',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
label: 'No',
|
|
53
|
+
value: 'no',
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
if (p.isCancel(shouldContinue) || shouldContinue === 'no') {
|
|
59
|
+
p.log.error('Canceled deleting the app, exiting')
|
|
60
|
+
program.error('')
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else if (appOwnerError) {
|
|
64
|
+
p.log.warn(`Cannot get the app owner ${formatError(appOwnerError)}`)
|
|
65
|
+
}
|
|
28
66
|
|
|
29
67
|
const { error } = await supabase
|
|
30
68
|
.storage
|
|
@@ -37,10 +75,10 @@ export async function deleteApp(appId: string, options: OptionsBase) {
|
|
|
37
75
|
.storage
|
|
38
76
|
.from(`apps/${appId}/${userId}`)
|
|
39
77
|
.remove(['versions'])
|
|
40
|
-
if (delError)
|
|
78
|
+
if (delError)
|
|
41
79
|
p.log.error('Could not delete app version')
|
|
42
|
-
|
|
43
|
-
|
|
80
|
+
// We should not care too much, most is in r2 anyways :/
|
|
81
|
+
// program.error('')
|
|
44
82
|
|
|
45
83
|
const { error: dbError } = await supabase
|
|
46
84
|
.from('apps')
|
package/src/app/set.ts
CHANGED
|
@@ -5,8 +5,8 @@ import mime from 'mime'
|
|
|
5
5
|
import { program } from 'commander'
|
|
6
6
|
import * as p from '@clack/prompts'
|
|
7
7
|
import type { Options } from '../api/app'
|
|
8
|
-
import {
|
|
9
|
-
import { createSupabaseClient, findSavedKey, formatError, getConfig, verifyUser } from '../utils'
|
|
8
|
+
import { checkAppExistsAndHasPermissionOrgErr, newIconPath } from '../api/app'
|
|
9
|
+
import { OrganizationPerm, createSupabaseClient, findSavedKey, formatError, getConfig, verifyUser } from '../utils'
|
|
10
10
|
|
|
11
11
|
export async function setApp(appId: string, options: Options) {
|
|
12
12
|
p.intro(`Set app`)
|
|
@@ -26,11 +26,11 @@ export async function setApp(appId: string, options: Options) {
|
|
|
26
26
|
|
|
27
27
|
const userId = await verifyUser(supabase, options.apikey, ['write', 'all'])
|
|
28
28
|
// Check we have app access to this appId
|
|
29
|
-
await
|
|
29
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, OrganizationPerm.admin)
|
|
30
30
|
|
|
31
31
|
const { name, icon, retention } = options
|
|
32
32
|
|
|
33
|
-
if (retention &&
|
|
33
|
+
if (retention && Number.isNaN(Number(retention))) {
|
|
34
34
|
p.log.error(`retention value must be a number`)
|
|
35
35
|
program.error(``)
|
|
36
36
|
}
|
package/src/bundle/cleanup.ts
CHANGED
|
@@ -6,9 +6,9 @@ import promptSync from 'prompt-sync'
|
|
|
6
6
|
import type { SupabaseClient } from '@supabase/supabase-js'
|
|
7
7
|
import type { Database } from '../types/supabase.types'
|
|
8
8
|
import type { OptionsBase } from '../utils'
|
|
9
|
-
import { createSupabaseClient, findSavedKey, getConfig, getHumanDate, verifyUser } from '../utils'
|
|
9
|
+
import { OrganizationPerm, createSupabaseClient, findSavedKey, getConfig, getHumanDate, verifyUser } from '../utils'
|
|
10
10
|
import { deleteSpecificVersion, displayBundles, getActiveAppVersions, getChannelsVersion } from '../api/versions'
|
|
11
|
-
import {
|
|
11
|
+
import { checkAppExistsAndHasPermissionOrgErr } from '../api/app'
|
|
12
12
|
import { checkLatest } from '../api/update'
|
|
13
13
|
|
|
14
14
|
interface Options extends OptionsBase {
|
|
@@ -57,15 +57,14 @@ export async function cleanupBundle(appid: string, options: Options) {
|
|
|
57
57
|
}
|
|
58
58
|
const supabase = await createSupabaseClient(options.apikey)
|
|
59
59
|
|
|
60
|
-
const userId = await verifyUser(supabase, options.apikey)
|
|
60
|
+
const userId = await verifyUser(supabase, options.apikey, ['write', 'all'])
|
|
61
61
|
|
|
62
62
|
// Check we have app access to this appId
|
|
63
|
-
await
|
|
63
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appid, OrganizationPerm.write)
|
|
64
64
|
p.log.info(`Querying all available versions in Capgo`)
|
|
65
65
|
|
|
66
66
|
// Get all active app versions we might possibly be able to cleanup
|
|
67
|
-
let allVersions: (Database['public']['Tables']['app_versions']['Row'] & { keep?: string })[] = await
|
|
68
|
-
getActiveAppVersions(supabase, appid, userId)
|
|
67
|
+
let allVersions: (Database['public']['Tables']['app_versions']['Row'] & { keep?: string })[] = await getActiveAppVersions(supabase, appid, userId)
|
|
69
68
|
|
|
70
69
|
const versionInUse = await getChannelsVersion(supabase, appid)
|
|
71
70
|
|
|
@@ -2,8 +2,8 @@ import * as p from '@clack/prompts'
|
|
|
2
2
|
import { program } from 'commander'
|
|
3
3
|
import { Table } from 'console-table-printer'
|
|
4
4
|
import type { OptionsBase } from '../utils'
|
|
5
|
-
import { checkCompatibility, createSupabaseClient, findSavedKey, getConfig, verifyUser } from '../utils'
|
|
6
|
-
import {
|
|
5
|
+
import { OrganizationPerm, checkCompatibility, createSupabaseClient, findSavedKey, getConfig, verifyUser } from '../utils'
|
|
6
|
+
import { checkAppExistsAndHasPermissionOrgErr } from '../api/app'
|
|
7
7
|
|
|
8
8
|
interface Options extends OptionsBase {
|
|
9
9
|
channel?: string
|
|
@@ -36,7 +36,7 @@ export async function checkCompatibilityCommand(appId: string, options: Options)
|
|
|
36
36
|
await verifyUser(supabase, options.apikey, ['write', 'all', 'read', 'upload'])
|
|
37
37
|
|
|
38
38
|
// Check we have app access to this appId
|
|
39
|
-
await
|
|
39
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, OrganizationPerm.read)
|
|
40
40
|
|
|
41
41
|
// const hashedLocalDependencies = new Map(dependenciesObject
|
|
42
42
|
// .filter((a) => !!a.native && a.native !== undefined)
|
package/src/bundle/delete.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import process from 'node:process'
|
|
2
2
|
import { program } from 'commander'
|
|
3
3
|
import * as p from '@clack/prompts'
|
|
4
|
-
import {
|
|
4
|
+
import { checkAppExistsAndHasPermissionOrgErr } from '../api/app'
|
|
5
5
|
import type { OptionsBase } from '../utils'
|
|
6
|
-
import { createSupabaseClient, findSavedKey, getConfig, verifyUser } from '../utils'
|
|
6
|
+
import { OrganizationPerm, createSupabaseClient, findSavedKey, getConfig, verifyUser } from '../utils'
|
|
7
7
|
import { deleteSpecificVersion } from '../api/versions'
|
|
8
8
|
|
|
9
9
|
interface Options extends OptionsBase {
|
|
@@ -28,7 +28,7 @@ export async function deleteBundle(bundleId: string, appId: string, options: Opt
|
|
|
28
28
|
|
|
29
29
|
const userId = await verifyUser(supabase, options.apikey, ['write', 'all'])
|
|
30
30
|
// Check we have app access to this appId
|
|
31
|
-
await
|
|
31
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, OrganizationPerm.write)
|
|
32
32
|
|
|
33
33
|
appId = appId || config?.app?.appId
|
|
34
34
|
if (!options.apikey) {
|
package/src/bundle/list.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import process from 'node:process'
|
|
2
2
|
import { program } from 'commander'
|
|
3
3
|
import * as p from '@clack/prompts'
|
|
4
|
-
import {
|
|
4
|
+
import { checkAppExistsAndHasPermissionOrgErr } from '../api/app'
|
|
5
5
|
import { displayBundles, getActiveAppVersions } from '../api/versions'
|
|
6
6
|
import type { OptionsBase } from '../utils'
|
|
7
|
-
import { createSupabaseClient, findSavedKey, getConfig, verifyUser } from '../utils'
|
|
7
|
+
import { OrganizationPerm, createSupabaseClient, findSavedKey, getConfig, verifyUser } from '../utils'
|
|
8
8
|
import { checkLatest } from '../api/update'
|
|
9
9
|
|
|
10
10
|
export async function listBundle(appId: string, options: OptionsBase) {
|
|
@@ -30,7 +30,7 @@ export async function listBundle(appId: string, options: OptionsBase) {
|
|
|
30
30
|
p.log.info(`Querying available versions of: ${appId} in Capgo`)
|
|
31
31
|
|
|
32
32
|
// Check we have app access to this appId
|
|
33
|
-
await
|
|
33
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, OrganizationPerm.read)
|
|
34
34
|
|
|
35
35
|
// Get all active app versions we might possibly be able to cleanup
|
|
36
36
|
const allVersions = await getActiveAppVersions(supabase, appId, userId)
|
package/src/bundle/unlink.ts
CHANGED
|
@@ -4,11 +4,12 @@ import * as p from '@clack/prompts'
|
|
|
4
4
|
import { getVersionData } from '../api/versions'
|
|
5
5
|
import { checkVersionNotUsedInDeviceOverride } from '../api/devices_override'
|
|
6
6
|
import { checkVersionNotUsedInChannel } from '../api/channels'
|
|
7
|
-
import {
|
|
7
|
+
import { checkAppExistsAndHasPermissionOrgErr } from '../api/app'
|
|
8
8
|
import type {
|
|
9
9
|
OptionsBase,
|
|
10
10
|
} from '../utils'
|
|
11
11
|
import {
|
|
12
|
+
OrganizationPerm,
|
|
12
13
|
checkPlanValid,
|
|
13
14
|
createSupabaseClient,
|
|
14
15
|
findSavedKey,
|
|
@@ -23,7 +24,7 @@ interface Options extends OptionsBase {
|
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
export async function unlinkDevice(channel: string, appId: string, options: Options) {
|
|
26
|
-
p.intro(`Unlink bundle`)
|
|
27
|
+
p.intro(`Unlink bundle ${options.apikey}`)
|
|
27
28
|
options.apikey = options.apikey || findSavedKey()
|
|
28
29
|
const config = await getConfig()
|
|
29
30
|
appId = appId || config?.app?.appId
|
|
@@ -46,9 +47,9 @@ export async function unlinkDevice(channel: string, appId: string, options: Opti
|
|
|
46
47
|
}
|
|
47
48
|
const supabase = await createSupabaseClient(options.apikey)
|
|
48
49
|
|
|
49
|
-
const userId = await verifyUser(supabase, options.apikey, ['
|
|
50
|
+
const userId = await verifyUser(supabase, options.apikey, ['all', 'write'])
|
|
50
51
|
// Check we have app access to this appId
|
|
51
|
-
await
|
|
52
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, OrganizationPerm.write)
|
|
52
53
|
|
|
53
54
|
if (!channel) {
|
|
54
55
|
p.log.error('Missing argument, you need to provide a channel')
|
|
@@ -57,8 +58,8 @@ export async function unlinkDevice(channel: string, appId: string, options: Opti
|
|
|
57
58
|
try {
|
|
58
59
|
await checkPlanValid(supabase, userId, options.apikey, appId)
|
|
59
60
|
|
|
60
|
-
const versionData = await getVersionData(supabase, appId,
|
|
61
|
-
await checkVersionNotUsedInChannel(supabase, appId,
|
|
61
|
+
const versionData = await getVersionData(supabase, appId, bundle)
|
|
62
|
+
await checkVersionNotUsedInChannel(supabase, appId, versionData)
|
|
62
63
|
await checkVersionNotUsedInDeviceOverride(supabase, appId, versionData)
|
|
63
64
|
await snag.track({
|
|
64
65
|
channel: 'bundle',
|
package/src/bundle/upload.ts
CHANGED
|
@@ -15,6 +15,7 @@ import type {
|
|
|
15
15
|
OptionsBase,
|
|
16
16
|
} from '../utils'
|
|
17
17
|
import {
|
|
18
|
+
EMPTY_UUID,
|
|
18
19
|
OrganizationPerm,
|
|
19
20
|
baseKeyPub,
|
|
20
21
|
checkCompatibility,
|
|
@@ -60,7 +61,7 @@ export async function uploadBundle(appid: string, options: Options, shouldExit =
|
|
|
60
61
|
p.intro(`Uploading`)
|
|
61
62
|
await checkLatest()
|
|
62
63
|
let { bundle, path, channel } = options
|
|
63
|
-
const { external, key
|
|
64
|
+
const { external, key, displayIvSession, autoMinUpdateVersion, ignoreMetadataCheck } = options
|
|
64
65
|
let { minUpdateVersion } = options
|
|
65
66
|
options.apikey = options.apikey || findSavedKey()
|
|
66
67
|
const snag = useLogSnag()
|
|
@@ -212,9 +213,6 @@ export async function uploadBundle(appid: string, options: Options, shouldExit =
|
|
|
212
213
|
p.log.error(`Version already exists ${formatError(appVersionError)}`)
|
|
213
214
|
program.error('')
|
|
214
215
|
}
|
|
215
|
-
// make bundle safe for s3 name https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-keys.html
|
|
216
|
-
const safeBundle = bundle.replace(/[^a-zA-Z0-9-_.!*'()]/g, '__')
|
|
217
|
-
const fileName = `${safeBundle}.zip`
|
|
218
216
|
|
|
219
217
|
let sessionKey
|
|
220
218
|
let checksum = ''
|
|
@@ -227,7 +225,11 @@ export async function uploadBundle(appid: string, options: Options, shouldExit =
|
|
|
227
225
|
s.start(`Calculating checksum`)
|
|
228
226
|
checksum = await getChecksum(zipped, 'crc32')
|
|
229
227
|
s.stop(`Checksum: ${checksum}`)
|
|
230
|
-
|
|
228
|
+
// key should be undefined or a string if false it should ingore encryption
|
|
229
|
+
if (key === false) {
|
|
230
|
+
p.log.info(`Encryption ignored`)
|
|
231
|
+
}
|
|
232
|
+
else if (key || existsSync(baseKeyPub)) {
|
|
231
233
|
const publicKey = typeof key === 'string' ? key : baseKeyPub
|
|
232
234
|
let keyData = options.keyData || ''
|
|
233
235
|
// check if publicKey exist
|
|
@@ -314,8 +316,7 @@ It will be also visible in your dashboard\n`)
|
|
|
314
316
|
const appOwner = await getAppOwner(supabase, appid)
|
|
315
317
|
|
|
316
318
|
const versionData = {
|
|
317
|
-
bucket_id: external ? undefined : fileName,
|
|
318
|
-
user_id: appOwner,
|
|
319
|
+
// bucket_id: external ? undefined : fileName,
|
|
319
320
|
name: bundle,
|
|
320
321
|
app_id: appid,
|
|
321
322
|
session_key: sessionKey,
|
|
@@ -323,6 +324,8 @@ It will be also visible in your dashboard\n`)
|
|
|
323
324
|
storage_provider: external ? 'external' : 'r2-direct',
|
|
324
325
|
minUpdateVersion,
|
|
325
326
|
native_packages: nativePackages,
|
|
327
|
+
owner_org: EMPTY_UUID,
|
|
328
|
+
user_id: userId,
|
|
326
329
|
checksum,
|
|
327
330
|
}
|
|
328
331
|
const { error: dbError } = await updateOrCreateVersion(supabase, versionData)
|
|
@@ -334,7 +337,7 @@ It will be also visible in your dashboard\n`)
|
|
|
334
337
|
const spinner = p.spinner()
|
|
335
338
|
spinner.start(`Uploading Bundle`)
|
|
336
339
|
|
|
337
|
-
const url = await uploadUrl(supabase, appid,
|
|
340
|
+
const url = await uploadUrl(supabase, appid, bundle)
|
|
338
341
|
if (!url) {
|
|
339
342
|
p.log.error(`Cannot get upload url`)
|
|
340
343
|
program.error('')
|
|
@@ -368,6 +371,7 @@ It will be also visible in your dashboard\n`)
|
|
|
368
371
|
app_id: appid,
|
|
369
372
|
created_by: appOwner,
|
|
370
373
|
version: versionId,
|
|
374
|
+
owner_org: EMPTY_UUID,
|
|
371
375
|
})
|
|
372
376
|
if (dbError3) {
|
|
373
377
|
p.log.error(`Cannot set channel, the upload key is not allowed to do that, use the "all" for this. ${formatError(dbError3)}`)
|
package/src/bundle/zip.ts
CHANGED
|
@@ -112,15 +112,6 @@ export async function zipBundle(appId: string, options: Options) {
|
|
|
112
112
|
if (!json)
|
|
113
113
|
s2.stop(`Saved to ${name}`)
|
|
114
114
|
|
|
115
|
-
if (options.json) {
|
|
116
|
-
const output = {
|
|
117
|
-
bundle,
|
|
118
|
-
filename: name,
|
|
119
|
-
checksum,
|
|
120
|
-
}
|
|
121
|
-
p.log.info(formatError(output))
|
|
122
|
-
}
|
|
123
|
-
|
|
124
115
|
await snag.track({
|
|
125
116
|
channel: 'app',
|
|
126
117
|
event: 'App zip',
|
|
@@ -133,5 +124,16 @@ export async function zipBundle(appId: string, options: Options) {
|
|
|
133
124
|
|
|
134
125
|
if (!json)
|
|
135
126
|
p.outro(`Done ✅`)
|
|
127
|
+
|
|
128
|
+
if (json) {
|
|
129
|
+
const output = {
|
|
130
|
+
bundle,
|
|
131
|
+
filename: name,
|
|
132
|
+
checksum,
|
|
133
|
+
}
|
|
134
|
+
// Keep the console log and stringify
|
|
135
|
+
// eslint-disable-next-line no-console
|
|
136
|
+
console.log(JSON.stringify(output, null, 2))
|
|
137
|
+
}
|
|
136
138
|
process.exit()
|
|
137
139
|
}
|
package/src/channel/add.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import process from 'node:process'
|
|
2
2
|
import { program } from 'commander'
|
|
3
3
|
import * as p from '@clack/prompts'
|
|
4
|
-
import {
|
|
4
|
+
import { checkAppExistsAndHasPermissionOrgErr } from '../api/app'
|
|
5
5
|
import { createChannel, findUnknownVersion } from '../api/channels'
|
|
6
6
|
import type { OptionsBase } from '../utils'
|
|
7
|
-
import { createSupabaseClient, findSavedKey, getConfig, useLogSnag, verifyUser } from '../utils'
|
|
7
|
+
import { EMPTY_UUID, OrganizationPerm, createSupabaseClient, findSavedKey, getConfig, useLogSnag, verifyUser } from '../utils'
|
|
8
8
|
|
|
9
9
|
interface Options extends OptionsBase {
|
|
10
10
|
default?: boolean
|
|
@@ -29,7 +29,7 @@ export async function addChannel(channelId: string, appId: string, options: Opti
|
|
|
29
29
|
|
|
30
30
|
const userId = await verifyUser(supabase, options.apikey, ['write', 'all'])
|
|
31
31
|
// Check we have app access to this appId
|
|
32
|
-
await
|
|
32
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, OrganizationPerm.admin)
|
|
33
33
|
|
|
34
34
|
p.log.info(`Creating channel ${appId}#${channelId} to Capgo`)
|
|
35
35
|
try {
|
|
@@ -42,7 +42,7 @@ export async function addChannel(channelId: string, appId: string, options: Opti
|
|
|
42
42
|
name: channelId,
|
|
43
43
|
app_id: appId,
|
|
44
44
|
version: data.id,
|
|
45
|
-
|
|
45
|
+
owner_org: EMPTY_UUID,
|
|
46
46
|
})
|
|
47
47
|
p.log.success(`Channel created ✅`)
|
|
48
48
|
await snag.track({
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import process from 'node:process'
|
|
2
2
|
import { program } from 'commander'
|
|
3
3
|
import * as p from '@clack/prompts'
|
|
4
|
-
import {
|
|
4
|
+
import { checkAppExistsAndHasPermissionOrgErr } from '../api/app'
|
|
5
5
|
import type { OptionsBase } from '../utils'
|
|
6
|
-
import { createSupabaseClient, findSavedKey, getConfig, verifyUser } from '../utils'
|
|
6
|
+
import { OrganizationPerm, createSupabaseClient, findSavedKey, getConfig, verifyUser } from '../utils'
|
|
7
7
|
|
|
8
8
|
interface Options extends OptionsBase {
|
|
9
9
|
channel?: string
|
|
@@ -36,9 +36,9 @@ export async function currentBundle(channel: string, appId: string, options: Opt
|
|
|
36
36
|
}
|
|
37
37
|
const supabase = await createSupabaseClient(options.apikey)
|
|
38
38
|
|
|
39
|
-
const
|
|
39
|
+
const _userId = await verifyUser(supabase, options.apikey, ['write', 'all', 'read'])
|
|
40
40
|
// Check we have app access to this appId
|
|
41
|
-
await
|
|
41
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, OrganizationPerm.read)
|
|
42
42
|
|
|
43
43
|
if (!channel) {
|
|
44
44
|
p.log.error(`Please provide a channel to get the bundle from.`)
|
|
@@ -50,7 +50,6 @@ export async function currentBundle(channel: string, appId: string, options: Opt
|
|
|
50
50
|
.select('version ( name )')
|
|
51
51
|
.eq('name', channel)
|
|
52
52
|
.eq('app_id', appId)
|
|
53
|
-
.eq('created_by', userId)
|
|
54
53
|
.limit(1)
|
|
55
54
|
|
|
56
55
|
if (error || supabaseChannel.length === 0) {
|
package/src/channel/delete.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import process from 'node:process'
|
|
2
2
|
import { program } from 'commander'
|
|
3
3
|
import * as p from '@clack/prompts'
|
|
4
|
-
import {
|
|
4
|
+
import { checkAppExistsAndHasPermissionOrgErr } from '../api/app'
|
|
5
5
|
import { delChannel } from '../api/channels'
|
|
6
6
|
import type { OptionsBase } from '../utils'
|
|
7
|
-
import { createSupabaseClient, findSavedKey, getConfig, useLogSnag, verifyUser } from '../utils'
|
|
7
|
+
import { OrganizationPerm, createSupabaseClient, findSavedKey, getConfig, useLogSnag, verifyUser } from '../utils'
|
|
8
8
|
|
|
9
9
|
export async function deleteChannel(channelId: string, appId: string, options: OptionsBase) {
|
|
10
10
|
p.intro(`Delete channel`)
|
|
@@ -25,7 +25,7 @@ export async function deleteChannel(channelId: string, appId: string, options: O
|
|
|
25
25
|
|
|
26
26
|
const userId = await verifyUser(supabase, options.apikey, ['write', 'all'])
|
|
27
27
|
// Check we have app access to this appId
|
|
28
|
-
await
|
|
28
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, OrganizationPerm.admin)
|
|
29
29
|
|
|
30
30
|
p.log.info(`Deleting channel ${appId}#${channelId} from Capgo`)
|
|
31
31
|
try {
|
package/src/channel/list.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import process from 'node:process'
|
|
2
2
|
import { program } from 'commander'
|
|
3
3
|
import * as p from '@clack/prompts'
|
|
4
|
-
import {
|
|
4
|
+
import { checkAppExistsAndHasPermissionOrgErr } from '../api/app'
|
|
5
5
|
import { displayChannels, getActiveChannels } from '../api/channels'
|
|
6
6
|
import type { OptionsBase } from '../utils'
|
|
7
|
-
import { createSupabaseClient, findSavedKey, getConfig, useLogSnag, verifyUser } from '../utils'
|
|
7
|
+
import { OrganizationPerm, createSupabaseClient, findSavedKey, getConfig, useLogSnag, verifyUser } from '../utils'
|
|
8
8
|
|
|
9
9
|
export async function listChannels(appId: string, options: OptionsBase) {
|
|
10
10
|
p.intro(`List channels`)
|
|
@@ -24,7 +24,7 @@ export async function listChannels(appId: string, options: OptionsBase) {
|
|
|
24
24
|
|
|
25
25
|
const userId = await verifyUser(supabase, options.apikey, ['write', 'all', 'read', 'upload'])
|
|
26
26
|
// Check we have app access to this appId
|
|
27
|
-
await
|
|
27
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, OrganizationPerm.read)
|
|
28
28
|
|
|
29
29
|
p.log.info(`Querying available channels in Capgo`)
|
|
30
30
|
|
package/src/channel/set.ts
CHANGED
|
@@ -2,11 +2,12 @@ import process from 'node:process'
|
|
|
2
2
|
import { program } from 'commander'
|
|
3
3
|
import * as p from '@clack/prompts'
|
|
4
4
|
import type { Database } from '../types/supabase.types'
|
|
5
|
-
import {
|
|
5
|
+
import { checkAppExistsAndHasPermissionOrgErr } from '../api/app'
|
|
6
6
|
import type {
|
|
7
7
|
OptionsBase,
|
|
8
8
|
} from '../utils'
|
|
9
9
|
import {
|
|
10
|
+
OrganizationPerm,
|
|
10
11
|
checkPlanValid,
|
|
11
12
|
createSupabaseClient,
|
|
12
13
|
findSavedKey,
|
|
@@ -51,7 +52,7 @@ export async function setChannel(channel: string, appId: string, options: Option
|
|
|
51
52
|
|
|
52
53
|
const userId = await verifyUser(supabase, options.apikey, ['write', 'all'])
|
|
53
54
|
// Check we have app access to this appId
|
|
54
|
-
await
|
|
55
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, OrganizationPerm.admin)
|
|
55
56
|
|
|
56
57
|
const { bundle, latest, downgrade, upgrade, ios, android, selfAssign, state, disableAutoUpdate } = options
|
|
57
58
|
if (!channel) {
|
package/src/index.ts
CHANGED
|
@@ -148,12 +148,13 @@ bundle
|
|
|
148
148
|
.action(listBundle)
|
|
149
149
|
.option('-a, --apikey <apikey>', 'apikey to link to your account')
|
|
150
150
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
151
|
+
// TODO: Fix this command!
|
|
152
|
+
// bundle
|
|
153
|
+
// .command('unlink [appId]')
|
|
154
|
+
// .description('Unlink a bundle in Capgo Cloud')
|
|
155
|
+
// .action(listBundle)
|
|
156
|
+
// .option('-a, --apikey <apikey>', 'apikey to link to your account')
|
|
157
|
+
// .option('-b, --bundle <bundle>', 'bundle version number of the bundle to unlink')
|
|
157
158
|
|
|
158
159
|
bundle
|
|
159
160
|
.command('cleanup [appId]')
|