@capgo/cli 4.13.2 → 4.13.4
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/dist/index.js +103 -103
- package/package.json +1 -1
- package/.github/FUNDING.yml +0 -1
- package/.github/workflows/autofix.yml +0 -25
- package/.github/workflows/build.yml +0 -46
- package/.github/workflows/bump_version.yml +0 -56
- package/.github/workflows/check_posix_paths.yml +0 -229
- package/.github/workflows/test.yml +0 -30
- package/.prettierignore +0 -6
- package/.vscode/launch.json +0 -23
- package/.vscode/settings.json +0 -46
- package/.vscode/tasks.json +0 -42
- package/CHANGELOG.md +0 -3392
- package/build.mjs +0 -21
- package/bun.lockb +0 -0
- package/bunfig.toml +0 -2
- package/capacitor.config.ts +0 -33
- package/crypto_explained.png +0 -0
- package/eslint.config.js +0 -10
- package/renovate.json +0 -23
- package/src/api/app.ts +0 -55
- package/src/api/channels.ts +0 -163
- package/src/api/crypto.ts +0 -116
- package/src/api/devices_override.ts +0 -41
- package/src/api/update.ts +0 -13
- package/src/api/versions.ts +0 -101
- package/src/app/add.ts +0 -157
- package/src/app/debug.ts +0 -258
- package/src/app/delete.ts +0 -110
- package/src/app/info.ts +0 -99
- package/src/app/list.ts +0 -67
- package/src/app/set.ts +0 -96
- package/src/bundle/check.ts +0 -42
- package/src/bundle/cleanup.ts +0 -123
- package/src/bundle/compatibility.ts +0 -70
- package/src/bundle/decrypt.ts +0 -54
- package/src/bundle/delete.ts +0 -52
- package/src/bundle/encrypt.ts +0 -60
- package/src/bundle/list.ts +0 -42
- package/src/bundle/unlink.ts +0 -88
- package/src/bundle/upload.ts +0 -552
- package/src/bundle/zip.ts +0 -145
- package/src/channel/add.ts +0 -80
- package/src/channel/currentBundle.ts +0 -72
- package/src/channel/delete.ts +0 -57
- package/src/channel/list.ts +0 -49
- package/src/channel/set.ts +0 -179
- package/src/config/index.ts +0 -156
- package/src/index.ts +0 -310
- package/src/init.ts +0 -495
- package/src/key.ts +0 -135
- package/src/login.ts +0 -70
- package/src/types/capacitor__cli.d.ts +0 -6
- package/src/types/supabase.types.ts +0 -2123
- package/src/user/account.ts +0 -11
- package/src/utils.ts +0 -1076
- package/test/VerifyZip.java +0 -83
- package/test/check-posix-paths.js +0 -21
- package/test/chunk_convert.ts +0 -28
- package/test/data.ts +0 -18769
- package/test/test_headers_rls.ts +0 -24
- package/test/test_semver.ts +0 -13
- package/test/test_upload/app.js +0 -3
- package/test/test_upload/assets/check-posix-paths.js +0 -21
- package/test/test_upload/index.html +0 -0
- package/test/test_zip_swift/Package.resolved +0 -24
- package/test/test_zip_swift/Package.swift +0 -29
- package/test/test_zip_swift/Sources/main.swift +0 -80
- package/tsconfig.json +0 -39
package/src/channel/add.ts
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { exit } from 'node:process'
|
|
2
|
-
import { program } from 'commander'
|
|
3
|
-
import { intro, log, outro } from '@clack/prompts'
|
|
4
|
-
import { checkAppExistsAndHasPermissionOrgErr } from '../api/app'
|
|
5
|
-
import { createChannel, findUnknownVersion } from '../api/channels'
|
|
6
|
-
import type { OptionsBase } from '../utils'
|
|
7
|
-
import { OrganizationPerm, createSupabaseClient, findSavedKey, formatError, getConfig, getOrganizationId, useLogSnag, verifyUser } from '../utils'
|
|
8
|
-
|
|
9
|
-
interface Options extends OptionsBase {
|
|
10
|
-
default?: boolean
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export async function addChannel(channelId: string, appId: string, options: Options, shouldExit = true) {
|
|
14
|
-
intro(`Create channel`)
|
|
15
|
-
options.apikey = options.apikey || findSavedKey()
|
|
16
|
-
const extConfig = await getConfig()
|
|
17
|
-
appId = appId || extConfig?.config?.appId
|
|
18
|
-
const snag = useLogSnag()
|
|
19
|
-
|
|
20
|
-
if (!options.apikey) {
|
|
21
|
-
log.error('Missing API key, you need to provide a API key to upload your bundle')
|
|
22
|
-
program.error('')
|
|
23
|
-
}
|
|
24
|
-
if (!appId) {
|
|
25
|
-
log.error('Missing argument, you need to provide a appId, or be in a capacitor project')
|
|
26
|
-
program.error('')
|
|
27
|
-
}
|
|
28
|
-
const supabase = await createSupabaseClient(options.apikey)
|
|
29
|
-
|
|
30
|
-
await verifyUser(supabase, options.apikey, ['write', 'all'])
|
|
31
|
-
// Check we have app access to this appId
|
|
32
|
-
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, OrganizationPerm.admin)
|
|
33
|
-
|
|
34
|
-
log.info(`Creating channel ${appId}#${channelId} to Capgo`)
|
|
35
|
-
try {
|
|
36
|
-
const data = await findUnknownVersion(supabase, appId)
|
|
37
|
-
const orgId = await getOrganizationId(supabase, appId)
|
|
38
|
-
if (!data) {
|
|
39
|
-
log.error(`Cannot find default version for channel creation, please contact Capgo support 🤨`)
|
|
40
|
-
program.error('')
|
|
41
|
-
}
|
|
42
|
-
const res = await createChannel(supabase, {
|
|
43
|
-
name: channelId,
|
|
44
|
-
app_id: appId,
|
|
45
|
-
version: data.id,
|
|
46
|
-
owner_org: orgId,
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
if (res.error) {
|
|
50
|
-
log.error(`Cannot create Channel 🙀\n${formatError(res.error)}`)
|
|
51
|
-
program.error('')
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
log.success(`Channel created ✅`)
|
|
55
|
-
await snag.track({
|
|
56
|
-
channel: 'channel',
|
|
57
|
-
event: 'Create channel',
|
|
58
|
-
icon: '✅',
|
|
59
|
-
user_id: orgId,
|
|
60
|
-
tags: {
|
|
61
|
-
'app-id': appId,
|
|
62
|
-
'channel': channelId,
|
|
63
|
-
},
|
|
64
|
-
notify: false,
|
|
65
|
-
}).catch()
|
|
66
|
-
}
|
|
67
|
-
catch (error) {
|
|
68
|
-
log.error(`Cannot create Channel 🙀`)
|
|
69
|
-
return false
|
|
70
|
-
}
|
|
71
|
-
if (shouldExit) {
|
|
72
|
-
outro(`Done ✅`)
|
|
73
|
-
exit()
|
|
74
|
-
}
|
|
75
|
-
return true
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export async function addChannelCommand(apikey: string, appId: string, options: Options) {
|
|
79
|
-
addChannel(apikey, appId, options, true)
|
|
80
|
-
}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { exit } from 'node:process'
|
|
2
|
-
import { program } from 'commander'
|
|
3
|
-
import { intro, log } from '@clack/prompts'
|
|
4
|
-
import { checkAppExistsAndHasPermissionOrgErr } from '../api/app'
|
|
5
|
-
import type { OptionsBase } from '../utils'
|
|
6
|
-
import { OrganizationPerm, createSupabaseClient, findSavedKey, getConfig, verifyUser } from '../utils'
|
|
7
|
-
|
|
8
|
-
interface Options extends OptionsBase {
|
|
9
|
-
channel?: string
|
|
10
|
-
quiet?: boolean
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
interface Channel {
|
|
14
|
-
version: {
|
|
15
|
-
name: string
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export async function currentBundle(channel: string, appId: string, options: Options) {
|
|
20
|
-
const { quiet } = options
|
|
21
|
-
|
|
22
|
-
if (!quiet)
|
|
23
|
-
intro(`List current bundle`)
|
|
24
|
-
|
|
25
|
-
options.apikey = options.apikey || findSavedKey(quiet)
|
|
26
|
-
const extConfig = await getConfig()
|
|
27
|
-
appId = appId || extConfig?.config?.appId
|
|
28
|
-
|
|
29
|
-
if (!options.apikey) {
|
|
30
|
-
log.error('Missing API key, you need to provide a API key to upload your bundle')
|
|
31
|
-
program.error('')
|
|
32
|
-
}
|
|
33
|
-
if (!appId) {
|
|
34
|
-
log.error('Missing argument, you need to provide a appId, or be in a capacitor project')
|
|
35
|
-
program.error('')
|
|
36
|
-
}
|
|
37
|
-
const supabase = await createSupabaseClient(options.apikey)
|
|
38
|
-
|
|
39
|
-
const _userId = await verifyUser(supabase, options.apikey, ['write', 'all', 'read'])
|
|
40
|
-
// Check we have app access to this appId
|
|
41
|
-
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, OrganizationPerm.read)
|
|
42
|
-
|
|
43
|
-
if (!channel) {
|
|
44
|
-
log.error(`Please provide a channel to get the bundle from.`)
|
|
45
|
-
program.error('')
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const { data: supabaseChannel, error } = await supabase
|
|
49
|
-
.from('channels')
|
|
50
|
-
.select('version ( name )')
|
|
51
|
-
.eq('name', channel)
|
|
52
|
-
.eq('app_id', appId)
|
|
53
|
-
.limit(1)
|
|
54
|
-
|
|
55
|
-
if (error || supabaseChannel.length === 0) {
|
|
56
|
-
log.error(`Error retrieving channel ${channel} for app ${appId}. Perhaps the channel does not exists?`)
|
|
57
|
-
program.error('')
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const { version } = supabaseChannel[0] as any as Channel
|
|
61
|
-
if (!version) {
|
|
62
|
-
log.error(`Error retrieving channel ${channel} for app ${appId}. Perhaps the channel does not exists?`)
|
|
63
|
-
program.error('')
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (!quiet)
|
|
67
|
-
log.info(`Current bundle for channel ${channel} is ${version.name}`)
|
|
68
|
-
else
|
|
69
|
-
log.info(version.name)
|
|
70
|
-
|
|
71
|
-
exit()
|
|
72
|
-
}
|
package/src/channel/delete.ts
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { exit } from 'node:process'
|
|
2
|
-
import { program } from 'commander'
|
|
3
|
-
import { intro, log, outro } from '@clack/prompts'
|
|
4
|
-
import { checkAppExistsAndHasPermissionOrgErr } from '../api/app'
|
|
5
|
-
import { delChannel } from '../api/channels'
|
|
6
|
-
import type { OptionsBase } from '../utils'
|
|
7
|
-
import { OrganizationPerm, createSupabaseClient, findSavedKey, formatError, getConfig, getOrganizationId, useLogSnag, verifyUser } from '../utils'
|
|
8
|
-
|
|
9
|
-
export async function deleteChannel(channelId: string, appId: string, options: OptionsBase) {
|
|
10
|
-
intro(`Delete channel`)
|
|
11
|
-
options.apikey = options.apikey || findSavedKey()
|
|
12
|
-
const extConfig = await getConfig()
|
|
13
|
-
appId = appId || extConfig?.config?.appId
|
|
14
|
-
const snag = useLogSnag()
|
|
15
|
-
|
|
16
|
-
if (!options.apikey) {
|
|
17
|
-
log.error('Missing API key, you need to provide a API key to upload your bundle')
|
|
18
|
-
program.error('')
|
|
19
|
-
}
|
|
20
|
-
if (!appId) {
|
|
21
|
-
log.error('Missing argument, you need to provide a appId, or be in a capacitor project')
|
|
22
|
-
program.error('')
|
|
23
|
-
}
|
|
24
|
-
const supabase = await createSupabaseClient(options.apikey)
|
|
25
|
-
|
|
26
|
-
const userId = await verifyUser(supabase, options.apikey, ['write', 'all'])
|
|
27
|
-
// Check we have app access to this appId
|
|
28
|
-
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, OrganizationPerm.admin)
|
|
29
|
-
|
|
30
|
-
log.info(`Deleting channel ${appId}#${channelId} from Capgo`)
|
|
31
|
-
try {
|
|
32
|
-
const deleteStatus = await delChannel(supabase, channelId, appId, userId)
|
|
33
|
-
if (deleteStatus.error) {
|
|
34
|
-
log.error(`Cannot delete Channel 🙀 ${formatError(deleteStatus.error)}`)
|
|
35
|
-
program.error('')
|
|
36
|
-
}
|
|
37
|
-
const orgId = await getOrganizationId(supabase, appId)
|
|
38
|
-
log.success(`Channel deleted`)
|
|
39
|
-
await snag.track({
|
|
40
|
-
channel: 'channel',
|
|
41
|
-
event: 'Delete channel',
|
|
42
|
-
icon: '✅',
|
|
43
|
-
user_id: orgId,
|
|
44
|
-
tags: {
|
|
45
|
-
'user-id': userId,
|
|
46
|
-
'app-id': appId,
|
|
47
|
-
'channel': channelId,
|
|
48
|
-
},
|
|
49
|
-
notify: false,
|
|
50
|
-
}).catch()
|
|
51
|
-
}
|
|
52
|
-
catch (error) {
|
|
53
|
-
log.error(`Cannot delete Channel 🙀`)
|
|
54
|
-
}
|
|
55
|
-
outro(`Done ✅`)
|
|
56
|
-
exit()
|
|
57
|
-
}
|
package/src/channel/list.ts
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { exit } from 'node:process'
|
|
2
|
-
import { program } from 'commander'
|
|
3
|
-
import { intro, log, outro } from '@clack/prompts'
|
|
4
|
-
import { checkAppExistsAndHasPermissionOrgErr } from '../api/app'
|
|
5
|
-
import { displayChannels, getActiveChannels } from '../api/channels'
|
|
6
|
-
import type { OptionsBase } from '../utils'
|
|
7
|
-
import { OrganizationPerm, createSupabaseClient, findSavedKey, getConfig, useLogSnag, verifyUser } from '../utils'
|
|
8
|
-
|
|
9
|
-
export async function listChannels(appId: string, options: OptionsBase) {
|
|
10
|
-
intro(`List channels`)
|
|
11
|
-
options.apikey = options.apikey || findSavedKey()
|
|
12
|
-
const extConfig = await getConfig()
|
|
13
|
-
appId = appId || extConfig?.config?.appId
|
|
14
|
-
const snag = useLogSnag()
|
|
15
|
-
|
|
16
|
-
if (!options.apikey)
|
|
17
|
-
log.error('Missing API key, you need to provide a API key to upload your bundle')
|
|
18
|
-
|
|
19
|
-
if (!appId) {
|
|
20
|
-
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', 'read', 'upload'])
|
|
26
|
-
// Check we have app access to this appId
|
|
27
|
-
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, OrganizationPerm.read)
|
|
28
|
-
|
|
29
|
-
log.info(`Querying available channels in Capgo`)
|
|
30
|
-
|
|
31
|
-
// Get all active app versions we might possibly be able to cleanup
|
|
32
|
-
const allVersions = await getActiveChannels(supabase, appId)
|
|
33
|
-
|
|
34
|
-
log.info(`Active channels in Capgo: ${allVersions?.length}`)
|
|
35
|
-
|
|
36
|
-
displayChannels(allVersions)
|
|
37
|
-
await snag.track({
|
|
38
|
-
channel: 'channel',
|
|
39
|
-
event: 'List channel',
|
|
40
|
-
icon: '✅',
|
|
41
|
-
user_id: userId,
|
|
42
|
-
tags: {
|
|
43
|
-
'app-id': appId,
|
|
44
|
-
},
|
|
45
|
-
notify: false,
|
|
46
|
-
}).catch()
|
|
47
|
-
outro(`Done ✅`)
|
|
48
|
-
exit()
|
|
49
|
-
}
|
package/src/channel/set.ts
DELETED
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
import { exit } from 'node:process'
|
|
2
|
-
import { program } from 'commander'
|
|
3
|
-
import { intro, log, outro } from '@clack/prompts'
|
|
4
|
-
import type { Database } from '../types/supabase.types'
|
|
5
|
-
import { checkAppExistsAndHasPermissionOrgErr } from '../api/app'
|
|
6
|
-
import type {
|
|
7
|
-
OptionsBase,
|
|
8
|
-
} from '../utils'
|
|
9
|
-
import {
|
|
10
|
-
OrganizationPerm,
|
|
11
|
-
checkPlanValid,
|
|
12
|
-
createSupabaseClient,
|
|
13
|
-
findSavedKey,
|
|
14
|
-
formatError,
|
|
15
|
-
getConfig,
|
|
16
|
-
getOrganizationId,
|
|
17
|
-
readPackageJson,
|
|
18
|
-
updateOrCreateChannel,
|
|
19
|
-
useLogSnag,
|
|
20
|
-
verifyUser,
|
|
21
|
-
} from '../utils'
|
|
22
|
-
|
|
23
|
-
interface Options extends OptionsBase {
|
|
24
|
-
bundle: string
|
|
25
|
-
state?: string
|
|
26
|
-
downgrade?: boolean
|
|
27
|
-
latest?: boolean
|
|
28
|
-
upgrade?: boolean
|
|
29
|
-
ios?: boolean
|
|
30
|
-
android?: boolean
|
|
31
|
-
selfAssign?: boolean
|
|
32
|
-
disableAutoUpdate: string
|
|
33
|
-
dev?: boolean
|
|
34
|
-
emulator?: boolean
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const disableAutoUpdatesPossibleOptions = ['major', 'minor', 'metadata', 'patch', 'none']
|
|
38
|
-
|
|
39
|
-
export async function setChannel(channel: string, appId: string, options: Options) {
|
|
40
|
-
intro(`Set channel`)
|
|
41
|
-
options.apikey = options.apikey || findSavedKey()
|
|
42
|
-
const extConfig = await getConfig()
|
|
43
|
-
appId = appId || extConfig?.config?.appId
|
|
44
|
-
const snag = useLogSnag()
|
|
45
|
-
|
|
46
|
-
if (!options.apikey) {
|
|
47
|
-
log.error('Missing API key, you need to provide a API key to upload your bundle')
|
|
48
|
-
program.error('')
|
|
49
|
-
}
|
|
50
|
-
if (!appId) {
|
|
51
|
-
log.error('Missing argument, you need to provide a appId, or be in a capacitor project')
|
|
52
|
-
program.error('')
|
|
53
|
-
}
|
|
54
|
-
const supabase = await createSupabaseClient(options.apikey)
|
|
55
|
-
|
|
56
|
-
const userId = await verifyUser(supabase, options.apikey, ['write', 'all'])
|
|
57
|
-
// Check we have app access to this appId
|
|
58
|
-
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, OrganizationPerm.admin)
|
|
59
|
-
const orgId = await getOrganizationId(supabase, appId)
|
|
60
|
-
|
|
61
|
-
const { bundle, state, downgrade, latest, upgrade, ios, android, selfAssign, disableAutoUpdate, dev, emulator } = options
|
|
62
|
-
if (!channel) {
|
|
63
|
-
log.error('Missing argument, you need to provide a channel')
|
|
64
|
-
program.error('')
|
|
65
|
-
}
|
|
66
|
-
if (latest && bundle) {
|
|
67
|
-
log.error('Cannot set latest and bundle at the same time')
|
|
68
|
-
program.error('')
|
|
69
|
-
}
|
|
70
|
-
if (bundle == null
|
|
71
|
-
&& state == null
|
|
72
|
-
&& latest == null
|
|
73
|
-
&& downgrade == null
|
|
74
|
-
&& upgrade == null
|
|
75
|
-
&& ios == null
|
|
76
|
-
&& android == null
|
|
77
|
-
&& selfAssign == null
|
|
78
|
-
&& dev == null
|
|
79
|
-
&& emulator == null
|
|
80
|
-
&& disableAutoUpdate == null) {
|
|
81
|
-
log.error('Missing argument, you need to provide a option to set')
|
|
82
|
-
program.error('')
|
|
83
|
-
}
|
|
84
|
-
try {
|
|
85
|
-
await checkPlanValid(supabase, orgId, options.apikey, appId)
|
|
86
|
-
const channelPayload: Database['public']['Tables']['channels']['Insert'] = {
|
|
87
|
-
created_by: userId,
|
|
88
|
-
app_id: appId,
|
|
89
|
-
name: channel,
|
|
90
|
-
owner_org: orgId,
|
|
91
|
-
version: undefined as any,
|
|
92
|
-
}
|
|
93
|
-
const pack = await readPackageJson()
|
|
94
|
-
const bundleVersion = latest ? pack?.version : bundle
|
|
95
|
-
if (bundleVersion != null) {
|
|
96
|
-
const { data, error: vError } = await supabase
|
|
97
|
-
.from('app_versions')
|
|
98
|
-
.select()
|
|
99
|
-
.eq('app_id', appId)
|
|
100
|
-
.eq('name', bundleVersion)
|
|
101
|
-
.eq('user_id', userId)
|
|
102
|
-
.eq('deleted', false)
|
|
103
|
-
.single()
|
|
104
|
-
if (vError || !data) {
|
|
105
|
-
log.error(`Cannot find version ${bundleVersion}`)
|
|
106
|
-
program.error('')
|
|
107
|
-
}
|
|
108
|
-
log.info(`Set ${appId} channel: ${channel} to @${bundleVersion}`)
|
|
109
|
-
channelPayload.version = data.id
|
|
110
|
-
}
|
|
111
|
-
if (state != null) {
|
|
112
|
-
if (state === 'public' || state === 'private')
|
|
113
|
-
log.info(`Set ${appId} channel: ${channel} to public or private is deprecated, use default or normal instead`)
|
|
114
|
-
|
|
115
|
-
log.info(`Set ${appId} channel: ${channel} to ${state === 'public' || state === 'default' ? 'default' : 'normal'}`)
|
|
116
|
-
channelPayload.public = state === 'public' || state === 'default'
|
|
117
|
-
}
|
|
118
|
-
if (downgrade != null) {
|
|
119
|
-
log.info(`Set ${appId} channel: ${channel} to ${downgrade ? 'allow' : 'disallow'} downgrade`)
|
|
120
|
-
channelPayload.disableAutoUpdateUnderNative = !downgrade
|
|
121
|
-
}
|
|
122
|
-
if (ios != null) {
|
|
123
|
-
log.info(`Set ${appId} channel: ${channel} to ${ios ? 'allow' : 'disallow'} ios update`)
|
|
124
|
-
channelPayload.ios = !!ios
|
|
125
|
-
}
|
|
126
|
-
if (android != null) {
|
|
127
|
-
log.info(`Set ${appId} channel: ${channel} to ${android ? 'allow' : 'disallow'} android update`)
|
|
128
|
-
channelPayload.android = !!android
|
|
129
|
-
}
|
|
130
|
-
if (selfAssign != null) {
|
|
131
|
-
log.info(`Set ${appId} channel: ${channel} to ${selfAssign ? 'allow' : 'disallow'} self assign to this channel`)
|
|
132
|
-
channelPayload.allow_device_self_set = !!selfAssign
|
|
133
|
-
}
|
|
134
|
-
if (disableAutoUpdate != null) {
|
|
135
|
-
let finalDisableAutoUpdate = disableAutoUpdate.toLocaleLowerCase()
|
|
136
|
-
|
|
137
|
-
// The user passed an unimplemented strategy
|
|
138
|
-
if (!disableAutoUpdatesPossibleOptions.includes(finalDisableAutoUpdate)) {
|
|
139
|
-
log.error(`Channel strategy ${finalDisableAutoUpdate} is not known. The possible values are: ${disableAutoUpdatesPossibleOptions.join(', ')}.`)
|
|
140
|
-
program.error('')
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// This metadata is called differently in the database
|
|
144
|
-
if (finalDisableAutoUpdate === 'metadata')
|
|
145
|
-
finalDisableAutoUpdate = 'version_number'
|
|
146
|
-
|
|
147
|
-
// This cast is safe, look above
|
|
148
|
-
channelPayload.disableAutoUpdate = finalDisableAutoUpdate as any
|
|
149
|
-
log.info(`Set ${appId} channel: ${channel} to ${finalDisableAutoUpdate} disable update strategy to this channel`)
|
|
150
|
-
}
|
|
151
|
-
try {
|
|
152
|
-
const { error: dbError } = await updateOrCreateChannel(supabase, channelPayload)
|
|
153
|
-
if (dbError) {
|
|
154
|
-
log.error(`Cannot set channel the upload key is not allowed to do that, use the "all" for this.`)
|
|
155
|
-
program.error('')
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
catch (e) {
|
|
159
|
-
log.error(`Cannot set channel the upload key is not allowed to do that, use the "all" for this.`)
|
|
160
|
-
program.error('')
|
|
161
|
-
}
|
|
162
|
-
await snag.track({
|
|
163
|
-
channel: 'channel',
|
|
164
|
-
event: 'Set channel',
|
|
165
|
-
icon: '✅',
|
|
166
|
-
user_id: orgId,
|
|
167
|
-
tags: {
|
|
168
|
-
'app-id': appId,
|
|
169
|
-
},
|
|
170
|
-
notify: false,
|
|
171
|
-
}).catch()
|
|
172
|
-
}
|
|
173
|
-
catch (err) {
|
|
174
|
-
log.error(`Unknow error ${formatError(err)}`)
|
|
175
|
-
program.error('')
|
|
176
|
-
}
|
|
177
|
-
outro(`Done ✅`)
|
|
178
|
-
exit()
|
|
179
|
-
}
|
package/src/config/index.ts
DELETED
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
import { resolve } from 'node:path'
|
|
2
|
-
import { cwd } from 'node:process'
|
|
3
|
-
import { accessSync, constants, readFileSync, writeFileSync } from 'node:fs'
|
|
4
|
-
|
|
5
|
-
export const CONFIG_FILE_NAME_TS = 'capacitor.config.ts'
|
|
6
|
-
export const CONFIG_FILE_NAME_JSON = 'capacitor.config.json'
|
|
7
|
-
|
|
8
|
-
export interface CapacitorConfig {
|
|
9
|
-
appId: string
|
|
10
|
-
appName: string
|
|
11
|
-
webDir: string
|
|
12
|
-
plugins?: Record<string, any>
|
|
13
|
-
android?: Record<string, any>
|
|
14
|
-
[key: string]: any
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
interface ExtConfigPairs {
|
|
18
|
-
config: CapacitorConfig
|
|
19
|
-
path: string
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function parseConfigObject(configString: string): CapacitorConfig {
|
|
23
|
-
// Remove comments
|
|
24
|
-
const noComments = configString.replace(/\/\/.*|\/\*[\s\S]*?\*\//g, '')
|
|
25
|
-
|
|
26
|
-
// Parse the object
|
|
27
|
-
// eslint-disable-next-line no-new-func
|
|
28
|
-
const configObject = Function(`return ${noComments.trim()}`)()
|
|
29
|
-
|
|
30
|
-
return configObject as CapacitorConfig
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function loadConfigTs(content: string): CapacitorConfig {
|
|
34
|
-
const configRegex = /const\s+config\s*:\s*CapacitorConfig\s*=\s*(\{[\s\S]*?\n\})/
|
|
35
|
-
const match = content.match(configRegex)
|
|
36
|
-
|
|
37
|
-
if (!match) {
|
|
38
|
-
throw new Error('Unable to find config object in TypeScript file')
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return parseConfigObject(match[1])
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function loadConfigJson(content: string): CapacitorConfig {
|
|
45
|
-
return JSON.parse(content) as CapacitorConfig
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export async function loadConfig(): Promise<ExtConfigPairs | undefined> {
|
|
49
|
-
const appRootDir = cwd()
|
|
50
|
-
const extConfigFilePathTS = resolve(appRootDir, CONFIG_FILE_NAME_TS)
|
|
51
|
-
const extConfigFilePathJSON = resolve(appRootDir, CONFIG_FILE_NAME_JSON)
|
|
52
|
-
|
|
53
|
-
try {
|
|
54
|
-
accessSync(extConfigFilePathTS, constants.R_OK)
|
|
55
|
-
const configContentTS = readFileSync(extConfigFilePathTS, 'utf-8')
|
|
56
|
-
return {
|
|
57
|
-
config: loadConfigTs(configContentTS),
|
|
58
|
-
path: extConfigFilePathTS,
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
catch (err) {
|
|
62
|
-
try {
|
|
63
|
-
accessSync(extConfigFilePathJSON, constants.R_OK)
|
|
64
|
-
const configContentJSON = readFileSync(extConfigFilePathJSON, 'utf-8')
|
|
65
|
-
return {
|
|
66
|
-
config: loadConfigJson(configContentJSON),
|
|
67
|
-
path: extConfigFilePathJSON,
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
catch (err) {
|
|
71
|
-
console.error('Cannot find capacitor.config.ts or capacitor.config.json')
|
|
72
|
-
return undefined
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export async function writeConfig(config: ExtConfigPairs): Promise<void> {
|
|
78
|
-
const { config: newConfig, path } = config
|
|
79
|
-
const content = readFileSync(path, 'utf-8')
|
|
80
|
-
|
|
81
|
-
const updatedContent = path.endsWith('.json')
|
|
82
|
-
? updateJsonContent(content, newConfig)
|
|
83
|
-
: updateTsContent(content, newConfig)
|
|
84
|
-
|
|
85
|
-
writeFileSync(path, updatedContent)
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function updateJsonContent(content: string, newConfig: CapacitorConfig): string {
|
|
89
|
-
const jsonObj = JSON.parse(content)
|
|
90
|
-
if (!jsonObj.plugins)
|
|
91
|
-
jsonObj.plugins = {}
|
|
92
|
-
if (!jsonObj.plugins.CapacitorUpdater)
|
|
93
|
-
jsonObj.plugins.CapacitorUpdater = {}
|
|
94
|
-
|
|
95
|
-
Object.assign(jsonObj.plugins.CapacitorUpdater, newConfig.plugins?.CapacitorUpdater)
|
|
96
|
-
|
|
97
|
-
return JSON.stringify(jsonObj, null, detectIndentation(content))
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function updateTsContent(content: string, newConfig: CapacitorConfig): string {
|
|
101
|
-
const capUpdaterRegex = /(\bCapacitorUpdater\s*:\s*\{[^}]*\})/g
|
|
102
|
-
|
|
103
|
-
return content.replace(capUpdaterRegex, (match) => {
|
|
104
|
-
const updatedSection = updateCapacitorUpdaterSection(match, newConfig.plugins?.CapacitorUpdater || {})
|
|
105
|
-
return updatedSection
|
|
106
|
-
})
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function updateCapacitorUpdaterSection(section: string, newConfig: Record<string, any>): string {
|
|
110
|
-
const lines = section.split('\n')
|
|
111
|
-
const updatedLines = lines.map((line) => {
|
|
112
|
-
// eslint-disable-next-line regexp/no-super-linear-backtracking
|
|
113
|
-
const keyValueMatch = line.match(/^\s*(\w+)\s*:\s*(.+?),?\s*$/)
|
|
114
|
-
if (keyValueMatch) {
|
|
115
|
-
const [, key] = keyValueMatch
|
|
116
|
-
if (key in newConfig) {
|
|
117
|
-
const newValue = formatValue(newConfig[key])
|
|
118
|
-
return line.replace(/:\s*.+/, `: ${newValue},`)
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
return line
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
// Add new properties
|
|
125
|
-
Object.entries(newConfig).forEach(([key, value]) => {
|
|
126
|
-
if (!updatedLines.some(line => line.includes(`${key}:`))) {
|
|
127
|
-
const indent = detectIndentation(section)
|
|
128
|
-
updatedLines.splice(-1, 0, `${' '.repeat(indent)}${key}: ${formatValue(value)},`)
|
|
129
|
-
}
|
|
130
|
-
})
|
|
131
|
-
|
|
132
|
-
return updatedLines.join('\n')
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function formatValue(value: any): string {
|
|
136
|
-
if (typeof value === 'string') {
|
|
137
|
-
// Convert multiline strings (like RSA keys) to single line
|
|
138
|
-
if (value.includes('\n')) {
|
|
139
|
-
return `'${value.replace(/\n/g, '\\n')}'`
|
|
140
|
-
}
|
|
141
|
-
return `'${value}'`
|
|
142
|
-
}
|
|
143
|
-
if (typeof value === 'number' || typeof value === 'boolean')
|
|
144
|
-
return String(value)
|
|
145
|
-
if (Array.isArray(value))
|
|
146
|
-
return `[${value.map(formatValue).join(', ')}]`
|
|
147
|
-
if (typeof value === 'object' && value !== null) {
|
|
148
|
-
return `{ ${Object.entries(value).map(([k, v]) => `${k}: ${formatValue(v)}`).join(', ')} }`
|
|
149
|
-
}
|
|
150
|
-
return 'null'
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
function detectIndentation(content: string): number {
|
|
154
|
-
const match = content.match(/^( +)/m)
|
|
155
|
-
return match ? match[1].length : 2
|
|
156
|
-
}
|