@globio/cli 0.1.4 → 0.1.6
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 +54 -14
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/src/auth/login.ts +22 -0
- package/src/commands/init.ts +1 -0
- package/src/commands/profiles.ts +26 -0
- package/src/index.ts +11 -0
package/dist/index.js
CHANGED
|
@@ -198,6 +198,19 @@ async function savePat(token) {
|
|
|
198
198
|
const account = await manageRequest("/account", { token });
|
|
199
199
|
return account;
|
|
200
200
|
}
|
|
201
|
+
function warnOnDuplicateAccount(accountEmail, targetProfileName) {
|
|
202
|
+
const allProfiles = config.listProfiles();
|
|
203
|
+
const duplicate = allProfiles.find((name) => {
|
|
204
|
+
const profile = config.getProfile(name);
|
|
205
|
+
return profile?.account_email === accountEmail && name !== targetProfileName;
|
|
206
|
+
});
|
|
207
|
+
if (!duplicate) return;
|
|
208
|
+
console.log("");
|
|
209
|
+
console.log(
|
|
210
|
+
chalk2.yellow(" \u26A0 ") + chalk2.white(accountEmail) + chalk2.gray(" is already logged in under profile ") + orange(`"${duplicate}"`) + chalk2.gray(".")
|
|
211
|
+
);
|
|
212
|
+
console.log("");
|
|
213
|
+
}
|
|
201
214
|
async function runTokenLogin(profileName) {
|
|
202
215
|
const hadProfiles = config.listProfiles().length > 0;
|
|
203
216
|
const token = await p.text({
|
|
@@ -217,6 +230,7 @@ async function runTokenLogin(profileName) {
|
|
|
217
230
|
spinner2.start("Validating personal access token...");
|
|
218
231
|
try {
|
|
219
232
|
const account = await savePat(token);
|
|
233
|
+
warnOnDuplicateAccount(account.email, profileName);
|
|
220
234
|
config.setProfile(profileName, {
|
|
221
235
|
pat: token,
|
|
222
236
|
account_email: account.email,
|
|
@@ -264,6 +278,7 @@ async function runBrowserLogin(profileName) {
|
|
|
264
278
|
method: "POST",
|
|
265
279
|
body: { code: status.code }
|
|
266
280
|
});
|
|
281
|
+
warnOnDuplicateAccount(exchange.account.email, profileName);
|
|
267
282
|
config.setProfile(profileName, {
|
|
268
283
|
pat: exchange.token,
|
|
269
284
|
account_email: exchange.account.email,
|
|
@@ -778,6 +793,7 @@ async function init(options = {}) {
|
|
|
778
793
|
|
|
779
794
|
export const globio = new Globio({
|
|
780
795
|
apiKey: process.env.GLOBIO_API_KEY!,
|
|
796
|
+
projectId: '${activeProjectId}',
|
|
781
797
|
});
|
|
782
798
|
`
|
|
783
799
|
);
|
|
@@ -816,8 +832,30 @@ export const globio = new Globio({
|
|
|
816
832
|
);
|
|
817
833
|
}
|
|
818
834
|
|
|
819
|
-
// src/commands/
|
|
835
|
+
// src/commands/profiles.ts
|
|
820
836
|
import chalk9 from "chalk";
|
|
837
|
+
async function profilesList() {
|
|
838
|
+
const profiles2 = config.listProfiles();
|
|
839
|
+
const active = config.getActiveProfile();
|
|
840
|
+
if (!profiles2.length) {
|
|
841
|
+
console.log(chalk9.gray("No profiles found. Run: globio login"));
|
|
842
|
+
return;
|
|
843
|
+
}
|
|
844
|
+
console.log("");
|
|
845
|
+
for (const name of profiles2) {
|
|
846
|
+
const data = config.getProfile(name);
|
|
847
|
+
const isActive = name === active;
|
|
848
|
+
const bullet = isActive ? orange("\u25CF") : chalk9.gray("\u25CB");
|
|
849
|
+
const label = isActive ? orange(name) : chalk9.white(name);
|
|
850
|
+
const email = data?.account_email ? muted(data.account_email) : chalk9.gray("unknown");
|
|
851
|
+
const tag = isActive ? muted(" (active)") : "";
|
|
852
|
+
console.log(` ${bullet} ${label} ${email}${tag}`);
|
|
853
|
+
}
|
|
854
|
+
console.log("");
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
// src/commands/services.ts
|
|
858
|
+
import chalk10 from "chalk";
|
|
821
859
|
var ALL_SERVICES = [
|
|
822
860
|
"id",
|
|
823
861
|
"doc",
|
|
@@ -834,19 +872,19 @@ async function servicesList(options = {}) {
|
|
|
834
872
|
void options.profile;
|
|
835
873
|
void config;
|
|
836
874
|
console.log("");
|
|
837
|
-
console.log(
|
|
875
|
+
console.log(chalk10.cyan("Available Globio services:"));
|
|
838
876
|
ALL_SERVICES.forEach((service) => {
|
|
839
|
-
console.log(" " +
|
|
877
|
+
console.log(" " + chalk10.white(service));
|
|
840
878
|
});
|
|
841
879
|
console.log("");
|
|
842
880
|
console.log(
|
|
843
|
-
|
|
881
|
+
chalk10.gray("Manage service access via console.globio.stanlink.online")
|
|
844
882
|
);
|
|
845
883
|
console.log("");
|
|
846
884
|
}
|
|
847
885
|
|
|
848
886
|
// src/commands/functions.ts
|
|
849
|
-
import
|
|
887
|
+
import chalk11 from "chalk";
|
|
850
888
|
import ora from "ora";
|
|
851
889
|
import { existsSync as existsSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
852
890
|
function resolveProfileName3(profile) {
|
|
@@ -859,7 +897,7 @@ async function functionsList(options = {}) {
|
|
|
859
897
|
const result = await client.code.listFunctions();
|
|
860
898
|
spinner2.stop();
|
|
861
899
|
if (!result.success || !result.data.length) {
|
|
862
|
-
console.log(
|
|
900
|
+
console.log(chalk11.gray("No functions found."));
|
|
863
901
|
return;
|
|
864
902
|
}
|
|
865
903
|
console.log("");
|
|
@@ -876,7 +914,7 @@ async function functionsList(options = {}) {
|
|
|
876
914
|
async function functionsCreate(slug, _options = {}) {
|
|
877
915
|
const filename = `${slug}.js`;
|
|
878
916
|
if (existsSync3(filename)) {
|
|
879
|
-
console.log(
|
|
917
|
+
console.log(chalk11.yellow(`${filename} already exists.`));
|
|
880
918
|
return;
|
|
881
919
|
}
|
|
882
920
|
const template = `/**
|
|
@@ -895,16 +933,16 @@ async function handler(input, globio) {
|
|
|
895
933
|
}
|
|
896
934
|
`;
|
|
897
935
|
writeFileSync3(filename, template);
|
|
898
|
-
console.log(
|
|
936
|
+
console.log(chalk11.green(`Created ${filename}`));
|
|
899
937
|
console.log(
|
|
900
|
-
|
|
938
|
+
chalk11.gray(`Deploy with: npx @globio/cli functions deploy ${slug}`)
|
|
901
939
|
);
|
|
902
940
|
}
|
|
903
941
|
async function functionsDeploy(slug, options) {
|
|
904
942
|
const filename = options.file ?? `${slug}.js`;
|
|
905
943
|
if (!existsSync3(filename)) {
|
|
906
944
|
console.log(
|
|
907
|
-
|
|
945
|
+
chalk11.red(
|
|
908
946
|
`File not found: ${filename}. Create it with: npx @globio/cli functions create ${slug}`
|
|
909
947
|
)
|
|
910
948
|
);
|
|
@@ -942,7 +980,7 @@ async function functionsInvoke(slug, options) {
|
|
|
942
980
|
try {
|
|
943
981
|
input = JSON.parse(options.input);
|
|
944
982
|
} catch {
|
|
945
|
-
console.error(
|
|
983
|
+
console.error(chalk11.red("--input must be valid JSON"));
|
|
946
984
|
process.exit(1);
|
|
947
985
|
}
|
|
948
986
|
}
|
|
@@ -952,7 +990,7 @@ async function functionsInvoke(slug, options) {
|
|
|
952
990
|
const result = await client.code.invoke(slug, input);
|
|
953
991
|
spinner2.stop();
|
|
954
992
|
if (!result.success) {
|
|
955
|
-
console.log(
|
|
993
|
+
console.log(chalk11.red("Invocation failed"));
|
|
956
994
|
console.error(result.error.message);
|
|
957
995
|
return;
|
|
958
996
|
}
|
|
@@ -970,7 +1008,7 @@ async function functionsLogs(slug, options) {
|
|
|
970
1008
|
const result = await client.code.getInvocations(slug, limit);
|
|
971
1009
|
spinner2.stop();
|
|
972
1010
|
if (!result.success || !result.data.length) {
|
|
973
|
-
console.log(
|
|
1011
|
+
console.log(chalk11.gray("No invocations yet."));
|
|
974
1012
|
return;
|
|
975
1013
|
}
|
|
976
1014
|
console.log("");
|
|
@@ -978,7 +1016,7 @@ async function functionsLogs(slug, options) {
|
|
|
978
1016
|
const status = inv.success ? "\x1B[38;2;244;140;6m\u2713\x1B[0m" : "\x1B[31m\u2717\x1B[0m";
|
|
979
1017
|
const date = new Date(inv.invoked_at * 1e3).toISOString().replace("T", " ").slice(0, 19);
|
|
980
1018
|
console.log(
|
|
981
|
-
` ${status} ${
|
|
1019
|
+
` ${status} ${chalk11.gray(date)} ${inv.duration_ms}ms ${chalk11.gray(`[${inv.trigger_type}]`)}`
|
|
982
1020
|
);
|
|
983
1021
|
});
|
|
984
1022
|
console.log("");
|
|
@@ -1036,6 +1074,8 @@ program.command("logout").description("Log out").option("--profile <name>", "Use
|
|
|
1036
1074
|
program.command("whoami").description("Show current account and project").option("--profile <name>", "Use a specific profile").action(whoami);
|
|
1037
1075
|
program.command("use <profile>").description("Switch active profile").action(useProfile);
|
|
1038
1076
|
program.command("init").description("Initialize a Globio project").option("--profile <name>", "Use a specific profile").action(init);
|
|
1077
|
+
var profiles = program.command("profiles").description("Manage login profiles").action(profilesList);
|
|
1078
|
+
profiles.command("list").description("List all profiles").action(profilesList);
|
|
1039
1079
|
var projects = program.command("projects").description("Manage projects");
|
|
1040
1080
|
projects.command("list").description("List projects").option("--profile <name>", "Use a specific profile").action(projectsList);
|
|
1041
1081
|
projects.command("create").description("Create a project").option("--profile <name>", "Use a specific profile").action(projectsCreate);
|
package/jsr.json
CHANGED
package/package.json
CHANGED
package/src/auth/login.ts
CHANGED
|
@@ -26,6 +26,26 @@ async function savePat(token: string) {
|
|
|
26
26
|
return account;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
function warnOnDuplicateAccount(accountEmail: string, targetProfileName: string) {
|
|
30
|
+
const allProfiles = config.listProfiles();
|
|
31
|
+
const duplicate = allProfiles.find((name) => {
|
|
32
|
+
const profile = config.getProfile(name);
|
|
33
|
+
return profile?.account_email === accountEmail && name !== targetProfileName;
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
if (!duplicate) return;
|
|
37
|
+
|
|
38
|
+
console.log('');
|
|
39
|
+
console.log(
|
|
40
|
+
chalk.yellow(' ⚠ ') +
|
|
41
|
+
chalk.white(accountEmail) +
|
|
42
|
+
chalk.gray(' is already logged in under profile ') +
|
|
43
|
+
orange(`"${duplicate}"`) +
|
|
44
|
+
chalk.gray('.')
|
|
45
|
+
);
|
|
46
|
+
console.log('');
|
|
47
|
+
}
|
|
48
|
+
|
|
29
49
|
async function runTokenLogin(profileName: string) {
|
|
30
50
|
const hadProfiles = config.listProfiles().length > 0;
|
|
31
51
|
const token = await p.text({
|
|
@@ -47,6 +67,7 @@ async function runTokenLogin(profileName: string) {
|
|
|
47
67
|
spinner.start('Validating personal access token...');
|
|
48
68
|
try {
|
|
49
69
|
const account = await savePat(token);
|
|
70
|
+
warnOnDuplicateAccount(account.email, profileName);
|
|
50
71
|
config.setProfile(profileName, {
|
|
51
72
|
pat: token,
|
|
52
73
|
account_email: account.email,
|
|
@@ -104,6 +125,7 @@ async function runBrowserLogin(profileName: string) {
|
|
|
104
125
|
body: { code: status.code },
|
|
105
126
|
});
|
|
106
127
|
|
|
128
|
+
warnOnDuplicateAccount(exchange.account.email, profileName);
|
|
107
129
|
config.setProfile(profileName, {
|
|
108
130
|
pat: exchange.token,
|
|
109
131
|
account_email: exchange.account.email,
|
package/src/commands/init.ts
CHANGED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { orange, muted } from '../lib/banner.js';
|
|
3
|
+
import { config } from '../lib/config.js';
|
|
4
|
+
|
|
5
|
+
export async function profilesList() {
|
|
6
|
+
const profiles = config.listProfiles();
|
|
7
|
+
const active = config.getActiveProfile();
|
|
8
|
+
|
|
9
|
+
if (!profiles.length) {
|
|
10
|
+
console.log(chalk.gray('No profiles found. Run: globio login'));
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
console.log('');
|
|
15
|
+
for (const name of profiles) {
|
|
16
|
+
const data = config.getProfile(name);
|
|
17
|
+
const isActive = name === active;
|
|
18
|
+
const bullet = isActive ? orange('●') : chalk.gray('○');
|
|
19
|
+
const label = isActive ? orange(name) : chalk.white(name);
|
|
20
|
+
const email = data?.account_email ? muted(data.account_email) : chalk.gray('unknown');
|
|
21
|
+
const tag = isActive ? muted(' (active)') : '';
|
|
22
|
+
|
|
23
|
+
console.log(` ${bullet} ${label} ${email}${tag}`);
|
|
24
|
+
}
|
|
25
|
+
console.log('');
|
|
26
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { useProfile } from './auth/useProfile.js';
|
|
|
6
6
|
import { whoami } from './auth/whoami.js';
|
|
7
7
|
import { init } from './commands/init.js';
|
|
8
8
|
import { projectsCreate, projectsList, projectsUse } from './commands/projects.js';
|
|
9
|
+
import { profilesList } from './commands/profiles.js';
|
|
9
10
|
import { servicesList } from './commands/services.js';
|
|
10
11
|
import {
|
|
11
12
|
functionsList,
|
|
@@ -62,6 +63,16 @@ program.command('use <profile>').description('Switch active profile').action(use
|
|
|
62
63
|
|
|
63
64
|
program.command('init').description('Initialize a Globio project').option('--profile <name>', 'Use a specific profile').action(init);
|
|
64
65
|
|
|
66
|
+
const profiles = program
|
|
67
|
+
.command('profiles')
|
|
68
|
+
.description('Manage login profiles')
|
|
69
|
+
.action(profilesList);
|
|
70
|
+
|
|
71
|
+
profiles
|
|
72
|
+
.command('list')
|
|
73
|
+
.description('List all profiles')
|
|
74
|
+
.action(profilesList);
|
|
75
|
+
|
|
65
76
|
const projects = program.command('projects').description('Manage projects');
|
|
66
77
|
projects.command('list').description('List projects').option('--profile <name>', 'Use a specific profile').action(projectsList);
|
|
67
78
|
projects.command('create').description('Create a project').option('--profile <name>', 'Use a specific profile').action(projectsCreate);
|