@capgo/cli 4.10.3 → 4.10.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/dist/index.js +48 -24
- package/package.json +1 -1
- package/src/api/channels.ts +21 -4
- package/src/app/add.ts +3 -3
- package/src/app/delete.ts +11 -8
- package/src/bundle/upload.ts +5 -5
- package/src/channel/add.ts +2 -2
- package/src/channel/delete.ts +3 -2
- package/src/channel/set.ts +1 -2
- package/src/utils.ts +22 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,29 @@
|
|
|
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.10.7](https://github.com/Cap-go/CLI/compare/v4.10.6...v4.10.7) (2024-05-27)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* add snag for multipart upload ([eef8d38](https://github.com/Cap-go/CLI/commit/eef8d38d01bc7b25def9d5e9995ec3ae5acfc8cf))
|
|
11
|
+
|
|
12
|
+
### [4.10.6](https://github.com/Cap-go/CLI/compare/v4.10.5...v4.10.6) (2024-05-24)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* userId in logsnag ([b4f0cef](https://github.com/Cap-go/CLI/commit/b4f0cefd4e4f3366e5e8e6698f7c7b7b907eebba))
|
|
18
|
+
|
|
19
|
+
### [4.10.5](https://github.com/Cap-go/CLI/compare/v4.10.4...v4.10.5) (2024-05-21)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Bug Fixes
|
|
23
|
+
|
|
24
|
+
* issue returning channel list ([aee3ed5](https://github.com/Cap-go/CLI/commit/aee3ed5cb011c10854f8a7806f69a80d10b389ac))
|
|
25
|
+
|
|
26
|
+
### [4.10.4](https://github.com/Cap-go/CLI/compare/v4.10.3...v4.10.4) (2024-05-15)
|
|
27
|
+
|
|
5
28
|
### [4.10.3](https://github.com/Cap-go/CLI/compare/v4.10.2...v4.10.3) (2024-05-14)
|
|
6
29
|
|
|
7
30
|
|
package/dist/index.js
CHANGED
|
@@ -109493,8 +109493,19 @@ async function finishMultipartDownload(key2, uploadId, url, parts) {
|
|
|
109493
109493
|
});
|
|
109494
109494
|
}
|
|
109495
109495
|
var PART_SIZE = 10 * 1024 * 1024;
|
|
109496
|
-
async function uploadMultipart(supabase, appId, name, data) {
|
|
109496
|
+
async function uploadMultipart(supabase, appId, name, data, orgId) {
|
|
109497
109497
|
try {
|
|
109498
|
+
const snag = useLogSnag();
|
|
109499
|
+
await snag.track({
|
|
109500
|
+
channel: "app",
|
|
109501
|
+
event: "App Multipart Prepare",
|
|
109502
|
+
icon: "\u23EB",
|
|
109503
|
+
user_id: orgId,
|
|
109504
|
+
tags: {
|
|
109505
|
+
"app-id": appId
|
|
109506
|
+
},
|
|
109507
|
+
notify: false
|
|
109508
|
+
}).catch();
|
|
109498
109509
|
const multipartPrep = await prepareMultipart(supabase, appId, name);
|
|
109499
109510
|
if (!multipartPrep) {
|
|
109500
109511
|
return false;
|
|
@@ -109504,6 +109515,16 @@ async function uploadMultipart(supabase, appId, name, data) {
|
|
|
109504
109515
|
const uploadPromises = Array.from({ length: partCount }, (_3, index) => uploadPart(data, PART_SIZE, multipartPrep.url, multipartPrep.key, multipartPrep.uploadId, index));
|
|
109505
109516
|
const parts = await Promise.all(uploadPromises);
|
|
109506
109517
|
await finishMultipartDownload(multipartPrep.key, multipartPrep.uploadId, multipartPrep.url, parts);
|
|
109518
|
+
await snag.track({
|
|
109519
|
+
channel: "app",
|
|
109520
|
+
event: "App Multipart done",
|
|
109521
|
+
icon: "\u23EB",
|
|
109522
|
+
user_id: orgId,
|
|
109523
|
+
tags: {
|
|
109524
|
+
"app-id": appId
|
|
109525
|
+
},
|
|
109526
|
+
notify: false
|
|
109527
|
+
}).catch();
|
|
109507
109528
|
return true;
|
|
109508
109529
|
} catch (e2) {
|
|
109509
109530
|
f2.error(`Could not upload via multipart ${formatError(e2)}`);
|
|
@@ -109783,7 +109804,7 @@ async function getUserId(options) {
|
|
|
109783
109804
|
// package.json
|
|
109784
109805
|
var package_default = {
|
|
109785
109806
|
name: "@capgo/cli",
|
|
109786
|
-
version: "4.10.
|
|
109807
|
+
version: "4.10.7",
|
|
109787
109808
|
description: "A CLI to upload to capgo servers",
|
|
109788
109809
|
author: "github.com/riderx",
|
|
109789
109810
|
license: "Apache 2.0",
|
|
@@ -110449,8 +110470,8 @@ function displayChannels(data) {
|
|
|
110449
110470
|
"Name": row.name,
|
|
110450
110471
|
...row.version ? { Version: row.version.name } : void 0,
|
|
110451
110472
|
"Public": row.public ? "\u2705" : "\u274C",
|
|
110452
|
-
"iOS": row.ios ? "\
|
|
110453
|
-
"Android": row.android ? "\
|
|
110473
|
+
"iOS": row.ios ? "\u2705" : "\u274C",
|
|
110474
|
+
"Android": row.android ? "\u2705" : "\u274C",
|
|
110454
110475
|
"\u2B06\uFE0F limit": row.disableAutoUpdate,
|
|
110455
110476
|
"\u2B07\uFE0F under native": row.disableAutoUpdateUnderNative ? "\u274C" : "\u2705",
|
|
110456
110477
|
"Self assign": row.allow_device_self_set ? "\u2705" : "\u274C",
|
|
@@ -110510,7 +110531,7 @@ async function addChannel(channelId, appId, options, shouldExit = true) {
|
|
|
110510
110531
|
program.error("");
|
|
110511
110532
|
}
|
|
110512
110533
|
const supabase = await createSupabaseClient(options.apikey);
|
|
110513
|
-
|
|
110534
|
+
await verifyUser(supabase, options.apikey, ["write", "all"]);
|
|
110514
110535
|
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, 4 /* admin */);
|
|
110515
110536
|
f2.info(`Creating channel ${appId}#${channelId} to Capgo`);
|
|
110516
110537
|
try {
|
|
@@ -110531,7 +110552,7 @@ async function addChannel(channelId, appId, options, shouldExit = true) {
|
|
|
110531
110552
|
channel: "channel",
|
|
110532
110553
|
event: "Create channel",
|
|
110533
110554
|
icon: "\u2705",
|
|
110534
|
-
user_id:
|
|
110555
|
+
user_id: orgId,
|
|
110535
110556
|
tags: {
|
|
110536
110557
|
"app-id": appId,
|
|
110537
110558
|
"channel": channelId
|
|
@@ -110730,7 +110751,7 @@ Trial expires in ${isTrial} days`);
|
|
|
110730
110751
|
channel: "app",
|
|
110731
110752
|
event: "App encryption",
|
|
110732
110753
|
icon: "\u{1F511}",
|
|
110733
|
-
user_id:
|
|
110754
|
+
user_id: orgId,
|
|
110734
110755
|
tags: {
|
|
110735
110756
|
"app-id": appid
|
|
110736
110757
|
},
|
|
@@ -110762,7 +110783,7 @@ The app size is ${mbSize} Mb, this may take a while to download for users
|
|
|
110762
110783
|
channel: "app-error",
|
|
110763
110784
|
event: "App Too Large",
|
|
110764
110785
|
icon: "\u{1F69B}",
|
|
110765
|
-
user_id:
|
|
110786
|
+
user_id: orgId,
|
|
110766
110787
|
tags: {
|
|
110767
110788
|
"app-id": appid
|
|
110768
110789
|
},
|
|
@@ -110786,7 +110807,7 @@ The app size is ${mbSize} Mb, this may take a while to download for users
|
|
|
110786
110807
|
channel: "app",
|
|
110787
110808
|
event: "App external",
|
|
110788
110809
|
icon: "\u{1F4E4}",
|
|
110789
|
-
user_id:
|
|
110810
|
+
user_id: orgId,
|
|
110790
110811
|
tags: {
|
|
110791
110812
|
"app-id": appid
|
|
110792
110813
|
},
|
|
@@ -110820,7 +110841,7 @@ The app size is ${mbSize} Mb, this may take a while to download for users
|
|
|
110820
110841
|
const startTime = import_node_perf_hooks.performance.now();
|
|
110821
110842
|
try {
|
|
110822
110843
|
if (options.multipart !== void 0 && options.multipart) {
|
|
110823
|
-
await uploadMultipart(supabase, appid, bundle2, zipped);
|
|
110844
|
+
await uploadMultipart(supabase, appid, bundle2, zipped, orgId);
|
|
110824
110845
|
} else {
|
|
110825
110846
|
const url = await uploadUrl(supabase, appid, bundle2);
|
|
110826
110847
|
if (!url) {
|
|
@@ -110913,7 +110934,7 @@ The app size is ${mbSize} Mb, this may take a while to download for users
|
|
|
110913
110934
|
channel: "app",
|
|
110914
110935
|
event: "App Uploaded",
|
|
110915
110936
|
icon: "\u23EB",
|
|
110916
|
-
user_id:
|
|
110937
|
+
user_id: orgId,
|
|
110917
110938
|
tags: {
|
|
110918
110939
|
"app-id": appid
|
|
110919
110940
|
},
|
|
@@ -111004,7 +111025,6 @@ async function loginCommand(apikey, options) {
|
|
|
111004
111025
|
}
|
|
111005
111026
|
|
|
111006
111027
|
// src/app/add.ts
|
|
111007
|
-
var import_node_crypto4 = require("node:crypto");
|
|
111008
111028
|
var import_node_fs10 = require("node:fs");
|
|
111009
111029
|
var import_node_process15 = __toESM(require("node:process"));
|
|
111010
111030
|
|
|
@@ -111168,13 +111188,14 @@ async function addAppInternal(appId, options, organization, throwErr = true) {
|
|
|
111168
111188
|
} else {
|
|
111169
111189
|
f2.warn(`Cannot find app icon in any of the following locations: ${icon}, ${newIconPath}`);
|
|
111170
111190
|
}
|
|
111171
|
-
const fileName = `
|
|
111191
|
+
const fileName = `icon`;
|
|
111172
111192
|
let signedURL = "https://xvwzpoazmxkqosrdewyv.supabase.co/storage/v1/object/public/images/capgo.png";
|
|
111173
111193
|
if (iconBuff && iconType) {
|
|
111174
|
-
const { error } = await supabase.storage.from(`images/${
|
|
111194
|
+
const { error } = await supabase.storage.from(`images/org/${organizationUid}/${appId}`).upload(fileName, iconBuff, {
|
|
111175
111195
|
contentType: iconType
|
|
111176
111196
|
});
|
|
111177
111197
|
if (error) {
|
|
111198
|
+
console.error(error);
|
|
111178
111199
|
f2.error(`Could not add app ${formatError(error)}`);
|
|
111179
111200
|
program.error("");
|
|
111180
111201
|
}
|
|
@@ -111897,9 +111918,8 @@ async function setChannel(channel2, appId, options) {
|
|
|
111897
111918
|
channel: "channel",
|
|
111898
111919
|
event: "Set channel",
|
|
111899
111920
|
icon: "\u2705",
|
|
111900
|
-
user_id:
|
|
111921
|
+
user_id: orgId,
|
|
111901
111922
|
tags: {
|
|
111902
|
-
"user-id": userId,
|
|
111903
111923
|
"app-id": appId
|
|
111904
111924
|
},
|
|
111905
111925
|
notify: false
|
|
@@ -112103,12 +112123,13 @@ async function deleteChannel(channelId, appId, options) {
|
|
|
112103
112123
|
f2.info(`Deleting channel ${appId}#${channelId} from Capgo`);
|
|
112104
112124
|
try {
|
|
112105
112125
|
await delChannel(supabase, channelId, appId, userId);
|
|
112126
|
+
const orgId = await getOrganizationId(supabase, appId);
|
|
112106
112127
|
f2.success(`Channel deleted`);
|
|
112107
112128
|
await snag.track({
|
|
112108
112129
|
channel: "channel",
|
|
112109
112130
|
event: "Delete channel",
|
|
112110
112131
|
icon: "\u2705",
|
|
112111
|
-
user_id:
|
|
112132
|
+
user_id: orgId,
|
|
112112
112133
|
tags: {
|
|
112113
112134
|
"user-id": userId,
|
|
112114
112135
|
"app-id": appId,
|
|
@@ -112159,7 +112180,7 @@ async function listChannels(appId, options) {
|
|
|
112159
112180
|
}
|
|
112160
112181
|
|
|
112161
112182
|
// src/app/set.ts
|
|
112162
|
-
var
|
|
112183
|
+
var import_node_crypto4 = require("node:crypto");
|
|
112163
112184
|
var import_node_fs15 = require("node:fs");
|
|
112164
112185
|
var import_node_process29 = __toESM(require("node:process"));
|
|
112165
112186
|
async function setApp(appId, options) {
|
|
@@ -112188,7 +112209,7 @@ async function setApp(appId, options) {
|
|
|
112188
112209
|
}
|
|
112189
112210
|
let iconBuff;
|
|
112190
112211
|
let iconType;
|
|
112191
|
-
const fileName = `icon_${(0,
|
|
112212
|
+
const fileName = `icon_${(0, import_node_crypto4.randomUUID)()}`;
|
|
112192
112213
|
let signedURL = "https://xvwzpoazmxkqosrdewyv.supabase.co/storage/v1/object/public/images/capgo.png";
|
|
112193
112214
|
if (icon && (0, import_node_fs15.existsSync)(icon)) {
|
|
112194
112215
|
iconBuff = (0, import_node_fs15.readFileSync)(icon);
|
|
@@ -112246,7 +112267,7 @@ async function deleteApp(appId, options) {
|
|
|
112246
112267
|
const supabase = await createSupabaseClient(options.apikey);
|
|
112247
112268
|
const userId = await verifyUser(supabase, options.apikey, ["write", "all"]);
|
|
112248
112269
|
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, 5 /* super_admin */);
|
|
112249
|
-
const { data: appOwnerRaw, error: appOwnerError } = await supabase.from("apps").select(`owner_org ( created_by )`).eq("app_id", appId).single();
|
|
112270
|
+
const { data: appOwnerRaw, error: appOwnerError } = await supabase.from("apps").select(`owner_org ( created_by, id )`).eq("app_id", appId).single();
|
|
112250
112271
|
const appOwner = appOwnerRaw;
|
|
112251
112272
|
if (!appOwnerError && (appOwner?.owner_org.created_by ?? "") !== userId) {
|
|
112252
112273
|
f2.warn("Deleting the app is not recomended for users that are not the organization owner");
|
|
@@ -112272,22 +112293,25 @@ async function deleteApp(appId, options) {
|
|
|
112272
112293
|
} else if (appOwnerError) {
|
|
112273
112294
|
f2.warn(`Cannot get the app owner ${formatError(appOwnerError)}`);
|
|
112274
112295
|
}
|
|
112275
|
-
const { error } = await supabase.storage.from(`images
|
|
112276
|
-
if (error)
|
|
112296
|
+
const { error } = await supabase.storage.from(`images`).remove([`org/${appOwner?.owner_org.id}/${appId}/icon`]);
|
|
112297
|
+
if (error) {
|
|
112298
|
+
console.error(error, `images/org/${appOwner?.owner_org.id}/${appId}`);
|
|
112277
112299
|
f2.error("Could not delete app logo");
|
|
112300
|
+
}
|
|
112278
112301
|
const { error: delError } = await supabase.storage.from(`apps/${appId}/${userId}`).remove(["versions"]);
|
|
112279
112302
|
if (delError)
|
|
112280
112303
|
f2.error("Could not delete app version");
|
|
112281
|
-
const { error: dbError } = await supabase.from("apps").delete().eq("app_id", appId)
|
|
112304
|
+
const { error: dbError } = await supabase.from("apps").delete().eq("app_id", appId);
|
|
112282
112305
|
if (dbError) {
|
|
112283
112306
|
f2.error("Could not delete app");
|
|
112284
112307
|
program.error("");
|
|
112285
112308
|
}
|
|
112309
|
+
const orgId = await getOrganizationId(supabase, appId);
|
|
112286
112310
|
await snag.track({
|
|
112287
112311
|
channel: "app",
|
|
112288
112312
|
event: "App Deleted",
|
|
112289
112313
|
icon: "\u{1F5D1}\uFE0F",
|
|
112290
|
-
user_id:
|
|
112314
|
+
user_id: orgId,
|
|
112291
112315
|
tags: {
|
|
112292
112316
|
"app-id": appId
|
|
112293
112317
|
},
|
package/package.json
CHANGED
package/src/api/channels.ts
CHANGED
|
@@ -74,7 +74,24 @@ interface version {
|
|
|
74
74
|
id: string
|
|
75
75
|
name: string
|
|
76
76
|
}
|
|
77
|
-
|
|
77
|
+
interface Channel {
|
|
78
|
+
id: number
|
|
79
|
+
name: string
|
|
80
|
+
public: boolean
|
|
81
|
+
ios: boolean
|
|
82
|
+
android: boolean
|
|
83
|
+
disableAutoUpdate: string
|
|
84
|
+
disableAutoUpdateUnderNative: boolean
|
|
85
|
+
allow_device_self_set: boolean
|
|
86
|
+
enable_progressive_deploy: boolean
|
|
87
|
+
secondaryVersionPercentage: number
|
|
88
|
+
secondVersion?: version
|
|
89
|
+
enableAbTesting: boolean
|
|
90
|
+
allow_emulator: boolean
|
|
91
|
+
allow_dev: boolean
|
|
92
|
+
version?: version
|
|
93
|
+
}
|
|
94
|
+
export function displayChannels(data: Channel[]) {
|
|
78
95
|
const t = new Table({
|
|
79
96
|
title: 'Channels',
|
|
80
97
|
charLength: { '❌': 2, '✅': 2 },
|
|
@@ -86,8 +103,8 @@ export function displayChannels(data: (Database['public']['Tables']['channels'][
|
|
|
86
103
|
'Name': row.name,
|
|
87
104
|
...(row.version ? { Version: row.version.name } : undefined),
|
|
88
105
|
'Public': row.public ? '✅' : '❌',
|
|
89
|
-
'iOS': row.ios ? '
|
|
90
|
-
'Android': row.android ? '
|
|
106
|
+
'iOS': row.ios ? '✅' : '❌',
|
|
107
|
+
'Android': row.android ? '✅' : '❌',
|
|
91
108
|
'⬆️ limit': row.disableAutoUpdate,
|
|
92
109
|
'⬇️ under native': row.disableAutoUpdateUnderNative ? '❌' : '✅',
|
|
93
110
|
'Self assign': row.allow_device_self_set ? '✅' : '❌',
|
|
@@ -136,5 +153,5 @@ export async function getActiveChannels(supabase: SupabaseClient<Database>, appi
|
|
|
136
153
|
p.log.error(`App ${appid} not found in database`)
|
|
137
154
|
program.error('')
|
|
138
155
|
}
|
|
139
|
-
return data
|
|
156
|
+
return data as any as Channel[]
|
|
140
157
|
}
|
package/src/app/add.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto'
|
|
2
1
|
import { existsSync, readFileSync } from 'node:fs'
|
|
3
2
|
import process from 'node:process'
|
|
4
3
|
import mime from 'mime'
|
|
@@ -95,17 +94,18 @@ export async function addAppInternal(appId: string, options: Options, organizati
|
|
|
95
94
|
p.log.warn(`Cannot find app icon in any of the following locations: ${icon}, ${newIconPath}`)
|
|
96
95
|
}
|
|
97
96
|
|
|
98
|
-
const fileName = `
|
|
97
|
+
const fileName = `icon`
|
|
99
98
|
let signedURL = 'https://xvwzpoazmxkqosrdewyv.supabase.co/storage/v1/object/public/images/capgo.png'
|
|
100
99
|
|
|
101
100
|
// upload image if available
|
|
102
101
|
if (iconBuff && iconType) {
|
|
103
102
|
const { error } = await supabase.storage
|
|
104
|
-
.from(`images/${
|
|
103
|
+
.from(`images/org/${organizationUid}/${appId}`)
|
|
105
104
|
.upload(fileName, iconBuff, {
|
|
106
105
|
contentType: iconType,
|
|
107
106
|
})
|
|
108
107
|
if (error) {
|
|
108
|
+
console.error(error)
|
|
109
109
|
p.log.error(`Could not add app ${formatError(error)}`)
|
|
110
110
|
program.error('')
|
|
111
111
|
}
|
package/src/app/delete.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { program } from 'commander'
|
|
|
3
3
|
import * as p from '@clack/prompts'
|
|
4
4
|
import { checkAppExistsAndHasPermissionOrgErr } from '../api/app'
|
|
5
5
|
import type { OptionsBase } from '../utils'
|
|
6
|
-
import { OrganizationPerm, createSupabaseClient, findSavedKey, formatError, getConfig, useLogSnag, verifyUser } from '../utils'
|
|
6
|
+
import { OrganizationPerm, createSupabaseClient, findSavedKey, formatError, getConfig, getOrganizationId, useLogSnag, verifyUser } from '../utils'
|
|
7
7
|
|
|
8
8
|
export async function deleteApp(appId: string, options: OptionsBase) {
|
|
9
9
|
p.intro(`Deleting`)
|
|
@@ -27,11 +27,11 @@ export async function deleteApp(appId: string, options: OptionsBase) {
|
|
|
27
27
|
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, OrganizationPerm.super_admin)
|
|
28
28
|
|
|
29
29
|
const { data: appOwnerRaw, error: appOwnerError } = await supabase.from('apps')
|
|
30
|
-
.select(`owner_org ( created_by )`)
|
|
30
|
+
.select(`owner_org ( created_by, id )`)
|
|
31
31
|
.eq('app_id', appId)
|
|
32
32
|
.single()
|
|
33
33
|
|
|
34
|
-
const appOwner = appOwnerRaw as { owner_org: { created_by: string } } | null
|
|
34
|
+
const appOwner = appOwnerRaw as { owner_org: { created_by: string, id: string } } | null
|
|
35
35
|
|
|
36
36
|
if (!appOwnerError && (appOwner?.owner_org.created_by ?? '') !== userId) {
|
|
37
37
|
// We are dealing with a member user that is not the owner
|
|
@@ -66,10 +66,12 @@ export async function deleteApp(appId: string, options: OptionsBase) {
|
|
|
66
66
|
|
|
67
67
|
const { error } = await supabase
|
|
68
68
|
.storage
|
|
69
|
-
.from(`images
|
|
70
|
-
.remove([appId])
|
|
71
|
-
if (error)
|
|
69
|
+
.from(`images`)
|
|
70
|
+
.remove([`org/${appOwner?.owner_org.id}/${appId}/icon`])
|
|
71
|
+
if (error) {
|
|
72
|
+
console.error(error, `images/org/${appOwner?.owner_org.id}/${appId}`)
|
|
72
73
|
p.log.error('Could not delete app logo')
|
|
74
|
+
}
|
|
73
75
|
|
|
74
76
|
const { error: delError } = await supabase
|
|
75
77
|
.storage
|
|
@@ -84,17 +86,18 @@ export async function deleteApp(appId: string, options: OptionsBase) {
|
|
|
84
86
|
.from('apps')
|
|
85
87
|
.delete()
|
|
86
88
|
.eq('app_id', appId)
|
|
87
|
-
.eq('user_id', userId)
|
|
89
|
+
// .eq('user_id', userId)
|
|
88
90
|
|
|
89
91
|
if (dbError) {
|
|
90
92
|
p.log.error('Could not delete app')
|
|
91
93
|
program.error('')
|
|
92
94
|
}
|
|
95
|
+
const orgId = await getOrganizationId(supabase, appId)
|
|
93
96
|
await snag.track({
|
|
94
97
|
channel: 'app',
|
|
95
98
|
event: 'App Deleted',
|
|
96
99
|
icon: '🗑️',
|
|
97
|
-
user_id:
|
|
100
|
+
user_id: orgId,
|
|
98
101
|
tags: {
|
|
99
102
|
'app-id': appId,
|
|
100
103
|
},
|
package/src/bundle/upload.ts
CHANGED
|
@@ -289,7 +289,7 @@ export async function uploadBundle(appid: string, options: Options, shouldExit =
|
|
|
289
289
|
channel: 'app',
|
|
290
290
|
event: 'App encryption',
|
|
291
291
|
icon: '🔑',
|
|
292
|
-
user_id:
|
|
292
|
+
user_id: orgId,
|
|
293
293
|
tags: {
|
|
294
294
|
'app-id': appid,
|
|
295
295
|
},
|
|
@@ -319,7 +319,7 @@ It will be also visible in your dashboard\n`)
|
|
|
319
319
|
channel: 'app-error',
|
|
320
320
|
event: 'App Too Large',
|
|
321
321
|
icon: '🚛',
|
|
322
|
-
user_id:
|
|
322
|
+
user_id: orgId,
|
|
323
323
|
tags: {
|
|
324
324
|
'app-id': appid,
|
|
325
325
|
},
|
|
@@ -345,7 +345,7 @@ It will be also visible in your dashboard\n`)
|
|
|
345
345
|
channel: 'app',
|
|
346
346
|
event: 'App external',
|
|
347
347
|
icon: '📤',
|
|
348
|
-
user_id:
|
|
348
|
+
user_id: orgId,
|
|
349
349
|
tags: {
|
|
350
350
|
'app-id': appid,
|
|
351
351
|
},
|
|
@@ -387,7 +387,7 @@ It will be also visible in your dashboard\n`)
|
|
|
387
387
|
|
|
388
388
|
try {
|
|
389
389
|
if (options.multipart !== undefined && options.multipart) {
|
|
390
|
-
await uploadMultipart(supabase, appid, bundle, zipped)
|
|
390
|
+
await uploadMultipart(supabase, appid, bundle, zipped, orgId)
|
|
391
391
|
}
|
|
392
392
|
else {
|
|
393
393
|
const url = await uploadUrl(supabase, appid, bundle)
|
|
@@ -496,7 +496,7 @@ It will be also visible in your dashboard\n`)
|
|
|
496
496
|
channel: 'app',
|
|
497
497
|
event: 'App Uploaded',
|
|
498
498
|
icon: '⏫',
|
|
499
|
-
user_id:
|
|
499
|
+
user_id: orgId,
|
|
500
500
|
tags: {
|
|
501
501
|
'app-id': appid,
|
|
502
502
|
},
|
package/src/channel/add.ts
CHANGED
|
@@ -27,7 +27,7 @@ export async function addChannel(channelId: string, appId: string, options: Opti
|
|
|
27
27
|
}
|
|
28
28
|
const supabase = await createSupabaseClient(options.apikey)
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
await verifyUser(supabase, options.apikey, ['write', 'all'])
|
|
31
31
|
// Check we have app access to this appId
|
|
32
32
|
await checkAppExistsAndHasPermissionOrgErr(supabase, options.apikey, appId, OrganizationPerm.admin)
|
|
33
33
|
|
|
@@ -50,7 +50,7 @@ export async function addChannel(channelId: string, appId: string, options: Opti
|
|
|
50
50
|
channel: 'channel',
|
|
51
51
|
event: 'Create channel',
|
|
52
52
|
icon: '✅',
|
|
53
|
-
user_id:
|
|
53
|
+
user_id: orgId,
|
|
54
54
|
tags: {
|
|
55
55
|
'app-id': appId,
|
|
56
56
|
'channel': channelId,
|
package/src/channel/delete.ts
CHANGED
|
@@ -4,7 +4,7 @@ import * as p from '@clack/prompts'
|
|
|
4
4
|
import { checkAppExistsAndHasPermissionOrgErr } from '../api/app'
|
|
5
5
|
import { delChannel } from '../api/channels'
|
|
6
6
|
import type { OptionsBase } from '../utils'
|
|
7
|
-
import { OrganizationPerm, createSupabaseClient, findSavedKey, getConfig, useLogSnag, verifyUser } from '../utils'
|
|
7
|
+
import { OrganizationPerm, createSupabaseClient, findSavedKey, getConfig, getOrganizationId, useLogSnag, verifyUser } from '../utils'
|
|
8
8
|
|
|
9
9
|
export async function deleteChannel(channelId: string, appId: string, options: OptionsBase) {
|
|
10
10
|
p.intro(`Delete channel`)
|
|
@@ -30,12 +30,13 @@ export async function deleteChannel(channelId: string, appId: string, options: O
|
|
|
30
30
|
p.log.info(`Deleting channel ${appId}#${channelId} from Capgo`)
|
|
31
31
|
try {
|
|
32
32
|
await delChannel(supabase, channelId, appId, userId)
|
|
33
|
+
const orgId = await getOrganizationId(supabase, appId)
|
|
33
34
|
p.log.success(`Channel deleted`)
|
|
34
35
|
await snag.track({
|
|
35
36
|
channel: 'channel',
|
|
36
37
|
event: 'Delete channel',
|
|
37
38
|
icon: '✅',
|
|
38
|
-
user_id:
|
|
39
|
+
user_id: orgId,
|
|
39
40
|
tags: {
|
|
40
41
|
'user-id': userId,
|
|
41
42
|
'app-id': appId,
|
package/src/channel/set.ts
CHANGED
|
@@ -161,9 +161,8 @@ export async function setChannel(channel: string, appId: string, options: Option
|
|
|
161
161
|
channel: 'channel',
|
|
162
162
|
event: 'Set channel',
|
|
163
163
|
icon: '✅',
|
|
164
|
-
user_id:
|
|
164
|
+
user_id: orgId,
|
|
165
165
|
tags: {
|
|
166
|
-
'user-id': userId,
|
|
167
166
|
'app-id': appId,
|
|
168
167
|
},
|
|
169
168
|
notify: false,
|
package/src/utils.ts
CHANGED
|
@@ -537,8 +537,19 @@ async function finishMultipartDownload(key: string, uploadId: string, url: strin
|
|
|
537
537
|
}
|
|
538
538
|
|
|
539
539
|
const PART_SIZE = 10 * 1024 * 1024
|
|
540
|
-
export async function uploadMultipart(supabase: SupabaseClient<Database>, appId: string, name: string, data: Buffer): Promise<boolean> {
|
|
540
|
+
export async function uploadMultipart(supabase: SupabaseClient<Database>, appId: string, name: string, data: Buffer, orgId: string): Promise<boolean> {
|
|
541
541
|
try {
|
|
542
|
+
const snag = useLogSnag()
|
|
543
|
+
await snag.track({
|
|
544
|
+
channel: 'app',
|
|
545
|
+
event: 'App Multipart Prepare',
|
|
546
|
+
icon: '⏫',
|
|
547
|
+
user_id: orgId,
|
|
548
|
+
tags: {
|
|
549
|
+
'app-id': appId,
|
|
550
|
+
},
|
|
551
|
+
notify: false,
|
|
552
|
+
}).catch()
|
|
542
553
|
const multipartPrep = await prepareMultipart(supabase, appId, name)
|
|
543
554
|
if (!multipartPrep) {
|
|
544
555
|
// Just pass the error
|
|
@@ -555,6 +566,16 @@ export async function uploadMultipart(supabase: SupabaseClient<Database>, appId:
|
|
|
555
566
|
|
|
556
567
|
await finishMultipartDownload(multipartPrep.key, multipartPrep.uploadId, multipartPrep.url, parts)
|
|
557
568
|
|
|
569
|
+
await snag.track({
|
|
570
|
+
channel: 'app',
|
|
571
|
+
event: 'App Multipart done',
|
|
572
|
+
icon: '⏫',
|
|
573
|
+
user_id: orgId,
|
|
574
|
+
tags: {
|
|
575
|
+
'app-id': appId,
|
|
576
|
+
},
|
|
577
|
+
notify: false,
|
|
578
|
+
}).catch()
|
|
558
579
|
return true
|
|
559
580
|
}
|
|
560
581
|
catch (e) {
|