@capgo/cli 4.7.0 → 4.8.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 +9 -0
- package/bun.lockb +0 -0
- package/dist/index.js +182 -68
- package/package.json +2 -2
- package/src/api/app.ts +3 -23
- package/src/app/add.ts +1 -1
- package/src/bundle/upload.ts +36 -26
- package/src/index.ts +1 -0
- package/src/init.ts +35 -31
- package/src/login.ts +4 -0
- package/src/utils.ts +109 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
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.8.1](https://github.com/Cap-go/CLI/compare/v4.8.0...v4.8.1) (2024-05-11)
|
|
6
|
+
|
|
7
|
+
## [4.8.0](https://github.com/Cap-go/CLI/compare/v4.7.0...v4.8.0) (2024-05-10)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Features
|
|
11
|
+
|
|
12
|
+
* auto select package manager and runner ([94f8bef](https://github.com/Cap-go/CLI/commit/94f8bef06efeafbd5cff1979f5ed75de2a523caa))
|
|
13
|
+
|
|
5
14
|
## [4.7.0](https://github.com/Cap-go/CLI/compare/v4.6.3...v4.7.0) (2024-05-10)
|
|
6
15
|
|
|
7
16
|
|
package/bun.lockb
CHANGED
|
Binary file
|
package/dist/index.js
CHANGED
|
@@ -92373,7 +92373,7 @@ var {
|
|
|
92373
92373
|
// package.json
|
|
92374
92374
|
var package_default = {
|
|
92375
92375
|
name: "@capgo/cli",
|
|
92376
|
-
version: "4.
|
|
92376
|
+
version: "4.8.1",
|
|
92377
92377
|
description: "A CLI to upload to capgo servers",
|
|
92378
92378
|
author: "github.com/riderx",
|
|
92379
92379
|
license: "Apache 2.0",
|
|
@@ -92418,7 +92418,7 @@ var package_default = {
|
|
|
92418
92418
|
dependencies: {
|
|
92419
92419
|
"@aws-sdk/client-s3": "^3.563.0",
|
|
92420
92420
|
"@capacitor/cli": "6.0.0",
|
|
92421
|
-
"@capgo/find-package-manager": "^0.0.
|
|
92421
|
+
"@capgo/find-package-manager": "^0.0.16",
|
|
92422
92422
|
"@clack/prompts": "^0.7.0",
|
|
92423
92423
|
"@supabase/supabase-js": "^2.42.7",
|
|
92424
92424
|
"@tomasklaen/checksum": "^1.1.0",
|
|
@@ -93558,20 +93558,41 @@ var findPackageManagerType = (path3 = ".", defaultPackageManager = "unknown") =>
|
|
|
93558
93558
|
}
|
|
93559
93559
|
return defaultPm;
|
|
93560
93560
|
};
|
|
93561
|
-
var findInstallCommand = (packageManagerType = findPackageManagerType()) => {
|
|
93561
|
+
var findInstallCommand = (packageManagerType = findPackageManagerType(), prefix = false) => {
|
|
93562
93562
|
switch (packageManagerType) {
|
|
93563
93563
|
case "bun":
|
|
93564
|
-
return "install";
|
|
93564
|
+
return prefix ? "bun install" : "install";
|
|
93565
93565
|
case "pnpm":
|
|
93566
|
-
return "install";
|
|
93566
|
+
return prefix ? "pnpm install" : "install";
|
|
93567
93567
|
case "yarn":
|
|
93568
|
-
return "
|
|
93568
|
+
return prefix ? "yarn install" : "install";
|
|
93569
93569
|
case "npm":
|
|
93570
|
-
return "install";
|
|
93570
|
+
return prefix ? "npm install" : "install";
|
|
93571
|
+
case "unknown":
|
|
93572
|
+
return prefix ? "unknown unknown" : "unknown";
|
|
93571
93573
|
default:
|
|
93572
|
-
return "install";
|
|
93574
|
+
return prefix ? "npm install" : "install";
|
|
93573
93575
|
}
|
|
93574
93576
|
};
|
|
93577
|
+
var findPackageManagerRunner = (path3 = ".", defaultPackageManagerRunner = "npx") => {
|
|
93578
|
+
const bunPath = `${path3}/bun.lockb`;
|
|
93579
|
+
const pnpmPath = `${path3}/pnpm-lock.yaml`;
|
|
93580
|
+
const yarnPath = `${path3}/yarn.lock`;
|
|
93581
|
+
const npmPath = `${path3}/package-lock.json`;
|
|
93582
|
+
if ((0, import_fs.existsSync)(bunPath)) {
|
|
93583
|
+
return "bunx";
|
|
93584
|
+
}
|
|
93585
|
+
if ((0, import_fs.existsSync)(pnpmPath)) {
|
|
93586
|
+
return "pnpm exec";
|
|
93587
|
+
}
|
|
93588
|
+
if ((0, import_fs.existsSync)(yarnPath)) {
|
|
93589
|
+
return "yarn dlx";
|
|
93590
|
+
}
|
|
93591
|
+
if ((0, import_fs.existsSync)(npmPath)) {
|
|
93592
|
+
return "npx";
|
|
93593
|
+
}
|
|
93594
|
+
return defaultPackageManagerRunner;
|
|
93595
|
+
};
|
|
93575
93596
|
|
|
93576
93597
|
// src/utils.ts
|
|
93577
93598
|
var baseKey = ".capgo_key";
|
|
@@ -93592,7 +93613,7 @@ async function getConfig() {
|
|
|
93592
93613
|
try {
|
|
93593
93614
|
config = await (0, import_config.loadConfig)();
|
|
93594
93615
|
} catch (err) {
|
|
93595
|
-
f2.error(
|
|
93616
|
+
f2.error(`No capacitor config file found, run \`cap init\` first ${formatError(err)}`);
|
|
93596
93617
|
program.error("");
|
|
93597
93618
|
}
|
|
93598
93619
|
return config;
|
|
@@ -93793,7 +93814,7 @@ function findSavedKey(quiet = false) {
|
|
|
93793
93814
|
key2 = (0, import_node_fs4.readFileSync)(keyPath, "utf8").trim();
|
|
93794
93815
|
}
|
|
93795
93816
|
if (!key2) {
|
|
93796
|
-
f2.error(`Cannot find API key in local folder or global, please login first with
|
|
93817
|
+
f2.error(`Cannot find API key in local folder or global, please login first with ${getPMAndCommand().runner} @capacitor/cli login`);
|
|
93797
93818
|
program.error("");
|
|
93798
93819
|
}
|
|
93799
93820
|
return key2;
|
|
@@ -93895,7 +93916,8 @@ async function updateOrCreateVersion(supabase, update) {
|
|
|
93895
93916
|
async function uploadUrl(supabase, appId, name) {
|
|
93896
93917
|
const data = {
|
|
93897
93918
|
app_id: appId,
|
|
93898
|
-
name
|
|
93919
|
+
name,
|
|
93920
|
+
version: 0
|
|
93899
93921
|
};
|
|
93900
93922
|
try {
|
|
93901
93923
|
const pathUploadLink = "private/upload_link";
|
|
@@ -93906,6 +93928,52 @@ async function uploadUrl(supabase, appId, name) {
|
|
|
93906
93928
|
}
|
|
93907
93929
|
return "";
|
|
93908
93930
|
}
|
|
93931
|
+
async function prepareMultipart(supabase, appId, name) {
|
|
93932
|
+
const data = {
|
|
93933
|
+
app_id: appId,
|
|
93934
|
+
name,
|
|
93935
|
+
version: 1
|
|
93936
|
+
};
|
|
93937
|
+
try {
|
|
93938
|
+
const pathUploadLink = "private/upload_link";
|
|
93939
|
+
const res = await supabase.functions.invoke(pathUploadLink, { body: JSON.stringify(data) });
|
|
93940
|
+
return res.data;
|
|
93941
|
+
} catch (error) {
|
|
93942
|
+
f2.error(`Cannot get upload url ${formatError(error)}`);
|
|
93943
|
+
return null;
|
|
93944
|
+
}
|
|
93945
|
+
}
|
|
93946
|
+
async function finishMultipartDownload(key2, uploadId, url, parts) {
|
|
93947
|
+
const metadata = {
|
|
93948
|
+
action: "mpu-complete",
|
|
93949
|
+
uploadId,
|
|
93950
|
+
key: key2
|
|
93951
|
+
};
|
|
93952
|
+
await distribution_default.post(url, {
|
|
93953
|
+
json: {
|
|
93954
|
+
parts
|
|
93955
|
+
},
|
|
93956
|
+
searchParams: new URLSearchParams({ body: btoa(JSON.stringify(metadata)) })
|
|
93957
|
+
});
|
|
93958
|
+
}
|
|
93959
|
+
var PART_SIZE = 10 * 1024 * 1024;
|
|
93960
|
+
async function uploadMultipart(supabase, appId, name, data) {
|
|
93961
|
+
try {
|
|
93962
|
+
const multipartPrep = await prepareMultipart(supabase, appId, name);
|
|
93963
|
+
if (!multipartPrep) {
|
|
93964
|
+
return false;
|
|
93965
|
+
}
|
|
93966
|
+
const fileSize = data.length;
|
|
93967
|
+
const partCount = Math.ceil(fileSize / PART_SIZE);
|
|
93968
|
+
const uploadPromises = Array.from({ length: partCount }, (_3, index) => uploadPart(data, PART_SIZE, multipartPrep.url, multipartPrep.key, multipartPrep.uploadId, index));
|
|
93969
|
+
const parts = await Promise.all(uploadPromises);
|
|
93970
|
+
await finishMultipartDownload(multipartPrep.key, multipartPrep.uploadId, multipartPrep.url, parts);
|
|
93971
|
+
return true;
|
|
93972
|
+
} catch (e2) {
|
|
93973
|
+
f2.error(`Could not upload via multipart ${formatError(e2)}`);
|
|
93974
|
+
return false;
|
|
93975
|
+
}
|
|
93976
|
+
}
|
|
93909
93977
|
async function deletedFailedVersion(supabase, appId, name) {
|
|
93910
93978
|
const data = {
|
|
93911
93979
|
app_id: appId,
|
|
@@ -93920,6 +93988,23 @@ async function deletedFailedVersion(supabase, appId, name) {
|
|
|
93920
93988
|
return Promise.reject(new Error("Cannot delete failed version"));
|
|
93921
93989
|
}
|
|
93922
93990
|
}
|
|
93991
|
+
async function uploadPart(data, partsize, url, key2, uploadId, index) {
|
|
93992
|
+
const dataToUpload = data.subarray(
|
|
93993
|
+
partsize * index,
|
|
93994
|
+
partsize * (index + 1)
|
|
93995
|
+
);
|
|
93996
|
+
const metadata = {
|
|
93997
|
+
action: "mpu-uploadpart",
|
|
93998
|
+
uploadId,
|
|
93999
|
+
partNumber: index + 1,
|
|
94000
|
+
key: key2
|
|
94001
|
+
};
|
|
94002
|
+
const response = await distribution_default.put(url, {
|
|
94003
|
+
body: dataToUpload,
|
|
94004
|
+
searchParams: new URLSearchParams({ body: btoa(JSON.stringify(metadata)) })
|
|
94005
|
+
});
|
|
94006
|
+
return await response.json();
|
|
94007
|
+
}
|
|
93923
94008
|
async function updateOrCreateChannel(supabase, update) {
|
|
93924
94009
|
if (!update.app_id || !update.name || !update.created_by) {
|
|
93925
94010
|
f2.error("missing app_id, name, or created_by");
|
|
@@ -93986,6 +94071,19 @@ function getHumanDate(createdA) {
|
|
|
93986
94071
|
const date = new Date(createdA || "");
|
|
93987
94072
|
return date.toLocaleString();
|
|
93988
94073
|
}
|
|
94074
|
+
var pmFetched = false;
|
|
94075
|
+
var pm = "npm";
|
|
94076
|
+
var pmCommand = "install";
|
|
94077
|
+
var pmRunner = "npx";
|
|
94078
|
+
function getPMAndCommand() {
|
|
94079
|
+
if (pmFetched)
|
|
94080
|
+
return { pm, command: pmCommand, installCommand: `${pm} ${pmCommand}`, runner: pmRunner };
|
|
94081
|
+
pm = findPackageManagerType(".", "npm");
|
|
94082
|
+
pmCommand = findInstallCommand(pm);
|
|
94083
|
+
pmFetched = true;
|
|
94084
|
+
pmRunner = findPackageManagerRunner();
|
|
94085
|
+
return { pm, command: pmCommand, installCommand: `${pm} ${pmCommand}`, runner: pmRunner };
|
|
94086
|
+
}
|
|
93989
94087
|
async function getLocalDepenencies() {
|
|
93990
94088
|
if (!(0, import_node_fs4.existsSync)("./package.json")) {
|
|
93991
94089
|
f2.error("Missing package.json, you need to be in a capacitor project");
|
|
@@ -94011,9 +94109,9 @@ async function getLocalDepenencies() {
|
|
|
94011
94109
|
}
|
|
94012
94110
|
}
|
|
94013
94111
|
if (!(0, import_node_fs4.existsSync)("./node_modules/")) {
|
|
94014
|
-
const
|
|
94015
|
-
const installCmd = findInstallCommand(
|
|
94016
|
-
f2.error(`Missing node_modules folder, please run ${
|
|
94112
|
+
const pm2 = findPackageManagerType(".", "npm");
|
|
94113
|
+
const installCmd = findInstallCommand(pm2);
|
|
94114
|
+
f2.error(`Missing node_modules folder, please run ${pm2} ${installCmd}`);
|
|
94017
94115
|
program.error("");
|
|
94018
94116
|
}
|
|
94019
94117
|
let anyInvalid = false;
|
|
@@ -94021,9 +94119,9 @@ async function getLocalDepenencies() {
|
|
|
94021
94119
|
const dependencyFolderExists = (0, import_node_fs4.existsSync)(`./node_modules/${key2}`);
|
|
94022
94120
|
if (!dependencyFolderExists) {
|
|
94023
94121
|
anyInvalid = true;
|
|
94024
|
-
const
|
|
94025
|
-
const installCmd = findInstallCommand(
|
|
94026
|
-
f2.error(`Missing dependency ${key2}, please run ${
|
|
94122
|
+
const pm2 = findPackageManagerType(".", "npm");
|
|
94123
|
+
const installCmd = findInstallCommand(pm2);
|
|
94124
|
+
f2.error(`Missing dependency ${key2}, please run ${pm2} ${installCmd}`);
|
|
94027
94125
|
return { name: key2, version: value };
|
|
94028
94126
|
}
|
|
94029
94127
|
let hasNativeFiles = false;
|
|
@@ -94266,6 +94364,7 @@ async function checkAppExists(supabase, appid) {
|
|
|
94266
94364
|
return !!app2;
|
|
94267
94365
|
}
|
|
94268
94366
|
async function checkAppExistsAndHasPermissionOrgErr(supabase, apikey, appid, requiredPermission) {
|
|
94367
|
+
const pm2 = getPMAndCommand();
|
|
94269
94368
|
const permissions = await isAllowedAppOrg(supabase, apikey, appid);
|
|
94270
94369
|
if (!permissions.okay) {
|
|
94271
94370
|
switch (permissions.error) {
|
|
@@ -94275,7 +94374,7 @@ async function checkAppExistsAndHasPermissionOrgErr(supabase, apikey, appid, req
|
|
|
94275
94374
|
break;
|
|
94276
94375
|
}
|
|
94277
94376
|
case "NO_APP": {
|
|
94278
|
-
f2.error(`App ${appid} does not exist`);
|
|
94377
|
+
f2.error(`App ${appid} does not exist, run first \`${pm2.runner} @capgo/cli app add ${appid}\` to create it`);
|
|
94279
94378
|
program.error("");
|
|
94280
94379
|
break;
|
|
94281
94380
|
}
|
|
@@ -94778,6 +94877,7 @@ var import_client_s3 = __toESM(require_dist_cjs71());
|
|
|
94778
94877
|
var alertMb2 = 20;
|
|
94779
94878
|
var UPLOAD_TIMEOUT = 12e4;
|
|
94780
94879
|
async function uploadBundle(appid, options, shouldExit = true) {
|
|
94880
|
+
const pm2 = getPMAndCommand();
|
|
94781
94881
|
oe(`Uploading`);
|
|
94782
94882
|
await checkLatest();
|
|
94783
94883
|
let { bundle: bundle2, path: path3, channel: channel2 } = options;
|
|
@@ -94801,7 +94901,7 @@ async function uploadBundle(appid, options, shouldExit = true) {
|
|
|
94801
94901
|
const snag = useLogSnag();
|
|
94802
94902
|
channel2 = channel2 || "dev";
|
|
94803
94903
|
const config = await getConfig();
|
|
94804
|
-
const localS3 = (config
|
|
94904
|
+
const localS3 = (config?.app?.extConfig?.plugins && config?.app?.extConfig?.plugins?.CapacitorUpdater && config?.app?.extConfig?.plugins?.CapacitorUpdater?.localS3) === true;
|
|
94805
94905
|
const checkNotifyAppReady = options.codeCheck;
|
|
94806
94906
|
appid = appid || config?.app?.appId;
|
|
94807
94907
|
const uuid = (0, import_node_crypto3.randomUUID)().split("-")[0];
|
|
@@ -94815,8 +94915,8 @@ async function uploadBundle(appid, options, shouldExit = true) {
|
|
|
94815
94915
|
f2.error(`Missing API key, you need to provide a API key to upload your bundle`);
|
|
94816
94916
|
program.error("");
|
|
94817
94917
|
}
|
|
94818
|
-
if (!appid || !
|
|
94819
|
-
f2.error("Missing argument, you need to provide a appid and a
|
|
94918
|
+
if (!appid || !path3) {
|
|
94919
|
+
f2.error("Missing argument, you need to provide a appid and a path (--path), or be in a capacitor project");
|
|
94820
94920
|
program.error("");
|
|
94821
94921
|
}
|
|
94822
94922
|
if (s3BucketName || s3Region || s3Apikey || s3Apisecret) {
|
|
@@ -94863,7 +94963,7 @@ async function uploadBundle(appid, options, shouldExit = true) {
|
|
|
94863
94963
|
localDependencies = localDependenciesWithChannel;
|
|
94864
94964
|
if (finalCompatibility.find((x3) => x3.localVersion !== x3.remoteVersion)) {
|
|
94865
94965
|
f2.error(`Your bundle is not compatible with the channel ${channel2}`);
|
|
94866
|
-
f2.warn(`You can check compatibility with "
|
|
94966
|
+
f2.warn(`You can check compatibility with "${pm2.runner} @capgo/cli bundle compatibility"`);
|
|
94867
94967
|
if (autoMinUpdateVersion) {
|
|
94868
94968
|
minUpdateVersion = bundle2;
|
|
94869
94969
|
f2.info(`Auto set min-update-version to ${minUpdateVersion}`);
|
|
@@ -95030,23 +95130,27 @@ The app size is ${mbSize} Mb, this may take a while to download for users
|
|
|
95030
95130
|
if (!external && zipped) {
|
|
95031
95131
|
const spinner = de();
|
|
95032
95132
|
spinner.start(`Uploading Bundle`);
|
|
95033
|
-
const url = await uploadUrl(supabase, appid, bundle2);
|
|
95034
|
-
if (!url) {
|
|
95035
|
-
f2.error(`Cannot get upload url`);
|
|
95036
|
-
program.error("");
|
|
95037
|
-
}
|
|
95038
95133
|
const startTime = import_node_perf_hooks.performance.now();
|
|
95039
95134
|
try {
|
|
95040
|
-
|
|
95041
|
-
|
|
95042
|
-
|
|
95043
|
-
|
|
95044
|
-
|
|
95045
|
-
|
|
95046
|
-
"
|
|
95047
|
-
|
|
95048
|
-
|
|
95049
|
-
|
|
95135
|
+
if (options.multipart !== void 0 && options.multipart) {
|
|
95136
|
+
await uploadMultipart(supabase, appid, bundle2, zipped);
|
|
95137
|
+
} else {
|
|
95138
|
+
const url = await uploadUrl(supabase, appid, bundle2);
|
|
95139
|
+
if (!url) {
|
|
95140
|
+
f2.error(`Cannot get upload url`);
|
|
95141
|
+
program.error("");
|
|
95142
|
+
}
|
|
95143
|
+
await distribution_default.put(url, {
|
|
95144
|
+
timeout: options.timeout || UPLOAD_TIMEOUT,
|
|
95145
|
+
retry: 5,
|
|
95146
|
+
body: zipped,
|
|
95147
|
+
headers: !localS3 ? {
|
|
95148
|
+
"Content-Type": "application/octet-stream",
|
|
95149
|
+
"Cache-Control": "public, max-age=456789, immutable",
|
|
95150
|
+
"x-amz-meta-crc32": checksum
|
|
95151
|
+
} : void 0
|
|
95152
|
+
});
|
|
95153
|
+
}
|
|
95050
95154
|
} catch (errorUpload) {
|
|
95051
95155
|
const endTime2 = import_node_perf_hooks.performance.now();
|
|
95052
95156
|
const uploadTime2 = ((endTime2 - startTime) / 1e3).toFixed(2);
|
|
@@ -95143,7 +95247,8 @@ async function uploadCommand(apikey, options) {
|
|
|
95143
95247
|
}
|
|
95144
95248
|
}
|
|
95145
95249
|
async function uploadDeprecatedCommand(apikey, options) {
|
|
95146
|
-
|
|
95250
|
+
const pm2 = getPMAndCommand();
|
|
95251
|
+
f2.warn(`\u26A0\uFE0F This command is deprecated, use "${pm2.runner} @capgo/cli bundle upload" instead \u26A0\uFE0F`);
|
|
95147
95252
|
try {
|
|
95148
95253
|
await uploadBundle(apikey, options, true);
|
|
95149
95254
|
} catch (error) {
|
|
@@ -95156,6 +95261,10 @@ async function uploadDeprecatedCommand(apikey, options) {
|
|
|
95156
95261
|
var import_node_fs9 = require("node:fs");
|
|
95157
95262
|
var import_node_os3 = require("node:os");
|
|
95158
95263
|
var import_node_process14 = __toESM(require("node:process"));
|
|
95264
|
+
async function doLoginExists() {
|
|
95265
|
+
const userHomeDir = (0, import_node_os3.homedir)();
|
|
95266
|
+
return (0, import_node_fs9.existsSync)(`${userHomeDir}/.capgo`) || (0, import_node_fs9.existsSync)(".capgo");
|
|
95267
|
+
}
|
|
95159
95268
|
async function login(apikey, options, shouldExit = true) {
|
|
95160
95269
|
if (shouldExit)
|
|
95161
95270
|
oe(`Login to Capgo`);
|
|
@@ -95343,7 +95452,7 @@ async function addApp(appId, options, throwErr = true) {
|
|
|
95343
95452
|
f2.error(`App ${appId} already exist`);
|
|
95344
95453
|
program.error("");
|
|
95345
95454
|
} else if (appExist) {
|
|
95346
|
-
return
|
|
95455
|
+
return false;
|
|
95347
95456
|
}
|
|
95348
95457
|
const { error: orgError, data: allOrganizations } = await supabase.rpc("get_orgs_v5");
|
|
95349
95458
|
if (orgError) {
|
|
@@ -95467,27 +95576,29 @@ async function markStep(userId, snag, step) {
|
|
|
95467
95576
|
return markSnag("onboarding-v2", userId, snag, `onboarding-step-${step}`);
|
|
95468
95577
|
}
|
|
95469
95578
|
async function step2(userId, snag, appId, options) {
|
|
95579
|
+
const pm2 = getPMAndCommand();
|
|
95470
95580
|
const doAdd = await se({ message: `Add ${appId} in Capgo?` });
|
|
95471
95581
|
await cancelCommand2(doAdd, userId, snag);
|
|
95472
95582
|
if (doAdd) {
|
|
95473
95583
|
const s = de();
|
|
95474
|
-
s.start(`Running:
|
|
95584
|
+
s.start(`Running: ${pm2.runner} @capgo/cli@latest app add ${appId}`);
|
|
95475
95585
|
const addRes = await addApp(appId, options, false);
|
|
95476
95586
|
if (!addRes)
|
|
95477
95587
|
s.stop(`App already add \u2705`);
|
|
95478
95588
|
else
|
|
95479
95589
|
s.stop(`App add Done \u2705`);
|
|
95480
95590
|
} else {
|
|
95481
|
-
f2.info(`Run yourself "
|
|
95591
|
+
f2.info(`Run yourself "${pm2.runner} @capgo/cli@latest app add ${appId}"`);
|
|
95482
95592
|
}
|
|
95483
95593
|
await markStep(userId, snag, 2);
|
|
95484
95594
|
}
|
|
95485
95595
|
async function step3(userId, snag, apikey, appId) {
|
|
95596
|
+
const pm2 = getPMAndCommand();
|
|
95486
95597
|
const doChannel = await se({ message: `Create default channel ${defaultChannel} for ${appId} in Capgo?` });
|
|
95487
95598
|
await cancelCommand2(doChannel, userId, snag);
|
|
95488
95599
|
if (doChannel) {
|
|
95489
95600
|
const s = de();
|
|
95490
|
-
s.start(`Running:
|
|
95601
|
+
s.start(`Running: ${pm2.runner} @capgo/cli@latest channel add ${defaultChannel} ${appId} --default`);
|
|
95491
95602
|
const addChannelRes = await addChannel(defaultChannel, appId, {
|
|
95492
95603
|
default: true,
|
|
95493
95604
|
apikey
|
|
@@ -95497,13 +95608,14 @@ async function step3(userId, snag, apikey, appId) {
|
|
|
95497
95608
|
else
|
|
95498
95609
|
s.stop(`Channel add Done \u2705`);
|
|
95499
95610
|
} else {
|
|
95500
|
-
f2.info(`Run yourself "
|
|
95611
|
+
f2.info(`Run yourself "${pm2.runner} @capgo/cli@latest channel add ${defaultChannel} ${appId} --default"`);
|
|
95501
95612
|
}
|
|
95502
95613
|
await markStep(userId, snag, 3);
|
|
95503
95614
|
}
|
|
95504
95615
|
var urlMigrateV6 = "https://capacitorjs.com/docs/updating/6-0";
|
|
95505
95616
|
var urlMigrateV5 = "https://capacitorjs.com/docs/updating/5-0";
|
|
95506
95617
|
async function step4(userId, snag, apikey, appId) {
|
|
95618
|
+
const pm2 = getPMAndCommand();
|
|
95507
95619
|
const doInstall = await se({ message: `Automatic Install "@capgo/capacitor-updater" dependency in ${appId}?` });
|
|
95508
95620
|
await cancelCommand2(doInstall, userId, snag);
|
|
95509
95621
|
if (doInstall) {
|
|
@@ -95527,22 +95639,20 @@ async function step4(userId, snag, apikey, appId) {
|
|
|
95527
95639
|
s.stop(`@capacitor/core version is ${coreVersion}, please update to Capacitor v6: ${urlMigrateV6} to access the best features of Capgo`);
|
|
95528
95640
|
versionToInstall = "^5.0.0";
|
|
95529
95641
|
}
|
|
95530
|
-
|
|
95531
|
-
if (pm === "unknown") {
|
|
95642
|
+
if (pm2.pm === "unknown") {
|
|
95532
95643
|
s.stop("Error");
|
|
95533
|
-
f2.warn(`Cannot reconize package manager, please run \`capgo init\` in a capacitor project with npm, pnpm or yarn`);
|
|
95644
|
+
f2.warn(`Cannot reconize package manager, please run \`capgo init\` in a capacitor project with npm, pnpm, bun or yarn`);
|
|
95534
95645
|
$e(`Bye \u{1F44B}`);
|
|
95535
95646
|
import_node_process16.default.exit();
|
|
95536
95647
|
}
|
|
95537
|
-
const installCmd = findInstallCommand(pm);
|
|
95538
95648
|
if (pack.dependencies["@capgo/capacitor-updater"]) {
|
|
95539
95649
|
s.stop(`Capgo already installed \u2705`);
|
|
95540
95650
|
} else {
|
|
95541
|
-
await (0, import_node_child_process6.execSync)(`${
|
|
95651
|
+
await (0, import_node_child_process6.execSync)(`${pm2.installCommand} @capgo/capacitor-updater@${versionToInstall}`, execOption);
|
|
95542
95652
|
s.stop(`Install Done \u2705`);
|
|
95543
95653
|
}
|
|
95544
95654
|
} else {
|
|
95545
|
-
f2.info(`Run yourself "
|
|
95655
|
+
f2.info(`Run yourself "${pm2.installCommand} @capgo/capacitor-updater@latest"`);
|
|
95546
95656
|
}
|
|
95547
95657
|
await markStep(userId, snag, 4);
|
|
95548
95658
|
}
|
|
@@ -95596,11 +95706,12 @@ ${codeInject};
|
|
|
95596
95706
|
}
|
|
95597
95707
|
}
|
|
95598
95708
|
async function step6(userId, snag, apikey, appId) {
|
|
95709
|
+
const pm2 = getPMAndCommand();
|
|
95599
95710
|
const doEncrypt = await se({ message: `Automatic configure end-to-end encryption in ${appId} updates?` });
|
|
95600
95711
|
await cancelCommand2(doEncrypt, userId, snag);
|
|
95601
95712
|
if (doEncrypt) {
|
|
95602
95713
|
const s = de();
|
|
95603
|
-
s.start(`Running:
|
|
95714
|
+
s.start(`Running: ${pm2.runner} @capgo/cli@latest key create`);
|
|
95604
95715
|
const keyRes = await createKey({ force: true }, false);
|
|
95605
95716
|
if (!keyRes) {
|
|
95606
95717
|
s.stop("Error");
|
|
@@ -95615,13 +95726,14 @@ async function step6(userId, snag, apikey, appId) {
|
|
|
95615
95726
|
await markStep(userId, snag, 6);
|
|
95616
95727
|
}
|
|
95617
95728
|
async function step7(userId, snag, apikey, appId) {
|
|
95618
|
-
const
|
|
95729
|
+
const pm2 = getPMAndCommand();
|
|
95730
|
+
const doBuild = await se({ message: `Automatic build ${appId} with "${pm2.pm} run build" ?` });
|
|
95619
95731
|
await cancelCommand2(doBuild, userId, snag);
|
|
95620
95732
|
if (doBuild) {
|
|
95621
95733
|
const s = de();
|
|
95622
95734
|
const projectType = await findProjectType();
|
|
95623
95735
|
const buildCommand = await findBuildCommandForProjectType(projectType);
|
|
95624
|
-
s.start(`Running:
|
|
95736
|
+
s.start(`Running: ${pm2.pm} run ${buildCommand} && ${pm2.runner} cap sync`);
|
|
95625
95737
|
const pack = JSON.parse((0, import_node_fs11.readFileSync)("package.json").toString());
|
|
95626
95738
|
if (!pack.scripts[buildCommand]) {
|
|
95627
95739
|
s.stop("Error");
|
|
@@ -95629,19 +95741,20 @@ async function step7(userId, snag, apikey, appId) {
|
|
|
95629
95741
|
$e(`Bye \u{1F44B}`);
|
|
95630
95742
|
import_node_process16.default.exit();
|
|
95631
95743
|
}
|
|
95632
|
-
(0, import_node_child_process6.execSync)(
|
|
95744
|
+
(0, import_node_child_process6.execSync)(`${pm2.pm} run ${buildCommand} && ${pm2.runner} cap sync`, execOption);
|
|
95633
95745
|
s.stop(`Build & Sync Done \u2705`);
|
|
95634
95746
|
} else {
|
|
95635
|
-
f2.info(`Build yourself with command:
|
|
95747
|
+
f2.info(`Build yourself with command: ${pm2.pm} run build && ${pm2.runner} cap sync`);
|
|
95636
95748
|
}
|
|
95637
95749
|
await markStep(userId, snag, 7);
|
|
95638
95750
|
}
|
|
95639
95751
|
async function step8(userId, snag, apikey, appId) {
|
|
95752
|
+
const pm2 = getPMAndCommand();
|
|
95640
95753
|
const doBundle = await se({ message: `Automatic upload ${appId} bundle to Capgo?` });
|
|
95641
95754
|
await cancelCommand2(doBundle, userId, snag);
|
|
95642
95755
|
if (doBundle) {
|
|
95643
95756
|
const s = de();
|
|
95644
|
-
s.start(`Running:
|
|
95757
|
+
s.start(`Running: ${pm2.runner} @capgo/cli@latest bundle upload`);
|
|
95645
95758
|
const uploadRes = await uploadBundle(appId, {
|
|
95646
95759
|
channel: defaultChannel,
|
|
95647
95760
|
apikey
|
|
@@ -95655,11 +95768,12 @@ async function step8(userId, snag, apikey, appId) {
|
|
|
95655
95768
|
s.stop(`Upload Done \u2705`);
|
|
95656
95769
|
}
|
|
95657
95770
|
} else {
|
|
95658
|
-
f2.info(`Upload yourself with command:
|
|
95771
|
+
f2.info(`Upload yourself with command: ${pm2.runner} @capgo/cli@latest bundle upload`);
|
|
95659
95772
|
}
|
|
95660
95773
|
await markStep(userId, snag, 8);
|
|
95661
95774
|
}
|
|
95662
95775
|
async function step9(userId, snag) {
|
|
95776
|
+
const pm2 = getPMAndCommand();
|
|
95663
95777
|
const doRun = await se({ message: `Run in device now ?` });
|
|
95664
95778
|
await cancelCommand2(doRun, userId, snag);
|
|
95665
95779
|
if (doRun) {
|
|
@@ -95676,11 +95790,11 @@ async function step9(userId, snag) {
|
|
|
95676
95790
|
}
|
|
95677
95791
|
const platform2 = plaformType;
|
|
95678
95792
|
const s = de();
|
|
95679
|
-
s.start(`Running:
|
|
95680
|
-
await (0, import_node_child_process6.spawnSync)(
|
|
95793
|
+
s.start(`Running: ${pm2.runner} cap run ${platform2}`);
|
|
95794
|
+
await (0, import_node_child_process6.spawnSync)(pm2.runner, ["cap", "run", platform2], { stdio: "inherit" });
|
|
95681
95795
|
s.stop(`Started Done \u2705`);
|
|
95682
95796
|
} else {
|
|
95683
|
-
f2.info(`Run yourself with command:
|
|
95797
|
+
f2.info(`Run yourself with command: ${pm2.runner} cap run <ios|android>`);
|
|
95684
95798
|
}
|
|
95685
95799
|
await markStep(userId, snag, 9);
|
|
95686
95800
|
}
|
|
@@ -95697,20 +95811,20 @@ async function step10(userId, snag, supabase, appId) {
|
|
|
95697
95811
|
}
|
|
95698
95812
|
await markStep(userId, snag, 10);
|
|
95699
95813
|
}
|
|
95700
|
-
async function initApp(
|
|
95814
|
+
async function initApp(apikeyCommand, appId, options) {
|
|
95815
|
+
const pm2 = getPMAndCommand();
|
|
95701
95816
|
oe(`Capgo onboarding \u{1F6EB}`);
|
|
95702
95817
|
await checkLatest();
|
|
95703
95818
|
const snag = useLogSnag();
|
|
95704
95819
|
const config = await getConfig();
|
|
95705
95820
|
appId = appId || config?.app?.appId;
|
|
95706
|
-
apikey =
|
|
95821
|
+
const apikey = apikeyCommand || findSavedKey();
|
|
95707
95822
|
const log = de();
|
|
95708
|
-
|
|
95709
|
-
|
|
95710
|
-
|
|
95711
|
-
log.stop("Login already done \u2705");
|
|
95712
|
-
else
|
|
95823
|
+
if (!doLoginExists() || apikeyCommand) {
|
|
95824
|
+
log.start(`Running: ${pm2.runner} @capgo/cli@latest login ***`);
|
|
95825
|
+
await login(apikey, options, false);
|
|
95713
95826
|
log.stop("Login Done \u2705");
|
|
95827
|
+
}
|
|
95714
95828
|
const supabase = await createSupabaseClient(apikey);
|
|
95715
95829
|
const userId = await verifyUser(supabase, apikey, ["upload", "all", "read", "write"]);
|
|
95716
95830
|
await markStep(userId, snag, 1);
|
|
@@ -95726,7 +95840,7 @@ async function initApp(apikey, appId, options) {
|
|
|
95726
95840
|
await markStep(userId, snag, 0);
|
|
95727
95841
|
f2.info(`Welcome onboard \u2708\uFE0F!`);
|
|
95728
95842
|
f2.info(`Your Capgo update system is setup`);
|
|
95729
|
-
f2.info(`Next time use
|
|
95843
|
+
f2.info(`Next time use \`${pm2.runner} @capgo/cli@latest bundle upload\` to only upload your bundle`);
|
|
95730
95844
|
$e(`Bye \u{1F44B}`);
|
|
95731
95845
|
import_node_process16.default.exit();
|
|
95732
95846
|
}
|
|
@@ -96595,7 +96709,7 @@ var bundle = program.command("bundle").description("Manage bundle");
|
|
|
96595
96709
|
bundle.command("upload [appId]").alias("u").description("Upload a new bundle in Capgo Cloud").action(uploadCommand).option("-a, --apikey <apikey>", "apikey to link to your account").option("-p, --path <path>", "path of the folder to upload").option("-c, --channel <channel>", "channel to link to").option("-e, --external <url>", "link to external url intead of upload to Capgo Cloud").option("--iv-session-key <key>", "Set the iv and session key for bundle url external").option("--s3-region <region>", "Region for your AWS S3 bucket").option("--s3-apikey <apikey>", "apikey for your AWS S3 account").option("--s3-apisecret <apisecret>", "api secret for your AWS S3 account").option("--s3-bucket-name <bucketName>", "Name for your AWS S3 bucket").option("--key <key>", "custom path for public signing key").option("--key-data <keyData>", "base64 public signing key").option("--bundle-url", "prints bundle url into stdout").option("--no-key", "ignore signing key and send clear update").option("--no-code-check", "Ignore checking if notifyAppReady() is called in soure code and index present in root folder").option("--display-iv-session", "Show in the console the iv and session key used to encrypt the update").option("-b, --bundle <bundle>", "bundle version number of the bundle to upload").option(
|
|
96596
96710
|
"--min-update-version <minUpdateVersion>",
|
|
96597
96711
|
"Minimal version required to update to this version. Used only if the disable auto update is set to metadata in channel"
|
|
96598
|
-
).option("--auto-min-update-version", "Set the min update version based on native packages").option("--ignore-metadata-check", "Ignores the metadata (node_modules) check when uploading").option("--timeout <timeout>", "Timeout for the upload process in seconds");
|
|
96712
|
+
).option("--auto-min-update-version", "Set the min update version based on native packages").option("--ignore-metadata-check", "Ignores the metadata (node_modules) check when uploading").option("--timeout <timeout>", "Timeout for the upload process in seconds").option("--multipart", "Uses multipart protocol to upload data to S3");
|
|
96599
96713
|
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");
|
|
96600
96714
|
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");
|
|
96601
96715
|
bundle.command("list [appId]").alias("l").description("List bundle in Capgo Cloud").action(listBundle).option("-a, --apikey <apikey>", "apikey to link to your account");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capgo/cli",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.8.1",
|
|
4
4
|
"description": "A CLI to upload to capgo servers",
|
|
5
5
|
"author": "github.com/riderx",
|
|
6
6
|
"license": "Apache 2.0",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@aws-sdk/client-s3": "^3.563.0",
|
|
47
47
|
"@capacitor/cli": "6.0.0",
|
|
48
|
-
"@capgo/find-package-manager": "^0.0.
|
|
48
|
+
"@capgo/find-package-manager": "^0.0.16",
|
|
49
49
|
"@clack/prompts": "^0.7.0",
|
|
50
50
|
"@supabase/supabase-js": "^2.42.7",
|
|
51
51
|
"@tomasklaen/checksum": "^1.1.0",
|
package/src/api/app.ts
CHANGED
|
@@ -3,7 +3,7 @@ import * as p from '@clack/prompts'
|
|
|
3
3
|
import { program } from 'commander'
|
|
4
4
|
import type { Database } from '../types/supabase.types'
|
|
5
5
|
import type { OptionsBase } from '../utils'
|
|
6
|
-
import { OrganizationPerm,
|
|
6
|
+
import { OrganizationPerm, getPMAndCommand, isAllowedAppOrg } from '../utils'
|
|
7
7
|
|
|
8
8
|
export async function checkAppExists(supabase: SupabaseClient<Database>, appid: string) {
|
|
9
9
|
const { data: app } = await supabase
|
|
@@ -12,28 +12,8 @@ export async function checkAppExists(supabase: SupabaseClient<Database>, appid:
|
|
|
12
12
|
return !!app
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
export async function checkAppExistsAndHasPermissionErr(supabase: SupabaseClient<Database>, apikey: string, appid: string, shouldExist = true) {
|
|
16
|
-
const appExist = await checkAppExists(supabase, appid)
|
|
17
|
-
const perm = await isAllowedApp(supabase, apikey, appid)
|
|
18
|
-
|
|
19
|
-
if (appExist && !shouldExist) {
|
|
20
|
-
p.log.error(`App ${appid} already exist`)
|
|
21
|
-
program.error('')
|
|
22
|
-
}
|
|
23
|
-
if (!appExist && shouldExist) {
|
|
24
|
-
p.log.error(`App ${appid} does not exist`)
|
|
25
|
-
program.error('')
|
|
26
|
-
}
|
|
27
|
-
if (appExist && !perm) {
|
|
28
|
-
p.log.error(`App ${appid} exist and you don't have permission to access it`)
|
|
29
|
-
if (appid === 'io.ionic.starter')
|
|
30
|
-
p.log.info('Modify your appid in your capacitor.config.json file to something unique, this is a default appid for ionic starter app')
|
|
31
|
-
|
|
32
|
-
program.error('')
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
15
|
export async function checkAppExistsAndHasPermissionOrgErr(supabase: SupabaseClient<Database>, apikey: string, appid: string, requiredPermission: OrganizationPerm) {
|
|
16
|
+
const pm = getPMAndCommand()
|
|
37
17
|
const permissions = await isAllowedAppOrg(supabase, apikey, appid)
|
|
38
18
|
if (!permissions.okay) {
|
|
39
19
|
switch (permissions.error) {
|
|
@@ -43,7 +23,7 @@ export async function checkAppExistsAndHasPermissionOrgErr(supabase: SupabaseCli
|
|
|
43
23
|
break
|
|
44
24
|
}
|
|
45
25
|
case 'NO_APP': {
|
|
46
|
-
p.log.error(`App ${appid} does not exist`)
|
|
26
|
+
p.log.error(`App ${appid} does not exist, run first \`${pm.runner} @capgo/cli app add ${appid}\` to create it`)
|
|
47
27
|
program.error('')
|
|
48
28
|
break
|
|
49
29
|
}
|
package/src/app/add.ts
CHANGED
package/src/bundle/upload.ts
CHANGED
|
@@ -33,11 +33,13 @@ import {
|
|
|
33
33
|
getLocalConfig,
|
|
34
34
|
getLocalDepenencies,
|
|
35
35
|
getOrganizationId,
|
|
36
|
+
getPMAndCommand,
|
|
36
37
|
hasOrganizationPerm,
|
|
37
38
|
regexSemver,
|
|
38
39
|
requireUpdateMetadata,
|
|
39
40
|
updateOrCreateChannel,
|
|
40
41
|
updateOrCreateVersion,
|
|
42
|
+
uploadMultipart,
|
|
41
43
|
uploadUrl,
|
|
42
44
|
useLogSnag,
|
|
43
45
|
verifyUser,
|
|
@@ -65,11 +67,13 @@ interface Options extends OptionsBase {
|
|
|
65
67
|
autoMinUpdateVersion?: boolean
|
|
66
68
|
ignoreMetadataCheck?: boolean
|
|
67
69
|
timeout?: number
|
|
70
|
+
multipart?: boolean
|
|
68
71
|
}
|
|
69
72
|
|
|
70
73
|
const UPLOAD_TIMEOUT = 120000
|
|
71
74
|
|
|
72
75
|
export async function uploadBundle(appid: string, options: Options, shouldExit = true) {
|
|
76
|
+
const pm = getPMAndCommand()
|
|
73
77
|
p.intro(`Uploading`)
|
|
74
78
|
await checkLatest()
|
|
75
79
|
let { bundle, path, channel } = options
|
|
@@ -96,8 +100,8 @@ export async function uploadBundle(appid: string, options: Options, shouldExit =
|
|
|
96
100
|
channel = channel || 'dev'
|
|
97
101
|
|
|
98
102
|
const config = await getConfig()
|
|
99
|
-
const localS3: boolean = (config
|
|
100
|
-
&& config
|
|
103
|
+
const localS3: boolean = (config?.app?.extConfig?.plugins && config?.app?.extConfig?.plugins?.CapacitorUpdater
|
|
104
|
+
&& config?.app?.extConfig?.plugins?.CapacitorUpdater?.localS3) === true
|
|
101
105
|
|
|
102
106
|
const checkNotifyAppReady = options.codeCheck
|
|
103
107
|
appid = appid || config?.app?.appId
|
|
@@ -114,8 +118,8 @@ export async function uploadBundle(appid: string, options: Options, shouldExit =
|
|
|
114
118
|
p.log.error(`Missing API key, you need to provide a API key to upload your bundle`)
|
|
115
119
|
program.error('')
|
|
116
120
|
}
|
|
117
|
-
if (!appid || !
|
|
118
|
-
p.log.error('Missing argument, you need to provide a appid and a
|
|
121
|
+
if (!appid || !path) {
|
|
122
|
+
p.log.error('Missing argument, you need to provide a appid and a path (--path), or be in a capacitor project')
|
|
119
123
|
program.error('')
|
|
120
124
|
}
|
|
121
125
|
// if one S3 variable is set, check that all are set
|
|
@@ -150,8 +154,6 @@ export async function uploadBundle(appid: string, options: Options, shouldExit =
|
|
|
150
154
|
const supabase = await createSupabaseClient(options.apikey)
|
|
151
155
|
const userId = await verifyUser(supabase, options.apikey, ['write', 'all', 'upload'])
|
|
152
156
|
// Check we have app access to this appId
|
|
153
|
-
// await checkAppExistsAndHasPermissionErr(supabase, options.apikey, appid);
|
|
154
|
-
|
|
155
157
|
const permissions = await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appid, OrganizationPerm.upload)
|
|
156
158
|
|
|
157
159
|
// Now if it does exist we will fetch the org id
|
|
@@ -186,7 +188,7 @@ export async function uploadBundle(appid: string, options: Options, shouldExit =
|
|
|
186
188
|
|
|
187
189
|
if (finalCompatibility.find(x => x.localVersion !== x.remoteVersion)) {
|
|
188
190
|
p.log.error(`Your bundle is not compatible with the channel ${channel}`)
|
|
189
|
-
p.log.warn(`You can check compatibility with "
|
|
191
|
+
p.log.warn(`You can check compatibility with "${pm.runner} @capgo/cli bundle compatibility"`)
|
|
190
192
|
|
|
191
193
|
if (autoMinUpdateVersion) {
|
|
192
194
|
minUpdateVersion = bundle
|
|
@@ -381,26 +383,32 @@ It will be also visible in your dashboard\n`)
|
|
|
381
383
|
if (!external && zipped) {
|
|
382
384
|
const spinner = p.spinner()
|
|
383
385
|
spinner.start(`Uploading Bundle`)
|
|
384
|
-
|
|
385
|
-
const url = await uploadUrl(supabase, appid, bundle)
|
|
386
|
-
if (!url) {
|
|
387
|
-
p.log.error(`Cannot get upload url`)
|
|
388
|
-
program.error('')
|
|
389
|
-
}
|
|
390
386
|
const startTime = performance.now()
|
|
387
|
+
|
|
391
388
|
try {
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
389
|
+
if (options.multipart !== undefined && options.multipart) {
|
|
390
|
+
await uploadMultipart(supabase, appid, bundle, zipped)
|
|
391
|
+
}
|
|
392
|
+
else {
|
|
393
|
+
const url = await uploadUrl(supabase, appid, bundle)
|
|
394
|
+
if (!url) {
|
|
395
|
+
p.log.error(`Cannot get upload url`)
|
|
396
|
+
program.error('')
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
await ky.put(url, {
|
|
400
|
+
timeout: options.timeout || UPLOAD_TIMEOUT,
|
|
401
|
+
retry: 5,
|
|
402
|
+
body: zipped,
|
|
403
|
+
headers: (!localS3
|
|
404
|
+
? {
|
|
405
|
+
'Content-Type': 'application/octet-stream',
|
|
406
|
+
'Cache-Control': 'public, max-age=456789, immutable',
|
|
407
|
+
'x-amz-meta-crc32': checksum,
|
|
408
|
+
}
|
|
409
|
+
: undefined),
|
|
410
|
+
})
|
|
411
|
+
}
|
|
404
412
|
}
|
|
405
413
|
catch (errorUpload) {
|
|
406
414
|
const endTime = performance.now()
|
|
@@ -411,6 +419,7 @@ It will be also visible in your dashboard\n`)
|
|
|
411
419
|
await deletedFailedVersion(supabase, appid, bundle)
|
|
412
420
|
program.error('')
|
|
413
421
|
}
|
|
422
|
+
|
|
414
423
|
versionData.storage_provider = 'r2'
|
|
415
424
|
const { error: dbError2 } = await updateOrCreateVersion(supabase, versionData)
|
|
416
425
|
if (dbError2) {
|
|
@@ -511,7 +520,8 @@ export async function uploadCommand(apikey: string, options: Options) {
|
|
|
511
520
|
}
|
|
512
521
|
|
|
513
522
|
export async function uploadDeprecatedCommand(apikey: string, options: Options) {
|
|
514
|
-
|
|
523
|
+
const pm = getPMAndCommand()
|
|
524
|
+
p.log.warn(`⚠️ This command is deprecated, use "${pm.runner} @capgo/cli bundle upload" instead ⚠️`)
|
|
515
525
|
try {
|
|
516
526
|
await uploadBundle(apikey, options, true)
|
|
517
527
|
}
|
package/src/index.ts
CHANGED
|
@@ -131,6 +131,7 @@ bundle
|
|
|
131
131
|
.option('--auto-min-update-version', 'Set the min update version based on native packages')
|
|
132
132
|
.option('--ignore-metadata-check', 'Ignores the metadata (node_modules) check when uploading')
|
|
133
133
|
.option('--timeout <timeout>', 'Timeout for the upload process in seconds')
|
|
134
|
+
.option('--multipart', 'Uses multipart protocol to upload data to S3')
|
|
134
135
|
|
|
135
136
|
bundle
|
|
136
137
|
.command('compatibility [appId]')
|
package/src/init.ts
CHANGED
|
@@ -2,7 +2,6 @@ import { readFileSync, writeFileSync } from 'node:fs'
|
|
|
2
2
|
import type { ExecSyncOptions } from 'node:child_process'
|
|
3
3
|
import { execSync, spawnSync } from 'node:child_process'
|
|
4
4
|
import process from 'node:process'
|
|
5
|
-
import { findInstallCommand, findPackageManagerType } from '@capgo/find-package-manager'
|
|
6
5
|
import * as p from '@clack/prompts'
|
|
7
6
|
import type { SupabaseClient } from '@supabase/supabase-js'
|
|
8
7
|
import type LogSnag from 'logsnag'
|
|
@@ -12,11 +11,11 @@ import { markSnag, waitLog } from './app/debug'
|
|
|
12
11
|
import { createKey } from './key'
|
|
13
12
|
import { addChannel } from './channel/add'
|
|
14
13
|
import { uploadBundle } from './bundle/upload'
|
|
15
|
-
import { login } from './login'
|
|
14
|
+
import { doLoginExists, login } from './login'
|
|
16
15
|
import { addApp } from './app/add'
|
|
17
16
|
import { checkLatest } from './api/update'
|
|
18
17
|
import type { Options } from './api/app'
|
|
19
|
-
import { convertAppName, createSupabaseClient, findBuildCommandForProjectType, findMainFile, findMainFileForProjectType, findProjectType, findSavedKey, getConfig, useLogSnag, verifyUser } from './utils'
|
|
18
|
+
import { convertAppName, createSupabaseClient, findBuildCommandForProjectType, findMainFile, findMainFileForProjectType, findProjectType, findSavedKey, getConfig, getPMAndCommand, useLogSnag, verifyUser } from './utils'
|
|
20
19
|
|
|
21
20
|
interface SuperOptions extends Options {
|
|
22
21
|
local: boolean
|
|
@@ -40,11 +39,12 @@ async function markStep(userId: string, snag: LogSnag, step: number | string) {
|
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
async function step2(userId: string, snag: LogSnag, appId: string, options: SuperOptions) {
|
|
42
|
+
const pm = getPMAndCommand()
|
|
43
43
|
const doAdd = await p.confirm({ message: `Add ${appId} in Capgo?` })
|
|
44
44
|
await cancelCommand(doAdd, userId, snag)
|
|
45
45
|
if (doAdd) {
|
|
46
46
|
const s = p.spinner()
|
|
47
|
-
s.start(`Running:
|
|
47
|
+
s.start(`Running: ${pm.runner} @capgo/cli@latest app add ${appId}`)
|
|
48
48
|
const addRes = await addApp(appId, options, false)
|
|
49
49
|
if (!addRes)
|
|
50
50
|
s.stop(`App already add ✅`)
|
|
@@ -52,18 +52,19 @@ async function step2(userId: string, snag: LogSnag, appId: string, options: Supe
|
|
|
52
52
|
s.stop(`App add Done ✅`)
|
|
53
53
|
}
|
|
54
54
|
else {
|
|
55
|
-
p.log.info(`Run yourself "
|
|
55
|
+
p.log.info(`Run yourself "${pm.runner} @capgo/cli@latest app add ${appId}"`)
|
|
56
56
|
}
|
|
57
57
|
await markStep(userId, snag, 2)
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
async function step3(userId: string, snag: LogSnag, apikey: string, appId: string) {
|
|
61
|
+
const pm = getPMAndCommand()
|
|
61
62
|
const doChannel = await p.confirm({ message: `Create default channel ${defaultChannel} for ${appId} in Capgo?` })
|
|
62
63
|
await cancelCommand(doChannel, userId, snag)
|
|
63
64
|
if (doChannel) {
|
|
64
65
|
const s = p.spinner()
|
|
65
66
|
// create production channel public
|
|
66
|
-
s.start(`Running:
|
|
67
|
+
s.start(`Running: ${pm.runner} @capgo/cli@latest channel add ${defaultChannel} ${appId} --default`)
|
|
67
68
|
const addChannelRes = await addChannel(defaultChannel, appId, {
|
|
68
69
|
default: true,
|
|
69
70
|
apikey,
|
|
@@ -74,7 +75,7 @@ async function step3(userId: string, snag: LogSnag, apikey: string, appId: strin
|
|
|
74
75
|
s.stop(`Channel add Done ✅`)
|
|
75
76
|
}
|
|
76
77
|
else {
|
|
77
|
-
p.log.info(`Run yourself "
|
|
78
|
+
p.log.info(`Run yourself "${pm.runner} @capgo/cli@latest channel add ${defaultChannel} ${appId} --default"`)
|
|
78
79
|
}
|
|
79
80
|
await markStep(userId, snag, 3)
|
|
80
81
|
}
|
|
@@ -82,6 +83,7 @@ async function step3(userId: string, snag: LogSnag, apikey: string, appId: strin
|
|
|
82
83
|
const urlMigrateV6 = 'https://capacitorjs.com/docs/updating/6-0'
|
|
83
84
|
const urlMigrateV5 = 'https://capacitorjs.com/docs/updating/5-0'
|
|
84
85
|
async function step4(userId: string, snag: LogSnag, apikey: string, appId: string) {
|
|
86
|
+
const pm = getPMAndCommand()
|
|
85
87
|
const doInstall = await p.confirm({ message: `Automatic Install "@capgo/capacitor-updater" dependency in ${appId}?` })
|
|
86
88
|
await cancelCommand(doInstall, userId, snag)
|
|
87
89
|
if (doInstall) {
|
|
@@ -107,27 +109,25 @@ async function step4(userId: string, snag: LogSnag, apikey: string, appId: strin
|
|
|
107
109
|
s.stop(`@capacitor/core version is ${coreVersion}, please update to Capacitor v6: ${urlMigrateV6} to access the best features of Capgo`)
|
|
108
110
|
versionToInstall = '^5.0.0'
|
|
109
111
|
}
|
|
110
|
-
|
|
111
|
-
if (pm === 'unknown') {
|
|
112
|
+
if (pm.pm === 'unknown') {
|
|
112
113
|
s.stop('Error')
|
|
113
|
-
p.log.warn(`Cannot reconize package manager, please run \`capgo init\` in a capacitor project with npm, pnpm or yarn`)
|
|
114
|
+
p.log.warn(`Cannot reconize package manager, please run \`capgo init\` in a capacitor project with npm, pnpm, bun or yarn`)
|
|
114
115
|
p.outro(`Bye 👋`)
|
|
115
116
|
process.exit()
|
|
116
117
|
}
|
|
117
118
|
// // use pm to install capgo
|
|
118
119
|
// // run command pm install @capgo/capacitor-updater@latest
|
|
119
|
-
const installCmd = findInstallCommand(pm)
|
|
120
120
|
// check if capgo is already installed in package.json
|
|
121
121
|
if (pack.dependencies['@capgo/capacitor-updater']) {
|
|
122
122
|
s.stop(`Capgo already installed ✅`)
|
|
123
123
|
}
|
|
124
124
|
else {
|
|
125
|
-
await execSync(`${pm}
|
|
125
|
+
await execSync(`${pm.installCommand} @capgo/capacitor-updater@${versionToInstall}`, execOption as ExecSyncOptions)
|
|
126
126
|
s.stop(`Install Done ✅`)
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
else {
|
|
130
|
-
p.log.info(`Run yourself "
|
|
130
|
+
p.log.info(`Run yourself "${pm.installCommand} @capgo/capacitor-updater@latest"`)
|
|
131
131
|
}
|
|
132
132
|
await markStep(userId, snag, 4)
|
|
133
133
|
}
|
|
@@ -180,11 +180,12 @@ async function step5(userId: string, snag: LogSnag, apikey: string, appId: strin
|
|
|
180
180
|
}
|
|
181
181
|
|
|
182
182
|
async function step6(userId: string, snag: LogSnag, apikey: string, appId: string) {
|
|
183
|
+
const pm = getPMAndCommand()
|
|
183
184
|
const doEncrypt = await p.confirm({ message: `Automatic configure end-to-end encryption in ${appId} updates?` })
|
|
184
185
|
await cancelCommand(doEncrypt, userId, snag)
|
|
185
186
|
if (doEncrypt) {
|
|
186
187
|
const s = p.spinner()
|
|
187
|
-
s.start(`Running:
|
|
188
|
+
s.start(`Running: ${pm.runner} @capgo/cli@latest key create`)
|
|
188
189
|
const keyRes = await createKey({ force: true }, false)
|
|
189
190
|
if (!keyRes) {
|
|
190
191
|
s.stop('Error')
|
|
@@ -201,13 +202,14 @@ async function step6(userId: string, snag: LogSnag, apikey: string, appId: strin
|
|
|
201
202
|
}
|
|
202
203
|
|
|
203
204
|
async function step7(userId: string, snag: LogSnag, apikey: string, appId: string) {
|
|
204
|
-
const
|
|
205
|
+
const pm = getPMAndCommand()
|
|
206
|
+
const doBuild = await p.confirm({ message: `Automatic build ${appId} with "${pm.pm} run build" ?` })
|
|
205
207
|
await cancelCommand(doBuild, userId, snag)
|
|
206
208
|
if (doBuild) {
|
|
207
209
|
const s = p.spinner()
|
|
208
210
|
const projectType = await findProjectType()
|
|
209
211
|
const buildCommand = await findBuildCommandForProjectType(projectType)
|
|
210
|
-
s.start(`Running:
|
|
212
|
+
s.start(`Running: ${pm.pm} run ${buildCommand} && ${pm.runner} cap sync`)
|
|
211
213
|
const pack = JSON.parse(readFileSync('package.json').toString())
|
|
212
214
|
// check in script build exist
|
|
213
215
|
if (!pack.scripts[buildCommand]) {
|
|
@@ -216,21 +218,22 @@ async function step7(userId: string, snag: LogSnag, apikey: string, appId: strin
|
|
|
216
218
|
p.outro(`Bye 👋`)
|
|
217
219
|
process.exit()
|
|
218
220
|
}
|
|
219
|
-
execSync(
|
|
221
|
+
execSync(`${pm.pm} run ${buildCommand} && ${pm.runner} cap sync`, execOption as ExecSyncOptions)
|
|
220
222
|
s.stop(`Build & Sync Done ✅`)
|
|
221
223
|
}
|
|
222
224
|
else {
|
|
223
|
-
p.log.info(`Build yourself with command:
|
|
225
|
+
p.log.info(`Build yourself with command: ${pm.pm} run build && ${pm.runner} cap sync`)
|
|
224
226
|
}
|
|
225
227
|
await markStep(userId, snag, 7)
|
|
226
228
|
}
|
|
227
229
|
|
|
228
230
|
async function step8(userId: string, snag: LogSnag, apikey: string, appId: string) {
|
|
231
|
+
const pm = getPMAndCommand()
|
|
229
232
|
const doBundle = await p.confirm({ message: `Automatic upload ${appId} bundle to Capgo?` })
|
|
230
233
|
await cancelCommand(doBundle, userId, snag)
|
|
231
234
|
if (doBundle) {
|
|
232
235
|
const s = p.spinner()
|
|
233
|
-
s.start(`Running:
|
|
236
|
+
s.start(`Running: ${pm.runner} @capgo/cli@latest bundle upload`)
|
|
234
237
|
const uploadRes = await uploadBundle(appId, {
|
|
235
238
|
channel: defaultChannel,
|
|
236
239
|
apikey,
|
|
@@ -246,12 +249,13 @@ async function step8(userId: string, snag: LogSnag, apikey: string, appId: strin
|
|
|
246
249
|
}
|
|
247
250
|
}
|
|
248
251
|
else {
|
|
249
|
-
p.log.info(`Upload yourself with command:
|
|
252
|
+
p.log.info(`Upload yourself with command: ${pm.runner} @capgo/cli@latest bundle upload`)
|
|
250
253
|
}
|
|
251
254
|
await markStep(userId, snag, 8)
|
|
252
255
|
}
|
|
253
256
|
|
|
254
257
|
async function step9(userId: string, snag: LogSnag) {
|
|
258
|
+
const pm = getPMAndCommand()
|
|
255
259
|
const doRun = await p.confirm({ message: `Run in device now ?` })
|
|
256
260
|
await cancelCommand(doRun, userId, snag)
|
|
257
261
|
if (doRun) {
|
|
@@ -269,12 +273,12 @@ async function step9(userId: string, snag: LogSnag) {
|
|
|
269
273
|
|
|
270
274
|
const platform = plaformType as 'ios' | 'android'
|
|
271
275
|
const s = p.spinner()
|
|
272
|
-
s.start(`Running:
|
|
273
|
-
await spawnSync(
|
|
276
|
+
s.start(`Running: ${pm.runner} cap run ${platform}`)
|
|
277
|
+
await spawnSync(pm.runner, ['cap', 'run', platform], { stdio: 'inherit' })
|
|
274
278
|
s.stop(`Started Done ✅`)
|
|
275
279
|
}
|
|
276
280
|
else {
|
|
277
|
-
p.log.info(`Run yourself with command:
|
|
281
|
+
p.log.info(`Run yourself with command: ${pm.runner} cap run <ios|android>`)
|
|
278
282
|
}
|
|
279
283
|
await markStep(userId, snag, 9)
|
|
280
284
|
}
|
|
@@ -294,21 +298,21 @@ async function step10(userId: string, snag: LogSnag, supabase: SupabaseClient<Da
|
|
|
294
298
|
await markStep(userId, snag, 10)
|
|
295
299
|
}
|
|
296
300
|
|
|
297
|
-
export async function initApp(
|
|
301
|
+
export async function initApp(apikeyCommand: string, appId: string, options: SuperOptions) {
|
|
302
|
+
const pm = getPMAndCommand()
|
|
298
303
|
p.intro(`Capgo onboarding 🛫`)
|
|
299
304
|
await checkLatest()
|
|
300
305
|
const snag = useLogSnag()
|
|
301
306
|
const config = await getConfig()
|
|
302
307
|
appId = appId || config?.app?.appId
|
|
303
|
-
apikey =
|
|
308
|
+
const apikey = apikeyCommand || findSavedKey()
|
|
304
309
|
|
|
305
310
|
const log = p.spinner()
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
log.stop('Login already done ✅')
|
|
310
|
-
else
|
|
311
|
+
if (!doLoginExists() || apikeyCommand) {
|
|
312
|
+
log.start(`Running: ${pm.runner} @capgo/cli@latest login ***`)
|
|
313
|
+
await login(apikey, options, false)
|
|
311
314
|
log.stop('Login Done ✅')
|
|
315
|
+
}
|
|
312
316
|
|
|
313
317
|
const supabase = await createSupabaseClient(apikey)
|
|
314
318
|
const userId = await verifyUser(supabase, apikey, ['upload', 'all', 'read', 'write'])
|
|
@@ -327,7 +331,7 @@ export async function initApp(apikey: string, appId: string, options: SuperOptio
|
|
|
327
331
|
await markStep(userId, snag, 0)
|
|
328
332
|
p.log.info(`Welcome onboard ✈️!`)
|
|
329
333
|
p.log.info(`Your Capgo update system is setup`)
|
|
330
|
-
p.log.info(`Next time use
|
|
334
|
+
p.log.info(`Next time use \`${pm.runner} @capgo/cli@latest bundle upload\` to only upload your bundle`)
|
|
331
335
|
p.outro(`Bye 👋`)
|
|
332
336
|
process.exit()
|
|
333
337
|
}
|
package/src/login.ts
CHANGED
|
@@ -9,6 +9,10 @@ import { checkLatest } from './api/update'
|
|
|
9
9
|
interface Options {
|
|
10
10
|
local: boolean
|
|
11
11
|
}
|
|
12
|
+
export async function doLoginExists() {
|
|
13
|
+
const userHomeDir = homedir()
|
|
14
|
+
return existsSync(`${userHomeDir}/.capgo`) || existsSync('.capgo')
|
|
15
|
+
}
|
|
12
16
|
|
|
13
17
|
export async function login(apikey: string, options: Options, shouldExit = true) {
|
|
14
18
|
if (shouldExit)
|
package/src/utils.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { existsSync, readFileSync, readdirSync } from 'node:fs'
|
|
|
2
2
|
import { homedir } from 'node:os'
|
|
3
3
|
import { resolve } from 'node:path'
|
|
4
4
|
import process from 'node:process'
|
|
5
|
+
import type { Buffer } from 'node:buffer'
|
|
5
6
|
import { loadConfig } from '@capacitor/cli/dist/config'
|
|
6
7
|
import { program } from 'commander'
|
|
7
8
|
import type { SupabaseClient } from '@supabase/supabase-js'
|
|
@@ -11,7 +12,8 @@ import { LogSnag } from 'logsnag'
|
|
|
11
12
|
import * as p from '@clack/prompts'
|
|
12
13
|
import ky from 'ky'
|
|
13
14
|
import { promiseFiles } from 'node-dir'
|
|
14
|
-
import {
|
|
15
|
+
import type { InstallCommand, PackageManagerRunner, PackageManagerType } from '@capgo/find-package-manager'
|
|
16
|
+
import { findInstallCommand, findPackageManagerRunner, findPackageManagerType } from '@capgo/find-package-manager'
|
|
15
17
|
import type { Database } from './types/supabase.types'
|
|
16
18
|
|
|
17
19
|
export const baseKey = '.capgo_key'
|
|
@@ -39,7 +41,7 @@ export async function getConfig() {
|
|
|
39
41
|
config = await loadConfig()
|
|
40
42
|
}
|
|
41
43
|
catch (err) {
|
|
42
|
-
p.log.error(
|
|
44
|
+
p.log.error(`No capacitor config file found, run \`cap init\` first ${formatError(err)}`)
|
|
43
45
|
program.error('')
|
|
44
46
|
}
|
|
45
47
|
return config
|
|
@@ -306,7 +308,7 @@ export function findSavedKey(quiet = false) {
|
|
|
306
308
|
key = readFileSync(keyPath, 'utf8').trim()
|
|
307
309
|
}
|
|
308
310
|
if (!key) {
|
|
309
|
-
p.log.error(`Cannot find API key in local folder or global, please login first with
|
|
311
|
+
p.log.error(`Cannot find API key in local folder or global, please login first with ${getPMAndCommand().runner} @capacitor/cli login`)
|
|
310
312
|
program.error('')
|
|
311
313
|
}
|
|
312
314
|
return key
|
|
@@ -482,6 +484,7 @@ export async function uploadUrl(supabase: SupabaseClient<Database>, appId: strin
|
|
|
482
484
|
const data = {
|
|
483
485
|
app_id: appId,
|
|
484
486
|
name,
|
|
487
|
+
version: 0,
|
|
485
488
|
}
|
|
486
489
|
try {
|
|
487
490
|
const pathUploadLink = 'private/upload_link'
|
|
@@ -494,6 +497,67 @@ export async function uploadUrl(supabase: SupabaseClient<Database>, appId: strin
|
|
|
494
497
|
return ''
|
|
495
498
|
}
|
|
496
499
|
|
|
500
|
+
async function prepareMultipart(supabase: SupabaseClient<Database>, appId: string, name: string): Promise<{ key: string, uploadId: string, url: string } | null> {
|
|
501
|
+
const data = {
|
|
502
|
+
app_id: appId,
|
|
503
|
+
name,
|
|
504
|
+
version: 1,
|
|
505
|
+
}
|
|
506
|
+
try {
|
|
507
|
+
const pathUploadLink = 'private/upload_link'
|
|
508
|
+
const res = await supabase.functions.invoke(pathUploadLink, { body: JSON.stringify(data) })
|
|
509
|
+
return res.data as any
|
|
510
|
+
}
|
|
511
|
+
catch (error) {
|
|
512
|
+
p.log.error(`Cannot get upload url ${formatError(error)}`)
|
|
513
|
+
return null
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
async function finishMultipartDownload(key: string, uploadId: string, url: string, parts: any[]) {
|
|
518
|
+
const metadata = {
|
|
519
|
+
action: 'mpu-complete',
|
|
520
|
+
uploadId,
|
|
521
|
+
key,
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
await ky.post(url, {
|
|
525
|
+
json: {
|
|
526
|
+
parts,
|
|
527
|
+
},
|
|
528
|
+
searchParams: new URLSearchParams({ body: btoa(JSON.stringify(metadata)) }),
|
|
529
|
+
})
|
|
530
|
+
|
|
531
|
+
// console.log(await response.json())
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
const PART_SIZE = 10 * 1024 * 1024
|
|
535
|
+
export async function uploadMultipart(supabase: SupabaseClient<Database>, appId: string, name: string, data: Buffer): Promise<boolean> {
|
|
536
|
+
try {
|
|
537
|
+
const multipartPrep = await prepareMultipart(supabase, appId, name)
|
|
538
|
+
if (!multipartPrep) {
|
|
539
|
+
// Just pass the error
|
|
540
|
+
return false
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
const fileSize = data.length
|
|
544
|
+
const partCount = Math.ceil(fileSize / PART_SIZE)
|
|
545
|
+
|
|
546
|
+
const uploadPromises = Array.from({ length: partCount }, (_, index) =>
|
|
547
|
+
uploadPart(data, PART_SIZE, multipartPrep.url, multipartPrep.key, multipartPrep.uploadId, index))
|
|
548
|
+
|
|
549
|
+
const parts = await Promise.all(uploadPromises)
|
|
550
|
+
|
|
551
|
+
await finishMultipartDownload(multipartPrep.key, multipartPrep.uploadId, multipartPrep.url, parts)
|
|
552
|
+
|
|
553
|
+
return true
|
|
554
|
+
}
|
|
555
|
+
catch (e) {
|
|
556
|
+
p.log.error(`Could not upload via multipart ${formatError(e)}`)
|
|
557
|
+
return false
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
|
|
497
561
|
export async function deletedFailedVersion(supabase: SupabaseClient<Database>, appId: string, name: string): Promise<void> {
|
|
498
562
|
const data = {
|
|
499
563
|
app_id: appId,
|
|
@@ -510,6 +574,34 @@ export async function deletedFailedVersion(supabase: SupabaseClient<Database>, a
|
|
|
510
574
|
}
|
|
511
575
|
}
|
|
512
576
|
|
|
577
|
+
async function uploadPart(
|
|
578
|
+
data: Buffer,
|
|
579
|
+
partsize: number,
|
|
580
|
+
url: string,
|
|
581
|
+
key: string,
|
|
582
|
+
uploadId: string,
|
|
583
|
+
index: number,
|
|
584
|
+
) {
|
|
585
|
+
const dataToUpload = data.subarray(
|
|
586
|
+
partsize * index,
|
|
587
|
+
partsize * (index + 1),
|
|
588
|
+
)
|
|
589
|
+
|
|
590
|
+
const metadata = {
|
|
591
|
+
action: 'mpu-uploadpart',
|
|
592
|
+
uploadId,
|
|
593
|
+
partNumber: index + 1,
|
|
594
|
+
key,
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
const response = await ky.put(url, {
|
|
598
|
+
body: dataToUpload,
|
|
599
|
+
searchParams: new URLSearchParams({ body: btoa(JSON.stringify(metadata)) }),
|
|
600
|
+
})
|
|
601
|
+
|
|
602
|
+
return await response.json()
|
|
603
|
+
}
|
|
604
|
+
|
|
513
605
|
export async function updateOrCreateChannel(supabase: SupabaseClient<Database>, update: Database['public']['Tables']['channels']['Insert']) {
|
|
514
606
|
// console.log('updateOrCreateChannel', update)
|
|
515
607
|
if (!update.app_id || !update.name || !update.created_by) {
|
|
@@ -625,6 +717,20 @@ export function getHumanDate(createdA: string | null) {
|
|
|
625
717
|
return date.toLocaleString()
|
|
626
718
|
}
|
|
627
719
|
|
|
720
|
+
let pmFetched = false
|
|
721
|
+
let pm: PackageManagerType = 'npm'
|
|
722
|
+
let pmCommand: InstallCommand = 'install'
|
|
723
|
+
let pmRunner: PackageManagerRunner = 'npx'
|
|
724
|
+
export function getPMAndCommand() {
|
|
725
|
+
if (pmFetched)
|
|
726
|
+
return { pm, command: pmCommand, installCommand: `${pm} ${pmCommand}`, runner: pmRunner }
|
|
727
|
+
pm = findPackageManagerType('.', 'npm')
|
|
728
|
+
pmCommand = findInstallCommand(pm)
|
|
729
|
+
pmFetched = true
|
|
730
|
+
pmRunner = findPackageManagerRunner()
|
|
731
|
+
return { pm, command: pmCommand, installCommand: `${pm} ${pmCommand}`, runner: pmRunner }
|
|
732
|
+
}
|
|
733
|
+
|
|
628
734
|
export async function getLocalDepenencies() {
|
|
629
735
|
if (!existsSync('./package.json')) {
|
|
630
736
|
p.log.error('Missing package.json, you need to be in a capacitor project')
|