@capgo/cli 3.9.2 → 3.10.1
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 +14 -0
- package/dist/index.js +1 -1
- package/package.json +3 -1
- package/src/api/channels.ts +1 -1
- package/src/api/crypto.ts +1 -1
- package/src/api/update.ts +4 -2
- package/src/api/versions.ts +4 -3
- package/src/app/add.ts +24 -13
- package/src/app/delete.ts +4 -2
- package/src/app/list.ts +13 -8
- package/src/app/set.ts +14 -8
- package/src/app/watch.ts +1 -1
- package/src/bundle/cleanup.ts +12 -10
- package/src/bundle/decrypt.ts +3 -1
- package/src/bundle/delete.ts +15 -8
- package/src/bundle/encrypt.ts +21 -5
- package/src/bundle/list.ts +9 -5
- package/src/bundle/unlink.ts +13 -6
- package/src/bundle/upload.ts +37 -5
- package/src/channel/add.ts +12 -7
- package/src/channel/delete.ts +10 -6
- package/src/channel/list.ts +8 -5
- package/src/channel/set.ts +33 -20
- package/src/init.ts +1 -1
- package/src/key.ts +26 -14
- package/src/login.ts +10 -4
- package/src/utils.ts +15 -5
package/src/app/add.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getType } from 'mime';
|
|
2
2
|
import { program } from 'commander';
|
|
3
3
|
import { randomUUID } from 'crypto';
|
|
4
|
+
import * as p from '@clack/prompts';
|
|
4
5
|
import { existsSync, readFileSync } from 'fs-extra';
|
|
5
6
|
import { checkLatest } from '../api/update';
|
|
6
7
|
import { checkAppExistsAndHasPermissionErr, checkAppExistsAndHasPermission, newIconPath, Options } from '../api/app';
|
|
@@ -10,6 +11,9 @@ import {
|
|
|
10
11
|
} from '../utils';
|
|
11
12
|
|
|
12
13
|
export const addApp = async (appId: string, options: Options, shouldExit = true) => {
|
|
14
|
+
if (shouldExit) {
|
|
15
|
+
p.intro(`Adding`);
|
|
16
|
+
}
|
|
13
17
|
await checkLatest();
|
|
14
18
|
options.apikey = options.apikey || findSavedKey()
|
|
15
19
|
const config = await getConfig();
|
|
@@ -17,10 +21,12 @@ export const addApp = async (appId: string, options: Options, shouldExit = true)
|
|
|
17
21
|
const snag = useLogSnag()
|
|
18
22
|
|
|
19
23
|
if (!options.apikey) {
|
|
20
|
-
|
|
24
|
+
p.log.error(`Missing API key, you need to provide a API key to upload your bundle`);
|
|
25
|
+
program.error('');
|
|
21
26
|
}
|
|
22
27
|
if (!appId) {
|
|
23
|
-
|
|
28
|
+
p.log.error("Missing argument, you need to provide a appId, or be in a capacitor project");
|
|
29
|
+
program.error('');
|
|
24
30
|
}
|
|
25
31
|
const supabase = createSupabaseClient(options.apikey)
|
|
26
32
|
|
|
@@ -40,10 +46,11 @@ export const addApp = async (appId: string, options: Options, shouldExit = true)
|
|
|
40
46
|
name = name || config?.app?.appName || 'Unknown'
|
|
41
47
|
icon = icon || "resources/icon.png" // default path for capacitor app
|
|
42
48
|
if (!icon || !name) {
|
|
43
|
-
|
|
49
|
+
p.log.error("Missing argument, you need to provide a appId and a name, or be in a capacitor project");
|
|
50
|
+
program.error('');
|
|
44
51
|
}
|
|
45
52
|
if (shouldExit) {
|
|
46
|
-
|
|
53
|
+
p.log.info(`Adding ${appId} to Capgo`);
|
|
47
54
|
}
|
|
48
55
|
let iconBuff;
|
|
49
56
|
let iconType;
|
|
@@ -52,15 +59,15 @@ export const addApp = async (appId: string, options: Options, shouldExit = true)
|
|
|
52
59
|
iconBuff = readFileSync(icon);
|
|
53
60
|
const contentType = getType(icon);
|
|
54
61
|
iconType = contentType || 'image/png';
|
|
55
|
-
|
|
62
|
+
p.log.warn(`Found app icon ${icon}`);
|
|
56
63
|
}
|
|
57
64
|
else if (existsSync(newIconPath)) {
|
|
58
65
|
iconBuff = readFileSync(newIconPath);
|
|
59
66
|
const contentType = getType(newIconPath);
|
|
60
67
|
iconType = contentType || 'image/png';
|
|
61
|
-
|
|
68
|
+
p.log.warn(`Found app icon ${newIconPath}`);
|
|
62
69
|
} else {
|
|
63
|
-
|
|
70
|
+
p.log.warn(`Cannot find app icon in any of the following locations: ${icon}, ${newIconPath}`);
|
|
64
71
|
}
|
|
65
72
|
|
|
66
73
|
// check if app already exist
|
|
@@ -68,7 +75,8 @@ export const addApp = async (appId: string, options: Options, shouldExit = true)
|
|
|
68
75
|
.rpc('exist_app_v2', { appid: appId })
|
|
69
76
|
.single()
|
|
70
77
|
if (app || dbError0) {
|
|
71
|
-
|
|
78
|
+
p.log.error(`App ${appId} already exists ${formatError(dbError0)}`);
|
|
79
|
+
program.error('');
|
|
72
80
|
}
|
|
73
81
|
|
|
74
82
|
const fileName = `icon_${randomUUID()}`
|
|
@@ -82,7 +90,8 @@ export const addApp = async (appId: string, options: Options, shouldExit = true)
|
|
|
82
90
|
contentType: iconType,
|
|
83
91
|
})
|
|
84
92
|
if (error) {
|
|
85
|
-
|
|
93
|
+
p.log.error(`Could not add app ${formatError(error)}`);
|
|
94
|
+
program.error('');
|
|
86
95
|
}
|
|
87
96
|
const { data: signedURLData } = await supabase
|
|
88
97
|
.storage
|
|
@@ -100,7 +109,8 @@ export const addApp = async (appId: string, options: Options, shouldExit = true)
|
|
|
100
109
|
app_id: appId,
|
|
101
110
|
})
|
|
102
111
|
if (dbError) {
|
|
103
|
-
|
|
112
|
+
p.log.error(`Could not add app ${formatError(dbError)}`);
|
|
113
|
+
program.error('');
|
|
104
114
|
}
|
|
105
115
|
const { error: dbVersionError } = await supabase
|
|
106
116
|
.from('app_versions')
|
|
@@ -116,7 +126,8 @@ export const addApp = async (appId: string, options: Options, shouldExit = true)
|
|
|
116
126
|
app_id: appId,
|
|
117
127
|
}])
|
|
118
128
|
if (dbVersionError) {
|
|
119
|
-
|
|
129
|
+
p.log.error(`Could not add app ${formatError(dbVersionError)}`);
|
|
130
|
+
program.error('');
|
|
120
131
|
}
|
|
121
132
|
await snag.publish({
|
|
122
133
|
channel: 'app',
|
|
@@ -128,9 +139,9 @@ export const addApp = async (appId: string, options: Options, shouldExit = true)
|
|
|
128
139
|
},
|
|
129
140
|
notify: false,
|
|
130
141
|
}).catch()
|
|
131
|
-
|
|
142
|
+
p.log.success(`App ${appId} added to Capgo. ${shouldExit ? 'You can upload a bundle now' : ''}`);
|
|
132
143
|
if (shouldExit) {
|
|
133
|
-
|
|
144
|
+
p.outro(`Done ✅`);
|
|
134
145
|
process.exit()
|
|
135
146
|
}
|
|
136
147
|
return true
|
package/src/app/delete.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { program } from "commander";
|
|
2
|
+
import * as p from '@clack/prompts';
|
|
2
3
|
import { OptionsBase } from "../api/utils";
|
|
3
4
|
import { checkAppExistsAndHasPermissionErr } from '../api/app';
|
|
4
5
|
import { createSupabaseClient, findSavedKey, formatError, getConfig, useLogSnag, verifyUser } from "../utils";
|
|
5
6
|
|
|
6
7
|
export const deleteApp = async (appId: string, options: OptionsBase) => {
|
|
8
|
+
p.intro(`Deleting`);
|
|
7
9
|
options.apikey = options.apikey || findSavedKey()
|
|
8
10
|
const config = await getConfig();
|
|
9
11
|
appId = appId || config?.app?.appId
|
|
@@ -55,7 +57,7 @@ export const deleteApp = async (appId: string, options: OptionsBase) => {
|
|
|
55
57
|
},
|
|
56
58
|
notify: false,
|
|
57
59
|
}).catch()
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
p.log.success(`App deleted in Capgo`);
|
|
61
|
+
p.outro('Done ✅');
|
|
60
62
|
process.exit()
|
|
61
63
|
}
|
package/src/app/list.ts
CHANGED
|
@@ -2,26 +2,27 @@ import { program } from 'commander';
|
|
|
2
2
|
import { Database } from 'types/supabase.types';
|
|
3
3
|
import { Table } from 'console-table-printer';
|
|
4
4
|
import { SupabaseClient } from '@supabase/supabase-js';
|
|
5
|
+
import * as p from '@clack/prompts';
|
|
5
6
|
import { checkAppExistsAndHasPermissionErr } from '../api/app';
|
|
6
7
|
import { OptionsBase } from '../api/utils';
|
|
7
8
|
import { createSupabaseClient, findSavedKey, formatError, getConfig, getHumanDate, verifyUser } from '../utils';
|
|
8
9
|
import { checkLatest } from '../api/update';
|
|
9
10
|
|
|
10
11
|
const displayApp = (data: Database['public']['Tables']['apps']['Row'][]) => {
|
|
11
|
-
const
|
|
12
|
+
const t = new Table({
|
|
12
13
|
title: "Apps",
|
|
13
14
|
charLength: { "❌": 2, "✅": 2 },
|
|
14
15
|
});
|
|
15
16
|
|
|
16
17
|
// add rows with color
|
|
17
18
|
data.reverse().forEach(row => {
|
|
18
|
-
|
|
19
|
+
t.addRow({
|
|
19
20
|
Name: row.name,
|
|
20
21
|
Created: getHumanDate(row.created_at)
|
|
21
22
|
});
|
|
22
23
|
});
|
|
23
24
|
|
|
24
|
-
p.
|
|
25
|
+
p.log.success(t.render());
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
export const getActiveApps = async (supabase: SupabaseClient<Database>, userId: string) => {
|
|
@@ -38,23 +39,27 @@ export const getActiveApps = async (supabase: SupabaseClient<Database>, userId:
|
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
export const listApp = async (appId: string, options: OptionsBase) => {
|
|
42
|
+
p.intro(`List apps in Capgo`);
|
|
43
|
+
|
|
41
44
|
await checkLatest();
|
|
42
45
|
options.apikey = options.apikey || findSavedKey()
|
|
43
46
|
const config = await getConfig();
|
|
44
47
|
|
|
45
48
|
appId = appId || config?.app?.appId
|
|
46
49
|
if (!options.apikey) {
|
|
47
|
-
|
|
50
|
+
p.log.error(`Missing API key, you need to provide an API key to delete your app`);
|
|
51
|
+
program.error('');
|
|
48
52
|
}
|
|
49
53
|
if (!appId) {
|
|
50
|
-
|
|
54
|
+
p.log.error("Missing argument, you need to provide a appId, or be in a capacitor project");
|
|
55
|
+
program.error('');
|
|
51
56
|
}
|
|
52
57
|
|
|
53
58
|
const supabase = createSupabaseClient(options.apikey)
|
|
54
59
|
|
|
55
60
|
const userId = await verifyUser(supabase, options.apikey);
|
|
56
61
|
|
|
57
|
-
|
|
62
|
+
p.log.info(`Getting active bundle in Capgo`);
|
|
58
63
|
|
|
59
64
|
// Check we have app access to this appId
|
|
60
65
|
await checkAppExistsAndHasPermissionErr(supabase, appId, options.apikey);
|
|
@@ -62,9 +67,9 @@ export const listApp = async (appId: string, options: OptionsBase) => {
|
|
|
62
67
|
// Get all active app versions we might possibly be able to cleanup
|
|
63
68
|
const allApps = await getActiveApps(supabase, userId);
|
|
64
69
|
|
|
65
|
-
|
|
70
|
+
p.log.info(`Active app in Capgo: ${allApps?.length}`);
|
|
66
71
|
|
|
67
72
|
displayApp(allApps);
|
|
68
|
-
|
|
73
|
+
p.outro(`Done ✅`);
|
|
69
74
|
process.exit()
|
|
70
75
|
}
|
package/src/app/set.ts
CHANGED
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
import { getType } from 'mime';
|
|
2
2
|
import { program } from "commander";
|
|
3
3
|
import { randomUUID } from "crypto";
|
|
4
|
+
import * as p from '@clack/prompts';
|
|
4
5
|
import { existsSync, readFileSync } from "fs-extra";
|
|
5
6
|
import { checkAppExistsAndHasPermissionErr, newIconPath, Options } from '../api/app';
|
|
6
7
|
import { createSupabaseClient, findSavedKey, formatError, getConfig, verifyUser } from "../utils";
|
|
7
8
|
|
|
8
9
|
export const setApp = async (appId: string, options: Options) => {
|
|
10
|
+
p.intro(`Set app`);
|
|
9
11
|
options.apikey = options.apikey || findSavedKey()
|
|
10
12
|
const config = await getConfig();
|
|
11
13
|
appId = appId || config?.app?.appId
|
|
12
14
|
|
|
13
15
|
if (!options.apikey) {
|
|
14
|
-
|
|
16
|
+
p.log.error(`Missing API key, you need to provide a API key to upload your bundle`);
|
|
17
|
+
program.error(``);
|
|
15
18
|
}
|
|
16
19
|
if (!appId) {
|
|
17
|
-
|
|
20
|
+
p.log.error("Missing argument, you need to provide a appId, or be in a capacitor project");
|
|
21
|
+
program.error(``);
|
|
18
22
|
}
|
|
19
23
|
const supabase = createSupabaseClient(options.apikey)
|
|
20
24
|
|
|
@@ -33,15 +37,15 @@ export const setApp = async (appId: string, options: Options) => {
|
|
|
33
37
|
iconBuff = readFileSync(icon);
|
|
34
38
|
const contentType = getType(icon);
|
|
35
39
|
iconType = contentType || 'image/png';
|
|
36
|
-
|
|
40
|
+
p.log.warn(`Found app icon ${icon}`);
|
|
37
41
|
}
|
|
38
42
|
else if (existsSync(newIconPath)) {
|
|
39
43
|
iconBuff = readFileSync(newIconPath);
|
|
40
44
|
const contentType = getType(newIconPath);
|
|
41
45
|
iconType = contentType || 'image/png';
|
|
42
|
-
|
|
46
|
+
p.log.warn(`Found app icon ${newIconPath}`);
|
|
43
47
|
} else {
|
|
44
|
-
|
|
48
|
+
p.log.warn(`Cannot find app icon in any of the following locations: ${icon}, ${newIconPath}`);
|
|
45
49
|
}
|
|
46
50
|
if (iconBuff && iconType) {
|
|
47
51
|
const { error } = await supabase.storage
|
|
@@ -50,7 +54,8 @@ export const setApp = async (appId: string, options: Options) => {
|
|
|
50
54
|
contentType: iconType,
|
|
51
55
|
})
|
|
52
56
|
if (error) {
|
|
53
|
-
|
|
57
|
+
p.log.error(`Could not add app ${formatError(error)}`);
|
|
58
|
+
program.error(``);
|
|
54
59
|
}
|
|
55
60
|
const { data: signedURLData } = await supabase
|
|
56
61
|
.storage
|
|
@@ -67,8 +72,9 @@ export const setApp = async (appId: string, options: Options) => {
|
|
|
67
72
|
.eq('app_id', appId)
|
|
68
73
|
.eq('user_id', userId)
|
|
69
74
|
if (dbError) {
|
|
70
|
-
|
|
75
|
+
p.log.error(`Could not add app ${formatError(dbError)}`);
|
|
76
|
+
program.error(``);
|
|
71
77
|
}
|
|
72
|
-
|
|
78
|
+
p.outro(`Done ✅`);
|
|
73
79
|
process.exit()
|
|
74
80
|
}
|
package/src/app/watch.ts
CHANGED
package/src/bundle/cleanup.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { program } from 'commander';
|
|
2
2
|
import semver from 'semver/preload';
|
|
3
|
+
import * as p from '@clack/prompts';
|
|
3
4
|
import promptSync from 'prompt-sync';
|
|
4
5
|
import { SupabaseClient } from '@supabase/supabase-js';
|
|
5
6
|
import { Database } from 'types/supabase.types';
|
|
@@ -25,7 +26,7 @@ const removeVersions = async (toRemove: Database['public']['Tables']['app_versio
|
|
|
25
26
|
|
|
26
27
|
// call deleteSpecificVersion one by one from toRemove sync
|
|
27
28
|
for await (const row of toRemove) {
|
|
28
|
-
|
|
29
|
+
p.log.warn(`Removing ${row.name} created on ${(getHumanDate(row.created_at))}`);
|
|
29
30
|
await deleteSpecificVersion(supabase, appid, userId, row.name);
|
|
30
31
|
}
|
|
31
32
|
}
|
|
@@ -43,6 +44,7 @@ const getRemovableVersionsInSemverRange = (data: Database['public']['Tables']['a
|
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
export const cleanupBundle = async (appid: string, options: Options) => {
|
|
47
|
+
p.intro(`Cleanup versions in Capgo`);
|
|
46
48
|
await checkLatest();
|
|
47
49
|
const apikey = options.apikey || findSavedKey()
|
|
48
50
|
const { bundle, keep = 4 } = options;
|
|
@@ -62,26 +64,26 @@ export const cleanupBundle = async (appid: string, options: Options) => {
|
|
|
62
64
|
|
|
63
65
|
// Check we have app access to this appId
|
|
64
66
|
await checkAppExistsAndHasPermissionErr(supabase, appid, apikey);
|
|
65
|
-
|
|
67
|
+
p.log.info(`Querying all available versions in Capgo`);
|
|
66
68
|
|
|
67
69
|
// Get all active app versions we might possibly be able to cleanup
|
|
68
70
|
let allVersions: (Database['public']['Tables']['app_versions']['Row'] & { keep?: string })[] = await
|
|
69
71
|
getActiveAppVersions(supabase, appid, userId);
|
|
70
72
|
|
|
71
|
-
|
|
73
|
+
p.log.info(`Total active versions in Capgo: ${allVersions?.length}`);
|
|
72
74
|
if (allVersions?.length === 0) {
|
|
73
|
-
|
|
75
|
+
p.log.error('No versions found, aborting cleanup');
|
|
74
76
|
return;
|
|
75
77
|
}
|
|
76
78
|
if (bundle) {
|
|
77
79
|
const nextMajor = `${semver.inc(bundle, 'major')}`;
|
|
78
|
-
|
|
80
|
+
p.log.info(`Querying available versions in Capgo between ${bundle} and ${nextMajor}`);
|
|
79
81
|
|
|
80
82
|
// Get all app versions that are in the given range
|
|
81
83
|
allVersions = getRemovableVersionsInSemverRange(allVersions, bundle,
|
|
82
84
|
nextMajor) as (Database['public']['Tables']['app_versions']['Row'] & { keep: string })[];
|
|
83
85
|
|
|
84
|
-
|
|
86
|
+
p.log.info(`Active versions in Capgo between ${bundle} and ${nextMajor}: ${allVersions?.length}`);
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
// Slice to keep and remove
|
|
@@ -98,7 +100,7 @@ export const cleanupBundle = async (appid: string, options: Options) => {
|
|
|
98
100
|
})
|
|
99
101
|
|
|
100
102
|
if (toRemove.length === 0) {
|
|
101
|
-
|
|
103
|
+
p.log.warn("Nothing to be removed, aborting removal...")
|
|
102
104
|
return;
|
|
103
105
|
}
|
|
104
106
|
displayBundles(allVersions);
|
|
@@ -107,14 +109,14 @@ export const cleanupBundle = async (appid: string, options: Options) => {
|
|
|
107
109
|
if (!force) {
|
|
108
110
|
const result = prompt("Do you want to continue removing the versions specified? Type yes to confirm: ");
|
|
109
111
|
if (result !== "yes") {
|
|
110
|
-
|
|
112
|
+
p.log.warn("Not confirmed, aborting removal...");
|
|
111
113
|
return;
|
|
112
114
|
}
|
|
113
115
|
}
|
|
114
116
|
|
|
115
117
|
// Yes, lets clean it up
|
|
116
|
-
|
|
118
|
+
p.log.success("You have confirmed removal, removing versions now");
|
|
117
119
|
await removeVersions(toRemove, supabase, appid, userId);
|
|
118
|
-
|
|
120
|
+
p.outro(`Done ✅`);
|
|
119
121
|
process.exit()
|
|
120
122
|
}
|
package/src/bundle/decrypt.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { program } from 'commander'
|
|
2
|
+
import * as p from '@clack/prompts';
|
|
2
3
|
import { existsSync, readFileSync, writeFileSync } from 'fs'
|
|
3
4
|
import { decryptSource } from '../api/crypto';
|
|
4
5
|
import { baseKey, getConfig } from '../utils';
|
|
@@ -10,6 +11,7 @@ interface Options {
|
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
export const decryptZip = async (zipPath: string, ivsessionKey: string, options: Options) => {
|
|
14
|
+
p.intro(`Decrypt zip file`);
|
|
13
15
|
await checkLatest();
|
|
14
16
|
// write in file .capgo the apikey in home directory
|
|
15
17
|
|
|
@@ -41,6 +43,6 @@ export const decryptZip = async (zipPath: string, ivsessionKey: string, options:
|
|
|
41
43
|
const decodedZip = decryptSource(zipFile, ivsessionKey, privateKey)
|
|
42
44
|
// write decodedZip in a file
|
|
43
45
|
writeFileSync(`${zipPath}_decrypted.zip`, decodedZip)
|
|
44
|
-
|
|
46
|
+
p.outro(`Decrypted zip file at ${zipPath}_decrypted.zip`);
|
|
45
47
|
process.exit()
|
|
46
48
|
}
|
package/src/bundle/delete.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { program } from 'commander';
|
|
2
|
+
import * as p from '@clack/prompts';
|
|
2
3
|
import { checkAppExistsAndHasPermissionErr } from '../api/app';
|
|
3
4
|
import { OptionsBase } from '../api/utils';
|
|
4
5
|
import { createSupabaseClient, findSavedKey, getConfig, verifyUser } from '../utils';
|
|
@@ -9,15 +10,18 @@ interface Options extends OptionsBase {
|
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
export const deleteBundle = async (appId: string, bundleId: string, options: Options) => {
|
|
13
|
+
p.intro(`Delete bundle`);
|
|
12
14
|
options.apikey = options.apikey || findSavedKey()
|
|
13
15
|
const config = await getConfig();
|
|
14
16
|
appId = appId || config?.app?.appId
|
|
15
17
|
|
|
16
18
|
if (!options.apikey) {
|
|
17
|
-
|
|
19
|
+
p.log.error("Missing API key, you need to provide a API key to upload your bundle");
|
|
20
|
+
program.error('');
|
|
18
21
|
}
|
|
19
22
|
if (!appId) {
|
|
20
|
-
|
|
23
|
+
p.log.error("Missing argument, you need to provide a appId, or be in a capacitor project");
|
|
24
|
+
program.error('');
|
|
21
25
|
}
|
|
22
26
|
const supabase = createSupabaseClient(options.apikey)
|
|
23
27
|
|
|
@@ -29,19 +33,22 @@ export const deleteBundle = async (appId: string, bundleId: string, options: Opt
|
|
|
29
33
|
|
|
30
34
|
appId = appId || config?.app?.appId
|
|
31
35
|
if (!apikey) {
|
|
32
|
-
|
|
36
|
+
p.log.error('Missing API key, you need to provide an API key to delete your app');
|
|
37
|
+
program.error('');
|
|
33
38
|
}
|
|
34
39
|
if (!bundleId) {
|
|
35
|
-
|
|
40
|
+
p.log.error('Missing argument, you need to provide a bundleId, or be in a capacitor project');
|
|
41
|
+
program.error('');
|
|
36
42
|
}
|
|
37
43
|
if (!appId) {
|
|
38
|
-
|
|
44
|
+
p.log.error('Missing argument, you need to provide a appId, or be in a capacitor project');
|
|
45
|
+
program.error('');
|
|
39
46
|
}
|
|
40
47
|
|
|
41
|
-
|
|
48
|
+
p.log.info(`Deleting bundle ${appId}@${bundleId} from Capgo`);
|
|
42
49
|
|
|
43
50
|
await deleteSpecificVersion(supabase, appId, userId, bundleId);
|
|
44
|
-
|
|
45
|
-
|
|
51
|
+
p.log.success(`Bundle ${appId}@${bundleId} deleted in Capgo`);
|
|
52
|
+
p.outro(`Done`);
|
|
46
53
|
process.exit()
|
|
47
54
|
}
|
package/src/bundle/encrypt.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { program } from 'commander'
|
|
2
2
|
import { existsSync, readFileSync, writeFileSync } from 'fs'
|
|
3
|
+
import ciDetect from '@npmcli/ci-detect';
|
|
4
|
+
import * as p from '@clack/prompts';
|
|
3
5
|
import { checkLatest } from '../api/update';
|
|
4
6
|
import { encryptSource } from '../api/crypto';
|
|
5
|
-
import { baseKeyPub } from '../utils';
|
|
7
|
+
import { baseKeyPub, defaulPublicKey } from '../utils';
|
|
6
8
|
|
|
7
9
|
interface Options {
|
|
8
10
|
key?: string
|
|
@@ -10,11 +12,14 @@ interface Options {
|
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
export const encryptZip = async (zipPath: string, options: Options) => {
|
|
15
|
+
p.intro(`Encryption`);
|
|
16
|
+
|
|
13
17
|
await checkLatest();
|
|
14
18
|
// write in file .capgo the apikey in home directory
|
|
15
19
|
|
|
16
20
|
if (!existsSync(zipPath)) {
|
|
17
|
-
|
|
21
|
+
p.log.error(`Error: Zip not found at the path ${zipPath}`);
|
|
22
|
+
program.error('');
|
|
18
23
|
}
|
|
19
24
|
|
|
20
25
|
const keyPath = options.key || baseKeyPub
|
|
@@ -23,7 +28,17 @@ export const encryptZip = async (zipPath: string, options: Options) => {
|
|
|
23
28
|
let publicKey = options.keyData || "";
|
|
24
29
|
|
|
25
30
|
if (!existsSync(keyPath) && !publicKey) {
|
|
26
|
-
|
|
31
|
+
p.log.warning(`Cannot find public key ${keyPath} or as keyData option`);
|
|
32
|
+
if (ciDetect()) {
|
|
33
|
+
p.log.error(`Error: Missing public key`);
|
|
34
|
+
program.error('');
|
|
35
|
+
}
|
|
36
|
+
const res = await p.confirm({ message: 'Do you want to use our public key ?' })
|
|
37
|
+
if (!res) {
|
|
38
|
+
p.log.error(`Error: Missing public key`);
|
|
39
|
+
program.error('');
|
|
40
|
+
}
|
|
41
|
+
publicKey = defaulPublicKey
|
|
27
42
|
} else if (existsSync(keyPath)) {
|
|
28
43
|
// open with fs publicKey path
|
|
29
44
|
const keyFile = readFileSync(keyPath)
|
|
@@ -32,9 +47,10 @@ export const encryptZip = async (zipPath: string, options: Options) => {
|
|
|
32
47
|
|
|
33
48
|
const zipFile = readFileSync(zipPath)
|
|
34
49
|
const encodedZip = encryptSource(zipFile, publicKey)
|
|
35
|
-
|
|
50
|
+
p.log.success(`ivSessionKey: ${encodedZip.ivSessionKey}`);
|
|
36
51
|
// write decodedZip in a file
|
|
37
52
|
writeFileSync(`${zipPath}_encrypted.zip`, encodedZip.encryptedData)
|
|
38
|
-
|
|
53
|
+
p.log.success(`Encrypted zip saved at ${zipPath}_encrypted.zip`);
|
|
54
|
+
p.outro(`Done ✅`);
|
|
39
55
|
process.exit()
|
|
40
56
|
}
|
package/src/bundle/list.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { program } from 'commander';
|
|
2
|
+
import * as p from '@clack/prompts';
|
|
2
3
|
import { checkAppExistsAndHasPermissionErr } from '../api/app';
|
|
3
4
|
import { OptionsBase } from '../api/utils';
|
|
4
5
|
import { getActiveAppVersions, displayBundles } from '../api/versions';
|
|
@@ -6,23 +7,26 @@ import { createSupabaseClient, findSavedKey, getConfig, verifyUser } from '../ut
|
|
|
6
7
|
import { checkLatest } from '../api/update';
|
|
7
8
|
|
|
8
9
|
export const listBundle = async (appId: string, options: OptionsBase) => {
|
|
10
|
+
p.intro(`List bundles`);
|
|
9
11
|
await checkLatest();
|
|
10
12
|
options.apikey = options.apikey || findSavedKey()
|
|
11
13
|
const config = await getConfig();
|
|
12
14
|
|
|
13
15
|
appId = appId || config?.app?.appId
|
|
14
16
|
if (!options.apikey) {
|
|
15
|
-
|
|
17
|
+
p.log.error("Missing API key, you need to provide a API key to upload your bundle");
|
|
18
|
+
program.error('');
|
|
16
19
|
}
|
|
17
20
|
if (!appId) {
|
|
18
|
-
|
|
21
|
+
p.log.error("Missing argument, you need to provide a appid, or be in a capacitor project");
|
|
22
|
+
program.error('');
|
|
19
23
|
}
|
|
20
24
|
|
|
21
25
|
const supabase = createSupabaseClient(options.apikey)
|
|
22
26
|
|
|
23
27
|
const userId = await verifyUser(supabase, options.apikey);
|
|
24
28
|
|
|
25
|
-
|
|
29
|
+
p.log.info(`Querying available versions of: ${appId} in Capgo`);
|
|
26
30
|
|
|
27
31
|
// Check we have app access to this appId
|
|
28
32
|
await checkAppExistsAndHasPermissionErr(supabase, appId, options.apikey);
|
|
@@ -30,9 +34,9 @@ export const listBundle = async (appId: string, options: OptionsBase) => {
|
|
|
30
34
|
// Get all active app versions we might possibly be able to cleanup
|
|
31
35
|
const allVersions = await getActiveAppVersions(supabase, appId, userId);
|
|
32
36
|
|
|
33
|
-
|
|
37
|
+
p.log.info(`Active versions in Capgo: ${allVersions?.length}`);
|
|
34
38
|
|
|
35
39
|
displayBundles(allVersions);
|
|
36
|
-
|
|
40
|
+
p.outro(`Done ✅`);
|
|
37
41
|
process.exit()
|
|
38
42
|
}
|
package/src/bundle/unlink.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { program } from 'commander';
|
|
2
2
|
import { getVersionData } from 'api/versions';
|
|
3
|
+
import * as p from '@clack/prompts';
|
|
3
4
|
import { checkVersionNotUsedInDeviceOverride } from '../api/devices_override';
|
|
4
5
|
import { checkVersionNotUsedInChannel } from '../api/channels';
|
|
5
6
|
import { OptionsBase } from '../api/utils';
|
|
@@ -14,6 +15,7 @@ interface Options extends OptionsBase {
|
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
export const unlinkDevice = async (channel: string, appId: string, options: Options) => {
|
|
18
|
+
p.intro(`Unlink bundle`);
|
|
17
19
|
options.apikey = options.apikey || findSavedKey()
|
|
18
20
|
const config = await getConfig();
|
|
19
21
|
appId = appId || config?.app?.appId
|
|
@@ -23,13 +25,16 @@ export const unlinkDevice = async (channel: string, appId: string, options: Opti
|
|
|
23
25
|
bundle = bundle || config?.app?.package?.version
|
|
24
26
|
|
|
25
27
|
if (!options.apikey) {
|
|
26
|
-
|
|
28
|
+
p.log.error("Missing API key, you need to provide a API key to upload your bundle");
|
|
29
|
+
program.error('');
|
|
27
30
|
}
|
|
28
31
|
if (!appId) {
|
|
29
|
-
|
|
32
|
+
p.log.error("Missing argument, you need to provide a appId, or be in a capacitor project");
|
|
33
|
+
program.error('');
|
|
30
34
|
}
|
|
31
35
|
if (!bundle) {
|
|
32
|
-
|
|
36
|
+
p.log.error("Missing argument, you need to provide a bundle, or be in a capacitor project");
|
|
37
|
+
program.error('');
|
|
33
38
|
}
|
|
34
39
|
const supabase = createSupabaseClient(options.apikey)
|
|
35
40
|
|
|
@@ -38,7 +43,8 @@ export const unlinkDevice = async (channel: string, appId: string, options: Opti
|
|
|
38
43
|
await checkAppExistsAndHasPermissionErr(supabase, appId, options.apikey);
|
|
39
44
|
|
|
40
45
|
if (!channel) {
|
|
41
|
-
|
|
46
|
+
p.log.error("Missing argument, you need to provide a channel");
|
|
47
|
+
program.error('');
|
|
42
48
|
}
|
|
43
49
|
try {
|
|
44
50
|
await checkPlanValid(supabase, userId)
|
|
@@ -57,8 +63,9 @@ export const unlinkDevice = async (channel: string, appId: string, options: Opti
|
|
|
57
63
|
notify: false,
|
|
58
64
|
}).catch()
|
|
59
65
|
} catch (err) {
|
|
60
|
-
|
|
66
|
+
p.log.error(`Unknow error ${formatError(err)}`);
|
|
67
|
+
program.error('');
|
|
61
68
|
}
|
|
62
|
-
|
|
69
|
+
p.outro('Done ✅');
|
|
63
70
|
process.exit()
|
|
64
71
|
}
|