@globio/cli 0.2.0 → 0.2.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/dist/index.js +702 -144
- package/jsr.json +1 -1
- package/package.json +2 -2
- package/src/auth/login.ts +86 -27
- package/src/auth/whoami.ts +27 -2
- package/src/commands/functions.ts +111 -20
- package/src/commands/hooks.ts +324 -0
- package/src/commands/init.ts +82 -13
- package/src/commands/migrate.ts +105 -54
- package/src/commands/profiles.ts +16 -1
- package/src/commands/projects.ts +141 -24
- package/src/commands/services.ts +11 -1
- package/src/index.ts +119 -13
- package/src/lib/table.ts +5 -0
package/jsr.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@globio/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "The official CLI for Globio — game backend as a service",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"@clack/prompts": "^0.9.0",
|
|
17
|
-
"@globio/sdk": "^1.
|
|
17
|
+
"@globio/sdk": "^1.1.0",
|
|
18
18
|
"chalk": "^5.3.0",
|
|
19
19
|
"cli-progress": "^3.12.0",
|
|
20
20
|
"commander": "^12.0.0",
|
package/src/auth/login.ts
CHANGED
|
@@ -2,7 +2,7 @@ import * as p from '@clack/prompts';
|
|
|
2
2
|
import { exec } from 'child_process';
|
|
3
3
|
import { config } from '../lib/config.js';
|
|
4
4
|
import { getConsoleCliAuthUrl, manageRequest, type ManageAccount } from '../lib/manage.js';
|
|
5
|
-
import { failure, getCliVersion, muted, orange, printBanner, white } from '../lib/banner.js';
|
|
5
|
+
import { failure, getCliVersion, jsonOutput, muted, orange, printBanner, white } from '../lib/banner.js';
|
|
6
6
|
|
|
7
7
|
const version = getCliVersion();
|
|
8
8
|
|
|
@@ -25,6 +25,19 @@ async function savePat(token: string) {
|
|
|
25
25
|
return account;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
function storeProfile(profileName: string, token: string, account: ManageAccount) {
|
|
29
|
+
const hadProfiles = config.listProfiles().length > 0;
|
|
30
|
+
config.setProfile(profileName, {
|
|
31
|
+
pat: token,
|
|
32
|
+
account_email: account.email,
|
|
33
|
+
account_name: account.display_name ?? account.email,
|
|
34
|
+
created_at: Date.now(),
|
|
35
|
+
});
|
|
36
|
+
if (profileName === 'default' || !hadProfiles) {
|
|
37
|
+
config.setActiveProfile(profileName);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
28
41
|
function warnOnDuplicateAccount(accountEmail: string, targetProfileName: string) {
|
|
29
42
|
const allProfiles = config.listProfiles();
|
|
30
43
|
const duplicate = allProfiles.find((name) => {
|
|
@@ -45,8 +58,30 @@ function warnOnDuplicateAccount(accountEmail: string, targetProfileName: string)
|
|
|
45
58
|
console.log('');
|
|
46
59
|
}
|
|
47
60
|
|
|
48
|
-
async function
|
|
49
|
-
|
|
61
|
+
async function completeTokenLogin(
|
|
62
|
+
token: string,
|
|
63
|
+
profileName: string,
|
|
64
|
+
json = false
|
|
65
|
+
) {
|
|
66
|
+
const account = await savePat(token);
|
|
67
|
+
if (!json) {
|
|
68
|
+
warnOnDuplicateAccount(account.email, profileName);
|
|
69
|
+
}
|
|
70
|
+
storeProfile(profileName, token, account);
|
|
71
|
+
|
|
72
|
+
if (json) {
|
|
73
|
+
jsonOutput({
|
|
74
|
+
success: true,
|
|
75
|
+
email: account.email,
|
|
76
|
+
name: account.display_name ?? account.email,
|
|
77
|
+
profile: profileName,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return account;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function runTokenLogin(profileName: string, json = false) {
|
|
50
85
|
const token = await p.text({
|
|
51
86
|
message: 'Paste your personal access token',
|
|
52
87
|
placeholder: 'glo_pat_...',
|
|
@@ -65,17 +100,7 @@ async function runTokenLogin(profileName: string) {
|
|
|
65
100
|
const spinner = p.spinner();
|
|
66
101
|
spinner.start('Validating personal access token...');
|
|
67
102
|
try {
|
|
68
|
-
const account = await
|
|
69
|
-
warnOnDuplicateAccount(account.email, profileName);
|
|
70
|
-
config.setProfile(profileName, {
|
|
71
|
-
pat: token,
|
|
72
|
-
account_email: account.email,
|
|
73
|
-
account_name: account.display_name ?? account.email,
|
|
74
|
-
created_at: Date.now(),
|
|
75
|
-
});
|
|
76
|
-
if (profileName === 'default' || !hadProfiles) {
|
|
77
|
-
config.setActiveProfile(profileName);
|
|
78
|
-
}
|
|
103
|
+
const account = await completeTokenLogin(token, profileName, json);
|
|
79
104
|
spinner.stop('Token validated.');
|
|
80
105
|
p.outro(`Logged in as ${account.email}\nProfile: ${profileName}`);
|
|
81
106
|
} catch (error) {
|
|
@@ -85,10 +110,9 @@ async function runTokenLogin(profileName: string) {
|
|
|
85
110
|
}
|
|
86
111
|
}
|
|
87
112
|
|
|
88
|
-
async function runBrowserLogin(profileName: string) {
|
|
113
|
+
async function runBrowserLogin(profileName: string, json = false) {
|
|
89
114
|
const state = crypto.randomUUID();
|
|
90
115
|
const spinner = p.spinner();
|
|
91
|
-
const hadProfiles = config.listProfiles().length > 0;
|
|
92
116
|
|
|
93
117
|
await manageRequest('/cli-auth/request', {
|
|
94
118
|
method: 'POST',
|
|
@@ -124,17 +148,28 @@ async function runBrowserLogin(profileName: string) {
|
|
|
124
148
|
body: { code: status.code },
|
|
125
149
|
});
|
|
126
150
|
|
|
127
|
-
|
|
151
|
+
if (!json) {
|
|
152
|
+
warnOnDuplicateAccount(exchange.account.email, profileName);
|
|
153
|
+
}
|
|
128
154
|
config.setProfile(profileName, {
|
|
129
155
|
pat: exchange.token,
|
|
130
156
|
account_email: exchange.account.email,
|
|
131
157
|
account_name: exchange.account.display_name ?? exchange.account.email,
|
|
132
158
|
created_at: Date.now(),
|
|
133
159
|
});
|
|
134
|
-
if (profileName === 'default' ||
|
|
160
|
+
if (profileName === 'default' || config.listProfiles().length === 1) {
|
|
135
161
|
config.setActiveProfile(profileName);
|
|
136
162
|
}
|
|
137
163
|
|
|
164
|
+
if (json) {
|
|
165
|
+
jsonOutput({
|
|
166
|
+
success: true,
|
|
167
|
+
email: exchange.account.email,
|
|
168
|
+
name: exchange.account.display_name ?? exchange.account.email,
|
|
169
|
+
profile: profileName,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
|
|
138
173
|
spinner.stop('Browser approval received.');
|
|
139
174
|
p.outro(`Logged in as ${exchange.account.email}\nProfile: ${profileName}`);
|
|
140
175
|
return;
|
|
@@ -151,11 +186,40 @@ async function runBrowserLogin(profileName: string) {
|
|
|
151
186
|
process.exit(1);
|
|
152
187
|
}
|
|
153
188
|
|
|
154
|
-
export async function login(
|
|
155
|
-
|
|
189
|
+
export async function login(
|
|
190
|
+
options: { token?: string; profile?: string; json?: boolean } = {}
|
|
191
|
+
) {
|
|
156
192
|
const profileName = options.profile ?? 'default';
|
|
157
193
|
const existing = config.getProfile(profileName);
|
|
158
194
|
|
|
195
|
+
if (options.token) {
|
|
196
|
+
try {
|
|
197
|
+
const account = await completeTokenLogin(options.token, profileName, options.json);
|
|
198
|
+
if (!options.json) {
|
|
199
|
+
console.log(`Logged in as ${account.email}\nProfile: ${profileName}`);
|
|
200
|
+
}
|
|
201
|
+
return;
|
|
202
|
+
} catch (error) {
|
|
203
|
+
if (options.json) {
|
|
204
|
+
jsonOutput({
|
|
205
|
+
success: false,
|
|
206
|
+
error: error instanceof Error ? error.message : 'Could not validate token',
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
console.log(failure(error instanceof Error ? error.message : 'Could not validate token'));
|
|
210
|
+
process.exit(1);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (options.json) {
|
|
215
|
+
jsonOutput({
|
|
216
|
+
success: false,
|
|
217
|
+
error: 'login --json requires --token <pat>',
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
printBanner(version);
|
|
222
|
+
|
|
159
223
|
if (existing) {
|
|
160
224
|
const proceed = await p.confirm({
|
|
161
225
|
message: `Already logged in as ${existing.account_email} on profile "${profileName}". Replace?`,
|
|
@@ -168,11 +232,6 @@ export async function login(options: { token?: boolean; profile?: string } = {})
|
|
|
168
232
|
}
|
|
169
233
|
}
|
|
170
234
|
|
|
171
|
-
if (options.token) {
|
|
172
|
-
await runTokenLogin(profileName);
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
235
|
const choice = await p.select({
|
|
177
236
|
message: 'Choose a login method',
|
|
178
237
|
options: [
|
|
@@ -187,12 +246,12 @@ export async function login(options: { token?: boolean; profile?: string } = {})
|
|
|
187
246
|
}
|
|
188
247
|
|
|
189
248
|
if (choice === 'token') {
|
|
190
|
-
await runTokenLogin(profileName);
|
|
249
|
+
await runTokenLogin(profileName, options.json);
|
|
191
250
|
return;
|
|
192
251
|
}
|
|
193
252
|
|
|
194
253
|
try {
|
|
195
|
-
await runBrowserLogin(profileName);
|
|
254
|
+
await runBrowserLogin(profileName, options.json);
|
|
196
255
|
} catch (error) {
|
|
197
256
|
p.outro(failure(error instanceof Error ? error.message : 'Could not connect to Globio.') + '\x1b[0m');
|
|
198
257
|
process.exit(1);
|
package/src/auth/whoami.ts
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
getCliVersion,
|
|
5
5
|
header,
|
|
6
6
|
inactive,
|
|
7
|
+
jsonOutput,
|
|
7
8
|
muted,
|
|
8
9
|
orange,
|
|
9
10
|
renderTable,
|
|
@@ -14,11 +15,24 @@ import {
|
|
|
14
15
|
|
|
15
16
|
const version = getCliVersion();
|
|
16
17
|
|
|
17
|
-
export async function whoami(options: { profile?: string } = {}) {
|
|
18
|
+
export async function whoami(options: { profile?: string; json?: boolean } = {}) {
|
|
18
19
|
const profileName = options.profile ?? config.getActiveProfile() ?? 'default';
|
|
19
20
|
const profile = config.getProfile(profileName);
|
|
21
|
+
const active = config.getActiveProfile();
|
|
20
22
|
|
|
21
23
|
if (!profile) {
|
|
24
|
+
if (options.json) {
|
|
25
|
+
jsonOutput({
|
|
26
|
+
profile: profileName,
|
|
27
|
+
active: false,
|
|
28
|
+
account_email: null,
|
|
29
|
+
account_name: null,
|
|
30
|
+
org_name: null,
|
|
31
|
+
active_project_id: null,
|
|
32
|
+
active_project_name: null,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
22
36
|
console.log(
|
|
23
37
|
header(version) +
|
|
24
38
|
' ' +
|
|
@@ -29,8 +43,19 @@ export async function whoami(options: { profile?: string } = {}) {
|
|
|
29
43
|
return;
|
|
30
44
|
}
|
|
31
45
|
|
|
46
|
+
if (options.json) {
|
|
47
|
+
jsonOutput({
|
|
48
|
+
profile: profileName,
|
|
49
|
+
active: profileName === active,
|
|
50
|
+
account_email: profile.account_email,
|
|
51
|
+
account_name: profile.account_name,
|
|
52
|
+
org_name: profile.org_name ?? null,
|
|
53
|
+
active_project_id: profile.active_project_id ?? null,
|
|
54
|
+
active_project_name: profile.active_project_name ?? null,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
32
58
|
const allProfiles = config.listProfiles();
|
|
33
|
-
const active = config.getActiveProfile();
|
|
34
59
|
const otherProfiles = allProfiles.filter((p) => p !== profileName).join(', ') || '—';
|
|
35
60
|
|
|
36
61
|
console.log(
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
green,
|
|
9
9
|
header,
|
|
10
10
|
inactive,
|
|
11
|
+
jsonOutput,
|
|
11
12
|
muted,
|
|
12
13
|
orange,
|
|
13
14
|
gold,
|
|
@@ -21,11 +22,33 @@ function resolveProfileName(profile?: string) {
|
|
|
21
22
|
return profile ?? config.getActiveProfile() ?? 'default';
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
function parseJsonField<T>(value: string | null | undefined): T | null {
|
|
26
|
+
if (!value) return null;
|
|
27
|
+
try {
|
|
28
|
+
return JSON.parse(value) as T;
|
|
29
|
+
} catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function functionsList(options: { profile?: string; json?: boolean } = {}) {
|
|
25
35
|
const profileName = resolveProfileName(options.profile);
|
|
26
36
|
const client = getClient(profileName);
|
|
27
37
|
const result = await client.code.listFunctions();
|
|
28
38
|
|
|
39
|
+
if (options.json) {
|
|
40
|
+
jsonOutput(
|
|
41
|
+
result.success
|
|
42
|
+
? result.data.map((fn: CodeFunction) => ({
|
|
43
|
+
slug: fn.slug,
|
|
44
|
+
type: fn.type,
|
|
45
|
+
trigger_event: fn.trigger_event,
|
|
46
|
+
active: fn.active,
|
|
47
|
+
}))
|
|
48
|
+
: []
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
29
52
|
if (!result.success || !result.data.length) {
|
|
30
53
|
console.log(header(version) + ' ' + muted('No functions found.') + '\n');
|
|
31
54
|
return;
|
|
@@ -53,9 +76,15 @@ export async function functionsList(options: { profile?: string } = {}) {
|
|
|
53
76
|
console.log('');
|
|
54
77
|
}
|
|
55
78
|
|
|
56
|
-
export async function functionsCreate(
|
|
79
|
+
export async function functionsCreate(
|
|
80
|
+
slug: string,
|
|
81
|
+
options: { profile?: string; json?: boolean } = {}
|
|
82
|
+
) {
|
|
57
83
|
const filename = `${slug}.js`;
|
|
58
84
|
if (existsSync(filename)) {
|
|
85
|
+
if (options.json) {
|
|
86
|
+
jsonOutput({ success: false, file: filename, error: 'File already exists' });
|
|
87
|
+
}
|
|
59
88
|
console.log(inactive(`${filename} already exists.`));
|
|
60
89
|
return;
|
|
61
90
|
}
|
|
@@ -76,13 +105,16 @@ async function handler(input, globio) {
|
|
|
76
105
|
}
|
|
77
106
|
`;
|
|
78
107
|
writeFileSync(filename, template);
|
|
108
|
+
if (options.json) {
|
|
109
|
+
jsonOutput({ success: true, file: filename });
|
|
110
|
+
}
|
|
79
111
|
console.log(green(`Created ${filename}`));
|
|
80
112
|
console.log(muted(`Deploy with: npx @globio/cli functions deploy ${slug}`));
|
|
81
113
|
}
|
|
82
114
|
|
|
83
115
|
export async function functionsDeploy(
|
|
84
116
|
slug: string,
|
|
85
|
-
options: { file?: string; name?: string; profile?: string }
|
|
117
|
+
options: { file?: string; name?: string; profile?: string; json?: boolean }
|
|
86
118
|
) {
|
|
87
119
|
const filename = options.file ?? `${slug}.js`;
|
|
88
120
|
if (!existsSync(filename)) {
|
|
@@ -97,8 +129,8 @@ export async function functionsDeploy(
|
|
|
97
129
|
const code = readFileSync(filename, 'utf-8');
|
|
98
130
|
const profileName = resolveProfileName(options.profile);
|
|
99
131
|
const client = getClient(profileName);
|
|
100
|
-
const spinner = ora(`Deploying ${slug}...`).start();
|
|
101
132
|
const existing = await client.code.getFunction(slug);
|
|
133
|
+
const spinner = options.json ? null : ora(`Deploying ${slug}...`).start();
|
|
102
134
|
|
|
103
135
|
let result;
|
|
104
136
|
if (existing.success) {
|
|
@@ -116,17 +148,28 @@ export async function functionsDeploy(
|
|
|
116
148
|
}
|
|
117
149
|
|
|
118
150
|
if (!result.success) {
|
|
119
|
-
|
|
151
|
+
if (options.json) {
|
|
152
|
+
jsonOutput({ success: false, error: result.error.message });
|
|
153
|
+
}
|
|
154
|
+
spinner?.fail('Deploy failed');
|
|
120
155
|
console.error(result.error.message);
|
|
121
156
|
process.exit(1);
|
|
122
157
|
}
|
|
123
158
|
|
|
124
|
-
|
|
159
|
+
if (options.json) {
|
|
160
|
+
jsonOutput({
|
|
161
|
+
success: true,
|
|
162
|
+
slug,
|
|
163
|
+
action: existing.success ? 'updated' : 'created',
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
spinner?.succeed(existing.success ? `Updated ${slug}` : `Deployed ${slug}`);
|
|
125
168
|
}
|
|
126
169
|
|
|
127
170
|
export async function functionsInvoke(
|
|
128
171
|
slug: string,
|
|
129
|
-
options: { input?: string; profile?: string }
|
|
172
|
+
options: { input?: string; profile?: string; json?: boolean }
|
|
130
173
|
) {
|
|
131
174
|
let input: Record<string, unknown> = {};
|
|
132
175
|
if (options.input) {
|
|
@@ -140,16 +183,26 @@ export async function functionsInvoke(
|
|
|
140
183
|
|
|
141
184
|
const profileName = resolveProfileName(options.profile);
|
|
142
185
|
const client = getClient(profileName);
|
|
143
|
-
const spinner = ora(`Invoking ${slug}...`).start();
|
|
186
|
+
const spinner = options.json ? null : ora(`Invoking ${slug}...`).start();
|
|
144
187
|
const result = await client.code.invoke(slug, input);
|
|
145
|
-
spinner
|
|
188
|
+
spinner?.stop();
|
|
146
189
|
|
|
147
190
|
if (!result.success) {
|
|
191
|
+
if (options.json) {
|
|
192
|
+
jsonOutput({ success: false, error: result.error.message });
|
|
193
|
+
}
|
|
148
194
|
console.log(failure('Invocation failed'));
|
|
149
195
|
console.error(result.error.message);
|
|
150
196
|
return;
|
|
151
197
|
}
|
|
152
198
|
|
|
199
|
+
if (options.json) {
|
|
200
|
+
jsonOutput({
|
|
201
|
+
result: result.data.result,
|
|
202
|
+
duration_ms: result.data.duration_ms,
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
153
206
|
console.log('');
|
|
154
207
|
console.log(orange('Result:'));
|
|
155
208
|
console.log(JSON.stringify(result.data.result, null, 2));
|
|
@@ -158,13 +211,36 @@ export async function functionsInvoke(
|
|
|
158
211
|
|
|
159
212
|
export async function functionsLogs(
|
|
160
213
|
slug: string,
|
|
161
|
-
options: { limit?: string; profile?: string }
|
|
214
|
+
options: { limit?: string; profile?: string; json?: boolean }
|
|
162
215
|
) {
|
|
163
216
|
const limit = options.limit ? parseInt(options.limit, 10) : 20;
|
|
164
217
|
const profileName = resolveProfileName(options.profile);
|
|
165
218
|
const client = getClient(profileName);
|
|
166
219
|
const result = await client.code.getInvocations(slug, limit);
|
|
167
220
|
|
|
221
|
+
if (options.json) {
|
|
222
|
+
jsonOutput(
|
|
223
|
+
result.success
|
|
224
|
+
? (result.data as Array<CodeInvocation & {
|
|
225
|
+
logs?: string | null;
|
|
226
|
+
error_message?: string | null;
|
|
227
|
+
input?: string | null;
|
|
228
|
+
result?: string | null;
|
|
229
|
+
}>).map((invocation) => ({
|
|
230
|
+
id: invocation.id,
|
|
231
|
+
trigger_type: invocation.trigger_type,
|
|
232
|
+
duration_ms: invocation.duration_ms,
|
|
233
|
+
success: invocation.success,
|
|
234
|
+
invoked_at: invocation.invoked_at,
|
|
235
|
+
logs: parseJsonField<string[]>(invocation.logs) ?? [],
|
|
236
|
+
error_message: invocation.error_message ?? null,
|
|
237
|
+
input: parseJsonField<Record<string, unknown>>(invocation.input),
|
|
238
|
+
result: parseJsonField<unknown>(invocation.result),
|
|
239
|
+
}))
|
|
240
|
+
: []
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
|
|
168
244
|
if (!result.success || !result.data.length) {
|
|
169
245
|
console.log(header(version) + ' ' + muted('No invocations yet.') + '\n');
|
|
170
246
|
return;
|
|
@@ -198,34 +274,49 @@ export async function functionsLogs(
|
|
|
198
274
|
console.log('');
|
|
199
275
|
}
|
|
200
276
|
|
|
201
|
-
export async function functionsDelete(
|
|
277
|
+
export async function functionsDelete(
|
|
278
|
+
slug: string,
|
|
279
|
+
options: { profile?: string; json?: boolean } = {}
|
|
280
|
+
) {
|
|
202
281
|
const profileName = resolveProfileName(options.profile);
|
|
203
282
|
const client = getClient(profileName);
|
|
204
|
-
const spinner = ora(`Deleting ${slug}...`).start();
|
|
283
|
+
const spinner = options.json ? null : ora(`Deleting ${slug}...`).start();
|
|
205
284
|
const result = await client.code.deleteFunction(slug);
|
|
206
285
|
if (!result.success) {
|
|
207
|
-
|
|
286
|
+
if (options.json) {
|
|
287
|
+
jsonOutput({ success: false, error: result.error.message });
|
|
288
|
+
}
|
|
289
|
+
spinner?.fail(`Delete failed for ${slug}`);
|
|
208
290
|
console.error(result.error.message);
|
|
209
291
|
process.exit(1);
|
|
210
292
|
}
|
|
211
|
-
|
|
293
|
+
if (options.json) {
|
|
294
|
+
jsonOutput({ success: true, slug });
|
|
295
|
+
}
|
|
296
|
+
spinner?.succeed(`Deleted ${slug}`);
|
|
212
297
|
}
|
|
213
298
|
|
|
214
299
|
export async function functionsToggle(
|
|
215
300
|
slug: string,
|
|
216
301
|
active: boolean,
|
|
217
|
-
options: { profile?: string } = {}
|
|
302
|
+
options: { profile?: string; json?: boolean } = {}
|
|
218
303
|
) {
|
|
219
304
|
const profileName = resolveProfileName(options.profile);
|
|
220
305
|
const client = getClient(profileName);
|
|
221
|
-
const spinner =
|
|
222
|
-
|
|
223
|
-
|
|
306
|
+
const spinner = options.json
|
|
307
|
+
? null
|
|
308
|
+
: ora(`${active ? 'Enabling' : 'Disabling'} ${slug}...`).start();
|
|
224
309
|
const result = await client.code.toggleFunction(slug, active);
|
|
225
310
|
if (!result.success) {
|
|
226
|
-
|
|
311
|
+
if (options.json) {
|
|
312
|
+
jsonOutput({ success: false, error: result.error.message });
|
|
313
|
+
}
|
|
314
|
+
spinner?.fail(`Toggle failed for ${slug}`);
|
|
227
315
|
console.error(result.error.message);
|
|
228
316
|
process.exit(1);
|
|
229
317
|
}
|
|
230
|
-
|
|
318
|
+
if (options.json) {
|
|
319
|
+
jsonOutput({ success: true, slug, active });
|
|
320
|
+
}
|
|
321
|
+
spinner?.succeed(`${slug} is now ${active ? 'active' : 'inactive'}`);
|
|
231
322
|
}
|