@globio/cli 0.1.8 → 0.1.9

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/jsr.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@globio/cli",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "license": "MIT",
5
5
  "exports": "./src/index.ts"
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@globio/cli",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "The official CLI for Globio — game backend as a service",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/auth/login.ts CHANGED
@@ -1,9 +1,8 @@
1
1
  import * as p from '@clack/prompts';
2
2
  import { exec } from 'child_process';
3
- import chalk from 'chalk';
4
3
  import { config } from '../lib/config.js';
5
4
  import { getConsoleCliAuthUrl, manageRequest, type ManageAccount } from '../lib/manage.js';
6
- import { getCliVersion, muted, orange, printBanner } from '../lib/banner.js';
5
+ import { failure, getCliVersion, muted, orange, printBanner, white } from '../lib/banner.js';
7
6
 
8
7
  const version = getCliVersion();
9
8
 
@@ -37,11 +36,11 @@ function warnOnDuplicateAccount(accountEmail: string, targetProfileName: string)
37
36
 
38
37
  console.log('');
39
38
  console.log(
40
- chalk.yellow(' ⚠ ') +
41
- chalk.white(accountEmail) +
42
- chalk.gray(' is already logged in under profile ') +
39
+ failure(' ⚠ ') +
40
+ white(accountEmail) +
41
+ '\x1b[2m is already logged in under profile \x1b[0m' +
43
42
  orange(`"${duplicate}"`) +
44
- chalk.gray('.')
43
+ '\x1b[2m.\x1b[0m'
45
44
  );
46
45
  console.log('');
47
46
  }
@@ -81,7 +80,7 @@ async function runTokenLogin(profileName: string) {
81
80
  p.outro(`Logged in as ${account.email}\nProfile: ${profileName}`);
82
81
  } catch (error) {
83
82
  spinner.stop('Validation failed.');
84
- p.outro(chalk.red(error instanceof Error ? error.message : 'Could not validate token'));
83
+ p.outro(failure(error instanceof Error ? error.message : 'Could not validate token') + '\x1b[0m');
85
84
  process.exit(1);
86
85
  }
87
86
  }
@@ -112,7 +111,7 @@ async function runBrowserLogin(profileName: string) {
112
111
 
113
112
  if (status.status === 'expired') {
114
113
  spinner.stop('Approval window expired.');
115
- p.outro(chalk.red('CLI auth request expired. Try again or use globio login --token.'));
114
+ p.outro(failure('CLI auth request expired. Try again or use globio login --token.') + '\x1b[0m');
116
115
  process.exit(1);
117
116
  }
118
117
 
@@ -148,7 +147,7 @@ async function runBrowserLogin(profileName: string) {
148
147
  }
149
148
 
150
149
  spinner.stop('Approval timed out.');
151
- p.outro(chalk.red('Timed out waiting for browser approval. Try again or use globio login --token.'));
150
+ p.outro(failure('Timed out waiting for browser approval. Try again or use globio login --token.') + '\x1b[0m');
152
151
  process.exit(1);
153
152
  }
154
153
 
@@ -195,7 +194,7 @@ export async function login(options: { token?: boolean; profile?: string } = {})
195
194
  try {
196
195
  await runBrowserLogin(profileName);
197
196
  } catch (error) {
198
- p.outro(chalk.red(error instanceof Error ? error.message : 'Could not connect to Globio.'));
197
+ p.outro(failure(error instanceof Error ? error.message : 'Could not connect to Globio.') + '\x1b[0m');
199
198
  process.exit(1);
200
199
  }
201
200
  }
@@ -1,5 +1,5 @@
1
- import chalk from 'chalk';
2
1
  import { config } from '../lib/config.js';
2
+ import { green, inactive } from '../lib/banner.js';
3
3
 
4
4
  export async function logout(options: { profile?: string } = {}) {
5
5
  const activeProfile = config.getActiveProfile();
@@ -7,7 +7,7 @@ export async function logout(options: { profile?: string } = {}) {
7
7
  const profile = profileName ? config.getProfile(profileName) : null;
8
8
 
9
9
  if (!profileName || !profile) {
10
- console.log(chalk.yellow(`No active session on profile "${profileName || 'default'}".`));
10
+ console.log(inactive(`No active session on profile "${profileName || 'default'}".`));
11
11
  return;
12
12
  }
13
13
 
@@ -17,14 +17,14 @@ export async function logout(options: { profile?: string } = {}) {
17
17
  const remaining = config.listProfiles();
18
18
  if (remaining.length > 0) {
19
19
  config.setActiveProfile(remaining[0]);
20
- console.log(chalk.green(`Logged out. Switched to profile: ${remaining[0]}`));
20
+ console.log(green(`Logged out. Switched to profile: ${remaining[0]}`));
21
21
  return;
22
22
  }
23
23
 
24
24
  config.setActiveProfile('');
25
- console.log(chalk.green('Logged out.'));
25
+ console.log(green('Logged out.'));
26
26
  return;
27
27
  }
28
28
 
29
- console.log(chalk.green(`Logged out profile: ${profileName}`));
29
+ console.log(green(`Logged out profile: ${profileName}`));
30
30
  }
@@ -1,37 +1,76 @@
1
- import chalk from 'chalk';
2
1
  import { config } from '../lib/config.js';
3
- import { muted, orange } from '../lib/banner.js';
2
+ import {
3
+ failure,
4
+ getCliVersion,
5
+ header,
6
+ inactive,
7
+ muted,
8
+ orange,
9
+ renderTable,
10
+ white,
11
+ gold,
12
+ reset,
13
+ } from '../lib/banner.js';
14
+
15
+ const version = getCliVersion();
4
16
 
5
17
  export async function whoami(options: { profile?: string } = {}) {
6
18
  const profileName = options.profile ?? config.getActiveProfile() ?? 'default';
7
19
  const profile = config.getProfile(profileName);
8
20
 
9
21
  if (!profile) {
10
- console.log(chalk.red('Not logged in. Run: globio login'));
22
+ console.log(
23
+ header(version) +
24
+ ' ' +
25
+ failure('Not logged in.') +
26
+ reset +
27
+ ' Run: globio login\n'
28
+ );
11
29
  return;
12
30
  }
13
31
 
14
32
  const allProfiles = config.listProfiles();
15
- const activeProfile = config.getActiveProfile();
33
+ const active = config.getActiveProfile();
34
+ const otherProfiles = allProfiles.filter((p) => p !== profileName).join(', ') || '—';
16
35
 
17
- console.log('');
18
36
  console.log(
19
- muted('Profile: ') + orange(profileName) + (profileName === activeProfile ? muted(' (active)') : '')
37
+ header(
38
+ version,
39
+ 'Logged in as ' +
40
+ orange(profile.account_name || profile.account_email) +
41
+ reset +
42
+ ' · ' +
43
+ muted(profile.account_email)
44
+ )
20
45
  );
21
- console.log(muted('Account: ') + profile.account_email);
22
- console.log(muted('Name: ') + (profile.account_name || '—'));
46
+
23
47
  console.log(
24
- muted('Project: ') +
25
- (profile.active_project_id
26
- ? orange(profile.active_project_name || 'unnamed') + muted(` (${profile.active_project_id})`)
27
- : chalk.gray('none — run: globio projects use <id>'))
48
+ renderTable({
49
+ columns: [
50
+ { header: 'Profile', width: 16 },
51
+ { header: 'Value', width: 44 },
52
+ ],
53
+ rows: [
54
+ [
55
+ 'Profile',
56
+ profileName === active
57
+ ? orange(profileName) + reset + ' ' + inactive('(active)')
58
+ : inactive(profileName),
59
+ ],
60
+ ['Other profiles', inactive(otherProfiles)],
61
+ ['Account', white(profile.account_name || '—')],
62
+ ['Organization', white(profile.org_name || '—')],
63
+ [
64
+ 'Active project',
65
+ profile.active_project_id
66
+ ? gold(profile.active_project_name || 'unnamed') +
67
+ reset +
68
+ ' ' +
69
+ inactive(profile.active_project_id)
70
+ : inactive('none — run: globio projects use <id>'),
71
+ ],
72
+ ],
73
+ })
28
74
  );
29
-
30
- if (allProfiles.length > 1) {
31
- console.log('');
32
- console.log(
33
- muted('Other profiles: ') + allProfiles.filter((name) => name !== profileName).join(', ')
34
- );
35
- }
36
75
  console.log('');
37
76
  }
@@ -1,11 +1,22 @@
1
- import chalk from 'chalk';
2
1
  import type { CodeFunction, CodeInvocation } from '@globio/sdk';
3
2
  import ora from 'ora';
4
3
  import { existsSync, readFileSync, writeFileSync } from 'fs';
5
4
  import { config } from '../lib/config.js';
6
- import { gold, muted, orange } from '../lib/banner.js';
5
+ import {
6
+ failure,
7
+ getCliVersion,
8
+ green,
9
+ header,
10
+ inactive,
11
+ muted,
12
+ orange,
13
+ gold,
14
+ renderTable,
15
+ } from '../lib/banner.js';
7
16
  import { getClient } from '../lib/sdk.js';
8
17
 
18
+ const version = getCliVersion();
19
+
9
20
  function resolveProfileName(profile?: string) {
10
21
  return profile ?? config.getActiveProfile() ?? 'default';
11
22
  }
@@ -13,32 +24,39 @@ function resolveProfileName(profile?: string) {
13
24
  export async function functionsList(options: { profile?: string } = {}) {
14
25
  const profileName = resolveProfileName(options.profile);
15
26
  const client = getClient(profileName);
16
- const spinner = ora('Fetching functions...').start();
17
27
  const result = await client.code.listFunctions();
18
- spinner.stop();
19
28
 
20
29
  if (!result.success || !result.data.length) {
21
- console.log(chalk.gray('No functions found.'));
30
+ console.log(header(version) + ' ' + muted('No functions found.') + '\n');
22
31
  return;
23
32
  }
24
33
 
25
- console.log('');
26
- result.data.forEach((fn: CodeFunction) => {
27
- const status = fn.active ? '\x1b[32m●\x1b[0m' : '\x1b[2m○\x1b[0m';
28
- const type =
29
- fn.type === 'hook' ? gold('[hook]') : orange('[function]');
30
- console.log(' ' + status + ' ' + type + ' ' + fn.slug);
31
- if (fn.type === 'hook' && fn.trigger_event) {
32
- console.log(muted(' trigger: ' + fn.trigger_event));
33
- }
34
- });
34
+ const rows = result.data.map((fn: CodeFunction) => [
35
+ fn.type === 'hook' ? gold(fn.slug) : orange(fn.slug),
36
+ fn.type === 'hook' ? gold('hook') : orange('function'),
37
+ fn.type === 'hook' && fn.trigger_event ? gold(fn.trigger_event) : muted('http'),
38
+ fn.active ? green('active') : inactive('inactive'),
39
+ ]);
40
+
41
+ console.log(header(version));
42
+ console.log(
43
+ renderTable({
44
+ columns: [
45
+ { header: 'Function', width: 24 },
46
+ { header: 'Type', width: 10 },
47
+ { header: 'Trigger', width: 20 },
48
+ { header: 'Status', width: 10 },
49
+ ],
50
+ rows,
51
+ })
52
+ );
35
53
  console.log('');
36
54
  }
37
55
 
38
56
  export async function functionsCreate(slug: string, _options: { profile?: string } = {}) {
39
57
  const filename = `${slug}.js`;
40
58
  if (existsSync(filename)) {
41
- console.log(chalk.yellow(`${filename} already exists.`));
59
+ console.log(inactive(`${filename} already exists.`));
42
60
  return;
43
61
  }
44
62
 
@@ -58,10 +76,8 @@ async function handler(input, globio) {
58
76
  }
59
77
  `;
60
78
  writeFileSync(filename, template);
61
- console.log(chalk.green(`Created ${filename}`));
62
- console.log(
63
- chalk.gray(`Deploy with: npx @globio/cli functions deploy ${slug}`)
64
- );
79
+ console.log(green(`Created ${filename}`));
80
+ console.log(muted(`Deploy with: npx @globio/cli functions deploy ${slug}`));
65
81
  }
66
82
 
67
83
  export async function functionsDeploy(
@@ -71,7 +87,7 @@ export async function functionsDeploy(
71
87
  const filename = options.file ?? `${slug}.js`;
72
88
  if (!existsSync(filename)) {
73
89
  console.log(
74
- chalk.red(
90
+ failure(
75
91
  `File not found: ${filename}. Create it with: npx @globio/cli functions create ${slug}`
76
92
  )
77
93
  );
@@ -117,7 +133,7 @@ export async function functionsInvoke(
117
133
  try {
118
134
  input = JSON.parse(options.input) as Record<string, unknown>;
119
135
  } catch {
120
- console.error(chalk.red('--input must be valid JSON'));
136
+ console.error(failure('--input must be valid JSON'));
121
137
  process.exit(1);
122
138
  }
123
139
  }
@@ -129,7 +145,7 @@ export async function functionsInvoke(
129
145
  spinner.stop();
130
146
 
131
147
  if (!result.success) {
132
- console.log(chalk.red('Invocation failed'));
148
+ console.log(failure('Invocation failed'));
133
149
  console.error(result.error.message);
134
150
  return;
135
151
  }
@@ -147,28 +163,38 @@ export async function functionsLogs(
147
163
  const limit = options.limit ? parseInt(options.limit, 10) : 20;
148
164
  const profileName = resolveProfileName(options.profile);
149
165
  const client = getClient(profileName);
150
- const spinner = ora('Fetching invocations...').start();
151
166
  const result = await client.code.getInvocations(slug, limit);
152
- spinner.stop();
153
167
 
154
168
  if (!result.success || !result.data.length) {
155
- console.log(chalk.gray('No invocations yet.'));
169
+ console.log(header(version) + ' ' + muted('No invocations yet.') + '\n');
156
170
  return;
157
171
  }
158
172
 
159
- console.log('');
160
- result.data.forEach((inv: CodeInvocation) => {
161
- const status = inv.success
162
- ? '\x1b[38;2;244;140;6m✓\x1b[0m'
163
- : '\x1b[31m✗\x1b[0m';
173
+ const rows = result.data.map((inv: CodeInvocation) => {
164
174
  const date = new Date(inv.invoked_at * 1000)
165
175
  .toISOString()
166
176
  .replace('T', ' ')
167
177
  .slice(0, 19);
168
- console.log(
169
- ` ${status} ${chalk.gray(date)} ${inv.duration_ms}ms ${chalk.gray(`[${inv.trigger_type}]`)}`
170
- );
178
+ return [
179
+ muted(date),
180
+ muted(inv.trigger_type),
181
+ muted(inv.duration_ms + 'ms'),
182
+ inv.success ? green('success') : failure('failed'),
183
+ ];
171
184
  });
185
+
186
+ console.log(header(version));
187
+ console.log(
188
+ renderTable({
189
+ columns: [
190
+ { header: 'Time', width: 21 },
191
+ { header: 'Trigger', width: 9 },
192
+ { header: 'Duration', width: 10 },
193
+ { header: 'Status', width: 10 },
194
+ ],
195
+ rows,
196
+ })
197
+ );
172
198
  console.log('');
173
199
  }
174
200
 
@@ -2,6 +2,7 @@ import * as p from '@clack/prompts';
2
2
  import { existsSync, readFileSync, writeFileSync } from 'fs';
3
3
  import { config } from '../lib/config.js';
4
4
  import {
5
+ failure,
5
6
  getCliVersion,
6
7
  muted,
7
8
  orange,
@@ -21,7 +22,7 @@ export async function init(options: { profile?: string } = {}) {
21
22
  const profileName = options.profile ?? config.getActiveProfile() ?? 'default';
22
23
  const profile = config.getProfile(profileName);
23
24
  if (!profile) {
24
- console.log('Run: npx @globio/cli login --profile ' + profileName);
25
+ console.log(failure('Run: npx @globio/cli login --profile ' + profileName));
25
26
  process.exit(1);
26
27
  }
27
28
 
@@ -37,7 +38,7 @@ export async function init(options: { profile?: string } = {}) {
37
38
  const { projectId: activeProjectId } = config.requireProject(profileName);
38
39
 
39
40
  if (!activeProjectKey) {
40
- console.log('No project API key cached. Run: npx @globio/cli projects use ' + activeProjectId);
41
+ console.log(failure('No project API key cached. Run: npx @globio/cli projects use ' + activeProjectId));
41
42
  process.exit(1);
42
43
  }
43
44
 
@@ -1,9 +1,10 @@
1
1
  import * as p from '@clack/prompts';
2
- import chalk from 'chalk';
3
2
  import { basename } from 'path';
4
3
  import {
4
+ failure,
5
5
  getCliVersion,
6
6
  gold,
7
+ green,
7
8
  muted,
8
9
  orange,
9
10
  printBanner,
@@ -47,14 +48,14 @@ export async function migrateFirestore(options: MigrateFirestoreOptions) {
47
48
  const snapshot = await firestore.listCollections();
48
49
  collections = snapshot.map((collection) => collection.id);
49
50
  console.log(
50
- chalk.cyan(
51
+ green(
51
52
  `Found ${collections.length} collections: ${collections.join(', ')}`
52
53
  )
53
54
  );
54
55
  } else if (options.collection) {
55
56
  collections = [options.collection];
56
57
  } else {
57
- console.log(chalk.red('Specify --collection <name> or --all'));
58
+ console.log(failure('Specify --collection <name> or --all'));
58
59
  process.exit(1);
59
60
  }
60
61
 
@@ -128,17 +129,17 @@ export async function migrateFirestore(options: MigrateFirestoreOptions) {
128
129
  bar.stop();
129
130
 
130
131
  console.log(
131
- chalk.green(` ✓ ${results[collectionId].success} documents migrated`)
132
+ green(` ✓ ${results[collectionId].success} documents migrated`)
132
133
  );
133
134
  if (indexFieldCount > 0) {
134
135
  console.log(
135
- chalk.gray(` Indexes created for ${indexFieldCount} fields`)
136
+ muted(` Indexes created for ${indexFieldCount} fields`)
136
137
  );
137
138
  }
138
139
  if (results[collectionId].failed > 0) {
139
- console.log(chalk.red(` ✗ ${results[collectionId].failed} failed`));
140
+ console.log(failure(` ✗ ${results[collectionId].failed} failed`) + '\x1b[0m');
140
141
  console.log(
141
- chalk.gray(
142
+ muted(
142
143
  ' Failed IDs: ' +
143
144
  results[collectionId].failedIds.slice(0, 10).join(', ') +
144
145
  (results[collectionId].failedIds.length > 10 ? '...' : '')
@@ -177,7 +178,7 @@ export async function migrateFirebaseStorage(options: MigrateStorageOptions) {
177
178
 
178
179
  const [files] = await bucket.getFiles(prefix ? { prefix } : {});
179
180
 
180
- console.log(chalk.cyan(`Found ${files.length} files to migrate`));
181
+ console.log(green(`Found ${files.length} files to migrate`));
181
182
 
182
183
  const bar = createProgressBar('Storage');
183
184
  bar.start(files.length, 0);
@@ -222,9 +223,9 @@ export async function migrateFirebaseStorage(options: MigrateStorageOptions) {
222
223
  bar.stop();
223
224
 
224
225
  console.log('');
225
- console.log(chalk.green(` ✓ ${success} files migrated`));
226
+ console.log(green(` ✓ ${success} files migrated`));
226
227
  if (failed > 0) {
227
- console.log(chalk.red(` ✗ ${failed} failed`));
228
+ console.log(failure(` ✗ ${failed} failed`) + '\x1b[0m');
228
229
  }
229
230
 
230
231
  p.outro(
@@ -1,26 +1,53 @@
1
- import chalk from 'chalk';
2
- import { orange, muted } from '../lib/banner.js';
1
+ import {
2
+ getCliVersion,
3
+ green,
4
+ header,
5
+ inactive,
6
+ muted,
7
+ orange,
8
+ renderTable,
9
+ reset,
10
+ white,
11
+ } from '../lib/banner.js';
3
12
  import { config } from '../lib/config.js';
4
13
 
14
+ const version = getCliVersion();
15
+
5
16
  export async function profilesList() {
6
17
  const profiles = config.listProfiles();
7
18
  const active = config.getActiveProfile();
8
19
 
9
20
  if (!profiles.length) {
10
- console.log(chalk.gray('No profiles found. Run: globio login'));
21
+ console.log(
22
+ header(version) + ' ' + muted('No profiles. Run: globio login') + '\n'
23
+ );
11
24
  return;
12
25
  }
13
26
 
14
- console.log('');
15
- for (const name of profiles) {
16
- const data = config.getProfile(name);
27
+ const rows = profiles.map((name) => {
28
+ const p = config.getProfile(name);
17
29
  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)') : '';
30
+ return [
31
+ isActive ? orange(name) : inactive(name),
32
+ p?.account_email
33
+ ? isActive
34
+ ? white(p.account_email)
35
+ : muted(p.account_email)
36
+ : inactive('—'),
37
+ isActive ? green('active') : inactive('—'),
38
+ ];
39
+ });
22
40
 
23
- console.log(` ${bullet} ${label} ${email}${tag}`);
24
- }
41
+ console.log(header(version));
42
+ console.log(
43
+ renderTable({
44
+ columns: [
45
+ { header: 'Profile', width: 16 },
46
+ { header: 'Account', width: 36 },
47
+ { header: 'Status', width: 10 },
48
+ ],
49
+ rows,
50
+ })
51
+ );
25
52
  console.log('');
26
53
  }
@@ -1,12 +1,28 @@
1
1
  import * as p from '@clack/prompts';
2
- import chalk from 'chalk';
3
2
  import { config } from '../lib/config.js';
4
3
  import {
5
4
  manageRequest,
6
5
  type ManageOrg,
7
6
  type ManageProject,
8
7
  type ManageProjectKey,
8
+ type ManageProjectServices,
9
9
  } from '../lib/manage.js';
10
+ import {
11
+ footer,
12
+ getCliVersion,
13
+ gold,
14
+ green,
15
+ header,
16
+ inactive,
17
+ muted,
18
+ orange,
19
+ renderTable,
20
+ reset,
21
+ white,
22
+ failure,
23
+ } from '../lib/banner.js';
24
+
25
+ const version = getCliVersion();
10
26
 
11
27
  function slugify(value: string) {
12
28
  return value
@@ -44,30 +60,36 @@ export async function projectsList(options: { profile?: string } = {}) {
44
60
 
45
61
  const projects = await manageRequest<ManageProject[]>('/projects', { profileName });
46
62
  const activeProjectId = config.getProfile(profileName)?.active_project_id;
47
- const grouped = new Map<string, ManageProject[]>();
48
-
49
- for (const project of projects) {
50
- const list = grouped.get(project.org_name) ?? [];
51
- list.push(project);
52
- grouped.set(project.org_name, list);
53
- }
54
63
 
55
- console.log('');
56
64
  if (!projects.length) {
57
- console.log(chalk.gray('No projects found.'));
58
- console.log('');
65
+ console.log(header(version) + ' ' + muted('No projects found.') + '\n');
59
66
  return;
60
67
  }
61
68
 
62
- for (const [orgName, orgProjects] of grouped.entries()) {
63
- console.log(chalk.cyan(`org: ${orgName}`));
64
- for (const project of orgProjects) {
65
- const marker = project.id === activeProjectId ? chalk.green('●') : chalk.gray('○');
66
- const active = project.id === activeProjectId ? chalk.green(' (active)') : '';
67
- console.log(` ${marker} ${project.slug.padEnd(22)} ${chalk.gray(project.id)}${active}`);
68
- }
69
- console.log('');
70
- }
69
+ const rows = projects.map((project) => [
70
+ activeProjectId === project.id
71
+ ? gold(project.name) + reset + ' ' + orange('●') + reset
72
+ : white(project.name),
73
+ muted(project.id),
74
+ muted(project.org_name || project.org_id),
75
+ inactive(project.environment?.slice(0, 4) ?? 'dev'),
76
+ ]);
77
+
78
+ console.log(header(version));
79
+ console.log(
80
+ renderTable({
81
+ columns: [
82
+ { header: 'Project', width: 24 },
83
+ { header: 'ID', width: 26 },
84
+ { header: 'Org', width: 16 },
85
+ { header: 'Env', width: 6 },
86
+ ],
87
+ rows,
88
+ })
89
+ );
90
+ console.log(
91
+ footer('● active project · run globio projects use <id> to switch')
92
+ );
71
93
  }
72
94
 
73
95
  export async function projectsUse(projectId: string, options: { profile?: string } = {}) {
@@ -77,7 +99,7 @@ export async function projectsUse(projectId: string, options: { profile?: string
77
99
  const projects = await manageRequest<ManageProject[]>('/projects', { profileName });
78
100
  const project = projects.find((item) => item.id === projectId);
79
101
  if (!project) {
80
- console.log(chalk.red(`Project not found: ${projectId}`));
102
+ console.log(failure(`Project not found: ${projectId}`));
81
103
  process.exit(1);
82
104
  }
83
105
 
@@ -87,13 +109,12 @@ export async function projectsUse(projectId: string, options: { profile?: string
87
109
  config.setProfile(profileName, {
88
110
  active_project_id: project.id,
89
111
  active_project_name: project.name,
112
+ org_name: project.org_name,
90
113
  project_api_key: apiKey,
91
114
  });
92
115
  config.setActiveProfile(profileName);
93
116
 
94
- console.log(
95
- chalk.green('Active project set to: ') + chalk.cyan(`${project.name} (${project.id})`)
96
- );
117
+ console.log(green('Active project: ') + `${project.name} (${project.id})`);
97
118
  }
98
119
 
99
120
  export async function projectsCreate(options: { profile?: string } = {}) {
@@ -102,7 +123,7 @@ export async function projectsCreate(options: { profile?: string } = {}) {
102
123
 
103
124
  const orgs = await manageRequest<ManageOrg[]>('/orgs', { profileName });
104
125
  if (!orgs.length) {
105
- console.log(chalk.red('No organizations found. Create one in the console first.'));
126
+ console.log(failure('No organizations found. Create one in the console first.'));
106
127
  process.exit(1);
107
128
  }
108
129
 
@@ -168,14 +189,15 @@ export async function projectsCreate(options: { profile?: string } = {}) {
168
189
  config.setProfile(profileName, {
169
190
  active_project_id: result.project.id,
170
191
  active_project_name: result.project.name,
192
+ org_name: orgs.find((org) => org.id === orgId)?.name,
171
193
  project_api_key: result.keys.server,
172
194
  });
173
195
  config.setActiveProfile(profileName);
174
196
 
175
197
  console.log('');
176
- console.log(chalk.green('Project created successfully.'));
177
- console.log(chalk.cyan('Project: ') + `${result.project.name} (${result.project.id})`);
178
- console.log(chalk.cyan('Client key: ') + result.keys.client);
179
- console.log(chalk.cyan('Server key: ') + result.keys.server);
198
+ console.log(green('Project created successfully.'));
199
+ console.log(orange('Project: ') + reset + `${result.project.name} (${result.project.id})`);
200
+ console.log(orange('Client key: ') + reset + result.keys.client);
201
+ console.log(orange('Server key: ') + reset + result.keys.server);
180
202
  console.log('');
181
203
  }