@capgo/cli 5.0.0-alpha.7 → 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 -41
- package/dist/index.js +329 -95820
- package/dist/package.json +83 -0
- package/package.json +48 -62
- 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 -2861
- 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 -140
- 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 -101
- package/src/app/add.ts +0 -191
- package/src/app/debug.ts +0 -220
- package/src/app/delete.ts +0 -106
- package/src/app/info.ts +0 -87
- package/src/app/list.ts +0 -67
- package/src/app/set.ts +0 -94
- package/src/bundle/check.ts +0 -42
- package/src/bundle/cleanup.ts +0 -127
- 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 -86
- package/src/bundle/upload.ts +0 -516
- package/src/bundle/zip.ts +0 -139
- package/src/channel/add.ts +0 -73
- package/src/channel/currentBundle.ts +0 -72
- package/src/channel/delete.ts +0 -51
- package/src/channel/list.ts +0 -49
- package/src/channel/set.ts +0 -174
- package/src/index.ts +0 -290
- 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 -2471
- package/src/utils.ts +0 -738
- 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/build.mjs
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import * as esbuild from 'esbuild'
|
|
2
|
-
|
|
3
|
-
// Replace 'your-external-dependencies-here' with actual externals from your project
|
|
4
|
-
const external = [];
|
|
5
|
-
|
|
6
|
-
esbuild.build({
|
|
7
|
-
entryPoints: ['src/index.ts'],
|
|
8
|
-
bundle: true,
|
|
9
|
-
platform: 'node',
|
|
10
|
-
target: 'node20',
|
|
11
|
-
external,
|
|
12
|
-
outdir: 'dist',
|
|
13
|
-
sourcemap: process.env.NODE_ENV === 'development',
|
|
14
|
-
banner: {
|
|
15
|
-
js: '#!/usr/bin/env node',
|
|
16
|
-
},
|
|
17
|
-
define: {
|
|
18
|
-
'process.env.SUPA_DB': '"production"',
|
|
19
|
-
},
|
|
20
|
-
loader: {
|
|
21
|
-
'.ts': 'ts',
|
|
22
|
-
},
|
|
23
|
-
}).catch(() => process.exit(1));
|
package/bun.lockb
DELETED
|
Binary file
|
package/capacitor.config.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2020 EPAM Systems
|
|
3
|
-
*
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
* you may not use this file except in compliance with the License.
|
|
6
|
-
* You may obtain a copy of the License at
|
|
7
|
-
*
|
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
*
|
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
* See the License for the specific language governing permissions and
|
|
14
|
-
* limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
import type { CapacitorConfig } from '@capacitor/cli'
|
|
17
|
-
|
|
18
|
-
const config: CapacitorConfig = {
|
|
19
|
-
appId: 'ee.forgr.capacitor_go',
|
|
20
|
-
appName: 'Capgo',
|
|
21
|
-
webDir: 'dist',
|
|
22
|
-
bundledWebRuntime: false,
|
|
23
|
-
plugins: {
|
|
24
|
-
PushNotifications: {
|
|
25
|
-
presentationOptions: ['badge', 'sound', 'alert'],
|
|
26
|
-
},
|
|
27
|
-
SplashScreen: {
|
|
28
|
-
launchAutoHide: false,
|
|
29
|
-
},
|
|
30
|
-
},
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export default config
|
package/crypto_explained.png
DELETED
|
Binary file
|
package/eslint.config.js
DELETED
package/renovate.json
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
|
3
|
-
"extends": [
|
|
4
|
-
"config:base",
|
|
5
|
-
"schedule:earlyMondays"
|
|
6
|
-
],
|
|
7
|
-
"lockFileMaintenance": {
|
|
8
|
-
"enabled": true,
|
|
9
|
-
"automerge": true,
|
|
10
|
-
"automergeType": "branch",
|
|
11
|
-
"platformAutomerge": true
|
|
12
|
-
},
|
|
13
|
-
"packageRules": [
|
|
14
|
-
{
|
|
15
|
-
"matchUpdateTypes": [
|
|
16
|
-
"minor",
|
|
17
|
-
"patch"
|
|
18
|
-
],
|
|
19
|
-
"matchCurrentVersion": "!/^0/",
|
|
20
|
-
"automerge": true
|
|
21
|
-
}
|
|
22
|
-
]
|
|
23
|
-
}
|
package/src/api/app.ts
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import type { SupabaseClient } from '@supabase/supabase-js'
|
|
2
|
-
import * as p from '@clack/prompts'
|
|
3
|
-
import { program } from 'commander'
|
|
4
|
-
import type { Database } from '../types/supabase.types'
|
|
5
|
-
import type { OptionsBase } from '../utils'
|
|
6
|
-
import { OrganizationPerm, isAllowedApp, isAllowedAppOrg } from '../utils'
|
|
7
|
-
|
|
8
|
-
export async function checkAppExists(supabase: SupabaseClient<Database>, appid: string) {
|
|
9
|
-
const { data: app } = await supabase
|
|
10
|
-
.rpc('exist_app_v2', { appid })
|
|
11
|
-
.single()
|
|
12
|
-
return !!app
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export async function checkAppExistsAndHasPermissionErr(supabase: SupabaseClient<Database>, apikey: string, appid: string, shouldExist = true) {
|
|
16
|
-
const appExist = await checkAppExists(supabase, appid)
|
|
17
|
-
const perm = await isAllowedApp(supabase, apikey, appid)
|
|
18
|
-
|
|
19
|
-
if (appExist && !shouldExist) {
|
|
20
|
-
p.log.error(`App ${appid} already exist`)
|
|
21
|
-
program.error('')
|
|
22
|
-
}
|
|
23
|
-
if (!appExist && shouldExist) {
|
|
24
|
-
p.log.error(`App ${appid} does not exist`)
|
|
25
|
-
program.error('')
|
|
26
|
-
}
|
|
27
|
-
if (appExist && !perm) {
|
|
28
|
-
p.log.error(`App ${appid} exist and you don't have permission to access it`)
|
|
29
|
-
if (appid === 'io.ionic.starter')
|
|
30
|
-
p.log.info('Modify your appid in your capacitor.config.json file to something unique, this is a default appid for ionic starter app')
|
|
31
|
-
|
|
32
|
-
program.error('')
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export async function checkAppExistsAndHasPermissionOrgErr(supabase: SupabaseClient<Database>, apikey: string, appid: string, requiredPermission: OrganizationPerm) {
|
|
37
|
-
const permissions = await isAllowedAppOrg(supabase, apikey, appid)
|
|
38
|
-
if (!permissions.okay) {
|
|
39
|
-
switch (permissions.error) {
|
|
40
|
-
case 'INVALID_APIKEY': {
|
|
41
|
-
p.log.error('Invalid apikey, such apikey does not exists!')
|
|
42
|
-
program.error('')
|
|
43
|
-
break
|
|
44
|
-
}
|
|
45
|
-
case 'NO_APP': {
|
|
46
|
-
p.log.error(`App ${appid} does not exist`)
|
|
47
|
-
program.error('')
|
|
48
|
-
break
|
|
49
|
-
}
|
|
50
|
-
case 'NO_ORG': {
|
|
51
|
-
p.log.error('Could not find organization, please contact support to resolve this!')
|
|
52
|
-
program.error('')
|
|
53
|
-
break
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const remotePermNumber = permissions.data as number
|
|
59
|
-
const requiredPermNumber = requiredPermission as number
|
|
60
|
-
|
|
61
|
-
if (requiredPermNumber > remotePermNumber) {
|
|
62
|
-
p.log.error(`Insuficcent permissions for app ${appid}. Current permission: ${OrganizationPerm[permissions.data]}, required for this action: ${OrganizationPerm[requiredPermission]}.`)
|
|
63
|
-
program.error('')
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return permissions.data
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export interface Options extends OptionsBase {
|
|
70
|
-
name?: string
|
|
71
|
-
icon?: string
|
|
72
|
-
retention?: number
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export const newIconPath = 'assets/icon.png'
|
package/src/api/channels.ts
DELETED
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import process from 'node:process'
|
|
2
|
-
import type { SupabaseClient } from '@supabase/supabase-js'
|
|
3
|
-
import { program } from 'commander'
|
|
4
|
-
import { Table } from 'console-table-printer'
|
|
5
|
-
import * as p from '@clack/prompts'
|
|
6
|
-
import type { Database } from '../types/supabase.types'
|
|
7
|
-
import { formatError } from '../utils'
|
|
8
|
-
|
|
9
|
-
export async function checkVersionNotUsedInChannel(supabase: SupabaseClient<Database>, appid: string, versionData: Database['public']['Tables']['app_versions']['Row']) {
|
|
10
|
-
const { data: channelFound, error: errorChannel } = await supabase
|
|
11
|
-
.from('channels')
|
|
12
|
-
.select()
|
|
13
|
-
.eq('app_id', appid)
|
|
14
|
-
.eq('version', versionData.id)
|
|
15
|
-
if (errorChannel) {
|
|
16
|
-
p.log.error(`Cannot check Version ${appid}@${versionData.name}`)
|
|
17
|
-
program.error('')
|
|
18
|
-
}
|
|
19
|
-
if (channelFound && channelFound.length > 0) {
|
|
20
|
-
p.intro(`❌ Version ${appid}@${versionData.name} is used in ${channelFound.length} channel`)
|
|
21
|
-
if (await p.confirm({ message: 'unlink it?' })) {
|
|
22
|
-
// loop on all channels and set version to unknown
|
|
23
|
-
for (const channel of channelFound) {
|
|
24
|
-
const s = p.spinner()
|
|
25
|
-
s.start(`Unlinking channel ${channel.name}`)
|
|
26
|
-
const { error: errorChannelUpdate } = await supabase
|
|
27
|
-
.from('channels')
|
|
28
|
-
.update({
|
|
29
|
-
version: (await findUnknownVersion(supabase, appid))?.id,
|
|
30
|
-
})
|
|
31
|
-
.eq('id', channel.id)
|
|
32
|
-
if (errorChannelUpdate) {
|
|
33
|
-
s.stop(`Cannot update channel ${channel.name} ${formatError(errorChannelUpdate)}`)
|
|
34
|
-
process.exit(1)
|
|
35
|
-
}
|
|
36
|
-
s.stop(`✅ Channel ${channel.name} unlinked`)
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
else {
|
|
40
|
-
p.log.error(`Unlink it first`)
|
|
41
|
-
program.error('')
|
|
42
|
-
}
|
|
43
|
-
p.outro(`Version unlinked from ${channelFound.length} channel`)
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function findUnknownVersion(supabase: SupabaseClient<Database>, appId: string) {
|
|
48
|
-
return supabase
|
|
49
|
-
.from('app_versions')
|
|
50
|
-
.select('id')
|
|
51
|
-
.eq('app_id', appId)
|
|
52
|
-
.eq('name', 'unknown')
|
|
53
|
-
.throwOnError()
|
|
54
|
-
.single().then(({ data }) => data)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export function createChannel(supabase: SupabaseClient<Database>, update: Database['public']['Tables']['channels']['Insert']) {
|
|
58
|
-
return supabase
|
|
59
|
-
.from('channels')
|
|
60
|
-
.insert(update)
|
|
61
|
-
.select()
|
|
62
|
-
.single()
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export function delChannel(supabase: SupabaseClient<Database>, name: string, appId: string, _userId: string) {
|
|
66
|
-
return supabase
|
|
67
|
-
.from('channels')
|
|
68
|
-
.delete()
|
|
69
|
-
.eq('name', name)
|
|
70
|
-
.eq('app_id', appId)
|
|
71
|
-
.single()
|
|
72
|
-
}
|
|
73
|
-
interface version {
|
|
74
|
-
id: string
|
|
75
|
-
name: string
|
|
76
|
-
}
|
|
77
|
-
export function displayChannels(data: (Database['public']['Tables']['channels']['Row'] & { version?: version, secondVersion?: version })[]) {
|
|
78
|
-
const t = new Table({
|
|
79
|
-
title: 'Channels',
|
|
80
|
-
charLength: { '❌': 2, '✅': 2 },
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
// add rows with color
|
|
84
|
-
data.reverse().forEach((row) => {
|
|
85
|
-
t.addRow({
|
|
86
|
-
'Name': row.name,
|
|
87
|
-
...(row.version ? { Version: row.version.name } : undefined),
|
|
88
|
-
'Public': row.public ? '✅' : '❌',
|
|
89
|
-
'iOS': row.ios ? '❌' : '✅',
|
|
90
|
-
'Android': row.android ? '❌' : '✅',
|
|
91
|
-
'⬆️ limit': row.disableAutoUpdate,
|
|
92
|
-
'⬇️ under native': row.disableAutoUpdateUnderNative ? '❌' : '✅',
|
|
93
|
-
'Self assign': row.allow_device_self_set ? '✅' : '❌',
|
|
94
|
-
'Progressive': row.enable_progressive_deploy ? '✅' : '❌',
|
|
95
|
-
...(row.enable_progressive_deploy && row.secondVersion ? { 'Next version': row.secondVersion.name } : undefined),
|
|
96
|
-
...(row.enable_progressive_deploy && row.secondVersion ? { 'Next %': row.secondaryVersionPercentage } : undefined),
|
|
97
|
-
'AB Testing': row.enableAbTesting ? '✅' : '❌',
|
|
98
|
-
...(row.enableAbTesting && row.secondVersion ? { 'Version B': row.secondVersion } : undefined),
|
|
99
|
-
...(row.enableAbTesting && row.secondVersion ? { 'A/B %': row.secondaryVersionPercentage } : undefined),
|
|
100
|
-
'Emulator': row.allow_emulator ? '✅' : '❌',
|
|
101
|
-
'Dev 📱': row.allow_dev ? '✅' : '❌',
|
|
102
|
-
})
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
p.log.success(t.render())
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export async function getActiveChannels(supabase: SupabaseClient<Database>, appid: string) {
|
|
109
|
-
const { data, error: vError } = await supabase
|
|
110
|
-
.from('channels')
|
|
111
|
-
.select(`
|
|
112
|
-
id,
|
|
113
|
-
name,
|
|
114
|
-
public,
|
|
115
|
-
allow_emulator,
|
|
116
|
-
allow_dev,
|
|
117
|
-
ios,
|
|
118
|
-
android,
|
|
119
|
-
allow_device_self_set,
|
|
120
|
-
disableAutoUpdateUnderNative,
|
|
121
|
-
disableAutoUpdate,
|
|
122
|
-
enable_progressive_deploy,
|
|
123
|
-
enableAbTesting,
|
|
124
|
-
secondaryVersionPercentage,
|
|
125
|
-
secondVersion (id, name),
|
|
126
|
-
created_at,
|
|
127
|
-
created_by,
|
|
128
|
-
app_id,
|
|
129
|
-
version (id, name)
|
|
130
|
-
`)
|
|
131
|
-
.eq('app_id', appid)
|
|
132
|
-
// .eq('created_by', userId)
|
|
133
|
-
.order('created_at', { ascending: false })
|
|
134
|
-
|
|
135
|
-
if (vError) {
|
|
136
|
-
p.log.error(`App ${appid} not found in database`)
|
|
137
|
-
program.error('')
|
|
138
|
-
}
|
|
139
|
-
return data
|
|
140
|
-
}
|
package/src/api/crypto.ts
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
constants,
|
|
3
|
-
createCipheriv,
|
|
4
|
-
createDecipheriv,
|
|
5
|
-
generateKeyPairSync,
|
|
6
|
-
privateEncrypt,
|
|
7
|
-
publicDecrypt,
|
|
8
|
-
randomBytes,
|
|
9
|
-
} from 'node:crypto'
|
|
10
|
-
import { Buffer } from 'node:buffer'
|
|
11
|
-
|
|
12
|
-
const algorithm = 'aes-128-cbc'
|
|
13
|
-
const formatB64 = 'base64'
|
|
14
|
-
const padding = constants.RSA_PKCS1_PADDING
|
|
15
|
-
|
|
16
|
-
export function decryptSource(source: Buffer, ivSessionKey: string, key: string): Buffer {
|
|
17
|
-
// console.log('decryptKeyType - ', decryptKeyType);
|
|
18
|
-
// console.log(key);
|
|
19
|
-
// console.log('\nivSessionKey', ivSessionKey)
|
|
20
|
-
const [ivB64, sessionb64Encrypted] = ivSessionKey.split(':')
|
|
21
|
-
// console.log('\nsessionb64Encrypted', sessionb64Encrypted)
|
|
22
|
-
// console.log('\nivB64', ivB64)
|
|
23
|
-
const sessionKey = publicDecrypt(
|
|
24
|
-
{
|
|
25
|
-
key,
|
|
26
|
-
padding,
|
|
27
|
-
},
|
|
28
|
-
Buffer.from(sessionb64Encrypted, formatB64),
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
// ivB64 to uft-8
|
|
32
|
-
const initVector = Buffer.from(ivB64, formatB64)
|
|
33
|
-
// console.log('\nSessionB64', sessionB64)
|
|
34
|
-
|
|
35
|
-
const decipher = createDecipheriv(algorithm, sessionKey, initVector)
|
|
36
|
-
decipher.setAutoPadding(true)
|
|
37
|
-
const decryptedData = Buffer.concat([decipher.update(source), decipher.final()])
|
|
38
|
-
|
|
39
|
-
return decryptedData
|
|
40
|
-
}
|
|
41
|
-
export interface Encoded {
|
|
42
|
-
ivSessionKey: string
|
|
43
|
-
encryptedData: Buffer
|
|
44
|
-
}
|
|
45
|
-
export function encryptSource(source: Buffer, key: string): Encoded {
|
|
46
|
-
// console.log('decryptKeyType - ', decryptKeyType);
|
|
47
|
-
// console.log(key);
|
|
48
|
-
|
|
49
|
-
// encrypt zip with key
|
|
50
|
-
const initVector = randomBytes(16)
|
|
51
|
-
const sessionKey = randomBytes(16)
|
|
52
|
-
// encrypt session key with public key
|
|
53
|
-
// console.log('\nencrypted.key', encrypted.key.toString(CryptoJS.enc.Base64))
|
|
54
|
-
const cipher = createCipheriv(algorithm, sessionKey, initVector)
|
|
55
|
-
cipher.setAutoPadding(true)
|
|
56
|
-
// console.log('\nsessionKey', sessionKey.toString())
|
|
57
|
-
// const sessionB64 = sessionKey.toString(formatB64)
|
|
58
|
-
// console.log('\nsessionB64', sessionB64)
|
|
59
|
-
const ivB64 = initVector.toString(formatB64)
|
|
60
|
-
// console.log('\nivB64', ivB64)
|
|
61
|
-
|
|
62
|
-
const sessionb64Encrypted = privateEncrypt(
|
|
63
|
-
{
|
|
64
|
-
key,
|
|
65
|
-
padding,
|
|
66
|
-
},
|
|
67
|
-
sessionKey,
|
|
68
|
-
).toString(formatB64)
|
|
69
|
-
|
|
70
|
-
// console.log('\nsessionb64Encrypted', sessionb64Encrypted)
|
|
71
|
-
const ivSessionKey = `${ivB64}:${sessionb64Encrypted}`
|
|
72
|
-
// console.log('\nivSessionKey', sessionKey)
|
|
73
|
-
// encrypted to buffer
|
|
74
|
-
|
|
75
|
-
const encryptedData = Buffer.concat([cipher.update(source), cipher.final()])
|
|
76
|
-
|
|
77
|
-
return {
|
|
78
|
-
encryptedData,
|
|
79
|
-
ivSessionKey,
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
export interface RSAKeys {
|
|
83
|
-
publicKey: string
|
|
84
|
-
privateKey: string
|
|
85
|
-
}
|
|
86
|
-
export function createRSA(): RSAKeys {
|
|
87
|
-
const { publicKey, privateKey } = generateKeyPairSync('rsa', {
|
|
88
|
-
// The standard secure default length for RSA keys is 2048 bits
|
|
89
|
-
modulusLength: 2048,
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
// Generate RSA key pair
|
|
93
|
-
return {
|
|
94
|
-
publicKey: publicKey.export({
|
|
95
|
-
type: 'pkcs1',
|
|
96
|
-
format: 'pem',
|
|
97
|
-
}) as string,
|
|
98
|
-
privateKey: privateKey.export({
|
|
99
|
-
type: 'pkcs1',
|
|
100
|
-
format: 'pem',
|
|
101
|
-
}) as string,
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
// test AES
|
|
105
|
-
|
|
106
|
-
// const source = 'Hello world'
|
|
107
|
-
// console.log('\nsource', source)
|
|
108
|
-
// const { publicKey, privateKey } = createRSA()
|
|
109
|
-
|
|
110
|
-
// console.log('\nencryptSource ================================================================')
|
|
111
|
-
// // convert source to base64
|
|
112
|
-
// const sourceBuff = Buffer.from(source)
|
|
113
|
-
// const res = encryptSource(sourceBuff, publicKey)
|
|
114
|
-
// console.log('\nencryptedData', res.encryptedData.toString('base64'))
|
|
115
|
-
// // console.log('\nres', res)
|
|
116
|
-
// console.log('\ndecryptSource ================================================================')
|
|
117
|
-
// const decodedSource = decryptSource(res.encryptedData, res.ivSessionKey, privateKey)
|
|
118
|
-
// // convert decodedSource from base64 to utf-8
|
|
119
|
-
// const decodedSourceString = decodedSource.toString('utf-8')
|
|
120
|
-
// console.log('\ndecodedSourceString', decodedSourceString)
|
|
121
|
-
// console.log('\n Is match', decodedSourceString === source)
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import process from 'node:process'
|
|
2
|
-
import type { SupabaseClient } from '@supabase/supabase-js'
|
|
3
|
-
import { program } from 'commander'
|
|
4
|
-
import * as p from '@clack/prompts'
|
|
5
|
-
import type { Database } from '../types/supabase.types'
|
|
6
|
-
import { formatError } from '../utils'
|
|
7
|
-
|
|
8
|
-
export async function checkVersionNotUsedInDeviceOverride(supabase: SupabaseClient<Database>, appid: string, versionData: Database['public']['Tables']['app_versions']['Row']) {
|
|
9
|
-
const { data: deviceFound, error: errorDevice } = await supabase
|
|
10
|
-
.from('devices_override')
|
|
11
|
-
.select()
|
|
12
|
-
.eq('app_id', appid)
|
|
13
|
-
.eq('version', versionData.id)
|
|
14
|
-
if (errorDevice) {
|
|
15
|
-
p.log.error(`Cannot check Device override ${appid}@${versionData.name}`)
|
|
16
|
-
program.error('')
|
|
17
|
-
}
|
|
18
|
-
if (deviceFound && deviceFound.length > 0) {
|
|
19
|
-
p.intro(`❌ Version ${appid}@${versionData.name} is used in ${deviceFound.length} device override`)
|
|
20
|
-
if (await p.confirm({ message: 'unlink it?' })) {
|
|
21
|
-
// loop on all devices and set version to unknown
|
|
22
|
-
for (const device of deviceFound) {
|
|
23
|
-
const s = p.spinner()
|
|
24
|
-
s.start(`Unlinking device ${device.device_id}`)
|
|
25
|
-
const { error: errorDeviceDel } = await supabase
|
|
26
|
-
.from('devices_override')
|
|
27
|
-
.delete()
|
|
28
|
-
.eq('device_id', device.device_id)
|
|
29
|
-
if (errorDeviceDel) {
|
|
30
|
-
s.stop(`Cannot unlink device ${device.device_id} ${formatError(errorDeviceDel)}`)
|
|
31
|
-
process.exit(1)
|
|
32
|
-
}
|
|
33
|
-
s.stop(`✅ Device ${device.device_id} unlinked`)
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
else {
|
|
37
|
-
p.log.error(`Unlink it first`)
|
|
38
|
-
program.error('')
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
package/src/api/update.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import getLatest from 'get-latest-version'
|
|
2
|
-
import * as p from '@clack/prompts'
|
|
3
|
-
import pack from '../../package.json'
|
|
4
|
-
|
|
5
|
-
export async function checkLatest() {
|
|
6
|
-
const latest = await getLatest('@capgo/cli')
|
|
7
|
-
if (latest !== pack.version) {
|
|
8
|
-
p.log.warning(`🚨 You are using @capgo/cli@${pack.version} it's not the latest version.
|
|
9
|
-
Please use @capgo/cli@${latest}" or @capgo/cli@latest to keep up to date with the latest features and bug fixes.`,
|
|
10
|
-
)
|
|
11
|
-
}
|
|
12
|
-
}
|
package/src/api/versions.ts
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import type { SupabaseClient } from '@supabase/supabase-js'
|
|
2
|
-
import { program } from 'commander'
|
|
3
|
-
import { Table } from 'console-table-printer'
|
|
4
|
-
import * as p from '@clack/prompts'
|
|
5
|
-
import type { Database } from '../types/supabase.types'
|
|
6
|
-
|
|
7
|
-
// import { definitions } from '../types/types_supabase';
|
|
8
|
-
import { getHumanDate } from '../utils'
|
|
9
|
-
import { checkVersionNotUsedInChannel } from './channels'
|
|
10
|
-
import { checkVersionNotUsedInDeviceOverride } from './devices_override'
|
|
11
|
-
|
|
12
|
-
export async function deleteAppVersion(supabase: SupabaseClient<Database>, appid: string, bundle: string) {
|
|
13
|
-
const { error: delAppSpecVersionError } = await supabase
|
|
14
|
-
.from('app_versions')
|
|
15
|
-
.update({
|
|
16
|
-
deleted: true,
|
|
17
|
-
})
|
|
18
|
-
.eq('app_id', appid)
|
|
19
|
-
.eq('deleted', false)
|
|
20
|
-
.eq('name', bundle)
|
|
21
|
-
if (delAppSpecVersionError) {
|
|
22
|
-
p.log.error(`App Version ${appid}@${bundle} not found in database`)
|
|
23
|
-
program.error('')
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export async function deleteSpecificVersion(supabase: SupabaseClient<Database>, appid: string, _userId: string, bundle: string) {
|
|
28
|
-
const versionData = await getVersionData(supabase, appid, bundle)
|
|
29
|
-
await checkVersionNotUsedInChannel(supabase, appid, versionData)
|
|
30
|
-
await checkVersionNotUsedInDeviceOverride(supabase, appid, versionData)
|
|
31
|
-
// Delete only a specific version in storage
|
|
32
|
-
await deleteAppVersion(supabase, appid, bundle)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function displayBundles(data: (Database['public']['Tables']['app_versions']['Row'] & { keep?: string })[]) {
|
|
36
|
-
if (!data.length) {
|
|
37
|
-
p.log.error('No bundle found')
|
|
38
|
-
// eslint-disable-next-line node/prefer-global/process
|
|
39
|
-
process.exit(1)
|
|
40
|
-
}
|
|
41
|
-
const t = new Table({
|
|
42
|
-
title: 'Bundles',
|
|
43
|
-
charLength: { '❌': 2, '✅': 2 },
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
// add rows with color
|
|
47
|
-
data.reverse().forEach((row) => {
|
|
48
|
-
t.addRow({
|
|
49
|
-
Version: row.name,
|
|
50
|
-
Created: getHumanDate(row.created_at),
|
|
51
|
-
...(row.keep != null ? { Keep: row.keep } : {}),
|
|
52
|
-
})
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
p.log.success(t.render())
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export async function getActiveAppVersions(supabase: SupabaseClient<Database>, appid: string, _userId: string) {
|
|
59
|
-
const { data, error: vError } = await supabase
|
|
60
|
-
.from('app_versions')
|
|
61
|
-
.select()
|
|
62
|
-
.eq('app_id', appid)
|
|
63
|
-
// .eq('user_id', userId)
|
|
64
|
-
.eq('deleted', false)
|
|
65
|
-
.order('created_at', { ascending: false })
|
|
66
|
-
|
|
67
|
-
if (vError) {
|
|
68
|
-
p.log.error(`App ${appid} not found in database`)
|
|
69
|
-
program.error('')
|
|
70
|
-
}
|
|
71
|
-
return data
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export async function getChannelsVersion(supabase: SupabaseClient<Database>, appid: string) {
|
|
75
|
-
// get all channels versionID
|
|
76
|
-
const { data: channels, error: channelsError } = await supabase
|
|
77
|
-
.from('channels')
|
|
78
|
-
.select('version')
|
|
79
|
-
.eq('app_id', appid)
|
|
80
|
-
|
|
81
|
-
if (channelsError) {
|
|
82
|
-
p.log.error(`App ${appid} not found in database`)
|
|
83
|
-
program.error('')
|
|
84
|
-
}
|
|
85
|
-
return channels.map(c => c.version)
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export async function getVersionData(supabase: SupabaseClient<Database>, appid: string, bundle: string) {
|
|
89
|
-
const { data: versionData, error: versionIdError } = await supabase
|
|
90
|
-
.from('app_versions')
|
|
91
|
-
.select()
|
|
92
|
-
.eq('app_id', appid)
|
|
93
|
-
.eq('name', bundle)
|
|
94
|
-
.eq('deleted', false)
|
|
95
|
-
.single()
|
|
96
|
-
if (!versionData || versionIdError) {
|
|
97
|
-
p.log.error(`App Version ${appid}@${bundle} doesn't exist`)
|
|
98
|
-
program.error('')
|
|
99
|
-
}
|
|
100
|
-
return versionData
|
|
101
|
-
}
|