@capgo/cli 4.2.4 → 4.2.8
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 +24 -0
- package/dist/index.js +109 -81
- 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 +6 -6
- 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,30 @@
|
|
|
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.8](https://github.com/Cap-go/CLI/compare/v4.2.7...v4.2.8) (2024-03-23)
|
|
6
|
+
|
|
7
|
+
### [4.2.7](https://github.com/Cap-go/CLI/compare/v4.2.6...v4.2.7) (2024-03-23)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Bug Fixes
|
|
11
|
+
|
|
12
|
+
* lint issue ([a836b3c](https://github.com/Cap-go/CLI/commit/a836b3cf59a6396f2200a3a5383d5dd10e19ad07))
|
|
13
|
+
|
|
14
|
+
### [4.2.6](https://github.com/Cap-go/CLI/compare/v4.2.5...v4.2.6) (2024-03-23)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Bug Fixes
|
|
18
|
+
|
|
19
|
+
* lint ([92b0e46](https://github.com/Cap-go/CLI/commit/92b0e462b7cc3d2c77b585d6596aba746df16b71))
|
|
20
|
+
* upload ([394b2ce](https://github.com/Cap-go/CLI/commit/394b2ceb1947de2e86870f1f3d57e9efe646b40a))
|
|
21
|
+
|
|
22
|
+
### [4.2.5](https://github.com/Cap-go/CLI/compare/v4.2.4...v4.2.5) (2024-03-22)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Bug Fixes
|
|
26
|
+
|
|
27
|
+
* zip json output ([4028f9b](https://github.com/Cap-go/CLI/commit/4028f9b79b3c53a7967a137784918f4ac614d011))
|
|
28
|
+
|
|
5
29
|
### [4.2.4](https://github.com/Cap-go/CLI/compare/v4.2.3...v4.2.4) (2024-03-22)
|
|
6
30
|
|
|
7
31
|
|
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.8",
|
|
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({
|
|
@@ -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;
|
|
@@ -63665,8 +63647,7 @@ The app size is ${mbSize} Mb, this may take a while to download for users
|
|
|
63665
63647
|
const nativePackages = hashedLocalDependencies.size > 0 || !options.ignoreMetadataCheck ? Array.from(hashedLocalDependencies, ([name, value]) => ({ name, version: value.version })) : void 0;
|
|
63666
63648
|
const appOwner = await getAppOwner(supabase, appid);
|
|
63667
63649
|
const versionData = {
|
|
63668
|
-
bucket_id: external ?
|
|
63669
|
-
user_id: appOwner,
|
|
63650
|
+
// bucket_id: external ? undefined : fileName,
|
|
63670
63651
|
name: bundle2,
|
|
63671
63652
|
app_id: appid,
|
|
63672
63653
|
session_key: sessionKey,
|
|
@@ -63674,6 +63655,8 @@ The app size is ${mbSize} Mb, this may take a while to download for users
|
|
|
63674
63655
|
storage_provider: external ? "external" : "r2-direct",
|
|
63675
63656
|
minUpdateVersion,
|
|
63676
63657
|
native_packages: nativePackages,
|
|
63658
|
+
owner_org: EMPTY_UUID,
|
|
63659
|
+
user_id: userId,
|
|
63677
63660
|
checksum
|
|
63678
63661
|
};
|
|
63679
63662
|
const { error: dbError } = await updateOrCreateVersion(supabase, versionData);
|
|
@@ -63684,7 +63667,7 @@ The app size is ${mbSize} Mb, this may take a while to download for users
|
|
|
63684
63667
|
if (!external && zipped) {
|
|
63685
63668
|
const spinner = de();
|
|
63686
63669
|
spinner.start(`Uploading Bundle`);
|
|
63687
|
-
const url = await uploadUrl(supabase, appid,
|
|
63670
|
+
const url = await uploadUrl(supabase, appid, bundle2);
|
|
63688
63671
|
if (!url) {
|
|
63689
63672
|
f2.error(`Cannot get upload url`);
|
|
63690
63673
|
program.error("");
|
|
@@ -63712,7 +63695,8 @@ The app size is ${mbSize} Mb, this may take a while to download for users
|
|
|
63712
63695
|
name: channel2,
|
|
63713
63696
|
app_id: appid,
|
|
63714
63697
|
created_by: appOwner,
|
|
63715
|
-
version: versionId
|
|
63698
|
+
version: versionId,
|
|
63699
|
+
owner_org: EMPTY_UUID
|
|
63716
63700
|
});
|
|
63717
63701
|
if (dbError3) {
|
|
63718
63702
|
f2.error(`Cannot set channel, the upload key is not allowed to do that, use the "all" for this. ${formatError(dbError3)}`);
|
|
@@ -63947,7 +63931,7 @@ async function addApp(appId, options, throwErr = true) {
|
|
|
63947
63931
|
program.error("");
|
|
63948
63932
|
}
|
|
63949
63933
|
const supabase = await createSupabaseClient(options.apikey);
|
|
63950
|
-
|
|
63934
|
+
let userId = await verifyUser(supabase, options.apikey, ["write", "all"]);
|
|
63951
63935
|
await checkPlanValid(supabase, userId, options.apikey, void 0, false);
|
|
63952
63936
|
const appExist = await checkAppExists(supabase, appId);
|
|
63953
63937
|
if (throwErr && appExist) {
|
|
@@ -63956,6 +63940,27 @@ async function addApp(appId, options, throwErr = true) {
|
|
|
63956
63940
|
} else if (appExist) {
|
|
63957
63941
|
return true;
|
|
63958
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`);
|
|
63959
63964
|
let { name, icon } = options;
|
|
63960
63965
|
appId = appId || config?.app?.appId;
|
|
63961
63966
|
name = name || config?.app?.appName || "Unknown";
|
|
@@ -63996,7 +64001,7 @@ async function addApp(appId, options, throwErr = true) {
|
|
|
63996
64001
|
}
|
|
63997
64002
|
const { error: dbError } = await supabase.from("apps").insert({
|
|
63998
64003
|
icon_url: signedURL,
|
|
63999
|
-
|
|
64004
|
+
owner_org: organizationUid,
|
|
64000
64005
|
name,
|
|
64001
64006
|
app_id: appId
|
|
64002
64007
|
});
|
|
@@ -64005,12 +64010,12 @@ async function addApp(appId, options, throwErr = true) {
|
|
|
64005
64010
|
program.error("");
|
|
64006
64011
|
}
|
|
64007
64012
|
const { error: dbVersionError } = await supabase.from("app_versions").insert([{
|
|
64008
|
-
|
|
64013
|
+
owner_org: organizationUid,
|
|
64009
64014
|
deleted: true,
|
|
64010
64015
|
name: "unknown",
|
|
64011
64016
|
app_id: appId
|
|
64012
64017
|
}, {
|
|
64013
|
-
|
|
64018
|
+
owner_org: organizationUid,
|
|
64014
64019
|
deleted: true,
|
|
64015
64020
|
name: "builtin",
|
|
64016
64021
|
app_id: appId
|
|
@@ -64325,20 +64330,20 @@ async function checkVersionNotUsedInDeviceOverride(supabase, appid, versionData)
|
|
|
64325
64330
|
}
|
|
64326
64331
|
|
|
64327
64332
|
// src/api/versions.ts
|
|
64328
|
-
async function deleteAppVersion(supabase, appid,
|
|
64333
|
+
async function deleteAppVersion(supabase, appid, bundle2) {
|
|
64329
64334
|
const { error: delAppSpecVersionError } = await supabase.from("app_versions").update({
|
|
64330
64335
|
deleted: true
|
|
64331
|
-
}).eq("app_id", appid).eq("deleted", false).eq("
|
|
64336
|
+
}).eq("app_id", appid).eq("deleted", false).eq("name", bundle2);
|
|
64332
64337
|
if (delAppSpecVersionError) {
|
|
64333
64338
|
f2.error(`App Version ${appid}@${bundle2} not found in database`);
|
|
64334
64339
|
program.error("");
|
|
64335
64340
|
}
|
|
64336
64341
|
}
|
|
64337
|
-
async function deleteSpecificVersion(supabase, appid,
|
|
64338
|
-
const versionData = await getVersionData(supabase, appid,
|
|
64339
|
-
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);
|
|
64340
64345
|
await checkVersionNotUsedInDeviceOverride(supabase, appid, versionData);
|
|
64341
|
-
await deleteAppVersion(supabase, appid,
|
|
64346
|
+
await deleteAppVersion(supabase, appid, bundle2);
|
|
64342
64347
|
}
|
|
64343
64348
|
function displayBundles(data) {
|
|
64344
64349
|
const t = new import_console_table_printer2.Table({
|
|
@@ -64354,8 +64359,8 @@ function displayBundles(data) {
|
|
|
64354
64359
|
});
|
|
64355
64360
|
f2.success(t.render());
|
|
64356
64361
|
}
|
|
64357
|
-
async function getActiveAppVersions(supabase, appid,
|
|
64358
|
-
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 });
|
|
64359
64364
|
if (vError) {
|
|
64360
64365
|
f2.error(`App ${appid} not found in database`);
|
|
64361
64366
|
program.error("");
|
|
@@ -64370,8 +64375,8 @@ async function getChannelsVersion(supabase, appid) {
|
|
|
64370
64375
|
}
|
|
64371
64376
|
return channels.map((c2) => c2.version);
|
|
64372
64377
|
}
|
|
64373
|
-
async function getVersionData(supabase, appid,
|
|
64374
|
-
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();
|
|
64375
64380
|
if (!versionData || versionIdError) {
|
|
64376
64381
|
f2.error(`App Version ${appid}@${bundle2} doesn't exist`);
|
|
64377
64382
|
program.error("");
|
|
@@ -64397,7 +64402,7 @@ async function listBundle(appId, options) {
|
|
|
64397
64402
|
const supabase = await createSupabaseClient(options.apikey);
|
|
64398
64403
|
const userId = await verifyUser(supabase, options.apikey, ["write", "all", "read", "upload"]);
|
|
64399
64404
|
f2.info(`Querying available versions of: ${appId} in Capgo`);
|
|
64400
|
-
await
|
|
64405
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, 1 /* read */);
|
|
64401
64406
|
const allVersions = await getActiveAppVersions(supabase, appId, userId);
|
|
64402
64407
|
f2.info(`Active versions in Capgo: ${allVersions?.length}`);
|
|
64403
64408
|
displayBundles(allVersions);
|
|
@@ -64572,7 +64577,7 @@ async function deleteBundle(bundleId, appId, options) {
|
|
|
64572
64577
|
}
|
|
64573
64578
|
const supabase = await createSupabaseClient(options.apikey);
|
|
64574
64579
|
const userId = await verifyUser(supabase, options.apikey, ["write", "all"]);
|
|
64575
|
-
await
|
|
64580
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, 3 /* write */);
|
|
64576
64581
|
appId = appId || config?.app?.appId;
|
|
64577
64582
|
if (!options.apikey) {
|
|
64578
64583
|
f2.error("Missing API key, you need to provide an API key to delete your app");
|
|
@@ -64612,7 +64617,7 @@ async function setChannel(channel2, appId, options) {
|
|
|
64612
64617
|
}
|
|
64613
64618
|
const supabase = await createSupabaseClient(options.apikey);
|
|
64614
64619
|
const userId = await verifyUser(supabase, options.apikey, ["write", "all"]);
|
|
64615
|
-
await
|
|
64620
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, 4 /* admin */);
|
|
64616
64621
|
const { bundle: bundle2, latest, downgrade, upgrade, ios, android, selfAssign, state, disableAutoUpdate } = options;
|
|
64617
64622
|
if (!channel2) {
|
|
64618
64623
|
f2.error("Missing argument, you need to provide a channel");
|
|
@@ -64724,13 +64729,13 @@ async function currentBundle(channel2, appId, options) {
|
|
|
64724
64729
|
program.error("");
|
|
64725
64730
|
}
|
|
64726
64731
|
const supabase = await createSupabaseClient(options.apikey);
|
|
64727
|
-
const
|
|
64728
|
-
await
|
|
64732
|
+
const _userId = await verifyUser(supabase, options.apikey, ["write", "all", "read"]);
|
|
64733
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, 1 /* read */);
|
|
64729
64734
|
if (!channel2) {
|
|
64730
64735
|
f2.error(`Please provide a channel to get the bundle from.`);
|
|
64731
64736
|
program.error("");
|
|
64732
64737
|
}
|
|
64733
|
-
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);
|
|
64734
64739
|
if (error || supabaseChannel.length === 0) {
|
|
64735
64740
|
f2.error(`Error retrieving channel ${channel2} for app ${appId}. Perhaps the channel does not exists?`);
|
|
64736
64741
|
program.error("");
|
|
@@ -64822,8 +64827,8 @@ async function cleanupBundle(appid, options) {
|
|
|
64822
64827
|
program.error("");
|
|
64823
64828
|
}
|
|
64824
64829
|
const supabase = await createSupabaseClient(options.apikey);
|
|
64825
|
-
const userId = await verifyUser(supabase, options.apikey);
|
|
64826
|
-
await
|
|
64830
|
+
const userId = await verifyUser(supabase, options.apikey, ["write", "all"]);
|
|
64831
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appid, 3 /* write */);
|
|
64827
64832
|
f2.info(`Querying all available versions in Capgo`);
|
|
64828
64833
|
let allVersions = await getActiveAppVersions(supabase, appid, userId);
|
|
64829
64834
|
const versionInUse = await getChannelsVersion(supabase, appid);
|
|
@@ -64889,7 +64894,7 @@ async function deleteChannel(channelId, appId, options) {
|
|
|
64889
64894
|
}
|
|
64890
64895
|
const supabase = await createSupabaseClient(options.apikey);
|
|
64891
64896
|
const userId = await verifyUser(supabase, options.apikey, ["write", "all"]);
|
|
64892
|
-
await
|
|
64897
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, 4 /* admin */);
|
|
64893
64898
|
f2.info(`Deleting channel ${appId}#${channelId} from Capgo`);
|
|
64894
64899
|
try {
|
|
64895
64900
|
await delChannel(supabase, channelId, appId, userId);
|
|
@@ -64928,7 +64933,7 @@ async function listChannels(appId, options) {
|
|
|
64928
64933
|
}
|
|
64929
64934
|
const supabase = await createSupabaseClient(options.apikey);
|
|
64930
64935
|
const userId = await verifyUser(supabase, options.apikey, ["write", "all", "read", "upload"]);
|
|
64931
|
-
await
|
|
64936
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, 1 /* read */);
|
|
64932
64937
|
f2.info(`Querying available channels in Capgo`);
|
|
64933
64938
|
const allVersions = await getActiveChannels(supabase, appId);
|
|
64934
64939
|
f2.info(`Active channels in Capgo: ${allVersions?.length}`);
|
|
@@ -64966,9 +64971,9 @@ async function setApp(appId, options) {
|
|
|
64966
64971
|
}
|
|
64967
64972
|
const supabase = await createSupabaseClient(options.apikey);
|
|
64968
64973
|
const userId = await verifyUser(supabase, options.apikey, ["write", "all"]);
|
|
64969
|
-
await
|
|
64974
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, 4 /* admin */);
|
|
64970
64975
|
const { name, icon, retention } = options;
|
|
64971
|
-
if (retention &&
|
|
64976
|
+
if (retention && Number.isNaN(Number(retention))) {
|
|
64972
64977
|
f2.error(`retention value must be a number`);
|
|
64973
64978
|
program.error(``);
|
|
64974
64979
|
} else if (retention && retention < 0) {
|
|
@@ -65034,15 +65039,39 @@ async function deleteApp(appId, options) {
|
|
|
65034
65039
|
}
|
|
65035
65040
|
const supabase = await createSupabaseClient(options.apikey);
|
|
65036
65041
|
const userId = await verifyUser(supabase, options.apikey, ["write", "all"]);
|
|
65037
|
-
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
|
+
}
|
|
65038
65069
|
const { error } = await supabase.storage.from(`images/${userId}`).remove([appId]);
|
|
65039
65070
|
if (error)
|
|
65040
65071
|
f2.error("Could not delete app logo");
|
|
65041
65072
|
const { error: delError } = await supabase.storage.from(`apps/${appId}/${userId}`).remove(["versions"]);
|
|
65042
|
-
if (delError)
|
|
65073
|
+
if (delError)
|
|
65043
65074
|
f2.error("Could not delete app version");
|
|
65044
|
-
program.error("");
|
|
65045
|
-
}
|
|
65046
65075
|
const { error: dbError } = await supabase.from("apps").delete().eq("app_id", appId).eq("user_id", userId);
|
|
65047
65076
|
if (dbError) {
|
|
65048
65077
|
f2.error("Could not delete app");
|
|
@@ -65085,7 +65114,7 @@ async function checkCompatibilityCommand(appId, options) {
|
|
|
65085
65114
|
}
|
|
65086
65115
|
const supabase = await createSupabaseClient(options.apikey);
|
|
65087
65116
|
await verifyUser(supabase, options.apikey, ["write", "all", "read", "upload"]);
|
|
65088
|
-
await
|
|
65117
|
+
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, 1 /* read */);
|
|
65089
65118
|
const { finalCompatibility } = await checkCompatibility(supabase, appId, channel2);
|
|
65090
65119
|
const t = new import_console_table_printer4.Table({
|
|
65091
65120
|
title: "Compatibility",
|
|
@@ -65124,7 +65153,6 @@ bundle.command("upload [appId]").alias("u").description("Upload a new bundle in
|
|
|
65124
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");
|
|
65125
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");
|
|
65126
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");
|
|
65127
|
-
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");
|
|
65128
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");
|
|
65129
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");
|
|
65130
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()
|