@capgo/cli 8.0.0-alpha.1 → 8.0.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/index.js +238 -411
- package/dist/package.json +89 -93
- package/dist/src/api/channels.d.ts +592 -16
- package/dist/src/api/channels.d.ts.map +1 -1
- package/dist/src/api/update.d.ts.map +1 -1
- package/dist/src/app/add.d.ts +2 -8
- package/dist/src/app/add.d.ts.map +1 -1
- package/dist/src/app/debug.d.ts +1 -1
- package/dist/src/app/debug.d.ts.map +1 -1
- package/dist/src/app/delete.d.ts +2 -1
- package/dist/src/app/delete.d.ts.map +1 -1
- package/dist/src/app/info.d.ts +9 -1
- package/dist/src/app/info.d.ts.map +1 -1
- package/dist/src/app/list.d.ts +19 -1
- package/dist/src/app/list.d.ts.map +1 -1
- package/dist/src/app/set.d.ts +2 -1
- package/dist/src/app/set.d.ts.map +1 -1
- package/dist/src/app/setting.d.ts +2 -1
- package/dist/src/app/setting.d.ts.map +1 -1
- package/dist/src/bundle/cleanup.d.ts +5 -1
- package/dist/src/bundle/cleanup.d.ts.map +1 -1
- package/dist/src/bundle/compatibility.d.ts +4 -4
- package/dist/src/bundle/compatibility.d.ts.map +1 -1
- package/dist/src/bundle/delete.d.ts +2 -1
- package/dist/src/bundle/delete.d.ts.map +1 -1
- package/dist/src/bundle/partial.d.ts +2 -2
- package/dist/src/bundle/partial.d.ts.map +1 -1
- package/dist/src/bundle/upload.d.ts +3 -3
- package/dist/src/bundle/upload.d.ts.map +1 -1
- package/dist/src/bundle/upload_interface.d.ts +1 -0
- package/dist/src/bundle/upload_interface.d.ts.map +1 -1
- package/dist/src/bundle/zip.d.ts.map +1 -1
- package/dist/src/channel/add.d.ts +2 -2
- package/dist/src/channel/add.d.ts.map +1 -1
- package/dist/src/channel/currentBundle.d.ts +2 -1
- package/dist/src/channel/currentBundle.d.ts.map +1 -1
- package/dist/src/channel/delete.d.ts +2 -1
- package/dist/src/channel/delete.d.ts.map +1 -1
- package/dist/src/channel/list.d.ts +2 -1
- package/dist/src/channel/list.d.ts.map +1 -1
- package/dist/src/channel/set.d.ts +2 -1
- package/dist/src/channel/set.d.ts.map +1 -1
- package/dist/src/checksum.d.ts +9 -0
- package/dist/src/checksum.d.ts.map +1 -0
- package/dist/src/init.d.ts.map +1 -1
- package/dist/src/keyV2.d.ts +2 -3
- package/dist/src/keyV2.d.ts.map +1 -1
- package/dist/src/login.d.ts +2 -2
- package/dist/src/login.d.ts.map +1 -1
- package/dist/src/organisation/list.d.ts +3 -0
- package/dist/src/organisation/list.d.ts.map +1 -1
- package/dist/src/sdk.d.ts +107 -4
- package/dist/src/sdk.d.ts.map +1 -1
- package/dist/src/sdk.js +247 -310
- package/dist/src/types/supabase.types.d.ts +313 -9
- package/dist/src/types/supabase.types.d.ts.map +1 -1
- package/dist/src/utils/latest-version.d.ts +7 -0
- package/dist/src/utils/latest-version.d.ts.map +1 -0
- package/dist/src/utils.d.ts +302 -21
- package/dist/src/utils.d.ts.map +1 -1
- package/package.json +11 -15
- package/dist/src/api/app.js +0 -45
- package/dist/src/api/app.js.map +0 -1
- package/dist/src/api/channels.js +0 -167
- package/dist/src/api/channels.js.map +0 -1
- package/dist/src/api/cryptoV2.js +0 -102
- package/dist/src/api/cryptoV2.js.map +0 -1
- package/dist/src/api/update.js +0 -14
- package/dist/src/api/update.js.map +0 -1
- package/dist/src/api/versions.js +0 -92
- package/dist/src/api/versions.js.map +0 -1
- package/dist/src/app/add.js +0 -150
- package/dist/src/app/add.js.map +0 -1
- package/dist/src/app/debug.js +0 -222
- package/dist/src/app/debug.js.map +0 -1
- package/dist/src/app/delete.js +0 -89
- package/dist/src/app/delete.js.map +0 -1
- package/dist/src/app/info.js +0 -84
- package/dist/src/app/info.js.map +0 -1
- package/dist/src/app/list.js +0 -48
- package/dist/src/app/list.js.map +0 -1
- package/dist/src/app/set.js +0 -96
- package/dist/src/app/set.js.map +0 -1
- package/dist/src/app/setting.js +0 -50
- package/dist/src/app/setting.js.map +0 -1
- package/dist/src/bundle/check.js +0 -30
- package/dist/src/bundle/check.js.map +0 -1
- package/dist/src/bundle/cleanup.js +0 -105
- package/dist/src/bundle/cleanup.js.map +0 -1
- package/dist/src/bundle/compatibility.js +0 -62
- package/dist/src/bundle/compatibility.js.map +0 -1
- package/dist/src/bundle/decryptV2.js +0 -76
- package/dist/src/bundle/decryptV2.js.map +0 -1
- package/dist/src/bundle/delete.js +0 -40
- package/dist/src/bundle/delete.js.map +0 -1
- package/dist/src/bundle/encryptV2.js +0 -108
- package/dist/src/bundle/encryptV2.js.map +0 -1
- package/dist/src/bundle/list.js +0 -36
- package/dist/src/bundle/list.js.map +0 -1
- package/dist/src/bundle/partial.js +0 -332
- package/dist/src/bundle/partial.js.map +0 -1
- package/dist/src/bundle/unlink.js +0 -70
- package/dist/src/bundle/unlink.js.map +0 -1
- package/dist/src/bundle/upload.js +0 -700
- package/dist/src/bundle/upload.js.map +0 -1
- package/dist/src/bundle/upload_interface.js +0 -2
- package/dist/src/bundle/upload_interface.js.map +0 -1
- package/dist/src/bundle/zip.js +0 -148
- package/dist/src/bundle/zip.js.map +0 -1
- package/dist/src/channel/add.js +0 -68
- package/dist/src/channel/add.js.map +0 -1
- package/dist/src/channel/currentBundle.js +0 -54
- package/dist/src/channel/currentBundle.js.map +0 -1
- package/dist/src/channel/delete.js +0 -77
- package/dist/src/channel/delete.js.map +0 -1
- package/dist/src/channel/list.js +0 -45
- package/dist/src/channel/list.js.map +0 -1
- package/dist/src/channel/set.js +0 -220
- package/dist/src/channel/set.js.map +0 -1
- package/dist/src/config/index.js +0 -31
- package/dist/src/config/index.js.map +0 -1
- package/dist/src/docs.js +0 -280
- package/dist/src/docs.js.map +0 -1
- package/dist/src/index.js +0 -504
- package/dist/src/index.js.map +0 -1
- package/dist/src/init.js +0 -797
- package/dist/src/init.js.map +0 -1
- package/dist/src/keyV2.js +0 -163
- package/dist/src/keyV2.js.map +0 -1
- package/dist/src/login.js +0 -51
- package/dist/src/login.js.map +0 -1
- package/dist/src/organisation/add.js +0 -82
- package/dist/src/organisation/add.js.map +0 -1
- package/dist/src/organisation/delete.js +0 -91
- package/dist/src/organisation/delete.js.map +0 -1
- package/dist/src/organisation/index.js +0 -5
- package/dist/src/organisation/index.js.map +0 -1
- package/dist/src/organisation/list.js +0 -60
- package/dist/src/organisation/list.js.map +0 -1
- package/dist/src/organisation/set.js +0 -95
- package/dist/src/organisation/set.js.map +0 -1
- package/dist/src/sdk.js.map +0 -1
- package/dist/src/types/supabase.types.js +0 -88
- package/dist/src/types/supabase.types.js.map +0 -1
- package/dist/src/user/account.js +0 -31
- package/dist/src/user/account.js.map +0 -1
- package/dist/src/utils.js +0 -1184
- package/dist/src/utils.js.map +0 -1
package/dist/src/utils.js
DELETED
|
@@ -1,1184 +0,0 @@
|
|
|
1
|
-
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
2
|
-
import { homedir, platform as osPlatform } from 'node:os';
|
|
3
|
-
import path, { dirname, join, relative, resolve, sep } from 'node:path';
|
|
4
|
-
import { cwd, env } from 'node:process';
|
|
5
|
-
import { findMonorepoRoot, findNXMonorepoRoot, isMonorepo, isNXMonorepo } from '@capacitor/cli/dist/util/monorepotools';
|
|
6
|
-
import { findInstallCommand, findPackageManagerRunner, findPackageManagerType } from '@capgo/find-package-manager';
|
|
7
|
-
import { confirm as confirmC, isCancel, log, select, spinner as spinnerC } from '@clack/prompts';
|
|
8
|
-
import { createClient, FunctionsHttpError } from '@supabase/supabase-js';
|
|
9
|
-
import { checksum as getChecksum } from '@tomasklaen/checksum';
|
|
10
|
-
import AdmZip from 'adm-zip';
|
|
11
|
-
import ky from 'ky';
|
|
12
|
-
import prettyjson from 'prettyjson';
|
|
13
|
-
import cleanVersion from 'semver/functions/clean';
|
|
14
|
-
import validVersion from 'semver/functions/valid';
|
|
15
|
-
import subset from 'semver/ranges/subset';
|
|
16
|
-
import * as tus from 'tus-js-client';
|
|
17
|
-
import { loadConfig, writeConfig } from './config';
|
|
18
|
-
export const baseKey = '.capgo_key';
|
|
19
|
-
export const baseKeyV2 = '.capgo_key_v2';
|
|
20
|
-
export const baseKeyPub = `${baseKey}.pub`;
|
|
21
|
-
export const baseKeyPubV2 = `${baseKeyV2}.pub`;
|
|
22
|
-
export const defaultHost = 'https://capgo.app';
|
|
23
|
-
export const defaultFileHost = 'https://files.capgo.app';
|
|
24
|
-
export const defaultApiHost = 'https://api.capgo.app';
|
|
25
|
-
export const defaultHostWeb = 'https://console.capgo.app';
|
|
26
|
-
export const UPLOAD_TIMEOUT = 120000;
|
|
27
|
-
export const ALERT_UPLOAD_SIZE_BYTES = 1024 * 1024 * 20; // 20MB
|
|
28
|
-
export const MAX_UPLOAD_LENGTH_BYTES = 1024 * 1024 * 1024; // 1GB
|
|
29
|
-
export const MAX_CHUNK_SIZE_BYTES = 1024 * 1024 * 99; // 99MB
|
|
30
|
-
export const PACKNAME = 'package.json';
|
|
31
|
-
export const regexSemver = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-z-][0-9a-z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-z-][0-9a-z-]*))*))?(?:\+([0-9a-z-]+(?:\.[0-9a-z-]+)*))?$/i;
|
|
32
|
-
export const formatError = (error) => error ? `\n${prettyjson.render(error)}` : '';
|
|
33
|
-
export function wait(ms) {
|
|
34
|
-
return new Promise((resolve) => {
|
|
35
|
-
setTimeout(resolve, ms);
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
export function projectIsMonorepo(dir) {
|
|
39
|
-
return isMonorepo(dir) || isNXMonorepo(dir);
|
|
40
|
-
}
|
|
41
|
-
export function findRoot(dir) {
|
|
42
|
-
if (isMonorepo(dir)) {
|
|
43
|
-
return findMonorepoRoot(dir);
|
|
44
|
-
}
|
|
45
|
-
else if (isNXMonorepo(dir)) {
|
|
46
|
-
return findNXMonorepoRoot(dir);
|
|
47
|
-
}
|
|
48
|
-
return dir;
|
|
49
|
-
}
|
|
50
|
-
// do not expose this function this prevent missuses
|
|
51
|
-
function readPackageJson(f = findRoot(cwd()), file = undefined) {
|
|
52
|
-
const fileSplit = file?.split(',')[0];
|
|
53
|
-
if (fileSplit) {
|
|
54
|
-
if (!existsSync(fileSplit)) {
|
|
55
|
-
const message = `Package.json at ${fileSplit} does not exist`;
|
|
56
|
-
log.error(message);
|
|
57
|
-
throw new Error(message);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
const packageJson = readFileSync(fileSplit ?? join(f, PACKNAME));
|
|
61
|
-
return JSON.parse(packageJson);
|
|
62
|
-
}
|
|
63
|
-
export function getPackageScripts(f = findRoot(cwd()), file = undefined) {
|
|
64
|
-
const packageJson = readPackageJson(f, file);
|
|
65
|
-
return packageJson.scripts;
|
|
66
|
-
}
|
|
67
|
-
export function getBundleVersion(f = findRoot(cwd()), file = undefined) {
|
|
68
|
-
const packageJson = readPackageJson(f, file);
|
|
69
|
-
return packageJson.version ?? '';
|
|
70
|
-
}
|
|
71
|
-
function returnVersion(version) {
|
|
72
|
-
const tmpVersion = version.replace('^', '').replace('~', '');
|
|
73
|
-
if (validVersion(tmpVersion)) {
|
|
74
|
-
return cleanVersion(tmpVersion) ?? tmpVersion;
|
|
75
|
-
}
|
|
76
|
-
return tmpVersion;
|
|
77
|
-
}
|
|
78
|
-
export async function getAllPackagesDependencies(f = findRoot(cwd()), file = undefined) {
|
|
79
|
-
// if file contain , split by comma and return the array
|
|
80
|
-
let files = file?.split(',');
|
|
81
|
-
files ??= [join(f, PACKNAME)];
|
|
82
|
-
if (files) {
|
|
83
|
-
for (const file of files) {
|
|
84
|
-
if (!existsSync(file)) {
|
|
85
|
-
const message = `Package.json at ${file} does not exist`;
|
|
86
|
-
log.error(message);
|
|
87
|
-
throw new Error(message);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
const dependencies = new Map();
|
|
92
|
-
for (const file of files) {
|
|
93
|
-
const packageJson = readFileSync(file);
|
|
94
|
-
const pkg = JSON.parse(packageJson);
|
|
95
|
-
for (const dependency in pkg.dependencies) {
|
|
96
|
-
dependencies.set(dependency, returnVersion(pkg.dependencies[dependency]));
|
|
97
|
-
}
|
|
98
|
-
for (const dependency in pkg.devDependencies) {
|
|
99
|
-
dependencies.set(dependency, returnVersion(pkg.devDependencies[dependency]));
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
return dependencies;
|
|
103
|
-
}
|
|
104
|
-
export async function getConfig() {
|
|
105
|
-
try {
|
|
106
|
-
const extConfig = await loadConfig();
|
|
107
|
-
if (!extConfig) {
|
|
108
|
-
const message = 'No capacitor config file found, run `cap init` first';
|
|
109
|
-
log.error(message);
|
|
110
|
-
throw new Error(message);
|
|
111
|
-
}
|
|
112
|
-
return extConfig;
|
|
113
|
-
}
|
|
114
|
-
catch (err) {
|
|
115
|
-
const message = `No capacitor config file found, run \`cap init\` first ${formatError(err)}`;
|
|
116
|
-
log.error(message);
|
|
117
|
-
throw new Error(message);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
export async function updateConfigbyKey(key, newConfig) {
|
|
121
|
-
const extConfig = await getConfig();
|
|
122
|
-
if (extConfig?.config) {
|
|
123
|
-
extConfig.config.plugins ??= {};
|
|
124
|
-
extConfig.config.plugins.extConfig ??= {};
|
|
125
|
-
extConfig.config.plugins[key] ??= {};
|
|
126
|
-
extConfig.config.plugins[key] = {
|
|
127
|
-
...extConfig.config.plugins[key],
|
|
128
|
-
...newConfig,
|
|
129
|
-
};
|
|
130
|
-
// console.log('extConfig', extConfig)
|
|
131
|
-
await writeConfig(key, extConfig);
|
|
132
|
-
}
|
|
133
|
-
return extConfig;
|
|
134
|
-
}
|
|
135
|
-
export async function updateConfigUpdater(newConfig) {
|
|
136
|
-
return updateConfigbyKey('CapacitorUpdater', newConfig);
|
|
137
|
-
}
|
|
138
|
-
export async function getLocalConfig() {
|
|
139
|
-
try {
|
|
140
|
-
const extConfig = await getConfig();
|
|
141
|
-
const capConfig = {
|
|
142
|
-
host: (extConfig?.config?.plugins?.CapacitorUpdater?.localHost || defaultHost),
|
|
143
|
-
hostWeb: (extConfig?.config?.plugins?.CapacitorUpdater?.localWebHost || defaultHostWeb),
|
|
144
|
-
hostFilesApi: (extConfig?.config?.plugins?.CapacitorUpdater?.localApiFiles || defaultFileHost),
|
|
145
|
-
hostApi: (extConfig?.config?.plugins?.CapacitorUpdater?.localApi || defaultApiHost),
|
|
146
|
-
};
|
|
147
|
-
if (extConfig?.config?.plugins?.CapacitorUpdater?.localSupa && extConfig?.config?.plugins?.CapacitorUpdater?.localSupaAnon) {
|
|
148
|
-
log.info('Using custom supabase instance from capacitor.config.json');
|
|
149
|
-
capConfig.supaKey = extConfig?.config?.plugins?.CapacitorUpdater?.localSupaAnon;
|
|
150
|
-
capConfig.supaHost = extConfig?.config?.plugins?.CapacitorUpdater?.localSupa;
|
|
151
|
-
}
|
|
152
|
-
return capConfig;
|
|
153
|
-
}
|
|
154
|
-
catch {
|
|
155
|
-
return {
|
|
156
|
-
host: defaultHost,
|
|
157
|
-
hostWeb: defaultHostWeb,
|
|
158
|
-
hostFilesApi: defaultFileHost,
|
|
159
|
-
hostApi: defaultApiHost,
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
// eslint-disable-next-line regexp/no-unused-capturing-group
|
|
164
|
-
const nativeFileRegex = /([A-Za-z0-9]+)\.(java|swift|kt|scala)$/;
|
|
165
|
-
export async function getRemoteConfig() {
|
|
166
|
-
// call host + /api/get_config and parse the result as json using ky
|
|
167
|
-
const localConfig = await getLocalConfig();
|
|
168
|
-
return ky
|
|
169
|
-
.get(`${localConfig.hostApi}/private/config`)
|
|
170
|
-
.then(res => res.json())
|
|
171
|
-
.then(data => ({ ...data, ...localConfig }))
|
|
172
|
-
.catch(() => {
|
|
173
|
-
log.info(`Local config ${formatError(localConfig)}`);
|
|
174
|
-
return localConfig;
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
export async function getRemoteFileConfig() {
|
|
178
|
-
const localConfig = await getLocalConfig();
|
|
179
|
-
// call host + /api/get_config and parse the result as json using ky
|
|
180
|
-
return ky
|
|
181
|
-
.get(`${localConfig.hostFilesApi}/files/config`)
|
|
182
|
-
.then(res => res.json())
|
|
183
|
-
.catch(() => {
|
|
184
|
-
return {
|
|
185
|
-
partialUpload: false,
|
|
186
|
-
TUSUpload: false,
|
|
187
|
-
partialUploadForced: false,
|
|
188
|
-
TUSUploadForced: false,
|
|
189
|
-
maxUploadLength: MAX_UPLOAD_LENGTH_BYTES,
|
|
190
|
-
maxChunkSize: MAX_CHUNK_SIZE_BYTES,
|
|
191
|
-
alertUploadSize: ALERT_UPLOAD_SIZE_BYTES,
|
|
192
|
-
};
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
export async function createSupabaseClient(apikey, supaHost, supaKey) {
|
|
196
|
-
const config = await getRemoteConfig();
|
|
197
|
-
if (supaHost && supaKey) {
|
|
198
|
-
log.info('Using custom supabase instance from provided options');
|
|
199
|
-
config.supaHost = supaHost;
|
|
200
|
-
config.supaKey = supaKey;
|
|
201
|
-
}
|
|
202
|
-
if (!config.supaHost || !config.supaKey) {
|
|
203
|
-
log.error('Cannot connect to server please try again later');
|
|
204
|
-
throw new Error('Cannot connect to server please try again later');
|
|
205
|
-
}
|
|
206
|
-
return createClient(config.supaHost, config.supaKey, {
|
|
207
|
-
auth: {
|
|
208
|
-
persistSession: false,
|
|
209
|
-
},
|
|
210
|
-
global: {
|
|
211
|
-
headers: {
|
|
212
|
-
capgkey: apikey,
|
|
213
|
-
},
|
|
214
|
-
},
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
export async function checkKey(supabase, apikey, keymode) {
|
|
218
|
-
const { data: apiAccess } = await supabase
|
|
219
|
-
.rpc('is_allowed_capgkey', { apikey, keymode })
|
|
220
|
-
.single();
|
|
221
|
-
if (!apiAccess) {
|
|
222
|
-
log.error(`Invalid API key or insufficient permissions.`);
|
|
223
|
-
// create a string from keymode array with comma and space and "or" for the last one
|
|
224
|
-
const keymodeStr = keymode.map((k, i) => {
|
|
225
|
-
if (keymode.length === 1)
|
|
226
|
-
return `"${k}"`;
|
|
227
|
-
if (i === keymode.length - 1)
|
|
228
|
-
return `or "${k}"`;
|
|
229
|
-
return `"${k}", `;
|
|
230
|
-
}).join('');
|
|
231
|
-
const message = `Your key should be: ${keymodeStr} mode.`;
|
|
232
|
-
log.error(message);
|
|
233
|
-
throw new Error('Invalid API key or insufficient permissions.');
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
export async function isPayingOrg(supabase, orgId) {
|
|
237
|
-
const { data } = await supabase
|
|
238
|
-
.rpc('is_paying_org', { orgid: orgId })
|
|
239
|
-
.single();
|
|
240
|
-
return data || false;
|
|
241
|
-
}
|
|
242
|
-
export async function isTrialOrg(supabase, orgId) {
|
|
243
|
-
const { data } = await supabase
|
|
244
|
-
.rpc('is_trial_org', { orgid: orgId })
|
|
245
|
-
.single();
|
|
246
|
-
return data || 0;
|
|
247
|
-
}
|
|
248
|
-
export async function isAllowedActionOrg(supabase, orgId) {
|
|
249
|
-
const { data } = await supabase
|
|
250
|
-
.rpc('is_allowed_action_org', { orgid: orgId })
|
|
251
|
-
.single();
|
|
252
|
-
return !!data;
|
|
253
|
-
}
|
|
254
|
-
export async function isAllowedActionAppIdApiKey(supabase, appId, apikey) {
|
|
255
|
-
const { data } = await supabase
|
|
256
|
-
.rpc('is_allowed_action', { apikey, appid: appId })
|
|
257
|
-
.single();
|
|
258
|
-
return !!data;
|
|
259
|
-
}
|
|
260
|
-
export async function isAllowedApp(supabase, apikey, appId) {
|
|
261
|
-
const { data } = await supabase
|
|
262
|
-
.rpc('is_app_owner', { apikey, appid: appId })
|
|
263
|
-
.single();
|
|
264
|
-
return !!data;
|
|
265
|
-
}
|
|
266
|
-
export var OrganizationPerm;
|
|
267
|
-
(function (OrganizationPerm) {
|
|
268
|
-
OrganizationPerm[OrganizationPerm["none"] = 0] = "none";
|
|
269
|
-
OrganizationPerm[OrganizationPerm["read"] = 1] = "read";
|
|
270
|
-
OrganizationPerm[OrganizationPerm["upload"] = 2] = "upload";
|
|
271
|
-
OrganizationPerm[OrganizationPerm["write"] = 3] = "write";
|
|
272
|
-
OrganizationPerm[OrganizationPerm["admin"] = 4] = "admin";
|
|
273
|
-
OrganizationPerm[OrganizationPerm["super_admin"] = 5] = "super_admin";
|
|
274
|
-
})(OrganizationPerm || (OrganizationPerm = {}));
|
|
275
|
-
export const hasOrganizationPerm = (perm, required) => perm >= required;
|
|
276
|
-
export async function isAllowedAppOrg(supabase, apikey, appId) {
|
|
277
|
-
const { data, error } = await supabase
|
|
278
|
-
.rpc('get_org_perm_for_apikey', { apikey, app_id: appId })
|
|
279
|
-
.single();
|
|
280
|
-
if (error) {
|
|
281
|
-
log.error('Cannot get permissions for organization!');
|
|
282
|
-
console.error(error);
|
|
283
|
-
throw new Error('Cannot get permissions for organization');
|
|
284
|
-
}
|
|
285
|
-
const ok = data.includes('perm');
|
|
286
|
-
if (ok) {
|
|
287
|
-
let perm = null;
|
|
288
|
-
switch (data) {
|
|
289
|
-
case 'perm_none': {
|
|
290
|
-
perm = OrganizationPerm.none;
|
|
291
|
-
break;
|
|
292
|
-
}
|
|
293
|
-
case 'perm_read': {
|
|
294
|
-
perm = OrganizationPerm.read;
|
|
295
|
-
break;
|
|
296
|
-
}
|
|
297
|
-
case 'perm_upload': {
|
|
298
|
-
perm = OrganizationPerm.upload;
|
|
299
|
-
break;
|
|
300
|
-
}
|
|
301
|
-
case 'perm_write': {
|
|
302
|
-
perm = OrganizationPerm.write;
|
|
303
|
-
break;
|
|
304
|
-
}
|
|
305
|
-
case 'perm_admin': {
|
|
306
|
-
perm = OrganizationPerm.admin;
|
|
307
|
-
break;
|
|
308
|
-
}
|
|
309
|
-
case 'perm_owner': {
|
|
310
|
-
perm = OrganizationPerm.super_admin;
|
|
311
|
-
break;
|
|
312
|
-
}
|
|
313
|
-
default: {
|
|
314
|
-
if (data.includes('invite')) {
|
|
315
|
-
log.info('Please accept/deny the organization invitation before trying to access the app');
|
|
316
|
-
throw new Error('Organization invitation pending');
|
|
317
|
-
}
|
|
318
|
-
log.error(`Invalid output when fetching organization permission. Response: ${data}`);
|
|
319
|
-
throw new Error(`Invalid output when fetching organization permission. Response: ${data}`);
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
return {
|
|
323
|
-
okay: true,
|
|
324
|
-
data: perm,
|
|
325
|
-
};
|
|
326
|
-
}
|
|
327
|
-
// This means that something went wrong here
|
|
328
|
-
let functionError = null;
|
|
329
|
-
switch (data) {
|
|
330
|
-
case 'INVALID_APIKEY': {
|
|
331
|
-
functionError = 'INVALID_APIKEY';
|
|
332
|
-
break;
|
|
333
|
-
}
|
|
334
|
-
case 'NO_APP': {
|
|
335
|
-
functionError = 'NO_APP';
|
|
336
|
-
break;
|
|
337
|
-
}
|
|
338
|
-
case 'NO_ORG': {
|
|
339
|
-
functionError = 'NO_ORG';
|
|
340
|
-
break;
|
|
341
|
-
}
|
|
342
|
-
default: {
|
|
343
|
-
log.error(`Invalid error when fetching organization permission. Response: ${data}`);
|
|
344
|
-
throw new Error(`Invalid error when fetching organization permission. Response: ${data}`);
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
return {
|
|
348
|
-
okay: false,
|
|
349
|
-
error: functionError,
|
|
350
|
-
};
|
|
351
|
-
}
|
|
352
|
-
export async function checkRemoteCliMessages(supabase, orgId, cliVersion) {
|
|
353
|
-
const { data: messages, error } = await supabase.rpc('get_organization_cli_warnings', { orgid: orgId, cli_version: cliVersion });
|
|
354
|
-
if (error) {
|
|
355
|
-
log.error(`Cannot get cli warnings: ${formatError(error)}`);
|
|
356
|
-
return;
|
|
357
|
-
}
|
|
358
|
-
if (messages.length > 0) {
|
|
359
|
-
log.warn(`Found ${messages.length} cli warnings for your organization.`);
|
|
360
|
-
let fatalError = null;
|
|
361
|
-
for (const message of messages) {
|
|
362
|
-
if (typeof message !== 'object' || typeof message.message !== 'string' || typeof message.fatal !== 'boolean') {
|
|
363
|
-
log.error(`Invalid cli warning: ${message}`);
|
|
364
|
-
continue;
|
|
365
|
-
}
|
|
366
|
-
const msg = message;
|
|
367
|
-
if (msg.fatal) {
|
|
368
|
-
log.error(`${msg.message.replaceAll('\\n', '\n')}`);
|
|
369
|
-
fatalError = new Error(msg.message);
|
|
370
|
-
}
|
|
371
|
-
else {
|
|
372
|
-
log.warn(`${msg.message.replaceAll('\\n', '\n')}`);
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
if (fatalError) {
|
|
376
|
-
log.error('Please fix the warnings and try again.');
|
|
377
|
-
throw fatalError;
|
|
378
|
-
}
|
|
379
|
-
log.info('End of cli warnings.');
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
export async function checkPlanValid(supabase, orgId, apikey, appId, warning = true) {
|
|
383
|
-
const config = await getRemoteConfig();
|
|
384
|
-
// isAllowedActionAppIdApiKey was updated in the orgs_v3 migration to work with the new system
|
|
385
|
-
const validPlan = await (appId ? isAllowedActionAppIdApiKey(supabase, appId, apikey) : isAllowedActionOrg(supabase, orgId));
|
|
386
|
-
if (!validPlan) {
|
|
387
|
-
log.error(`You need to upgrade your plan to continue to use capgo.\n Upgrade here: ${config.hostWeb}/dashboard/settings/plans\n`);
|
|
388
|
-
wait(100);
|
|
389
|
-
import('open')
|
|
390
|
-
.then((module) => {
|
|
391
|
-
module.default(`${config.hostWeb}/dashboard/settings/plans`);
|
|
392
|
-
});
|
|
393
|
-
wait(500);
|
|
394
|
-
throw new Error('Plan upgrade required');
|
|
395
|
-
}
|
|
396
|
-
const [trialDays, ispaying] = await Promise.all([
|
|
397
|
-
isTrialOrg(supabase, orgId),
|
|
398
|
-
isPayingOrg(supabase, orgId),
|
|
399
|
-
]);
|
|
400
|
-
if (trialDays > 0 && warning && !ispaying)
|
|
401
|
-
log.warn(`WARNING !!\nTrial expires in ${trialDays} days, upgrade here: ${config.hostWeb}/dashboard/settings/plans\n`);
|
|
402
|
-
}
|
|
403
|
-
export async function checkPlanValidUpload(supabase, orgId, apikey, appId, warning = true) {
|
|
404
|
-
const config = await getRemoteConfig();
|
|
405
|
-
// isAllowedActionAppIdApiKey was updated in the orgs_v3 migration to work with the new system
|
|
406
|
-
const { data: validPlan } = await supabase.rpc('is_allowed_action_org_action', { orgid: orgId, actions: ['storage'] });
|
|
407
|
-
if (!validPlan) {
|
|
408
|
-
log.error(`You need to upgrade your plan to continue to use capgo.\n Upgrade here: ${config.hostWeb}/dashboard/settings/plans\n`);
|
|
409
|
-
wait(100);
|
|
410
|
-
import('open')
|
|
411
|
-
.then((module) => {
|
|
412
|
-
module.default(`${config.hostWeb}/dashboard/settings/plans`);
|
|
413
|
-
});
|
|
414
|
-
wait(500);
|
|
415
|
-
throw new Error('Plan upgrade required for upload');
|
|
416
|
-
}
|
|
417
|
-
const [trialDays, ispaying] = await Promise.all([
|
|
418
|
-
isTrialOrg(supabase, orgId),
|
|
419
|
-
isPayingOrg(supabase, orgId),
|
|
420
|
-
]);
|
|
421
|
-
if (trialDays > 0 && warning && !ispaying)
|
|
422
|
-
log.warn(`WARNING !!\nTrial expires in ${trialDays} days, upgrade here: ${config.hostWeb}/dashboard/settings/plans\n`);
|
|
423
|
-
}
|
|
424
|
-
export function findSavedKey(quiet = false) {
|
|
425
|
-
const envKey = env.CAPGO_TOKEN?.trim();
|
|
426
|
-
if (envKey) {
|
|
427
|
-
if (!quiet)
|
|
428
|
-
log.info('Use CAPGO_TOKEN environment variable');
|
|
429
|
-
return envKey;
|
|
430
|
-
}
|
|
431
|
-
// search for key in home dir
|
|
432
|
-
const userHomeDir = homedir();
|
|
433
|
-
let key;
|
|
434
|
-
let keyPath = `${userHomeDir}/.capgo`;
|
|
435
|
-
if (existsSync(keyPath)) {
|
|
436
|
-
if (!quiet)
|
|
437
|
-
log.info(`Use global API key ${keyPath}`);
|
|
438
|
-
key = readFileSync(keyPath, 'utf8').trim();
|
|
439
|
-
}
|
|
440
|
-
keyPath = `.capgo`;
|
|
441
|
-
if (!key && existsSync(keyPath)) {
|
|
442
|
-
if (!quiet)
|
|
443
|
-
log.info(`Use local API key ${keyPath}`);
|
|
444
|
-
key = readFileSync(keyPath, 'utf8').trim();
|
|
445
|
-
}
|
|
446
|
-
if (!key) {
|
|
447
|
-
const message = `Cannot find API key in local folder or global, please login first with ${getPMAndCommand().runner} @capacitor/cli login`;
|
|
448
|
-
log.error(message);
|
|
449
|
-
throw new Error(message);
|
|
450
|
-
}
|
|
451
|
-
return key;
|
|
452
|
-
}
|
|
453
|
-
async function* getFiles(dir) {
|
|
454
|
-
const dirents = await readdirSync(dir, { withFileTypes: true });
|
|
455
|
-
for (const dirent of dirents) {
|
|
456
|
-
const res = resolve(dir, dirent.name);
|
|
457
|
-
if (dirent.isDirectory()
|
|
458
|
-
&& !dirent.name.startsWith('.')
|
|
459
|
-
&& !dirent.name.startsWith('node_modules')
|
|
460
|
-
&& !dirent.name.startsWith('dist')) {
|
|
461
|
-
yield* getFiles(res);
|
|
462
|
-
}
|
|
463
|
-
else {
|
|
464
|
-
yield res;
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
export function getContentType(filename) {
|
|
469
|
-
const imageExtensions = /\.(jpg|jpeg|png|gif|bmp|webp)$/i;
|
|
470
|
-
const match = filename.match(imageExtensions);
|
|
471
|
-
if (match) {
|
|
472
|
-
const ext = match[1].toLowerCase();
|
|
473
|
-
switch (ext) {
|
|
474
|
-
case 'jpg':
|
|
475
|
-
case 'jpeg':
|
|
476
|
-
return 'image/jpeg';
|
|
477
|
-
case 'png':
|
|
478
|
-
return 'image/png';
|
|
479
|
-
case 'webp':
|
|
480
|
-
return 'image/webp';
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
return null;
|
|
484
|
-
}
|
|
485
|
-
export async function findProjectType() {
|
|
486
|
-
// for nuxtjs check if nuxt.config.js exists
|
|
487
|
-
// for nextjs check if next.config.js exists
|
|
488
|
-
// for angular check if angular.json exists
|
|
489
|
-
// for sveltekit check if svelte.config.js exists or svelte is in package.json dependancies
|
|
490
|
-
// for vue check if vue.config.js exists or vue is in package.json dependancies
|
|
491
|
-
// for react check if package.json exists and react is in dependencies
|
|
492
|
-
const pwd = cwd();
|
|
493
|
-
let isTypeScript = false;
|
|
494
|
-
// Check for TypeScript configuration file
|
|
495
|
-
const tsConfigPath = resolve(pwd, 'tsconfig.json');
|
|
496
|
-
if (existsSync(tsConfigPath)) {
|
|
497
|
-
isTypeScript = true;
|
|
498
|
-
}
|
|
499
|
-
for await (const f of getFiles(pwd)) {
|
|
500
|
-
// find number of folder in path after pwd
|
|
501
|
-
if (f.includes('angular.json')) {
|
|
502
|
-
log.info('Found angular project');
|
|
503
|
-
return isTypeScript ? 'angular-ts' : 'angular-js';
|
|
504
|
-
}
|
|
505
|
-
if (f.includes('nuxt.config.js') || f.includes('nuxt.config.ts')) {
|
|
506
|
-
log.info('Found nuxtjs project');
|
|
507
|
-
return isTypeScript ? 'nuxtjs-ts' : 'nuxtjs-js';
|
|
508
|
-
}
|
|
509
|
-
if (f.includes('next.config.js') || f.includes('next.config.mjs')) {
|
|
510
|
-
log.info('Found nextjs project');
|
|
511
|
-
return isTypeScript ? 'nextjs-ts' : 'nextjs-js';
|
|
512
|
-
}
|
|
513
|
-
if (f.includes('svelte.config.js')) {
|
|
514
|
-
log.info('Found sveltekit project');
|
|
515
|
-
return isTypeScript ? 'sveltekit-ts' : 'sveltekit-js';
|
|
516
|
-
}
|
|
517
|
-
if (f.includes('rolluconfig.js')) {
|
|
518
|
-
log.info('Found svelte project');
|
|
519
|
-
return isTypeScript ? 'svelte-ts' : 'svelte-js';
|
|
520
|
-
}
|
|
521
|
-
if (f.includes('vue.config.js')) {
|
|
522
|
-
log.info('Found vue project');
|
|
523
|
-
return isTypeScript ? 'vue-ts' : 'vue-js';
|
|
524
|
-
}
|
|
525
|
-
if (f.includes(PACKNAME)) {
|
|
526
|
-
const folder = dirname(f);
|
|
527
|
-
const dependencies = await getAllPackagesDependencies(folder);
|
|
528
|
-
if (dependencies) {
|
|
529
|
-
if (dependencies.get('react')) {
|
|
530
|
-
log.info('Found react project test');
|
|
531
|
-
return isTypeScript ? 'react-ts' : 'react-js';
|
|
532
|
-
}
|
|
533
|
-
if (dependencies.get('vue')) {
|
|
534
|
-
log.info('Found vue project');
|
|
535
|
-
return isTypeScript ? 'vue-ts' : 'vue-js';
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
return 'unknown';
|
|
541
|
-
}
|
|
542
|
-
export function findMainFileForProjectType(projectType, isTypeScript) {
|
|
543
|
-
if (projectType === 'angular-js' || projectType === 'angular-ts') {
|
|
544
|
-
return isTypeScript ? 'src/main.ts' : 'src/main.js';
|
|
545
|
-
}
|
|
546
|
-
if (projectType === 'nextjs-js' || projectType === 'nextjs-ts') {
|
|
547
|
-
return isTypeScript ? 'src/app/layout.tsx' : 'src/app/layout.js';
|
|
548
|
-
}
|
|
549
|
-
if (projectType === 'svelte-js' || projectType === 'svelte-ts') {
|
|
550
|
-
return isTypeScript ? 'src/main.ts' : 'src/main.js';
|
|
551
|
-
}
|
|
552
|
-
if (projectType === 'vue-js' || projectType === 'vue-ts') {
|
|
553
|
-
return isTypeScript ? 'src/main.ts' : 'src/main.js';
|
|
554
|
-
}
|
|
555
|
-
if (projectType === 'react-js' || projectType === 'react-ts') {
|
|
556
|
-
return isTypeScript ? 'src/index.tsx' : 'src/index.js';
|
|
557
|
-
}
|
|
558
|
-
return null;
|
|
559
|
-
}
|
|
560
|
-
// create a function to find the right command to build the project in static mode depending on the project type
|
|
561
|
-
export async function findBuildCommandForProjectType(projectType) {
|
|
562
|
-
if (projectType === 'angular') {
|
|
563
|
-
log.info('Angular project detected');
|
|
564
|
-
return 'build';
|
|
565
|
-
}
|
|
566
|
-
if (projectType === 'nuxtjs') {
|
|
567
|
-
log.info('Nuxtjs project detected');
|
|
568
|
-
return 'generate';
|
|
569
|
-
}
|
|
570
|
-
if (projectType === 'nextjs') {
|
|
571
|
-
log.info('Nextjs project detected');
|
|
572
|
-
log.warn('Please make sure you have configured static export in your next.config.js: https://nextjs.org/docs/pages/building-your-application/deploying/static-exports');
|
|
573
|
-
log.warn('Please make sure you have the output: \'export\' and distDir: \'dist\' in your next.config.js');
|
|
574
|
-
const doContinue = await confirmC({ message: 'Do you want to continue?' });
|
|
575
|
-
if (!doContinue) {
|
|
576
|
-
const message = 'Build command selection aborted by user';
|
|
577
|
-
log.error(message);
|
|
578
|
-
throw new Error(message);
|
|
579
|
-
}
|
|
580
|
-
return 'build';
|
|
581
|
-
}
|
|
582
|
-
if (projectType === 'sveltekit') {
|
|
583
|
-
log.info('Sveltekit project detected');
|
|
584
|
-
log.warn('Please make sure you have the adapter-static installed: https://kit.svelte.dev/docs/adapter-static');
|
|
585
|
-
log.warn('Please make sure you have the pages: \'dist\' and assets: \'dest\', in your svelte.config.js adaptater');
|
|
586
|
-
const doContinue = await confirmC({ message: 'Do you want to continue?' });
|
|
587
|
-
if (!doContinue) {
|
|
588
|
-
const message = 'Build command selection aborted by user';
|
|
589
|
-
log.error(message);
|
|
590
|
-
throw new Error(message);
|
|
591
|
-
}
|
|
592
|
-
return 'build';
|
|
593
|
-
}
|
|
594
|
-
return 'build';
|
|
595
|
-
}
|
|
596
|
-
export async function findMainFile() {
|
|
597
|
-
// eslint-disable-next-line regexp/no-unused-capturing-group
|
|
598
|
-
const mainRegex = /(main|index)\.(ts|tsx|js|jsx)$/;
|
|
599
|
-
// search for main.ts or main.js in local dir and subdirs
|
|
600
|
-
let mainFile = '';
|
|
601
|
-
const pwd = cwd();
|
|
602
|
-
const pwdL = pwd.split('/').length;
|
|
603
|
-
for await (const f of getFiles(pwd)) {
|
|
604
|
-
// find number of folder in path after pwd
|
|
605
|
-
const folders = f.split('/').length - pwdL;
|
|
606
|
-
if (folders <= 2 && mainRegex.test(f)) {
|
|
607
|
-
mainFile = f;
|
|
608
|
-
log.info(`Found main file here ${f}`);
|
|
609
|
-
break;
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
return mainFile;
|
|
613
|
-
}
|
|
614
|
-
export async function updateOrCreateVersion(supabase, update) {
|
|
615
|
-
return supabase.from('app_versions')
|
|
616
|
-
.upsert(update, { onConflict: 'name,app_id' })
|
|
617
|
-
.eq('app_id', update.app_id)
|
|
618
|
-
.eq('name', update.name);
|
|
619
|
-
}
|
|
620
|
-
export async function uploadUrl(supabase, appId, name) {
|
|
621
|
-
const data = {
|
|
622
|
-
app_id: appId,
|
|
623
|
-
name,
|
|
624
|
-
version: 0,
|
|
625
|
-
};
|
|
626
|
-
try {
|
|
627
|
-
const pathUploadLink = 'files/upload_link';
|
|
628
|
-
const res = await supabase.functions.invoke(pathUploadLink, { body: JSON.stringify(data) });
|
|
629
|
-
if (res.error) {
|
|
630
|
-
// Handle error case
|
|
631
|
-
if (res.error instanceof FunctionsHttpError) {
|
|
632
|
-
const errorBody = await res.error.context.json();
|
|
633
|
-
log.error(`Upload URL error: ${errorBody.status || JSON.stringify(errorBody)}`);
|
|
634
|
-
}
|
|
635
|
-
else {
|
|
636
|
-
log.error(`Cannot get upload url: ${res.error.message}`);
|
|
637
|
-
}
|
|
638
|
-
return '';
|
|
639
|
-
}
|
|
640
|
-
return res.data.url;
|
|
641
|
-
}
|
|
642
|
-
catch (error) {
|
|
643
|
-
log.error(`Cannot get upload url ${formatError(error)}`);
|
|
644
|
-
}
|
|
645
|
-
return '';
|
|
646
|
-
}
|
|
647
|
-
async function* walkDirectory(dir) {
|
|
648
|
-
const entries = readdirSync(dir, { withFileTypes: true });
|
|
649
|
-
for (const entry of entries) {
|
|
650
|
-
const fullPath = join(dir, entry.name);
|
|
651
|
-
if (entry.isDirectory()) {
|
|
652
|
-
yield* walkDirectory(fullPath);
|
|
653
|
-
}
|
|
654
|
-
else {
|
|
655
|
-
yield fullPath;
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
export async function generateManifest(path) {
|
|
660
|
-
const allFiles = [];
|
|
661
|
-
const ignoredFiles = ['.DS_Store', '.git', '.gitignore', 'node_modules', 'package-lock.json', 'tsconfig.json', 'tsconfig.app.json', 'tsconfig.spec.json', 'tsconfig.app.json', 'tsconfig.spec.json', 'tsconfig.app.json', 'tsconfig.spec.json'];
|
|
662
|
-
for await (const file of walkDirectory(path)) {
|
|
663
|
-
if (ignoredFiles.some(ignoredFile => file.includes(ignoredFile))) {
|
|
664
|
-
log.info(`Ignoring file ${file}, please ensure you have only required files in your dist folder`);
|
|
665
|
-
continue;
|
|
666
|
-
}
|
|
667
|
-
const buffer = readFileSync(file);
|
|
668
|
-
// ignore files with size 0
|
|
669
|
-
if (buffer.length === 0) {
|
|
670
|
-
log.info(`Ignoring empty file ${file}, please ensure you have only required files in your dist folder`);
|
|
671
|
-
continue;
|
|
672
|
-
}
|
|
673
|
-
const hash = await getChecksum(buffer, 'sha256');
|
|
674
|
-
let filePath = relative(path, file);
|
|
675
|
-
if (filePath.startsWith('/'))
|
|
676
|
-
filePath = filePath.substring(1);
|
|
677
|
-
allFiles.push({ file: filePath, hash });
|
|
678
|
-
}
|
|
679
|
-
return allFiles;
|
|
680
|
-
}
|
|
681
|
-
export async function zipFile(filePath) {
|
|
682
|
-
if (osPlatform() === 'win32') {
|
|
683
|
-
return zipFileWindows(filePath);
|
|
684
|
-
}
|
|
685
|
-
else {
|
|
686
|
-
return zipFileUnix(filePath);
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
export function zipFileUnix(filePath) {
|
|
690
|
-
const zip = new AdmZip();
|
|
691
|
-
zip.addLocalFolder(filePath);
|
|
692
|
-
return zip.toBuffer();
|
|
693
|
-
}
|
|
694
|
-
export async function zipFileWindows(filePath) {
|
|
695
|
-
log.info('Zipping file windows mode');
|
|
696
|
-
const zip = new AdmZip();
|
|
697
|
-
const addToZip = (folderPath, zipPath) => {
|
|
698
|
-
const items = readdirSync(folderPath);
|
|
699
|
-
for (const item of items) {
|
|
700
|
-
const itemPath = join(folderPath, item);
|
|
701
|
-
const stats = statSync(itemPath);
|
|
702
|
-
if (stats.isFile()) {
|
|
703
|
-
const fileContent = readFileSync(itemPath);
|
|
704
|
-
zip.addFile(join(zipPath, item).split(sep).join('/'), fileContent);
|
|
705
|
-
}
|
|
706
|
-
else if (stats.isDirectory()) {
|
|
707
|
-
addToZip(itemPath, join(zipPath, item));
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
};
|
|
711
|
-
addToZip(filePath, '');
|
|
712
|
-
return zip.toBuffer();
|
|
713
|
-
}
|
|
714
|
-
export async function uploadTUS(apikey, data, orgId, appId, name, spinner, localConfig, chunkSize) {
|
|
715
|
-
return new Promise((resolve, reject) => {
|
|
716
|
-
sendEvent(apikey, {
|
|
717
|
-
channel: 'app',
|
|
718
|
-
event: 'App TUS upload',
|
|
719
|
-
icon: '⏫',
|
|
720
|
-
user_id: orgId,
|
|
721
|
-
tags: {
|
|
722
|
-
'app-id': appId,
|
|
723
|
-
},
|
|
724
|
-
notify: false,
|
|
725
|
-
});
|
|
726
|
-
const upload = new tus.Upload(data, {
|
|
727
|
-
endpoint: `${localConfig.hostFilesApi}/files/upload/attachments/`,
|
|
728
|
-
// parallelUploads: multipart,
|
|
729
|
-
chunkSize,
|
|
730
|
-
metadataForPartialUploads: {
|
|
731
|
-
filename: `orgs/${orgId}/apps/${appId}/${name}.zip`,
|
|
732
|
-
filetype: 'application/gzip',
|
|
733
|
-
},
|
|
734
|
-
metadata: {
|
|
735
|
-
filename: `orgs/${orgId}/apps/${appId}/${name}.zip`,
|
|
736
|
-
filetype: 'application/zip',
|
|
737
|
-
},
|
|
738
|
-
headers: {
|
|
739
|
-
Authorization: apikey,
|
|
740
|
-
},
|
|
741
|
-
// Callback for errors which cannot be fixed using retries
|
|
742
|
-
onError(error) {
|
|
743
|
-
log.error(`Error uploading bundle: ${error.message}`);
|
|
744
|
-
if (error instanceof tus.DetailedError) {
|
|
745
|
-
const body = error.originalResponse?.getBody();
|
|
746
|
-
const jsonBody = JSON.parse(body || '{"error": "unknown error"}');
|
|
747
|
-
reject(jsonBody.status || jsonBody.error || jsonBody.message || 'unknown error');
|
|
748
|
-
}
|
|
749
|
-
else {
|
|
750
|
-
reject(error.message || error.toString() || 'unknown error');
|
|
751
|
-
}
|
|
752
|
-
},
|
|
753
|
-
// Callback for reporting upload progress
|
|
754
|
-
onProgress(bytesUploaded, bytesTotal) {
|
|
755
|
-
const percentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2);
|
|
756
|
-
spinner.message(`Uploaded ${percentage}%`);
|
|
757
|
-
},
|
|
758
|
-
// Callback for once the upload is completed
|
|
759
|
-
async onSuccess() {
|
|
760
|
-
await sendEvent(apikey, {
|
|
761
|
-
channel: 'app',
|
|
762
|
-
event: 'App TUS done',
|
|
763
|
-
icon: '⏫',
|
|
764
|
-
user_id: orgId,
|
|
765
|
-
tags: {
|
|
766
|
-
'app-id': appId,
|
|
767
|
-
},
|
|
768
|
-
notify: false,
|
|
769
|
-
}).catch();
|
|
770
|
-
resolve(true);
|
|
771
|
-
},
|
|
772
|
-
});
|
|
773
|
-
// Start the upload
|
|
774
|
-
upload.start();
|
|
775
|
-
});
|
|
776
|
-
}
|
|
777
|
-
export async function deletedFailedVersion(supabase, appId, name) {
|
|
778
|
-
const data = {
|
|
779
|
-
app_id: appId,
|
|
780
|
-
name,
|
|
781
|
-
};
|
|
782
|
-
try {
|
|
783
|
-
const pathFailed = 'private/delete_failed_version';
|
|
784
|
-
const res = await supabase.functions.invoke(pathFailed, { body: JSON.stringify(data), method: 'DELETE' });
|
|
785
|
-
if (res.error) {
|
|
786
|
-
if (res.error instanceof FunctionsHttpError) {
|
|
787
|
-
const errorBody = await res.error.context.json();
|
|
788
|
-
log.error(`Cannot delete failed version: ${errorBody.status || JSON.stringify(errorBody)}`);
|
|
789
|
-
}
|
|
790
|
-
else {
|
|
791
|
-
log.error(`Cannot delete failed version: ${res.error.message}`);
|
|
792
|
-
}
|
|
793
|
-
return;
|
|
794
|
-
}
|
|
795
|
-
return res.data?.status;
|
|
796
|
-
}
|
|
797
|
-
catch (error) {
|
|
798
|
-
if (error instanceof FunctionsHttpError) {
|
|
799
|
-
const errorBody = await error.context.json();
|
|
800
|
-
log.error(`Cannot delete failed version: ${errorBody.message || JSON.stringify(errorBody)}`);
|
|
801
|
-
}
|
|
802
|
-
else {
|
|
803
|
-
log.error(`Cannot delete failed version: ${formatError(error)}`);
|
|
804
|
-
}
|
|
805
|
-
}
|
|
806
|
-
}
|
|
807
|
-
export async function updateOrCreateChannel(supabase, update) {
|
|
808
|
-
// console.log('updateOrCreateChannel', update)
|
|
809
|
-
if (!update.app_id || !update.name || !update.created_by) {
|
|
810
|
-
log.error('missing app_id, name, or created_by');
|
|
811
|
-
return Promise.reject(new Error('missing app_id, name, or created_by'));
|
|
812
|
-
}
|
|
813
|
-
const { data, error } = await supabase
|
|
814
|
-
.from('channels')
|
|
815
|
-
.select()
|
|
816
|
-
.eq('app_id', update.app_id)
|
|
817
|
-
.eq('name', update.name)
|
|
818
|
-
.single();
|
|
819
|
-
if (data && !error) {
|
|
820
|
-
return supabase
|
|
821
|
-
.from('channels')
|
|
822
|
-
.update(update)
|
|
823
|
-
.eq('app_id', update.app_id)
|
|
824
|
-
.eq('name', update.name)
|
|
825
|
-
.select()
|
|
826
|
-
.single();
|
|
827
|
-
}
|
|
828
|
-
return supabase
|
|
829
|
-
.from('channels')
|
|
830
|
-
.insert(update)
|
|
831
|
-
.select()
|
|
832
|
-
.single();
|
|
833
|
-
}
|
|
834
|
-
export async function sendEvent(capgkey, payload) {
|
|
835
|
-
try {
|
|
836
|
-
const config = await getRemoteConfig();
|
|
837
|
-
const response = await ky.post(`${config.hostApi}/private/events`, {
|
|
838
|
-
json: payload,
|
|
839
|
-
headers: {
|
|
840
|
-
capgkey,
|
|
841
|
-
},
|
|
842
|
-
timeout: 10000, // 10 seconds timeout
|
|
843
|
-
retry: 3,
|
|
844
|
-
}).json();
|
|
845
|
-
if (response.error) {
|
|
846
|
-
log.error(`Failed to send LogSnag event: ${response.error}`);
|
|
847
|
-
}
|
|
848
|
-
}
|
|
849
|
-
catch {
|
|
850
|
-
}
|
|
851
|
-
}
|
|
852
|
-
export async function getOrganization(supabase, roles) {
|
|
853
|
-
const { error: orgError, data: allOrganizations } = await supabase
|
|
854
|
-
.rpc('get_orgs_v6');
|
|
855
|
-
if (orgError) {
|
|
856
|
-
log.error('Cannot get the list of organizations - exiting');
|
|
857
|
-
log.error(`Error ${JSON.stringify(orgError)}`);
|
|
858
|
-
throw new Error('Cannot get the list of organizations');
|
|
859
|
-
}
|
|
860
|
-
const adminOrgs = allOrganizations.filter(org => !!roles.find(role => role === org.role));
|
|
861
|
-
if (allOrganizations.length === 0) {
|
|
862
|
-
log.error('Could not get organization please create an organization first');
|
|
863
|
-
throw new Error('No organizations available');
|
|
864
|
-
}
|
|
865
|
-
if (adminOrgs.length === 0) {
|
|
866
|
-
log.error(`Could not find organization with roles: ${roles.join(' or ')} please create an organization or ask the admin to add you to the organization with this roles`);
|
|
867
|
-
throw new Error('Could not find organization with required roles');
|
|
868
|
-
}
|
|
869
|
-
const organizationUidRaw = (adminOrgs.length > 1)
|
|
870
|
-
? await select({
|
|
871
|
-
message: 'Please pick the organization that you want to insert to',
|
|
872
|
-
options: adminOrgs.map((org) => {
|
|
873
|
-
return { value: org.gid, label: org.name };
|
|
874
|
-
}),
|
|
875
|
-
})
|
|
876
|
-
: adminOrgs[0].gid;
|
|
877
|
-
if (isCancel(organizationUidRaw)) {
|
|
878
|
-
log.error('Canceled organization selection, exiting');
|
|
879
|
-
throw new Error('Organization selection cancelled');
|
|
880
|
-
}
|
|
881
|
-
const organizationUid = organizationUidRaw;
|
|
882
|
-
const organization = allOrganizations.find(org => org.gid === organizationUid);
|
|
883
|
-
log.info(`Using the organization "${organization.name}" as the app owner`);
|
|
884
|
-
return organization;
|
|
885
|
-
}
|
|
886
|
-
export async function verifyUser(supabase, apikey, keymod = ['all']) {
|
|
887
|
-
await checkKey(supabase, apikey, keymod);
|
|
888
|
-
const { data: dataUser, error: userIdError } = await supabase
|
|
889
|
-
.rpc('get_user_id', { apikey })
|
|
890
|
-
.single();
|
|
891
|
-
const userId = (dataUser || '').toString();
|
|
892
|
-
if (!userId || userIdError) {
|
|
893
|
-
log.error(`Cannot auth user with apikey`);
|
|
894
|
-
throw new Error('Cannot authenticate user with provided API key');
|
|
895
|
-
}
|
|
896
|
-
return userId;
|
|
897
|
-
}
|
|
898
|
-
export async function getOrganizationId(supabase, appId) {
|
|
899
|
-
const { data, error } = await supabase.from('apps')
|
|
900
|
-
.select('owner_org')
|
|
901
|
-
.eq('app_id', appId)
|
|
902
|
-
.single();
|
|
903
|
-
if (!data || error) {
|
|
904
|
-
log.error(`Cannot get organization id for app id ${appId}`);
|
|
905
|
-
formatError(error);
|
|
906
|
-
throw new Error(`Cannot get organization id for app id ${appId}`);
|
|
907
|
-
}
|
|
908
|
-
return data.owner_org;
|
|
909
|
-
}
|
|
910
|
-
export async function requireUpdateMetadata(supabase, channel, appId) {
|
|
911
|
-
const { data, error } = await supabase
|
|
912
|
-
.from('channels')
|
|
913
|
-
.select('disable_auto_update')
|
|
914
|
-
.eq('name', channel)
|
|
915
|
-
.eq('app_id', appId)
|
|
916
|
-
.limit(1);
|
|
917
|
-
if (error) {
|
|
918
|
-
log.error(`Cannot check if disableAutoUpdate is required ${formatError(error)}`);
|
|
919
|
-
throw new Error('Cannot check if disableAutoUpdate is required');
|
|
920
|
-
}
|
|
921
|
-
// Channel does not exist and the default is never 'version_number'
|
|
922
|
-
if (data.length === 0)
|
|
923
|
-
return false;
|
|
924
|
-
const { disable_auto_update } = (data[0]);
|
|
925
|
-
return disable_auto_update === 'version_number';
|
|
926
|
-
}
|
|
927
|
-
export function getHumanDate(createdA) {
|
|
928
|
-
const date = new Date(createdA || '');
|
|
929
|
-
return date.toLocaleString();
|
|
930
|
-
}
|
|
931
|
-
let pmFetched = false;
|
|
932
|
-
let pm = 'npm';
|
|
933
|
-
let pmCommand = 'install';
|
|
934
|
-
let pmRunner = 'npx';
|
|
935
|
-
export function getPMAndCommand() {
|
|
936
|
-
if (pmFetched)
|
|
937
|
-
return { pm, command: pmCommand, installCommand: `${pm} ${pmCommand}`, runner: pmRunner };
|
|
938
|
-
const dir = findRoot(cwd());
|
|
939
|
-
pm = findPackageManagerType(dir, 'npm');
|
|
940
|
-
pmCommand = findInstallCommand(pm);
|
|
941
|
-
pmFetched = true;
|
|
942
|
-
pmRunner = findPackageManagerRunner(dir);
|
|
943
|
-
return { pm, command: pmCommand, installCommand: `${pm} ${pmCommand}`, runner: pmRunner };
|
|
944
|
-
}
|
|
945
|
-
function readDirRecursively(dir) {
|
|
946
|
-
const entries = readdirSync(dir, { withFileTypes: true });
|
|
947
|
-
const files = entries.flatMap((entry) => {
|
|
948
|
-
const fullPath = join(dir, entry.name);
|
|
949
|
-
if (entry.isDirectory()) {
|
|
950
|
-
return readDirRecursively(fullPath);
|
|
951
|
-
}
|
|
952
|
-
else {
|
|
953
|
-
// Use relative path to avoid issues with long paths on Windows
|
|
954
|
-
return fullPath.split(`node_modules${sep}`)[1] || fullPath;
|
|
955
|
-
}
|
|
956
|
-
});
|
|
957
|
-
return files;
|
|
958
|
-
}
|
|
959
|
-
export async function getLocalDepenencies(packageJsonPath, nodeModulesString) {
|
|
960
|
-
const nodeModules = nodeModulesString ? nodeModulesString.split(',') : [];
|
|
961
|
-
let dependencies;
|
|
962
|
-
try {
|
|
963
|
-
dependencies = await getAllPackagesDependencies('', packageJsonPath);
|
|
964
|
-
}
|
|
965
|
-
catch (err) {
|
|
966
|
-
log.error('Invalid package.json, JSON parsing failed');
|
|
967
|
-
console.error('json parse error: ', err);
|
|
968
|
-
throw err instanceof Error ? err : new Error('Invalid package.json');
|
|
969
|
-
}
|
|
970
|
-
const firstPackageJson = packageJsonPath?.split(',')[0];
|
|
971
|
-
const dir = !firstPackageJson ? findRoot(cwd()) : path.resolve(firstPackageJson).replace(PACKNAME, '');
|
|
972
|
-
if (!dependencies) {
|
|
973
|
-
log.error('Missing dependencies section in package.json');
|
|
974
|
-
throw new Error('Missing dependencies section in package.json');
|
|
975
|
-
}
|
|
976
|
-
for (const [key, value] of Object.entries(dependencies)) {
|
|
977
|
-
if (typeof value !== 'string') {
|
|
978
|
-
log.error(`Invalid dependency ${key}: ${value}, expected string, got ${typeof value}`);
|
|
979
|
-
throw new Error(`Invalid dependency ${key}: expected string version`);
|
|
980
|
-
}
|
|
981
|
-
}
|
|
982
|
-
const nodeModulesPaths = nodeModules.length === 0
|
|
983
|
-
? [join(cwd(), 'node_modules')]
|
|
984
|
-
: nodeModules;
|
|
985
|
-
const anyValidPath = nodeModulesPaths.some(path => existsSync(path));
|
|
986
|
-
if (!anyValidPath) {
|
|
987
|
-
const pm = findPackageManagerType(dir, 'npm');
|
|
988
|
-
const installCmd = findInstallCommand(pm);
|
|
989
|
-
log.error(`Missing node_modules folder at ${nodeModulesPaths.join(', ')}, please run ${pm} ${installCmd}`);
|
|
990
|
-
throw new Error('Missing node_modules folder');
|
|
991
|
-
}
|
|
992
|
-
let anyInvalid = false;
|
|
993
|
-
const dependenciesObject = await Promise.all(Array.from(dependencies.entries())
|
|
994
|
-
.map(async ([key, value]) => {
|
|
995
|
-
let dependencyFound = false;
|
|
996
|
-
let hasNativeFiles = false;
|
|
997
|
-
for (const modulePath of nodeModulesPaths) {
|
|
998
|
-
const dependencyFolderPath = join(modulePath, key);
|
|
999
|
-
if (existsSync(dependencyFolderPath)) {
|
|
1000
|
-
dependencyFound = true;
|
|
1001
|
-
try {
|
|
1002
|
-
const files = readDirRecursively(dependencyFolderPath);
|
|
1003
|
-
if (files.some(fileName => nativeFileRegex.test(fileName))) {
|
|
1004
|
-
hasNativeFiles = true;
|
|
1005
|
-
break;
|
|
1006
|
-
}
|
|
1007
|
-
}
|
|
1008
|
-
catch (error) {
|
|
1009
|
-
log.error(`Error reading node_modules files for ${key} package in ${modulePath}`);
|
|
1010
|
-
console.error(error);
|
|
1011
|
-
throw error instanceof Error ? error : new Error(`Error reading node_modules files for ${key}`);
|
|
1012
|
-
}
|
|
1013
|
-
}
|
|
1014
|
-
}
|
|
1015
|
-
if (!dependencyFound) {
|
|
1016
|
-
anyInvalid = true;
|
|
1017
|
-
const pm = findPackageManagerType(dir, 'npm');
|
|
1018
|
-
const installCmd = findInstallCommand(pm);
|
|
1019
|
-
log.error(`Missing dependency ${key}, please run ${pm} ${installCmd}`);
|
|
1020
|
-
return { name: key, version: value };
|
|
1021
|
-
}
|
|
1022
|
-
return {
|
|
1023
|
-
name: key,
|
|
1024
|
-
version: value,
|
|
1025
|
-
native: hasNativeFiles,
|
|
1026
|
-
};
|
|
1027
|
-
})).catch(() => []);
|
|
1028
|
-
if (anyInvalid || dependenciesObject.find(a => a.native === undefined)) {
|
|
1029
|
-
log.error('Missing dependencies or invalid dependencies');
|
|
1030
|
-
log.error('If you use monorepo, workspace or any special package manager you can use the --package-json [path,] and --node-modules [path,] options to make the command work properly');
|
|
1031
|
-
throw new Error('Missing dependencies or invalid dependencies');
|
|
1032
|
-
}
|
|
1033
|
-
return dependenciesObject;
|
|
1034
|
-
}
|
|
1035
|
-
export async function getRemoteChecksums(supabase, appId, channel) {
|
|
1036
|
-
const { data, error } = await supabase
|
|
1037
|
-
.from('channels')
|
|
1038
|
-
.select(`version(checksum)`)
|
|
1039
|
-
.eq('name', channel)
|
|
1040
|
-
.eq('app_id', appId)
|
|
1041
|
-
.single();
|
|
1042
|
-
const channelData = data;
|
|
1043
|
-
if (error
|
|
1044
|
-
|| channelData === null
|
|
1045
|
-
|| !channelData.version
|
|
1046
|
-
|| !channelData.version.checksum) {
|
|
1047
|
-
return null;
|
|
1048
|
-
}
|
|
1049
|
-
return channelData.version.checksum;
|
|
1050
|
-
}
|
|
1051
|
-
export function convertNativePackages(nativePackages) {
|
|
1052
|
-
if (!nativePackages) {
|
|
1053
|
-
log.error(`Error parsing native packages, perhaps the metadata does not exist in Capgo?`);
|
|
1054
|
-
throw new Error('Error parsing native packages');
|
|
1055
|
-
}
|
|
1056
|
-
// Check types
|
|
1057
|
-
for (const data of nativePackages) {
|
|
1058
|
-
if (typeof data !== 'object') {
|
|
1059
|
-
log.error(`Invalid remote native package data: ${data}, expected object, got ${typeof data}`);
|
|
1060
|
-
throw new Error('Invalid remote native package data');
|
|
1061
|
-
}
|
|
1062
|
-
const { name, version } = data;
|
|
1063
|
-
if (!name || typeof name !== 'string') {
|
|
1064
|
-
log.error(`Invalid remote native package name: ${name}, expected string, got ${typeof name}`);
|
|
1065
|
-
throw new Error('Invalid remote native package name');
|
|
1066
|
-
}
|
|
1067
|
-
if (!version || typeof version !== 'string') {
|
|
1068
|
-
log.error(`Invalid remote native package version: ${version}, expected string, got ${typeof version}`);
|
|
1069
|
-
throw new Error('Invalid remote native package version');
|
|
1070
|
-
}
|
|
1071
|
-
}
|
|
1072
|
-
const mappedRemoteNativePackages = new Map((nativePackages)
|
|
1073
|
-
.map(a => [a.name, a]));
|
|
1074
|
-
return mappedRemoteNativePackages;
|
|
1075
|
-
}
|
|
1076
|
-
export async function getRemoteDepenencies(supabase, appId, channel) {
|
|
1077
|
-
const { data: remoteNativePackages, error } = await supabase
|
|
1078
|
-
.from('channels')
|
|
1079
|
-
.select(`version (
|
|
1080
|
-
native_packages
|
|
1081
|
-
)`)
|
|
1082
|
-
.eq('name', channel)
|
|
1083
|
-
.eq('app_id', appId)
|
|
1084
|
-
.single();
|
|
1085
|
-
if (error) {
|
|
1086
|
-
log.error(`Error fetching native packages: ${error.message}`);
|
|
1087
|
-
throw new Error(`Error fetching native packages: ${error.message}`);
|
|
1088
|
-
}
|
|
1089
|
-
return convertNativePackages(remoteNativePackages.version.native_packages ?? []);
|
|
1090
|
-
}
|
|
1091
|
-
export async function checkChecksum(supabase, appId, channel, currentChecksum) {
|
|
1092
|
-
const s = spinnerC();
|
|
1093
|
-
s.start(`Checking bundle checksum compatibility with channel ${channel}`);
|
|
1094
|
-
const remoteChecksum = await getRemoteChecksums(supabase, appId, channel);
|
|
1095
|
-
if (!remoteChecksum) {
|
|
1096
|
-
s.stop(`No checksum found for channel ${channel}, the bundle will be uploaded`);
|
|
1097
|
-
return;
|
|
1098
|
-
}
|
|
1099
|
-
if (remoteChecksum && remoteChecksum === currentChecksum) {
|
|
1100
|
-
// cannot upload the same bundle
|
|
1101
|
-
log.error(`Cannot upload the same bundle content.\nCurrent bundle checksum matches remote bundle for channel ${channel}\nDid you builded your app before uploading?\nPS: You can ignore this check with "--ignore-checksum-check"`);
|
|
1102
|
-
throw new Error('Cannot upload the same bundle content');
|
|
1103
|
-
}
|
|
1104
|
-
s.stop(`Checksum compatible with ${channel} channel`);
|
|
1105
|
-
}
|
|
1106
|
-
export function getAppId(appId, config) {
|
|
1107
|
-
const finalAppId = appId || config?.plugins?.CapacitorUpdater?.appId || config?.appId;
|
|
1108
|
-
return finalAppId;
|
|
1109
|
-
}
|
|
1110
|
-
export function isCompatible(pkg) {
|
|
1111
|
-
// Only check compatibility if there's a local version
|
|
1112
|
-
// If there's a local version but no remote version, or versions don't match, it's incompatible
|
|
1113
|
-
if (!pkg.localVersion)
|
|
1114
|
-
return true; // If no local version, it's compatible (remote-only package)
|
|
1115
|
-
if (!pkg.remoteVersion)
|
|
1116
|
-
return false; // If local version but no remote version, it's incompatible
|
|
1117
|
-
try {
|
|
1118
|
-
return subset(pkg.localVersion, pkg.remoteVersion);
|
|
1119
|
-
}
|
|
1120
|
-
catch {
|
|
1121
|
-
return false; // If version comparison fails, consider it incompatible
|
|
1122
|
-
}
|
|
1123
|
-
}
|
|
1124
|
-
export async function checkCompatibility(supabase, appId, channel, packageJsonPath, nodeModules) {
|
|
1125
|
-
const dependenciesObject = await getLocalDepenencies(packageJsonPath, nodeModules);
|
|
1126
|
-
const mappedRemoteNativePackages = await getRemoteDepenencies(supabase, appId, channel);
|
|
1127
|
-
const finalDepenencies = dependenciesObject
|
|
1128
|
-
.filter(a => !!a.native)
|
|
1129
|
-
.map((local) => {
|
|
1130
|
-
const remotePackage = mappedRemoteNativePackages.get(local.name);
|
|
1131
|
-
if (remotePackage) {
|
|
1132
|
-
return {
|
|
1133
|
-
name: local.name,
|
|
1134
|
-
localVersion: local.version,
|
|
1135
|
-
remoteVersion: remotePackage.version,
|
|
1136
|
-
};
|
|
1137
|
-
}
|
|
1138
|
-
return {
|
|
1139
|
-
name: local.name,
|
|
1140
|
-
localVersion: local.version,
|
|
1141
|
-
remoteVersion: undefined,
|
|
1142
|
-
};
|
|
1143
|
-
});
|
|
1144
|
-
// Only include remote packages that are not in local for informational purposes
|
|
1145
|
-
// These won't affect compatibility
|
|
1146
|
-
const removeNotInLocal = [...mappedRemoteNativePackages]
|
|
1147
|
-
.filter(([remoteName]) => dependenciesObject.find(a => a.name === remoteName) === undefined)
|
|
1148
|
-
.map(([name, version]) => ({ name, localVersion: undefined, remoteVersion: version.version }));
|
|
1149
|
-
finalDepenencies.push(...removeNotInLocal);
|
|
1150
|
-
return {
|
|
1151
|
-
finalCompatibility: finalDepenencies,
|
|
1152
|
-
localDependencies: dependenciesObject,
|
|
1153
|
-
};
|
|
1154
|
-
}
|
|
1155
|
-
export async function checkCompatibilityNativePackages(supabase, appId, channel, nativePackages) {
|
|
1156
|
-
const mappedRemoteNativePackages = await getRemoteDepenencies(supabase, appId, channel);
|
|
1157
|
-
const finalDepenencies = nativePackages
|
|
1158
|
-
.map((local) => {
|
|
1159
|
-
const remotePackage = mappedRemoteNativePackages.get(local.name);
|
|
1160
|
-
if (remotePackage) {
|
|
1161
|
-
return {
|
|
1162
|
-
name: local.name,
|
|
1163
|
-
localVersion: local.version,
|
|
1164
|
-
remoteVersion: remotePackage.version,
|
|
1165
|
-
};
|
|
1166
|
-
}
|
|
1167
|
-
return {
|
|
1168
|
-
name: local.name,
|
|
1169
|
-
localVersion: local.version,
|
|
1170
|
-
remoteVersion: undefined,
|
|
1171
|
-
};
|
|
1172
|
-
});
|
|
1173
|
-
// Only include remote packages that are not in local for informational purposes
|
|
1174
|
-
// These won't affect compatibility
|
|
1175
|
-
const removeNotInLocal = [...mappedRemoteNativePackages]
|
|
1176
|
-
.filter(([remoteName]) => nativePackages.find(a => a.name === remoteName) === undefined)
|
|
1177
|
-
.map(([name, version]) => ({ name, localVersion: undefined, remoteVersion: version.version }));
|
|
1178
|
-
finalDepenencies.push(...removeNotInLocal);
|
|
1179
|
-
return {
|
|
1180
|
-
finalCompatibility: finalDepenencies,
|
|
1181
|
-
localDependencies: nativePackages,
|
|
1182
|
-
};
|
|
1183
|
-
}
|
|
1184
|
-
//# sourceMappingURL=utils.js.map
|