@capgo/cli 4.2.3 → 4.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/dist/index.js +113 -83
- package/package.json +1 -1
- package/src/api/channels.ts +2 -4
- package/src/api/versions.ts +9 -11
- package/src/app/add.ts +35 -4
- package/src/app/debug.ts +9 -3
- package/src/app/delete.ts +44 -6
- package/src/app/set.ts +4 -4
- package/src/bundle/cleanup.ts +5 -6
- package/src/bundle/compatibility.ts +3 -3
- package/src/bundle/delete.ts +3 -3
- package/src/bundle/list.ts +3 -3
- package/src/bundle/unlink.ts +7 -6
- package/src/bundle/upload.ts +12 -8
- package/src/bundle/zip.ts +11 -9
- package/src/channel/add.ts +4 -4
- package/src/channel/currentBundle.ts +4 -5
- package/src/channel/delete.ts +3 -3
- package/src/channel/list.ts +3 -3
- package/src/channel/set.ts +3 -2
- package/src/index.ts +7 -6
- package/src/types/supabase.types.ts +57 -29
- package/src/utils.ts +7 -6
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,35 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [4.2.7](https://github.com/Cap-go/CLI/compare/v4.2.6...v4.2.7) (2024-03-23)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* lint issue ([a836b3c](https://github.com/Cap-go/CLI/commit/a836b3cf59a6396f2200a3a5383d5dd10e19ad07))
|
|
11
|
+
|
|
12
|
+
### [4.2.6](https://github.com/Cap-go/CLI/compare/v4.2.5...v4.2.6) (2024-03-23)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* lint ([92b0e46](https://github.com/Cap-go/CLI/commit/92b0e462b7cc3d2c77b585d6596aba746df16b71))
|
|
18
|
+
* upload ([394b2ce](https://github.com/Cap-go/CLI/commit/394b2ceb1947de2e86870f1f3d57e9efe646b40a))
|
|
19
|
+
|
|
20
|
+
### [4.2.5](https://github.com/Cap-go/CLI/compare/v4.2.4...v4.2.5) (2024-03-22)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### Bug Fixes
|
|
24
|
+
|
|
25
|
+
* zip json output ([4028f9b](https://github.com/Cap-go/CLI/commit/4028f9b79b3c53a7967a137784918f4ac614d011))
|
|
26
|
+
|
|
27
|
+
### [4.2.4](https://github.com/Cap-go/CLI/compare/v4.2.3...v4.2.4) (2024-03-22)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
### Bug Fixes
|
|
31
|
+
|
|
32
|
+
* make no-key works ([11eed1a](https://github.com/Cap-go/CLI/commit/11eed1a515d44800ef369303dd14c5218b2164ca))
|
|
33
|
+
|
|
5
34
|
### [4.2.3](https://github.com/Cap-go/CLI/compare/v4.2.2...v4.2.3) (2024-03-12)
|
|
6
35
|
|
|
7
36
|
|
package/dist/index.js
CHANGED
|
@@ -61137,7 +61137,7 @@ var {
|
|
|
61137
61137
|
// package.json
|
|
61138
61138
|
var package_default = {
|
|
61139
61139
|
name: "@capgo/cli",
|
|
61140
|
-
version: "4.2.
|
|
61140
|
+
version: "4.2.7",
|
|
61141
61141
|
description: "A CLI to upload to capgo servers",
|
|
61142
61142
|
main: "dist/index.js",
|
|
61143
61143
|
bin: {
|
|
@@ -62309,6 +62309,7 @@ var baseKeyPub = `${baseKey}.pub`;
|
|
|
62309
62309
|
var defaultHost = "https://capgo.app";
|
|
62310
62310
|
var defaultApiHost = "https://api.capgo.app";
|
|
62311
62311
|
var defaultHostWeb = "https://web.capgo.app";
|
|
62312
|
+
var EMPTY_UUID = "00000000-0000-0000-0000-000000000000";
|
|
62312
62313
|
var regexSemver = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
|
|
62313
62314
|
var formatError = (error) => error ? `
|
|
62314
62315
|
${import_prettyjson.default.render(error)}` : "";
|
|
@@ -62411,17 +62412,13 @@ async function getAppOwner(supabase, appId) {
|
|
|
62411
62412
|
}
|
|
62412
62413
|
return data.user_id;
|
|
62413
62414
|
}
|
|
62414
|
-
async function isAllowedApp(supabase, apikey, appId) {
|
|
62415
|
-
const { data } = await supabase.rpc("is_app_owner", { apikey, appid: appId }).single();
|
|
62416
|
-
return !!data;
|
|
62417
|
-
}
|
|
62418
62415
|
var OrganizationPerm = /* @__PURE__ */ ((OrganizationPerm2) => {
|
|
62419
62416
|
OrganizationPerm2[OrganizationPerm2["none"] = 0] = "none";
|
|
62420
62417
|
OrganizationPerm2[OrganizationPerm2["read"] = 1] = "read";
|
|
62421
62418
|
OrganizationPerm2[OrganizationPerm2["upload"] = 2] = "upload";
|
|
62422
62419
|
OrganizationPerm2[OrganizationPerm2["write"] = 3] = "write";
|
|
62423
62420
|
OrganizationPerm2[OrganizationPerm2["admin"] = 4] = "admin";
|
|
62424
|
-
OrganizationPerm2[OrganizationPerm2["
|
|
62421
|
+
OrganizationPerm2[OrganizationPerm2["super_admin"] = 5] = "super_admin";
|
|
62425
62422
|
return OrganizationPerm2;
|
|
62426
62423
|
})(OrganizationPerm || {});
|
|
62427
62424
|
var hasOrganizationPerm = (perm, required) => perm >= required;
|
|
@@ -62457,7 +62454,7 @@ async function isAllowedAppOrg(supabase, apikey, appId) {
|
|
|
62457
62454
|
break;
|
|
62458
62455
|
}
|
|
62459
62456
|
case "perm_owner": {
|
|
62460
|
-
perm = 5 /*
|
|
62457
|
+
perm = 5 /* super_admin */;
|
|
62461
62458
|
break;
|
|
62462
62459
|
}
|
|
62463
62460
|
default: {
|
|
@@ -62568,10 +62565,10 @@ async function findMainFile() {
|
|
|
62568
62565
|
async function updateOrCreateVersion(supabase, update) {
|
|
62569
62566
|
return supabase.from("app_versions").upsert(update, { onConflict: "name,app_id" }).eq("app_id", update.app_id).eq("name", update.name);
|
|
62570
62567
|
}
|
|
62571
|
-
async function uploadUrl(supabase, appId,
|
|
62568
|
+
async function uploadUrl(supabase, appId, name) {
|
|
62572
62569
|
const data = {
|
|
62573
62570
|
app_id: appId,
|
|
62574
|
-
|
|
62571
|
+
name
|
|
62575
62572
|
};
|
|
62576
62573
|
try {
|
|
62577
62574
|
const pathUploadLink = "private/upload_link";
|
|
@@ -62878,14 +62875,6 @@ The app size is ${mbSize} Mb, this may take a while to download for users
|
|
|
62878
62875
|
(0, import_node_fs6.writeFileSync)(name, zipped);
|
|
62879
62876
|
if (!json)
|
|
62880
62877
|
s2.stop(`Saved to ${name}`);
|
|
62881
|
-
if (options.json) {
|
|
62882
|
-
const output = {
|
|
62883
|
-
bundle: bundle2,
|
|
62884
|
-
filename: name,
|
|
62885
|
-
checksum
|
|
62886
|
-
};
|
|
62887
|
-
f2.info(formatError(output));
|
|
62888
|
-
}
|
|
62889
62878
|
await snag.track({
|
|
62890
62879
|
channel: "app",
|
|
62891
62880
|
event: "App zip",
|
|
@@ -62897,6 +62886,14 @@ The app size is ${mbSize} Mb, this may take a while to download for users
|
|
|
62897
62886
|
}).catch();
|
|
62898
62887
|
if (!json)
|
|
62899
62888
|
$e(`Done \u2705`);
|
|
62889
|
+
if (json) {
|
|
62890
|
+
const output = {
|
|
62891
|
+
bundle: bundle2,
|
|
62892
|
+
filename: name,
|
|
62893
|
+
checksum
|
|
62894
|
+
};
|
|
62895
|
+
console.log(JSON.stringify(output, null, 2));
|
|
62896
|
+
}
|
|
62900
62897
|
import_node_process9.default.exit();
|
|
62901
62898
|
}
|
|
62902
62899
|
|
|
@@ -62938,24 +62935,6 @@ async function checkAppExists(supabase, appid) {
|
|
|
62938
62935
|
const { data: app2 } = await supabase.rpc("exist_app_v2", { appid }).single();
|
|
62939
62936
|
return !!app2;
|
|
62940
62937
|
}
|
|
62941
|
-
async function checkAppExistsAndHasPermissionErr(supabase, apikey, appid, shouldExist = true) {
|
|
62942
|
-
const appExist = await checkAppExists(supabase, appid);
|
|
62943
|
-
const perm = await isAllowedApp(supabase, apikey, appid);
|
|
62944
|
-
if (appExist && !shouldExist) {
|
|
62945
|
-
f2.error(`App ${appid} already exist`);
|
|
62946
|
-
program.error("");
|
|
62947
|
-
}
|
|
62948
|
-
if (!appExist && shouldExist) {
|
|
62949
|
-
f2.error(`App ${appid} does not exist`);
|
|
62950
|
-
program.error("");
|
|
62951
|
-
}
|
|
62952
|
-
if (appExist && !perm) {
|
|
62953
|
-
f2.error(`App ${appid} exist and you don't have permission to access it`);
|
|
62954
|
-
if (appid === "io.ionic.starter")
|
|
62955
|
-
f2.info("Modify your appid in your capacitor.config.json file to something unique, this is a default appid for ionic starter app");
|
|
62956
|
-
program.error("");
|
|
62957
|
-
}
|
|
62958
|
-
}
|
|
62959
62938
|
async function checkAppExistsAndHasPermissionOrgErr(supabase, apikey, appid, requiredPermission) {
|
|
62960
62939
|
const permissions = await isAllowedAppOrg(supabase, apikey, appid);
|
|
62961
62940
|
if (!permissions.okay) {
|
|
@@ -62988,6 +62967,11 @@ async function checkAppExistsAndHasPermissionOrgErr(supabase, apikey, appid, req
|
|
|
62988
62967
|
var newIconPath = "assets/icon.png";
|
|
62989
62968
|
|
|
62990
62969
|
// src/app/debug.ts
|
|
62970
|
+
function wait2(ms) {
|
|
62971
|
+
return new Promise((resolve2) => {
|
|
62972
|
+
setTimeout(resolve2, ms);
|
|
62973
|
+
});
|
|
62974
|
+
}
|
|
62991
62975
|
async function markSnag(channel2, userId, snag, event, icon = "\u2705") {
|
|
62992
62976
|
await snag.track({
|
|
62993
62977
|
channel: channel2,
|
|
@@ -63098,7 +63082,7 @@ async function waitLog(channel2, supabase, appId, snag, userId, deviceId) {
|
|
|
63098
63082
|
now = (/* @__PURE__ */ new Date()).toISOString();
|
|
63099
63083
|
query.after = now;
|
|
63100
63084
|
}
|
|
63101
|
-
await
|
|
63085
|
+
await wait2(1e3);
|
|
63102
63086
|
}
|
|
63103
63087
|
return Promise.resolve();
|
|
63104
63088
|
}
|
|
@@ -63121,7 +63105,7 @@ async function debugApp(appId, options) {
|
|
|
63121
63105
|
const snag = useLogSnag();
|
|
63122
63106
|
const userId = await verifyUser(supabase, options.apikey);
|
|
63123
63107
|
f2.info(`Getting active bundle in Capgo`);
|
|
63124
|
-
await
|
|
63108
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, 4 /* admin */);
|
|
63125
63109
|
const doRun = await se({ message: `Automatic check if update working in device ?` });
|
|
63126
63110
|
await cancelCommand("debug", doRun, userId, snag);
|
|
63127
63111
|
if (doRun) {
|
|
@@ -63302,8 +63286,8 @@ var import_node_process12 = __toESM(require("node:process"));
|
|
|
63302
63286
|
// src/api/channels.ts
|
|
63303
63287
|
var import_node_process11 = __toESM(require("node:process"));
|
|
63304
63288
|
var import_console_table_printer = __toESM(require_dist18());
|
|
63305
|
-
async function checkVersionNotUsedInChannel(supabase, appid,
|
|
63306
|
-
const { data: channelFound, error: errorChannel } = await supabase.from("channels").select().eq("app_id", appid).eq("
|
|
63289
|
+
async function checkVersionNotUsedInChannel(supabase, appid, versionData) {
|
|
63290
|
+
const { data: channelFound, error: errorChannel } = await supabase.from("channels").select().eq("app_id", appid).eq("version", versionData.id);
|
|
63307
63291
|
if (errorChannel) {
|
|
63308
63292
|
f2.error(`Cannot check Version ${appid}@${versionData.name}`);
|
|
63309
63293
|
program.error("");
|
|
@@ -63336,8 +63320,8 @@ function findUnknownVersion(supabase, appId) {
|
|
|
63336
63320
|
function createChannel(supabase, update) {
|
|
63337
63321
|
return supabase.from("channels").insert(update).select().single();
|
|
63338
63322
|
}
|
|
63339
|
-
function delChannel(supabase, name, appId,
|
|
63340
|
-
return supabase.from("channels").delete().eq("name", name).eq("app_id", appId).
|
|
63323
|
+
function delChannel(supabase, name, appId, _userId) {
|
|
63324
|
+
return supabase.from("channels").delete().eq("name", name).eq("app_id", appId).single();
|
|
63341
63325
|
}
|
|
63342
63326
|
function displayChannels(data) {
|
|
63343
63327
|
const t = new import_console_table_printer.Table({
|
|
@@ -63411,7 +63395,7 @@ async function addChannel(channelId, appId, options, shouldExit = true) {
|
|
|
63411
63395
|
}
|
|
63412
63396
|
const supabase = await createSupabaseClient(options.apikey);
|
|
63413
63397
|
const userId = await verifyUser(supabase, options.apikey, ["write", "all"]);
|
|
63414
|
-
await
|
|
63398
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, 4 /* admin */);
|
|
63415
63399
|
f2.info(`Creating channel ${appId}#${channelId} to Capgo`);
|
|
63416
63400
|
try {
|
|
63417
63401
|
const data = await findUnknownVersion(supabase, appId);
|
|
@@ -63423,7 +63407,7 @@ async function addChannel(channelId, appId, options, shouldExit = true) {
|
|
|
63423
63407
|
name: channelId,
|
|
63424
63408
|
app_id: appId,
|
|
63425
63409
|
version: data.id,
|
|
63426
|
-
|
|
63410
|
+
owner_org: EMPTY_UUID
|
|
63427
63411
|
});
|
|
63428
63412
|
f2.success(`Channel created \u2705`);
|
|
63429
63413
|
await snag.track({
|
|
@@ -63463,7 +63447,7 @@ async function uploadBundle(appid, options, shouldExit = true) {
|
|
|
63463
63447
|
oe(`Uploading`);
|
|
63464
63448
|
await checkLatest();
|
|
63465
63449
|
let { bundle: bundle2, path: path3, channel: channel2 } = options;
|
|
63466
|
-
const { external, key: key2
|
|
63450
|
+
const { external, key: key2, displayIvSession, autoMinUpdateVersion, ignoreMetadataCheck } = options;
|
|
63467
63451
|
let { minUpdateVersion } = options;
|
|
63468
63452
|
options.apikey = options.apikey || findSavedKey();
|
|
63469
63453
|
const snag = useLogSnag();
|
|
@@ -63573,8 +63557,6 @@ Trial expires in ${isTrial2} days`);
|
|
|
63573
63557
|
f2.error(`Version already exists ${formatError(appVersionError)}`);
|
|
63574
63558
|
program.error("");
|
|
63575
63559
|
}
|
|
63576
|
-
const safeBundle = bundle2.replace(/[^a-zA-Z0-9-_.!*'()]/g, "__");
|
|
63577
|
-
const fileName = `${safeBundle}.zip`;
|
|
63578
63560
|
let sessionKey;
|
|
63579
63561
|
let checksum = "";
|
|
63580
63562
|
let zipped = null;
|
|
@@ -63586,7 +63568,9 @@ Trial expires in ${isTrial2} days`);
|
|
|
63586
63568
|
s.start(`Calculating checksum`);
|
|
63587
63569
|
checksum = await (0, import_checksum2.checksum)(zipped, "crc32");
|
|
63588
63570
|
s.stop(`Checksum: ${checksum}`);
|
|
63589
|
-
if (key2
|
|
63571
|
+
if (key2 === false) {
|
|
63572
|
+
f2.info(`Encryption ignored`);
|
|
63573
|
+
} else if (key2 || (0, import_node_fs8.existsSync)(baseKeyPub)) {
|
|
63590
63574
|
const publicKey = typeof key2 === "string" ? key2 : baseKeyPub;
|
|
63591
63575
|
let keyData = options.keyData || "";
|
|
63592
63576
|
if (!keyData && !(0, import_node_fs8.existsSync)(publicKey)) {
|
|
@@ -63663,8 +63647,7 @@ The app size is ${mbSize} Mb, this may take a while to download for users
|
|
|
63663
63647
|
const nativePackages = hashedLocalDependencies.size > 0 || !options.ignoreMetadataCheck ? Array.from(hashedLocalDependencies, ([name, value]) => ({ name, version: value.version })) : void 0;
|
|
63664
63648
|
const appOwner = await getAppOwner(supabase, appid);
|
|
63665
63649
|
const versionData = {
|
|
63666
|
-
bucket_id: external ?
|
|
63667
|
-
user_id: appOwner,
|
|
63650
|
+
// bucket_id: external ? undefined : fileName,
|
|
63668
63651
|
name: bundle2,
|
|
63669
63652
|
app_id: appid,
|
|
63670
63653
|
session_key: sessionKey,
|
|
@@ -63672,6 +63655,8 @@ The app size is ${mbSize} Mb, this may take a while to download for users
|
|
|
63672
63655
|
storage_provider: external ? "external" : "r2-direct",
|
|
63673
63656
|
minUpdateVersion,
|
|
63674
63657
|
native_packages: nativePackages,
|
|
63658
|
+
owner_org: EMPTY_UUID,
|
|
63659
|
+
user_id: userId,
|
|
63675
63660
|
checksum
|
|
63676
63661
|
};
|
|
63677
63662
|
const { error: dbError } = await updateOrCreateVersion(supabase, versionData);
|
|
@@ -63682,7 +63667,7 @@ The app size is ${mbSize} Mb, this may take a while to download for users
|
|
|
63682
63667
|
if (!external && zipped) {
|
|
63683
63668
|
const spinner = de();
|
|
63684
63669
|
spinner.start(`Uploading Bundle`);
|
|
63685
|
-
const url = await uploadUrl(supabase, appid,
|
|
63670
|
+
const url = await uploadUrl(supabase, appid, bundle2);
|
|
63686
63671
|
if (!url) {
|
|
63687
63672
|
f2.error(`Cannot get upload url`);
|
|
63688
63673
|
program.error("");
|
|
@@ -63710,7 +63695,8 @@ The app size is ${mbSize} Mb, this may take a while to download for users
|
|
|
63710
63695
|
name: channel2,
|
|
63711
63696
|
app_id: appid,
|
|
63712
63697
|
created_by: appOwner,
|
|
63713
|
-
version: versionId
|
|
63698
|
+
version: versionId,
|
|
63699
|
+
owner_org: EMPTY_UUID
|
|
63714
63700
|
});
|
|
63715
63701
|
if (dbError3) {
|
|
63716
63702
|
f2.error(`Cannot set channel, the upload key is not allowed to do that, use the "all" for this. ${formatError(dbError3)}`);
|
|
@@ -63945,7 +63931,7 @@ async function addApp(appId, options, throwErr = true) {
|
|
|
63945
63931
|
program.error("");
|
|
63946
63932
|
}
|
|
63947
63933
|
const supabase = await createSupabaseClient(options.apikey);
|
|
63948
|
-
|
|
63934
|
+
let userId = await verifyUser(supabase, options.apikey, ["write", "all"]);
|
|
63949
63935
|
await checkPlanValid(supabase, userId, options.apikey, void 0, false);
|
|
63950
63936
|
const appExist = await checkAppExists(supabase, appId);
|
|
63951
63937
|
if (throwErr && appExist) {
|
|
@@ -63954,6 +63940,27 @@ async function addApp(appId, options, throwErr = true) {
|
|
|
63954
63940
|
} else if (appExist) {
|
|
63955
63941
|
return true;
|
|
63956
63942
|
}
|
|
63943
|
+
const { error: orgError, data: allOrganizations } = await supabase.rpc("get_orgs_v4");
|
|
63944
|
+
if (orgError) {
|
|
63945
|
+
f2.error("Cannot get the list of organizations - exiting");
|
|
63946
|
+
f2.error(`Error ${JSON.stringify(orgError)}`);
|
|
63947
|
+
program.error("");
|
|
63948
|
+
}
|
|
63949
|
+
const adminOrgs = allOrganizations.filter((org) => org.role === "admin" || org.role === "super_admin");
|
|
63950
|
+
const organizationUidRaw = adminOrgs.length > 1 ? await ie({
|
|
63951
|
+
message: "Please pick the organization that you want to insert to",
|
|
63952
|
+
options: adminOrgs.map((org) => {
|
|
63953
|
+
return { value: org.gid, label: org.name };
|
|
63954
|
+
})
|
|
63955
|
+
}) : adminOrgs[0].gid;
|
|
63956
|
+
if (eD(organizationUidRaw)) {
|
|
63957
|
+
f2.error("Canceled organization selection, exiting");
|
|
63958
|
+
program.error("");
|
|
63959
|
+
}
|
|
63960
|
+
const organizationUid = organizationUidRaw;
|
|
63961
|
+
const organization = allOrganizations.find((org) => org.gid === organizationUid);
|
|
63962
|
+
userId = organization.created_by;
|
|
63963
|
+
f2.info(`Using the organization "${organization.name}" as the app owner`);
|
|
63957
63964
|
let { name, icon } = options;
|
|
63958
63965
|
appId = appId || config?.app?.appId;
|
|
63959
63966
|
name = name || config?.app?.appName || "Unknown";
|
|
@@ -63994,7 +64001,7 @@ async function addApp(appId, options, throwErr = true) {
|
|
|
63994
64001
|
}
|
|
63995
64002
|
const { error: dbError } = await supabase.from("apps").insert({
|
|
63996
64003
|
icon_url: signedURL,
|
|
63997
|
-
|
|
64004
|
+
owner_org: organizationUid,
|
|
63998
64005
|
name,
|
|
63999
64006
|
app_id: appId
|
|
64000
64007
|
});
|
|
@@ -64003,12 +64010,12 @@ async function addApp(appId, options, throwErr = true) {
|
|
|
64003
64010
|
program.error("");
|
|
64004
64011
|
}
|
|
64005
64012
|
const { error: dbVersionError } = await supabase.from("app_versions").insert([{
|
|
64006
|
-
|
|
64013
|
+
owner_org: organizationUid,
|
|
64007
64014
|
deleted: true,
|
|
64008
64015
|
name: "unknown",
|
|
64009
64016
|
app_id: appId
|
|
64010
64017
|
}, {
|
|
64011
|
-
|
|
64018
|
+
owner_org: organizationUid,
|
|
64012
64019
|
deleted: true,
|
|
64013
64020
|
name: "builtin",
|
|
64014
64021
|
app_id: appId
|
|
@@ -64323,20 +64330,20 @@ async function checkVersionNotUsedInDeviceOverride(supabase, appid, versionData)
|
|
|
64323
64330
|
}
|
|
64324
64331
|
|
|
64325
64332
|
// src/api/versions.ts
|
|
64326
|
-
async function deleteAppVersion(supabase, appid,
|
|
64333
|
+
async function deleteAppVersion(supabase, appid, bundle2) {
|
|
64327
64334
|
const { error: delAppSpecVersionError } = await supabase.from("app_versions").update({
|
|
64328
64335
|
deleted: true
|
|
64329
|
-
}).eq("app_id", appid).eq("deleted", false).eq("
|
|
64336
|
+
}).eq("app_id", appid).eq("deleted", false).eq("name", bundle2);
|
|
64330
64337
|
if (delAppSpecVersionError) {
|
|
64331
64338
|
f2.error(`App Version ${appid}@${bundle2} not found in database`);
|
|
64332
64339
|
program.error("");
|
|
64333
64340
|
}
|
|
64334
64341
|
}
|
|
64335
|
-
async function deleteSpecificVersion(supabase, appid,
|
|
64336
|
-
const versionData = await getVersionData(supabase, appid,
|
|
64337
|
-
await checkVersionNotUsedInChannel(supabase, appid,
|
|
64342
|
+
async function deleteSpecificVersion(supabase, appid, _userId, bundle2) {
|
|
64343
|
+
const versionData = await getVersionData(supabase, appid, bundle2);
|
|
64344
|
+
await checkVersionNotUsedInChannel(supabase, appid, versionData);
|
|
64338
64345
|
await checkVersionNotUsedInDeviceOverride(supabase, appid, versionData);
|
|
64339
|
-
await deleteAppVersion(supabase, appid,
|
|
64346
|
+
await deleteAppVersion(supabase, appid, bundle2);
|
|
64340
64347
|
}
|
|
64341
64348
|
function displayBundles(data) {
|
|
64342
64349
|
const t = new import_console_table_printer2.Table({
|
|
@@ -64352,8 +64359,8 @@ function displayBundles(data) {
|
|
|
64352
64359
|
});
|
|
64353
64360
|
f2.success(t.render());
|
|
64354
64361
|
}
|
|
64355
|
-
async function getActiveAppVersions(supabase, appid,
|
|
64356
|
-
const { data, error: vError } = await supabase.from("app_versions").select().eq("app_id", appid).eq("
|
|
64362
|
+
async function getActiveAppVersions(supabase, appid, _userId) {
|
|
64363
|
+
const { data, error: vError } = await supabase.from("app_versions").select().eq("app_id", appid).eq("deleted", false).order("created_at", { ascending: false });
|
|
64357
64364
|
if (vError) {
|
|
64358
64365
|
f2.error(`App ${appid} not found in database`);
|
|
64359
64366
|
program.error("");
|
|
@@ -64368,8 +64375,8 @@ async function getChannelsVersion(supabase, appid) {
|
|
|
64368
64375
|
}
|
|
64369
64376
|
return channels.map((c2) => c2.version);
|
|
64370
64377
|
}
|
|
64371
|
-
async function getVersionData(supabase, appid,
|
|
64372
|
-
const { data: versionData, error: versionIdError } = await supabase.from("app_versions").select().eq("app_id", appid).eq("
|
|
64378
|
+
async function getVersionData(supabase, appid, bundle2) {
|
|
64379
|
+
const { data: versionData, error: versionIdError } = await supabase.from("app_versions").select().eq("app_id", appid).eq("name", bundle2).eq("deleted", false).single();
|
|
64373
64380
|
if (!versionData || versionIdError) {
|
|
64374
64381
|
f2.error(`App Version ${appid}@${bundle2} doesn't exist`);
|
|
64375
64382
|
program.error("");
|
|
@@ -64395,7 +64402,7 @@ async function listBundle(appId, options) {
|
|
|
64395
64402
|
const supabase = await createSupabaseClient(options.apikey);
|
|
64396
64403
|
const userId = await verifyUser(supabase, options.apikey, ["write", "all", "read", "upload"]);
|
|
64397
64404
|
f2.info(`Querying available versions of: ${appId} in Capgo`);
|
|
64398
|
-
await
|
|
64405
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, 1 /* read */);
|
|
64399
64406
|
const allVersions = await getActiveAppVersions(supabase, appId, userId);
|
|
64400
64407
|
f2.info(`Active versions in Capgo: ${allVersions?.length}`);
|
|
64401
64408
|
displayBundles(allVersions);
|
|
@@ -64570,7 +64577,7 @@ async function deleteBundle(bundleId, appId, options) {
|
|
|
64570
64577
|
}
|
|
64571
64578
|
const supabase = await createSupabaseClient(options.apikey);
|
|
64572
64579
|
const userId = await verifyUser(supabase, options.apikey, ["write", "all"]);
|
|
64573
|
-
await
|
|
64580
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, 3 /* write */);
|
|
64574
64581
|
appId = appId || config?.app?.appId;
|
|
64575
64582
|
if (!options.apikey) {
|
|
64576
64583
|
f2.error("Missing API key, you need to provide an API key to delete your app");
|
|
@@ -64610,7 +64617,7 @@ async function setChannel(channel2, appId, options) {
|
|
|
64610
64617
|
}
|
|
64611
64618
|
const supabase = await createSupabaseClient(options.apikey);
|
|
64612
64619
|
const userId = await verifyUser(supabase, options.apikey, ["write", "all"]);
|
|
64613
|
-
await
|
|
64620
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, 4 /* admin */);
|
|
64614
64621
|
const { bundle: bundle2, latest, downgrade, upgrade, ios, android, selfAssign, state, disableAutoUpdate } = options;
|
|
64615
64622
|
if (!channel2) {
|
|
64616
64623
|
f2.error("Missing argument, you need to provide a channel");
|
|
@@ -64722,13 +64729,13 @@ async function currentBundle(channel2, appId, options) {
|
|
|
64722
64729
|
program.error("");
|
|
64723
64730
|
}
|
|
64724
64731
|
const supabase = await createSupabaseClient(options.apikey);
|
|
64725
|
-
const
|
|
64726
|
-
await
|
|
64732
|
+
const _userId = await verifyUser(supabase, options.apikey, ["write", "all", "read"]);
|
|
64733
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, 1 /* read */);
|
|
64727
64734
|
if (!channel2) {
|
|
64728
64735
|
f2.error(`Please provide a channel to get the bundle from.`);
|
|
64729
64736
|
program.error("");
|
|
64730
64737
|
}
|
|
64731
|
-
const { data: supabaseChannel, error } = await supabase.from("channels").select("version ( name )").eq("name", channel2).eq("app_id", appId).
|
|
64738
|
+
const { data: supabaseChannel, error } = await supabase.from("channels").select("version ( name )").eq("name", channel2).eq("app_id", appId).limit(1);
|
|
64732
64739
|
if (error || supabaseChannel.length === 0) {
|
|
64733
64740
|
f2.error(`Error retrieving channel ${channel2} for app ${appId}. Perhaps the channel does not exists?`);
|
|
64734
64741
|
program.error("");
|
|
@@ -64820,8 +64827,8 @@ async function cleanupBundle(appid, options) {
|
|
|
64820
64827
|
program.error("");
|
|
64821
64828
|
}
|
|
64822
64829
|
const supabase = await createSupabaseClient(options.apikey);
|
|
64823
|
-
const userId = await verifyUser(supabase, options.apikey);
|
|
64824
|
-
await
|
|
64830
|
+
const userId = await verifyUser(supabase, options.apikey, ["write", "all"]);
|
|
64831
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appid, 3 /* write */);
|
|
64825
64832
|
f2.info(`Querying all available versions in Capgo`);
|
|
64826
64833
|
let allVersions = await getActiveAppVersions(supabase, appid, userId);
|
|
64827
64834
|
const versionInUse = await getChannelsVersion(supabase, appid);
|
|
@@ -64887,7 +64894,7 @@ async function deleteChannel(channelId, appId, options) {
|
|
|
64887
64894
|
}
|
|
64888
64895
|
const supabase = await createSupabaseClient(options.apikey);
|
|
64889
64896
|
const userId = await verifyUser(supabase, options.apikey, ["write", "all"]);
|
|
64890
|
-
await
|
|
64897
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, 4 /* admin */);
|
|
64891
64898
|
f2.info(`Deleting channel ${appId}#${channelId} from Capgo`);
|
|
64892
64899
|
try {
|
|
64893
64900
|
await delChannel(supabase, channelId, appId, userId);
|
|
@@ -64926,7 +64933,7 @@ async function listChannels(appId, options) {
|
|
|
64926
64933
|
}
|
|
64927
64934
|
const supabase = await createSupabaseClient(options.apikey);
|
|
64928
64935
|
const userId = await verifyUser(supabase, options.apikey, ["write", "all", "read", "upload"]);
|
|
64929
|
-
await
|
|
64936
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, 1 /* read */);
|
|
64930
64937
|
f2.info(`Querying available channels in Capgo`);
|
|
64931
64938
|
const allVersions = await getActiveChannels(supabase, appId);
|
|
64932
64939
|
f2.info(`Active channels in Capgo: ${allVersions?.length}`);
|
|
@@ -64964,9 +64971,9 @@ async function setApp(appId, options) {
|
|
|
64964
64971
|
}
|
|
64965
64972
|
const supabase = await createSupabaseClient(options.apikey);
|
|
64966
64973
|
const userId = await verifyUser(supabase, options.apikey, ["write", "all"]);
|
|
64967
|
-
await
|
|
64974
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, 4 /* admin */);
|
|
64968
64975
|
const { name, icon, retention } = options;
|
|
64969
|
-
if (retention &&
|
|
64976
|
+
if (retention && Number.isNaN(Number(retention))) {
|
|
64970
64977
|
f2.error(`retention value must be a number`);
|
|
64971
64978
|
program.error(``);
|
|
64972
64979
|
} else if (retention && retention < 0) {
|
|
@@ -65032,15 +65039,39 @@ async function deleteApp(appId, options) {
|
|
|
65032
65039
|
}
|
|
65033
65040
|
const supabase = await createSupabaseClient(options.apikey);
|
|
65034
65041
|
const userId = await verifyUser(supabase, options.apikey, ["write", "all"]);
|
|
65035
|
-
await
|
|
65042
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, 5 /* super_admin */);
|
|
65043
|
+
const { data: appOwnerRaw, error: appOwnerError } = await supabase.from("apps").select(`owner_org ( created_by )`).eq("app_id", appId).single();
|
|
65044
|
+
const appOwner = appOwnerRaw;
|
|
65045
|
+
if (!appOwnerError && (appOwner?.owner_org.created_by ?? "") !== userId) {
|
|
65046
|
+
f2.warn("Deleting the app is not recomended for users that are not the organization owner");
|
|
65047
|
+
f2.warn("You are invited as a super_admin but your are not the owner");
|
|
65048
|
+
f2.warn("It's strongly recomended that you do not continue!");
|
|
65049
|
+
const shouldContinue = await ie({
|
|
65050
|
+
message: "Do you want to continue?",
|
|
65051
|
+
options: [
|
|
65052
|
+
{
|
|
65053
|
+
label: "Yes",
|
|
65054
|
+
value: "yes"
|
|
65055
|
+
},
|
|
65056
|
+
{
|
|
65057
|
+
label: "No",
|
|
65058
|
+
value: "no"
|
|
65059
|
+
}
|
|
65060
|
+
]
|
|
65061
|
+
});
|
|
65062
|
+
if (eD(shouldContinue) || shouldContinue === "no") {
|
|
65063
|
+
f2.error("Canceled deleting the app, exiting");
|
|
65064
|
+
program.error("");
|
|
65065
|
+
}
|
|
65066
|
+
} else if (appOwnerError) {
|
|
65067
|
+
f2.warn(`Cannot get the app owner ${formatError(appOwnerError)}`);
|
|
65068
|
+
}
|
|
65036
65069
|
const { error } = await supabase.storage.from(`images/${userId}`).remove([appId]);
|
|
65037
65070
|
if (error)
|
|
65038
65071
|
f2.error("Could not delete app logo");
|
|
65039
65072
|
const { error: delError } = await supabase.storage.from(`apps/${appId}/${userId}`).remove(["versions"]);
|
|
65040
|
-
if (delError)
|
|
65073
|
+
if (delError)
|
|
65041
65074
|
f2.error("Could not delete app version");
|
|
65042
|
-
program.error("");
|
|
65043
|
-
}
|
|
65044
65075
|
const { error: dbError } = await supabase.from("apps").delete().eq("app_id", appId).eq("user_id", userId);
|
|
65045
65076
|
if (dbError) {
|
|
65046
65077
|
f2.error("Could not delete app");
|
|
@@ -65083,7 +65114,7 @@ async function checkCompatibilityCommand(appId, options) {
|
|
|
65083
65114
|
}
|
|
65084
65115
|
const supabase = await createSupabaseClient(options.apikey);
|
|
65085
65116
|
await verifyUser(supabase, options.apikey, ["write", "all", "read", "upload"]);
|
|
65086
|
-
await
|
|
65117
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, 1 /* read */);
|
|
65087
65118
|
const { finalCompatibility } = await checkCompatibility(supabase, appId, channel2);
|
|
65088
65119
|
const t = new import_console_table_printer4.Table({
|
|
65089
65120
|
title: "Compatibility",
|
|
@@ -65122,7 +65153,6 @@ bundle.command("upload [appId]").alias("u").description("Upload a new bundle in
|
|
|
65122
65153
|
bundle.command("compatibility [appId]").action(checkCompatibilityCommand).option("-a, --apikey <apikey>", "apikey to link to your account").option("-c, --channel <channel>", "channel to check the compatibility with").option("--text", "output text instead of emojis");
|
|
65123
65154
|
bundle.command("delete [bundleId] [appId]").alias("d").description("Delete a bundle in Capgo Cloud").action(deleteBundle).option("-a, --apikey <apikey>", "apikey to link to your account");
|
|
65124
65155
|
bundle.command("list [appId]").alias("l").description("List bundle in Capgo Cloud").action(listBundle).option("-a, --apikey <apikey>", "apikey to link to your account");
|
|
65125
|
-
bundle.command("unlink [appId]").description("Unlink a bundle in Capgo Cloud").action(listBundle).option("-a, --apikey <apikey>", "apikey to link to your account").option("-b, --bundle <bundle>", "bundle version number of the bundle to unlink");
|
|
65126
65156
|
bundle.command("cleanup [appId]").alias("c").action(cleanupBundle).description("Cleanup bundle in Capgo Cloud").option("-b, --bundle <bundle>", "bundle version number of the app to delete").option("-a, --apikey <apikey>", "apikey to link to your account").option("-k, --keep <keep>", "number of version to keep").option("-f, --force", "force removal");
|
|
65127
65157
|
bundle.command("decrypt [zipPath] [sessionKey]").description("Decrypt a signed zip bundle").action(decryptZip).option("--key <key>", "custom path for private signing key").option("--key-data <keyData>", "base64 private signing key");
|
|
65128
65158
|
bundle.command("encrypt [zipPath]").description("Encrypt a zip bundle").action(encryptZip).option("--key <key>", "custom path for private signing key").option("--key-data <keyData>", "base64 private signing key");
|
package/package.json
CHANGED
package/src/api/channels.ts
CHANGED
|
@@ -6,12 +6,11 @@ import * as p from '@clack/prompts'
|
|
|
6
6
|
import type { Database } from '../types/supabase.types'
|
|
7
7
|
import { formatError } from '../utils'
|
|
8
8
|
|
|
9
|
-
export async function checkVersionNotUsedInChannel(supabase: SupabaseClient<Database>, appid: string,
|
|
9
|
+
export async function checkVersionNotUsedInChannel(supabase: SupabaseClient<Database>, appid: string, versionData: Database['public']['Tables']['app_versions']['Row']) {
|
|
10
10
|
const { data: channelFound, error: errorChannel } = await supabase
|
|
11
11
|
.from('channels')
|
|
12
12
|
.select()
|
|
13
13
|
.eq('app_id', appid)
|
|
14
|
-
.eq('created_by', userId)
|
|
15
14
|
.eq('version', versionData.id)
|
|
16
15
|
if (errorChannel) {
|
|
17
16
|
p.log.error(`Cannot check Version ${appid}@${versionData.name}`)
|
|
@@ -63,13 +62,12 @@ export function createChannel(supabase: SupabaseClient<Database>, update: Databa
|
|
|
63
62
|
.single()
|
|
64
63
|
}
|
|
65
64
|
|
|
66
|
-
export function delChannel(supabase: SupabaseClient<Database>, name: string, appId: string,
|
|
65
|
+
export function delChannel(supabase: SupabaseClient<Database>, name: string, appId: string, _userId: string) {
|
|
67
66
|
return supabase
|
|
68
67
|
.from('channels')
|
|
69
68
|
.delete()
|
|
70
69
|
.eq('name', name)
|
|
71
70
|
.eq('app_id', appId)
|
|
72
|
-
.eq('created_by', userId)
|
|
73
71
|
.single()
|
|
74
72
|
}
|
|
75
73
|
interface version {
|
package/src/api/versions.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { getHumanDate } from '../utils'
|
|
|
9
9
|
import { checkVersionNotUsedInChannel } from './channels'
|
|
10
10
|
import { checkVersionNotUsedInDeviceOverride } from './devices_override'
|
|
11
11
|
|
|
12
|
-
export async function deleteAppVersion(supabase: SupabaseClient<Database>, appid: string,
|
|
12
|
+
export async function deleteAppVersion(supabase: SupabaseClient<Database>, appid: string, bundle: string) {
|
|
13
13
|
const { error: delAppSpecVersionError } = await supabase
|
|
14
14
|
.from('app_versions')
|
|
15
15
|
.update({
|
|
@@ -17,7 +17,6 @@ export async function deleteAppVersion(supabase: SupabaseClient<Database>, appid
|
|
|
17
17
|
})
|
|
18
18
|
.eq('app_id', appid)
|
|
19
19
|
.eq('deleted', false)
|
|
20
|
-
.eq('user_id', userId)
|
|
21
20
|
.eq('name', bundle)
|
|
22
21
|
if (delAppSpecVersionError) {
|
|
23
22
|
p.log.error(`App Version ${appid}@${bundle} not found in database`)
|
|
@@ -25,12 +24,12 @@ export async function deleteAppVersion(supabase: SupabaseClient<Database>, appid
|
|
|
25
24
|
}
|
|
26
25
|
}
|
|
27
26
|
|
|
28
|
-
export async function deleteSpecificVersion(supabase: SupabaseClient<Database>, appid: string,
|
|
29
|
-
const versionData = await getVersionData(supabase, appid,
|
|
30
|
-
await checkVersionNotUsedInChannel(supabase, appid,
|
|
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)
|
|
31
30
|
await checkVersionNotUsedInDeviceOverride(supabase, appid, versionData)
|
|
32
31
|
// Delete only a specific version in storage
|
|
33
|
-
await deleteAppVersion(supabase, appid,
|
|
32
|
+
await deleteAppVersion(supabase, appid, bundle)
|
|
34
33
|
}
|
|
35
34
|
|
|
36
35
|
export function displayBundles(data: (Database['public']['Tables']['app_versions']['Row'] & { keep?: string })[]) {
|
|
@@ -51,12 +50,12 @@ export function displayBundles(data: (Database['public']['Tables']['app_versions
|
|
|
51
50
|
p.log.success(t.render())
|
|
52
51
|
}
|
|
53
52
|
|
|
54
|
-
export async function getActiveAppVersions(supabase: SupabaseClient<Database>, appid: string,
|
|
53
|
+
export async function getActiveAppVersions(supabase: SupabaseClient<Database>, appid: string, _userId: string) {
|
|
55
54
|
const { data, error: vError } = await supabase
|
|
56
55
|
.from('app_versions')
|
|
57
56
|
.select()
|
|
58
57
|
.eq('app_id', appid)
|
|
59
|
-
.eq('user_id', userId)
|
|
58
|
+
// .eq('user_id', userId)
|
|
60
59
|
.eq('deleted', false)
|
|
61
60
|
.order('created_at', { ascending: false })
|
|
62
61
|
|
|
@@ -68,7 +67,7 @@ export async function getActiveAppVersions(supabase: SupabaseClient<Database>, a
|
|
|
68
67
|
}
|
|
69
68
|
|
|
70
69
|
export async function getChannelsVersion(supabase: SupabaseClient<Database>, appid: string) {
|
|
71
|
-
// get all channels versionID
|
|
70
|
+
// get all channels versionID
|
|
72
71
|
const { data: channels, error: channelsError } = await supabase
|
|
73
72
|
.from('channels')
|
|
74
73
|
.select('version')
|
|
@@ -81,12 +80,11 @@ export async function getChannelsVersion(supabase: SupabaseClient<Database>, app
|
|
|
81
80
|
return channels.map(c => c.version)
|
|
82
81
|
}
|
|
83
82
|
|
|
84
|
-
export async function getVersionData(supabase: SupabaseClient<Database>, appid: string,
|
|
83
|
+
export async function getVersionData(supabase: SupabaseClient<Database>, appid: string, bundle: string) {
|
|
85
84
|
const { data: versionData, error: versionIdError } = await supabase
|
|
86
85
|
.from('app_versions')
|
|
87
86
|
.select()
|
|
88
87
|
.eq('app_id', appid)
|
|
89
|
-
.eq('user_id', userId)
|
|
90
88
|
.eq('name', bundle)
|
|
91
89
|
.eq('deleted', false)
|
|
92
90
|
.single()
|