@globio/cli 0.0.1 → 0.1.1

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/src/index.ts ADDED
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { login } from './auth/login.js';
4
+ import { logout } from './auth/logout.js';
5
+ import { whoami } from './auth/whoami.js';
6
+ import { init } from './commands/init.js';
7
+ import { projectsList, projectsUse } from './commands/projects.js';
8
+ import { servicesList } from './commands/services.js';
9
+ import {
10
+ functionsList,
11
+ functionsCreate,
12
+ functionsDeploy,
13
+ functionsInvoke,
14
+ functionsLogs,
15
+ functionsDelete,
16
+ functionsToggle,
17
+ } from './commands/functions.js';
18
+ import {
19
+ migrateFirestore,
20
+ migrateFirebaseStorage,
21
+ } from './commands/migrate.js';
22
+ import { getCliVersion, printBanner } from './lib/banner.js';
23
+
24
+ const version = getCliVersion();
25
+
26
+ const program = new Command();
27
+
28
+ program
29
+ .name('globio')
30
+ .description('The official Globio CLI')
31
+ .version(version)
32
+ .addHelpText('beforeAll', () => {
33
+ printBanner(version);
34
+ return '';
35
+ });
36
+
37
+ program.command('login').description('Log in to your Globio account').action(login);
38
+ program.command('logout').description('Log out').action(logout);
39
+ program.command('whoami').description('Show current account and project').action(whoami);
40
+
41
+ program.command('init').description('Initialize a Globio project').action(init);
42
+
43
+ const projects = program.command('projects').description('Manage projects');
44
+ projects.command('list').description('List projects').action(projectsList);
45
+ projects.command('use <projectId>').description('Set active project').action(projectsUse);
46
+
47
+ program.command('services').description('List available Globio services').action(servicesList);
48
+
49
+ const functions = program
50
+ .command('functions')
51
+ .alias('fn')
52
+ .description('Manage GlobalCode edge functions');
53
+
54
+ functions.command('list').description('List all functions').action(functionsList);
55
+ functions.command('create <slug>').description('Scaffold a new function file locally').action(functionsCreate);
56
+ functions
57
+ .command('deploy <slug>')
58
+ .description('Deploy a function to GlobalCode')
59
+ .option('-f, --file <path>', 'Path to function file')
60
+ .option('-n, --name <name>', 'Display name')
61
+ .action(functionsDeploy);
62
+ functions
63
+ .command('invoke <slug>')
64
+ .description('Invoke a function')
65
+ .option('-i, --input <json>', 'JSON input payload')
66
+ .action(functionsInvoke);
67
+ functions
68
+ .command('logs <slug>')
69
+ .description('Show invocation history')
70
+ .option('-l, --limit <n>', 'Number of entries', '20')
71
+ .action(functionsLogs);
72
+ functions.command('delete <slug>').description('Delete a function').action(functionsDelete);
73
+ functions.command('enable <slug>').description('Enable a function').action((slug) => functionsToggle(slug, true));
74
+ functions.command('disable <slug>').description('Disable a function').action((slug) => functionsToggle(slug, false));
75
+
76
+ const migrate = program
77
+ .command('migrate')
78
+ .description('Migrate from Firebase to Globio');
79
+
80
+ migrate
81
+ .command('firestore')
82
+ .description('Migrate Firestore collections to GlobalDoc')
83
+ .requiredOption('--from <path>', 'Path to Firebase service account JSON')
84
+ .option('--collection <name>', 'Migrate a specific collection')
85
+ .option('--all', 'Migrate all collections')
86
+ .action(migrateFirestore);
87
+
88
+ migrate
89
+ .command('firebase-storage')
90
+ .description('Migrate Firebase Storage to GlobalVault')
91
+ .requiredOption('--from <path>', 'Path to Firebase service account JSON')
92
+ .requiredOption('--bucket <name>', 'Firebase Storage bucket')
93
+ .option('--folder <path>', 'Migrate a specific folder')
94
+ .option('--all', 'Migrate all files')
95
+ .action(migrateFirebaseStorage);
96
+
97
+ if (process.argv.length <= 2) {
98
+ printBanner(version);
99
+ program.help();
100
+ }
101
+
102
+ await program.parseAsync();
@@ -0,0 +1,51 @@
1
+ import { readFileSync } from 'fs';
2
+ import figlet from 'figlet';
3
+ import gradientString from 'gradient-string';
4
+
5
+ const globioGradient = gradientString(
6
+ '#e85d04',
7
+ '#f48c06',
8
+ '#faa307',
9
+ '#ffba08',
10
+ '#ffd000'
11
+ );
12
+
13
+ export function printBanner(version: string) {
14
+ const art = figlet.textSync('Globio', {
15
+ font: 'ANSI Shadow',
16
+ horizontalLayout: 'default',
17
+ });
18
+
19
+ console.log(globioGradient.multiline(art));
20
+ console.log(
21
+ globioGradient(' ⇒⇒') +
22
+ ' Game Backend as a Service' +
23
+ ' \x1b[2mv' +
24
+ version +
25
+ '\x1b[0m'
26
+ );
27
+ console.log('');
28
+ }
29
+
30
+ export function printSuccess(message: string) {
31
+ console.log('\x1b[38;2;250;163;7m✓\x1b[0m ' + message);
32
+ }
33
+
34
+ export function printError(message: string) {
35
+ console.log('\x1b[31m✗\x1b[0m ' + message);
36
+ }
37
+
38
+ export function printInfo(message: string) {
39
+ console.log('\x1b[2m›\x1b[0m ' + message);
40
+ }
41
+
42
+ export const orange = (s: string) => '\x1b[38;2;244;140;6m' + s + '\x1b[0m';
43
+
44
+ export const gold = (s: string) => '\x1b[38;2;255;208;0m' + s + '\x1b[0m';
45
+
46
+ export const muted = (s: string) => '\x1b[2m' + s + '\x1b[0m';
47
+
48
+ export function getCliVersion() {
49
+ const file = readFileSync(new URL('../package.json', import.meta.url), 'utf8');
50
+ return (JSON.parse(file) as { version: string }).version;
51
+ }
@@ -0,0 +1,47 @@
1
+ import chalk from 'chalk';
2
+ import Conf from 'conf';
3
+
4
+ interface GlobioConfig {
5
+ apiKey?: string;
6
+ projectId?: string;
7
+ projectName?: string;
8
+ email?: string;
9
+ }
10
+
11
+ const store = new Conf<GlobioConfig>({
12
+ projectName: 'globio',
13
+ defaults: {},
14
+ });
15
+
16
+ export const config = {
17
+ get: (): GlobioConfig => store.store,
18
+ set: (values: Partial<GlobioConfig>) => {
19
+ Object.entries(values).forEach(([key, value]) => {
20
+ if (value !== undefined) {
21
+ store.set(key as keyof GlobioConfig, value);
22
+ }
23
+ });
24
+ },
25
+ clear: () => store.clear(),
26
+ getApiKey: () => store.get('apiKey'),
27
+ requireAuth: () => {
28
+ const key = store.get('apiKey');
29
+ if (!key) {
30
+ console.error(chalk.red('Not logged in. Run: npx @globio/cli login'));
31
+ process.exit(1);
32
+ }
33
+ return key;
34
+ },
35
+ requireProject: () => {
36
+ const projectId = store.get('projectId');
37
+ if (!projectId) {
38
+ console.error(
39
+ chalk.red('No active project. Run: npx @globio/cli projects use <projectId>')
40
+ );
41
+ process.exit(1);
42
+ }
43
+ return projectId;
44
+ },
45
+ };
46
+
47
+ export type { GlobioConfig };
@@ -0,0 +1,19 @@
1
+ export async function initFirebase(serviceAccountPath: string) {
2
+ const admin = await import('firebase-admin');
3
+ const { readFileSync } = await import('fs');
4
+
5
+ const serviceAccount = JSON.parse(readFileSync(serviceAccountPath, 'utf-8'));
6
+
7
+ if (!admin.default.apps.length) {
8
+ admin.default.initializeApp({
9
+ credential: admin.default.credential.cert(serviceAccount),
10
+ storageBucket: serviceAccount.project_id + '.appspot.com',
11
+ });
12
+ }
13
+
14
+ return {
15
+ firestore: admin.default.firestore(),
16
+ storage: admin.default.storage(),
17
+ app: admin.default.app(),
18
+ };
19
+ }
@@ -0,0 +1,17 @@
1
+ import chalk from 'chalk';
2
+ import cliProgress from 'cli-progress';
3
+
4
+ export function createProgressBar(label: string) {
5
+ const bar = new cliProgress.SingleBar(
6
+ {
7
+ format:
8
+ chalk.cyan(label) +
9
+ ' [{bar}] {percentage}% | {value}/{total}',
10
+ barCompleteChar: '█',
11
+ barIncompleteChar: '░',
12
+ hideCursor: true,
13
+ },
14
+ cliProgress.Presets.shades_classic
15
+ );
16
+ return bar;
17
+ }
package/src/lib/sdk.ts ADDED
@@ -0,0 +1,13 @@
1
+ import { Globio } from '@globio/sdk';
2
+ import { config } from './config.js';
3
+
4
+ export function getClient(): Globio {
5
+ const apiKey = config.requireAuth();
6
+ config.requireProject();
7
+ return new Globio({ apiKey });
8
+ }
9
+
10
+ export function getClientWithKey(apiKey: string, projectId: string): Globio {
11
+ void projectId;
12
+ return new Globio({ apiKey });
13
+ }
@@ -0,0 +1,38 @@
1
+ import * as p from '@clack/prompts';
2
+
3
+ export async function promptInit() {
4
+ return p.group(
5
+ {
6
+ apiKey: () =>
7
+ p.text({
8
+ message: 'Globio API key',
9
+ placeholder: 'gk_live_...',
10
+ validate: (value) => (!value ? 'Required' : undefined),
11
+ }),
12
+ projectId: () =>
13
+ p.text({
14
+ message: 'Project ID',
15
+ placeholder: 'proj_...',
16
+ validate: (value) => (!value ? 'Required' : undefined),
17
+ }),
18
+ migrateFromFirebase: () =>
19
+ p.confirm({
20
+ message: 'Migrating from Firebase?',
21
+ initialValue: false,
22
+ }),
23
+ serviceAccountPath: ({ results }) =>
24
+ results.migrateFromFirebase
25
+ ? p.text({
26
+ message: 'Path to Firebase service account JSON',
27
+ placeholder: './serviceAccountKey.json',
28
+ })
29
+ : Promise.resolve(undefined),
30
+ },
31
+ {
32
+ onCancel: () => {
33
+ p.cancel('Cancelled.');
34
+ process.exit(0);
35
+ },
36
+ }
37
+ );
38
+ }
@@ -0,0 +1,8 @@
1
+ import * as p from '@clack/prompts';
2
+
3
+ export async function confirmMigration(message: string) {
4
+ return p.confirm({
5
+ message,
6
+ initialValue: false,
7
+ });
8
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "outDir": "dist",
8
+ "rootDir": "src",
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true
11
+ },
12
+ "include": ["src"]
13
+ }