@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.
- package/README.md +197 -37
- package/dist/index.js +327 -65172
- package/dist/package.json +83 -0
- package/package.json +48 -61
- package/.eslintignore +0 -4
- package/.github/FUNDING.yml +0 -1
- package/.github/workflows/build.yml +0 -46
- package/.github/workflows/bump_version.yml +0 -56
- package/.github/workflows/test.yml +0 -30
- package/.prettierignore +0 -6
- package/.vscode/launch.json +0 -23
- package/.vscode/settings.json +0 -5
- package/.vscode/tasks.json +0 -42
- package/CHANGELOG.md +0 -2727
- package/build.mjs +0 -23
- package/bun.lockb +0 -0
- package/capacitor.config.ts +0 -33
- package/crypto_explained.png +0 -0
- package/eslint.config.js +0 -3
- package/renovate.json +0 -23
- package/src/api/app.ts +0 -75
- package/src/api/channels.ts +0 -142
- package/src/api/crypto.ts +0 -121
- package/src/api/devices_override.ts +0 -41
- package/src/api/update.ts +0 -12
- package/src/api/versions.ts +0 -98
- package/src/app/add.ts +0 -154
- package/src/app/debug.ts +0 -214
- package/src/app/delete.ts +0 -68
- package/src/app/info.ts +0 -87
- package/src/app/list.ts +0 -63
- package/src/app/set.ts +0 -94
- package/src/bundle/check.ts +0 -42
- package/src/bundle/cleanup.ts +0 -128
- package/src/bundle/compatibility.ts +0 -70
- package/src/bundle/decrypt.ts +0 -65
- package/src/bundle/delete.ts +0 -53
- package/src/bundle/encrypt.ts +0 -69
- package/src/bundle/list.ts +0 -43
- package/src/bundle/unlink.ts +0 -80
- package/src/bundle/upload.ts +0 -434
- package/src/bundle/zip.ts +0 -137
- package/src/channel/add.ts +0 -73
- package/src/channel/currentBundle.ts +0 -73
- package/src/channel/delete.ts +0 -51
- package/src/channel/list.ts +0 -49
- package/src/channel/set.ts +0 -171
- package/src/index.ts +0 -285
- package/src/init.ts +0 -301
- package/src/key.ts +0 -158
- package/src/login.ts +0 -66
- package/src/types/capacitor__cli.d.ts +0 -6
- package/src/types/supabase.types.ts +0 -2065
- package/src/utils.ts +0 -719
- 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/tsconfig.json +0 -39
package/src/bundle/check.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs'
|
|
2
|
-
import path from 'node:path'
|
|
3
|
-
|
|
4
|
-
function searchInFile(filePath: string, searchString: string) {
|
|
5
|
-
const content = fs.readFileSync(filePath, 'utf8')
|
|
6
|
-
return content.includes(searchString)
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function searchInDirectory(dirPath: string, searchString: string) {
|
|
10
|
-
const files = fs.readdirSync(dirPath)
|
|
11
|
-
for (const file of files) {
|
|
12
|
-
const filePath = path.join(dirPath, file)
|
|
13
|
-
const stats = fs.statSync(filePath)
|
|
14
|
-
|
|
15
|
-
if (stats.isDirectory()) {
|
|
16
|
-
if (searchInDirectory(filePath, searchString))
|
|
17
|
-
return true
|
|
18
|
-
}
|
|
19
|
-
else if (stats.isFile() && path.extname(filePath) === '.js') {
|
|
20
|
-
if (searchInFile(filePath, searchString))
|
|
21
|
-
return true
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return false
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export function checkIndexPosition(dirPath: string): boolean {
|
|
29
|
-
// look for index.html in the root folder or if there only one folder in the root folder look for index.html in this folder
|
|
30
|
-
const files = fs.readdirSync(dirPath)
|
|
31
|
-
if (files.length === 1) {
|
|
32
|
-
const filePath = path.join(dirPath, files[0])
|
|
33
|
-
const stats = fs.statSync(filePath)
|
|
34
|
-
if (stats.isDirectory())
|
|
35
|
-
return checkIndexPosition(filePath)
|
|
36
|
-
}
|
|
37
|
-
const index = files.indexOf('index.html')
|
|
38
|
-
if (index > -1)
|
|
39
|
-
return true
|
|
40
|
-
|
|
41
|
-
return false
|
|
42
|
-
}
|
package/src/bundle/cleanup.ts
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import process from 'node:process'
|
|
2
|
-
import { program } from 'commander'
|
|
3
|
-
import semver from 'semver/preload'
|
|
4
|
-
import * as p from '@clack/prompts'
|
|
5
|
-
import promptSync from 'prompt-sync'
|
|
6
|
-
import type { SupabaseClient } from '@supabase/supabase-js'
|
|
7
|
-
import type { Database } from '../types/supabase.types'
|
|
8
|
-
import type { OptionsBase } from '../utils'
|
|
9
|
-
import { createSupabaseClient, findSavedKey, getConfig, getHumanDate, verifyUser } from '../utils'
|
|
10
|
-
import { deleteSpecificVersion, displayBundles, getActiveAppVersions, getChannelsVersion } from '../api/versions'
|
|
11
|
-
import { checkAppExistsAndHasPermissionErr } from '../api/app'
|
|
12
|
-
import { checkLatest } from '../api/update'
|
|
13
|
-
|
|
14
|
-
interface Options extends OptionsBase {
|
|
15
|
-
version: string
|
|
16
|
-
bundle: string
|
|
17
|
-
keep: number
|
|
18
|
-
force: boolean
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const prompt = promptSync()
|
|
22
|
-
|
|
23
|
-
async function removeVersions(toRemove: Database['public']['Tables']['app_versions']['Row'][], supabase: SupabaseClient<Database>, appid: string, userId: string) {
|
|
24
|
-
// call deleteSpecificVersion one by one from toRemove sync
|
|
25
|
-
for await (const row of toRemove) {
|
|
26
|
-
p.log.warn(`Removing ${row.name} created on ${(getHumanDate(row.created_at))}`)
|
|
27
|
-
await deleteSpecificVersion(supabase, appid, userId, row.name)
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function getRemovableVersionsInSemverRange(data: Database['public']['Tables']['app_versions']['Row'][], bundle: string, nextMajor: string) {
|
|
32
|
-
const toRemove: Database['public']['Tables']['app_versions']['Row'][] = []
|
|
33
|
-
|
|
34
|
-
data?.forEach((row) => {
|
|
35
|
-
if (semver.gte(row.name, bundle) && semver.lt(row.name, `${nextMajor}`))
|
|
36
|
-
toRemove.push(row)
|
|
37
|
-
})
|
|
38
|
-
return toRemove
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export async function cleanupBundle(appid: string, options: Options) {
|
|
42
|
-
p.intro(`Cleanup versions in Capgo`)
|
|
43
|
-
await checkLatest()
|
|
44
|
-
options.apikey = options.apikey || findSavedKey()
|
|
45
|
-
const { bundle, keep = 4 } = options
|
|
46
|
-
const force = options.force || false
|
|
47
|
-
|
|
48
|
-
const config = await getConfig()
|
|
49
|
-
appid = appid || config?.app?.appId
|
|
50
|
-
if (!options.apikey) {
|
|
51
|
-
p.log.error('Missing API key, you need to provide an API key to delete your app')
|
|
52
|
-
program.error('')
|
|
53
|
-
}
|
|
54
|
-
if (!appid) {
|
|
55
|
-
p.log.error('Missing argument, you need to provide a appid, or be in a capacitor project')
|
|
56
|
-
program.error('')
|
|
57
|
-
}
|
|
58
|
-
const supabase = await createSupabaseClient(options.apikey)
|
|
59
|
-
|
|
60
|
-
const userId = await verifyUser(supabase, options.apikey)
|
|
61
|
-
|
|
62
|
-
// Check we have app access to this appId
|
|
63
|
-
await checkAppExistsAndHasPermissionErr(supabase, options.apikey, appid)
|
|
64
|
-
p.log.info(`Querying all available versions in Capgo`)
|
|
65
|
-
|
|
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)
|
|
69
|
-
|
|
70
|
-
const versionInUse = await getChannelsVersion(supabase, appid)
|
|
71
|
-
|
|
72
|
-
p.log.info(`Total active versions in Capgo: ${allVersions?.length}`)
|
|
73
|
-
if (allVersions?.length === 0) {
|
|
74
|
-
p.log.error('No versions found, aborting cleanup')
|
|
75
|
-
return
|
|
76
|
-
}
|
|
77
|
-
if (bundle) {
|
|
78
|
-
const nextMajor = `${semver.inc(bundle, 'major')}`
|
|
79
|
-
p.log.info(`Querying available versions in Capgo between ${bundle} and ${nextMajor}`)
|
|
80
|
-
|
|
81
|
-
// Get all app versions that are in the given range
|
|
82
|
-
allVersions = getRemovableVersionsInSemverRange(allVersions, bundle, nextMajor) as (Database['public']['Tables']['app_versions']['Row'] & { keep: string })[]
|
|
83
|
-
|
|
84
|
-
p.log.info(`Active versions in Capgo between ${bundle} and ${nextMajor}: ${allVersions?.length}`)
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Slice to keep and remove
|
|
88
|
-
|
|
89
|
-
const toRemove: (Database['public']['Tables']['app_versions']['Row'] & { keep?: string })[] = []
|
|
90
|
-
// Slice to keep and remove
|
|
91
|
-
let kept = 0
|
|
92
|
-
allVersions.forEach((v) => {
|
|
93
|
-
const isInUse = versionInUse.find(vi => vi === v.id)
|
|
94
|
-
if (kept < keep || isInUse) {
|
|
95
|
-
if (isInUse)
|
|
96
|
-
v.keep = '✅ (Linked to channel)'
|
|
97
|
-
else
|
|
98
|
-
v.keep = '✅'
|
|
99
|
-
|
|
100
|
-
kept += 1
|
|
101
|
-
}
|
|
102
|
-
else {
|
|
103
|
-
v.keep = '❌'
|
|
104
|
-
toRemove.push(v)
|
|
105
|
-
}
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
if (toRemove.length === 0) {
|
|
109
|
-
p.log.warn('Nothing to be removed, aborting removal...')
|
|
110
|
-
return
|
|
111
|
-
}
|
|
112
|
-
displayBundles(allVersions)
|
|
113
|
-
|
|
114
|
-
// Check user wants to clean that all up
|
|
115
|
-
if (!force) {
|
|
116
|
-
const result = prompt('Do you want to continue removing the versions specified? Type yes to confirm: ')
|
|
117
|
-
if (result !== 'yes') {
|
|
118
|
-
p.log.warn('Not confirmed, aborting removal...')
|
|
119
|
-
return
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// Yes, lets clean it up
|
|
124
|
-
p.log.success('You have confirmed removal, removing versions now')
|
|
125
|
-
await removeVersions(toRemove, supabase, appid, userId)
|
|
126
|
-
p.outro(`Done ✅`)
|
|
127
|
-
process.exit()
|
|
128
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import * as p from '@clack/prompts'
|
|
2
|
-
import { program } from 'commander'
|
|
3
|
-
import { Table } from 'console-table-printer'
|
|
4
|
-
import type { OptionsBase } from '../utils'
|
|
5
|
-
import { checkCompatibility, createSupabaseClient, findSavedKey, getConfig, verifyUser } from '../utils'
|
|
6
|
-
import { checkAppExistsAndHasPermissionErr } from '../api/app'
|
|
7
|
-
|
|
8
|
-
interface Options extends OptionsBase {
|
|
9
|
-
channel?: string
|
|
10
|
-
text?: boolean
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export async function checkCompatibilityCommand(appId: string, options: Options) {
|
|
14
|
-
p.intro(`Check compatibility`)
|
|
15
|
-
options.apikey = options.apikey || findSavedKey()
|
|
16
|
-
const config = await getConfig()
|
|
17
|
-
appId = appId || config?.app?.appId
|
|
18
|
-
|
|
19
|
-
const { channel } = options
|
|
20
|
-
|
|
21
|
-
if (!channel) {
|
|
22
|
-
p.log.error('Missing argument, you need to provide a channel')
|
|
23
|
-
program.error('')
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (!options.apikey) {
|
|
27
|
-
p.log.error('Missing API key, you need to provide a API key to upload your bundle')
|
|
28
|
-
program.error('')
|
|
29
|
-
}
|
|
30
|
-
if (!appId) {
|
|
31
|
-
p.log.error('Missing argument, you need to provide a appId, or be in a capacitor project')
|
|
32
|
-
program.error('')
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const supabase = await createSupabaseClient(options.apikey)
|
|
36
|
-
await verifyUser(supabase, options.apikey, ['write', 'all', 'read', 'upload'])
|
|
37
|
-
|
|
38
|
-
// Check we have app access to this appId
|
|
39
|
-
await checkAppExistsAndHasPermissionErr(supabase, options.apikey, appId)
|
|
40
|
-
|
|
41
|
-
// const hashedLocalDependencies = new Map(dependenciesObject
|
|
42
|
-
// .filter((a) => !!a.native && a.native !== undefined)
|
|
43
|
-
// .map((a) => [a.name, a]))
|
|
44
|
-
|
|
45
|
-
// const nativePackages = Array.from(hashedLocalDependencies, ([name, value]) => ({ name, version: value.version }))
|
|
46
|
-
// await supabase.from('app_versions').update({ native_packages: nativePackages }).eq('id', '9654')
|
|
47
|
-
|
|
48
|
-
const { finalCompatibility } = await checkCompatibility(supabase, appId, channel)
|
|
49
|
-
|
|
50
|
-
const t = new Table({
|
|
51
|
-
title: 'Compatibility',
|
|
52
|
-
charLength: { '❌': 2, '✅': 2 },
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
const yesSymbol = options.text ? 'Yes' : '✅'
|
|
56
|
-
const noSymbol = options.text ? 'No' : '❌'
|
|
57
|
-
|
|
58
|
-
finalCompatibility.forEach((data) => {
|
|
59
|
-
const { name, localVersion, remoteVersion } = data
|
|
60
|
-
|
|
61
|
-
t.addRow({
|
|
62
|
-
'Package': name,
|
|
63
|
-
'Local version': localVersion ?? 'None',
|
|
64
|
-
'Remote version': remoteVersion ?? 'None',
|
|
65
|
-
'Compatible': remoteVersion === localVersion ? yesSymbol : noSymbol,
|
|
66
|
-
})
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
p.log.success(t.render())
|
|
70
|
-
}
|
package/src/bundle/decrypt.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { existsSync, readFileSync, writeFileSync } from 'node:fs'
|
|
2
|
-
import process from 'node:process'
|
|
3
|
-
import { program } from 'commander'
|
|
4
|
-
import * as p from '@clack/prompts'
|
|
5
|
-
import { decryptSource } from '../api/crypto'
|
|
6
|
-
import { baseKeyPub, checKOldEncryption, getConfig } from '../utils'
|
|
7
|
-
import { checkLatest } from '../api/update'
|
|
8
|
-
|
|
9
|
-
interface Options {
|
|
10
|
-
key?: string
|
|
11
|
-
keyData?: string
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export async function decryptZip(zipPath: string, ivsessionKey: string, options: Options) {
|
|
15
|
-
p.intro(`Decrypt zip file`)
|
|
16
|
-
await checkLatest()
|
|
17
|
-
// write in file .capgo the apikey in home directory
|
|
18
|
-
|
|
19
|
-
if (!existsSync(zipPath)) {
|
|
20
|
-
p.log.error(`Zip not found at the path ${zipPath}`)
|
|
21
|
-
program.error('')
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const config = await getConfig()
|
|
25
|
-
const { extConfig } = config.app
|
|
26
|
-
// console.log('config - ', config)
|
|
27
|
-
// console.log('extConfig - ', extConfig)
|
|
28
|
-
|
|
29
|
-
await checKOldEncryption()
|
|
30
|
-
// console.log(`There ${hasPrivateKeyInConfig ? 'IS' : 'IS NOT'} a privateKey in the config`);
|
|
31
|
-
|
|
32
|
-
if (!options.key && !existsSync(baseKeyPub) && !extConfig.plugins?.CapacitorUpdater?.publicKey) {
|
|
33
|
-
p.log.error(`Public key not found at the path ${baseKeyPub} or in ${config.app.extConfigFilePath}`)
|
|
34
|
-
program.error('')
|
|
35
|
-
}
|
|
36
|
-
const keyPath = options.key || baseKeyPub
|
|
37
|
-
// check if private exist
|
|
38
|
-
|
|
39
|
-
let publicKey = extConfig?.plugins?.CapacitorUpdater?.publicKey
|
|
40
|
-
|
|
41
|
-
if (!existsSync(keyPath) && !publicKey) {
|
|
42
|
-
p.log.error(`Cannot find a public key at ${keyPath} or as keyData option or in ${config.app.extConfigFilePath}`)
|
|
43
|
-
program.error('')
|
|
44
|
-
}
|
|
45
|
-
else if (existsSync(keyPath)) {
|
|
46
|
-
// open with fs publicKey path
|
|
47
|
-
const keyFile = readFileSync(keyPath)
|
|
48
|
-
publicKey = keyFile.toString()
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// let's doublecheck and make sure the key we are using is the right type based on the decryption strategy
|
|
52
|
-
if (publicKey && !publicKey.startsWith('-----BEGIN RSA PUBLIC KEY-----')) {
|
|
53
|
-
p.log.error(`the public key provided is not a valid RSA Public key`)
|
|
54
|
-
program.error('')
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const zipFile = readFileSync(zipPath)
|
|
58
|
-
|
|
59
|
-
const decodedZip = decryptSource(zipFile, ivsessionKey, options.keyData ?? publicKey ?? '')
|
|
60
|
-
// write decodedZip in a file
|
|
61
|
-
writeFileSync(`${zipPath}_decrypted.zip`, decodedZip)
|
|
62
|
-
p.log.success(`Decrypted zip file at ${zipPath}_decrypted.zip`)
|
|
63
|
-
p.outro(`Done ✅`)
|
|
64
|
-
process.exit()
|
|
65
|
-
}
|
package/src/bundle/delete.ts
DELETED
|
@@ -1,53 +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, verifyUser } from '../utils'
|
|
7
|
-
import { deleteSpecificVersion } from '../api/versions'
|
|
8
|
-
|
|
9
|
-
interface Options extends OptionsBase {
|
|
10
|
-
bundle: string
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export async function deleteBundle(bundleId: string, appId: string, options: Options) {
|
|
14
|
-
p.intro(`Delete bundle`)
|
|
15
|
-
options.apikey = options.apikey || findSavedKey()
|
|
16
|
-
const config = await getConfig()
|
|
17
|
-
appId = appId || config?.app?.appId
|
|
18
|
-
|
|
19
|
-
if (!options.apikey) {
|
|
20
|
-
p.log.error('Missing API key, you need to provide a API key to upload your bundle')
|
|
21
|
-
program.error('')
|
|
22
|
-
}
|
|
23
|
-
if (!appId) {
|
|
24
|
-
p.log.error('Missing argument, you need to provide a appId, or be in a capacitor project')
|
|
25
|
-
program.error('')
|
|
26
|
-
}
|
|
27
|
-
const supabase = await createSupabaseClient(options.apikey)
|
|
28
|
-
|
|
29
|
-
const userId = await verifyUser(supabase, options.apikey, ['write', 'all'])
|
|
30
|
-
// Check we have app access to this appId
|
|
31
|
-
await checkAppExistsAndHasPermissionErr(supabase, options.apikey, appId)
|
|
32
|
-
|
|
33
|
-
appId = appId || config?.app?.appId
|
|
34
|
-
if (!options.apikey) {
|
|
35
|
-
p.log.error('Missing API key, you need to provide an API key to delete your app')
|
|
36
|
-
program.error('')
|
|
37
|
-
}
|
|
38
|
-
if (!bundleId) {
|
|
39
|
-
p.log.error('Missing argument, you need to provide a bundleId, or be in a capacitor project')
|
|
40
|
-
program.error('')
|
|
41
|
-
}
|
|
42
|
-
if (!appId) {
|
|
43
|
-
p.log.error('Missing argument, you need to provide a appId, or be in a capacitor project')
|
|
44
|
-
program.error('')
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
p.log.info(`Deleting bundle ${appId}@${bundleId} from Capgo`)
|
|
48
|
-
|
|
49
|
-
await deleteSpecificVersion(supabase, appId, userId, bundleId)
|
|
50
|
-
p.log.success(`Bundle ${appId}@${bundleId} deleted in Capgo`)
|
|
51
|
-
p.outro(`Done`)
|
|
52
|
-
process.exit()
|
|
53
|
-
}
|
package/src/bundle/encrypt.ts
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { existsSync, readFileSync, writeFileSync } from 'node:fs'
|
|
2
|
-
import process from 'node:process'
|
|
3
|
-
import { program } from 'commander'
|
|
4
|
-
import ciDetect from 'ci-info'
|
|
5
|
-
import * as p from '@clack/prompts'
|
|
6
|
-
import { checkLatest } from '../api/update'
|
|
7
|
-
import { encryptSource } from '../api/crypto'
|
|
8
|
-
import { baseKey, checKOldEncryption, getLocalConfig } from '../utils'
|
|
9
|
-
|
|
10
|
-
interface Options {
|
|
11
|
-
key?: string
|
|
12
|
-
keyData?: string
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export async function encryptZip(zipPath: string, options: Options) {
|
|
16
|
-
p.intro(`Encryption`)
|
|
17
|
-
|
|
18
|
-
await checkLatest()
|
|
19
|
-
const localConfig = await getLocalConfig()
|
|
20
|
-
// console.log('localConfig - ', localConfig)
|
|
21
|
-
// console.log('config - ', config)
|
|
22
|
-
|
|
23
|
-
await checKOldEncryption()
|
|
24
|
-
|
|
25
|
-
if (!existsSync(zipPath)) {
|
|
26
|
-
p.log.error(`Error: Zip not found at the path ${zipPath}`)
|
|
27
|
-
program.error('')
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const keyPath = options.key || baseKey
|
|
31
|
-
// check if privateKey exist
|
|
32
|
-
|
|
33
|
-
let privateKey = options.keyData || ''
|
|
34
|
-
|
|
35
|
-
if (!existsSync(keyPath) && !privateKey) {
|
|
36
|
-
p.log.warning(`Cannot find a private key at ${keyPath} or as a keyData option`)
|
|
37
|
-
if (ciDetect.isCI) {
|
|
38
|
-
p.log.error(`Error: Missing key`)
|
|
39
|
-
program.error('')
|
|
40
|
-
}
|
|
41
|
-
const res = await p.confirm({ message: `Do you want to use our private key?` })
|
|
42
|
-
if (!res) {
|
|
43
|
-
p.log.error(`Error: Missing private key`)
|
|
44
|
-
program.error('')
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
privateKey = localConfig.signKey || ''
|
|
48
|
-
}
|
|
49
|
-
else if (existsSync(keyPath)) {
|
|
50
|
-
// open with fs key path
|
|
51
|
-
const keyFile = readFileSync(keyPath)
|
|
52
|
-
privateKey = keyFile.toString()
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// let's doublecheck and make sure the key we are using is the right type based on the decryption strategy
|
|
56
|
-
if (privateKey && !privateKey.startsWith('-----BEGIN RSA PRIVATE KEY-----')) {
|
|
57
|
-
p.log.error(`the private key provided is not a valid RSA Private key`)
|
|
58
|
-
program.error('')
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const zipFile = readFileSync(zipPath)
|
|
62
|
-
const encodedZip = encryptSource(zipFile, privateKey)
|
|
63
|
-
p.log.success(`ivSessionKey: ${encodedZip.ivSessionKey}`)
|
|
64
|
-
// write decodedZip in a file
|
|
65
|
-
writeFileSync(`${zipPath}_encrypted.zip`, encodedZip.encryptedData)
|
|
66
|
-
p.log.success(`Encrypted zip saved at ${zipPath}_encrypted.zip`)
|
|
67
|
-
p.outro(`Done ✅`)
|
|
68
|
-
process.exit()
|
|
69
|
-
}
|
package/src/bundle/list.ts
DELETED
|
@@ -1,43 +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 { displayBundles, getActiveAppVersions } from '../api/versions'
|
|
6
|
-
import type { OptionsBase } from '../utils'
|
|
7
|
-
import { createSupabaseClient, findSavedKey, getConfig, verifyUser } from '../utils'
|
|
8
|
-
import { checkLatest } from '../api/update'
|
|
9
|
-
|
|
10
|
-
export async function listBundle(appId: string, options: OptionsBase) {
|
|
11
|
-
p.intro(`List bundles`)
|
|
12
|
-
await checkLatest()
|
|
13
|
-
options.apikey = options.apikey || findSavedKey()
|
|
14
|
-
const config = await getConfig()
|
|
15
|
-
|
|
16
|
-
appId = appId || config?.app?.appId
|
|
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
|
-
|
|
26
|
-
const supabase = await createSupabaseClient(options.apikey)
|
|
27
|
-
|
|
28
|
-
const userId = await verifyUser(supabase, options.apikey, ['write', 'all', 'read', 'upload'])
|
|
29
|
-
|
|
30
|
-
p.log.info(`Querying available versions of: ${appId} in Capgo`)
|
|
31
|
-
|
|
32
|
-
// Check we have app access to this appId
|
|
33
|
-
await checkAppExistsAndHasPermissionErr(supabase, options.apikey, appId)
|
|
34
|
-
|
|
35
|
-
// Get all active app versions we might possibly be able to cleanup
|
|
36
|
-
const allVersions = await getActiveAppVersions(supabase, appId, userId)
|
|
37
|
-
|
|
38
|
-
p.log.info(`Active versions in Capgo: ${allVersions?.length}`)
|
|
39
|
-
|
|
40
|
-
displayBundles(allVersions)
|
|
41
|
-
p.outro(`Done ✅`)
|
|
42
|
-
process.exit()
|
|
43
|
-
}
|
package/src/bundle/unlink.ts
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import process from 'node:process'
|
|
2
|
-
import { program } from 'commander'
|
|
3
|
-
import * as p from '@clack/prompts'
|
|
4
|
-
import { getVersionData } from '../api/versions'
|
|
5
|
-
import { checkVersionNotUsedInDeviceOverride } from '../api/devices_override'
|
|
6
|
-
import { checkVersionNotUsedInChannel } from '../api/channels'
|
|
7
|
-
import { checkAppExistsAndHasPermissionErr } from '../api/app'
|
|
8
|
-
import type {
|
|
9
|
-
OptionsBase,
|
|
10
|
-
} from '../utils'
|
|
11
|
-
import {
|
|
12
|
-
checkPlanValid,
|
|
13
|
-
createSupabaseClient,
|
|
14
|
-
findSavedKey,
|
|
15
|
-
formatError,
|
|
16
|
-
getConfig,
|
|
17
|
-
useLogSnag,
|
|
18
|
-
verifyUser,
|
|
19
|
-
} from '../utils'
|
|
20
|
-
|
|
21
|
-
interface Options extends OptionsBase {
|
|
22
|
-
bundle?: string
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export async function unlinkDevice(channel: string, appId: string, options: Options) {
|
|
26
|
-
p.intro(`Unlink bundle`)
|
|
27
|
-
options.apikey = options.apikey || findSavedKey()
|
|
28
|
-
const config = await getConfig()
|
|
29
|
-
appId = appId || config?.app?.appId
|
|
30
|
-
const snag = useLogSnag()
|
|
31
|
-
let { bundle } = options
|
|
32
|
-
|
|
33
|
-
bundle = bundle || config?.app?.package?.version
|
|
34
|
-
|
|
35
|
-
if (!options.apikey) {
|
|
36
|
-
p.log.error('Missing API key, you need to provide a API key to upload your bundle')
|
|
37
|
-
program.error('')
|
|
38
|
-
}
|
|
39
|
-
if (!appId) {
|
|
40
|
-
p.log.error('Missing argument, you need to provide a appId, or be in a capacitor project')
|
|
41
|
-
program.error('')
|
|
42
|
-
}
|
|
43
|
-
if (!bundle) {
|
|
44
|
-
p.log.error('Missing argument, you need to provide a bundle, or be in a capacitor project')
|
|
45
|
-
program.error('')
|
|
46
|
-
}
|
|
47
|
-
const supabase = await createSupabaseClient(options.apikey)
|
|
48
|
-
|
|
49
|
-
const userId = await verifyUser(supabase, options.apikey, ['write', 'all'])
|
|
50
|
-
// Check we have app access to this appId
|
|
51
|
-
await checkAppExistsAndHasPermissionErr(supabase, options.apikey, appId)
|
|
52
|
-
|
|
53
|
-
if (!channel) {
|
|
54
|
-
p.log.error('Missing argument, you need to provide a channel')
|
|
55
|
-
program.error('')
|
|
56
|
-
}
|
|
57
|
-
try {
|
|
58
|
-
await checkPlanValid(supabase, userId, options.apikey, appId)
|
|
59
|
-
|
|
60
|
-
const versionData = await getVersionData(supabase, appId, userId, bundle)
|
|
61
|
-
await checkVersionNotUsedInChannel(supabase, appId, userId, versionData)
|
|
62
|
-
await checkVersionNotUsedInDeviceOverride(supabase, appId, versionData)
|
|
63
|
-
await snag.track({
|
|
64
|
-
channel: 'bundle',
|
|
65
|
-
event: 'Unlink bundle',
|
|
66
|
-
icon: '✅',
|
|
67
|
-
user_id: userId,
|
|
68
|
-
tags: {
|
|
69
|
-
'app-id': appId,
|
|
70
|
-
},
|
|
71
|
-
notify: false,
|
|
72
|
-
}).catch()
|
|
73
|
-
}
|
|
74
|
-
catch (err) {
|
|
75
|
-
p.log.error(`Unknow error ${formatError(err)}`)
|
|
76
|
-
program.error('')
|
|
77
|
-
}
|
|
78
|
-
p.outro('Done ✅')
|
|
79
|
-
process.exit()
|
|
80
|
-
}
|