@globio/cli 0.0.1 → 0.1.0

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 CHANGED
@@ -1,2 +1,603 @@
1
1
  #!/usr/bin/env node
2
- console.log("globio CLI placeholder");
2
+
3
+ // src/index.ts
4
+ import { Command } from "commander";
5
+
6
+ // src/auth/login.ts
7
+ import * as p from "@clack/prompts";
8
+ import chalk2 from "chalk";
9
+
10
+ // src/lib/config.ts
11
+ import chalk from "chalk";
12
+ import Conf from "conf";
13
+ var store = new Conf({
14
+ projectName: "globio",
15
+ defaults: {}
16
+ });
17
+ var config = {
18
+ get: () => store.store,
19
+ set: (values) => {
20
+ Object.entries(values).forEach(([key, value]) => {
21
+ if (value !== void 0) {
22
+ store.set(key, value);
23
+ }
24
+ });
25
+ },
26
+ clear: () => store.clear(),
27
+ getApiKey: () => store.get("apiKey"),
28
+ requireAuth: () => {
29
+ const key = store.get("apiKey");
30
+ if (!key) {
31
+ console.error(chalk.red("Not logged in. Run: npx @globio/cli login"));
32
+ process.exit(1);
33
+ }
34
+ return key;
35
+ },
36
+ requireProject: () => {
37
+ const projectId = store.get("projectId");
38
+ if (!projectId) {
39
+ console.error(
40
+ chalk.red("No active project. Run: npx @globio/cli projects use <projectId>")
41
+ );
42
+ process.exit(1);
43
+ }
44
+ return projectId;
45
+ }
46
+ };
47
+
48
+ // src/auth/login.ts
49
+ var DEFAULT_BASE_URL = "https://api.globio.stanlink.online";
50
+ async function login() {
51
+ console.log("");
52
+ p.intro(chalk2.bgCyan(chalk2.black(" Globio CLI ")));
53
+ const values = await p.group(
54
+ {
55
+ apiKey: () => p.text({
56
+ message: "Paste your Globio API key",
57
+ placeholder: "gk_live_...",
58
+ validate: (value) => !value ? "API key is required" : void 0
59
+ }),
60
+ projectId: () => p.text({
61
+ message: "Paste your Project ID",
62
+ placeholder: "proj_...",
63
+ validate: (value) => !value ? "Project ID is required" : void 0
64
+ })
65
+ },
66
+ {
67
+ onCancel: () => {
68
+ p.cancel("Login cancelled.");
69
+ process.exit(0);
70
+ }
71
+ }
72
+ );
73
+ const spinner2 = p.spinner();
74
+ spinner2.start("Validating credentials...");
75
+ try {
76
+ const response = await fetch(`${DEFAULT_BASE_URL}/id/health`, {
77
+ headers: {
78
+ "X-Globio-Key": values.apiKey
79
+ }
80
+ });
81
+ if (!response.ok) {
82
+ spinner2.stop("Validation failed.");
83
+ p.outro(chalk2.red("Invalid API key or project ID."));
84
+ process.exit(1);
85
+ }
86
+ config.set({
87
+ apiKey: values.apiKey,
88
+ projectId: values.projectId
89
+ });
90
+ spinner2.stop("Credentials validated.");
91
+ p.outro(
92
+ chalk2.green("Logged in. Active project: ") + chalk2.cyan(values.projectId)
93
+ );
94
+ } catch {
95
+ spinner2.stop("");
96
+ p.outro(chalk2.red("Could not connect to Globio. Check your credentials."));
97
+ process.exit(1);
98
+ }
99
+ }
100
+
101
+ // src/auth/logout.ts
102
+ import * as p2 from "@clack/prompts";
103
+ import chalk3 from "chalk";
104
+ async function logout() {
105
+ config.clear();
106
+ p2.outro(chalk3.green("Logged out."));
107
+ }
108
+
109
+ // src/auth/whoami.ts
110
+ import chalk4 from "chalk";
111
+ async function whoami() {
112
+ const cfg = config.get();
113
+ if (!cfg.apiKey) {
114
+ console.log(chalk4.red("Not logged in."));
115
+ return;
116
+ }
117
+ console.log("");
118
+ console.log(chalk4.cyan("API Key: ") + cfg.apiKey);
119
+ console.log(chalk4.cyan("Project: ") + (cfg.projectId ?? "none"));
120
+ console.log("");
121
+ }
122
+
123
+ // src/commands/init.ts
124
+ import * as p5 from "@clack/prompts";
125
+ import chalk7 from "chalk";
126
+ import { existsSync, readFileSync, writeFileSync } from "fs";
127
+
128
+ // src/prompts/init.ts
129
+ import * as p3 from "@clack/prompts";
130
+ async function promptInit() {
131
+ return p3.group(
132
+ {
133
+ apiKey: () => p3.text({
134
+ message: "Globio API key",
135
+ placeholder: "gk_live_...",
136
+ validate: (value) => !value ? "Required" : void 0
137
+ }),
138
+ projectId: () => p3.text({
139
+ message: "Project ID",
140
+ placeholder: "proj_...",
141
+ validate: (value) => !value ? "Required" : void 0
142
+ }),
143
+ migrateFromFirebase: () => p3.confirm({
144
+ message: "Migrating from Firebase?",
145
+ initialValue: false
146
+ }),
147
+ serviceAccountPath: ({ results }) => results.migrateFromFirebase ? p3.text({
148
+ message: "Path to Firebase service account JSON",
149
+ placeholder: "./serviceAccountKey.json"
150
+ }) : Promise.resolve(void 0)
151
+ },
152
+ {
153
+ onCancel: () => {
154
+ p3.cancel("Cancelled.");
155
+ process.exit(0);
156
+ }
157
+ }
158
+ );
159
+ }
160
+
161
+ // src/commands/migrate.ts
162
+ import * as p4 from "@clack/prompts";
163
+ import chalk6 from "chalk";
164
+ import { basename } from "path";
165
+
166
+ // src/lib/firebase.ts
167
+ async function initFirebase(serviceAccountPath) {
168
+ const admin = await import("firebase-admin");
169
+ const { readFileSync: readFileSync3 } = await import("fs");
170
+ const serviceAccount = JSON.parse(readFileSync3(serviceAccountPath, "utf-8"));
171
+ if (!admin.default.apps.length) {
172
+ admin.default.initializeApp({
173
+ credential: admin.default.credential.cert(serviceAccount),
174
+ storageBucket: serviceAccount.project_id + ".appspot.com"
175
+ });
176
+ }
177
+ return {
178
+ firestore: admin.default.firestore(),
179
+ storage: admin.default.storage(),
180
+ app: admin.default.app()
181
+ };
182
+ }
183
+
184
+ // src/lib/progress.ts
185
+ import chalk5 from "chalk";
186
+ import cliProgress from "cli-progress";
187
+ function createProgressBar(label) {
188
+ const bar = new cliProgress.SingleBar(
189
+ {
190
+ format: chalk5.cyan(label) + " [{bar}] {percentage}% | {value}/{total}",
191
+ barCompleteChar: "\u2588",
192
+ barIncompleteChar: "\u2591",
193
+ hideCursor: true
194
+ },
195
+ cliProgress.Presets.shades_classic
196
+ );
197
+ return bar;
198
+ }
199
+
200
+ // src/lib/sdk.ts
201
+ import { Globio } from "@globio/sdk";
202
+ function getClient() {
203
+ const apiKey = config.requireAuth();
204
+ config.requireProject();
205
+ return new Globio({ apiKey });
206
+ }
207
+
208
+ // src/commands/migrate.ts
209
+ async function migrateFirestore(options) {
210
+ console.log("");
211
+ p4.intro(chalk6.bgYellow(chalk6.black(" Globio Migration \u2014 Firestore ")));
212
+ const { firestore } = await initFirebase(options.from);
213
+ const client = getClient();
214
+ let collections = [];
215
+ if (options.all) {
216
+ const snapshot = await firestore.listCollections();
217
+ collections = snapshot.map((collection) => collection.id);
218
+ console.log(
219
+ chalk6.cyan(
220
+ `Found ${collections.length} collections: ${collections.join(", ")}`
221
+ )
222
+ );
223
+ } else if (options.collection) {
224
+ collections = [options.collection];
225
+ } else {
226
+ console.log(chalk6.red("Specify --collection <name> or --all"));
227
+ process.exit(1);
228
+ }
229
+ const results = {};
230
+ for (const collectionId of collections) {
231
+ console.log("");
232
+ console.log(chalk6.cyan(`Migrating collection: ${collectionId}`));
233
+ const countSnap = await firestore.collection(collectionId).count().get();
234
+ const total = countSnap.data().count;
235
+ const bar = createProgressBar(collectionId);
236
+ bar.start(total, 0);
237
+ results[collectionId] = {
238
+ success: 0,
239
+ failed: 0,
240
+ failedIds: []
241
+ };
242
+ let lastDoc = null;
243
+ let processed = 0;
244
+ while (processed < total) {
245
+ let query = firestore.collection(collectionId).limit(100);
246
+ if (lastDoc) {
247
+ query = query.startAfter(lastDoc);
248
+ }
249
+ const snapshot = await query.get();
250
+ if (snapshot.empty) {
251
+ break;
252
+ }
253
+ for (const doc of snapshot.docs) {
254
+ try {
255
+ const result = await client.doc.set(collectionId, doc.id, doc.data());
256
+ if (!result.success) {
257
+ throw new Error(result.error.message);
258
+ }
259
+ results[collectionId].success++;
260
+ } catch {
261
+ results[collectionId].failed++;
262
+ results[collectionId].failedIds.push(doc.id);
263
+ }
264
+ processed++;
265
+ bar.update(processed);
266
+ }
267
+ lastDoc = snapshot.docs[snapshot.docs.length - 1] ?? null;
268
+ }
269
+ bar.stop();
270
+ console.log(
271
+ chalk6.green(` \u2713 ${results[collectionId].success} documents migrated`)
272
+ );
273
+ if (results[collectionId].failed > 0) {
274
+ console.log(chalk6.red(` \u2717 ${results[collectionId].failed} failed`));
275
+ console.log(
276
+ chalk6.gray(
277
+ " Failed IDs: " + results[collectionId].failedIds.slice(0, 10).join(", ") + (results[collectionId].failedIds.length > 10 ? "..." : "")
278
+ )
279
+ );
280
+ }
281
+ }
282
+ console.log("");
283
+ p4.outro(chalk6.green("Firestore migration complete."));
284
+ console.log(
285
+ chalk6.gray(
286
+ "Your Firebase data is intact. Delete it manually when ready."
287
+ )
288
+ );
289
+ }
290
+ async function migrateFirebaseStorage(options) {
291
+ console.log("");
292
+ p4.intro(chalk6.bgYellow(chalk6.black(" Globio Migration \u2014 Storage ")));
293
+ const { storage } = await initFirebase(options.from);
294
+ const client = getClient();
295
+ const bucketName = options.bucket.replace(/^gs:\/\//, "");
296
+ const bucket = storage.bucket(bucketName);
297
+ const prefix = options.folder ? options.folder.replace(/^\//, "") : "";
298
+ const [files] = await bucket.getFiles(prefix ? { prefix } : {});
299
+ console.log(chalk6.cyan(`Found ${files.length} files to migrate`));
300
+ const bar = createProgressBar("Storage");
301
+ bar.start(files.length, 0);
302
+ let success = 0;
303
+ let failed = 0;
304
+ for (const file of files) {
305
+ try {
306
+ const [buffer] = await file.download();
307
+ const uploadFile = new File(
308
+ [new Uint8Array(buffer)],
309
+ basename(file.name) || file.name
310
+ );
311
+ const result = await client.vault.uploadFile(uploadFile, {
312
+ metadata: {
313
+ original_path: file.name
314
+ }
315
+ });
316
+ if (!result.success) {
317
+ throw new Error(result.error.message);
318
+ }
319
+ success++;
320
+ } catch {
321
+ failed++;
322
+ }
323
+ bar.increment();
324
+ }
325
+ bar.stop();
326
+ console.log("");
327
+ console.log(chalk6.green(` \u2713 ${success} files migrated`));
328
+ if (failed > 0) {
329
+ console.log(chalk6.red(` \u2717 ${failed} failed`));
330
+ }
331
+ p4.outro(chalk6.green("Storage migration complete."));
332
+ }
333
+
334
+ // src/commands/init.ts
335
+ async function init() {
336
+ console.log("");
337
+ p5.intro(chalk7.bgCyan(chalk7.black(" Globio \u2014 Game Backend as a Service ")));
338
+ const values = await promptInit();
339
+ config.set({
340
+ apiKey: values.apiKey,
341
+ projectId: values.projectId
342
+ });
343
+ if (!existsSync("globio.config.ts")) {
344
+ writeFileSync(
345
+ "globio.config.ts",
346
+ `import { GlobioClient } from '@globio/sdk';
347
+
348
+ export const globio = new GlobioClient({
349
+ apiKey: process.env.GLOBIO_API_KEY!,
350
+ });
351
+ `
352
+ );
353
+ console.log(chalk7.green("\u2713 Created globio.config.ts"));
354
+ }
355
+ if (!existsSync(".env")) {
356
+ writeFileSync(".env", `GLOBIO_API_KEY=${values.apiKey}
357
+ `);
358
+ console.log(chalk7.green("\u2713 Created .env"));
359
+ }
360
+ if (values.migrateFromFirebase && values.serviceAccountPath) {
361
+ console.log("");
362
+ console.log(chalk7.cyan("Starting Firebase migration..."));
363
+ await migrateFirestore({
364
+ from: values.serviceAccountPath,
365
+ all: true
366
+ });
367
+ const serviceAccount = JSON.parse(
368
+ readFileSync(values.serviceAccountPath, "utf-8")
369
+ );
370
+ await migrateFirebaseStorage({
371
+ from: values.serviceAccountPath,
372
+ bucket: `${serviceAccount.project_id}.appspot.com`,
373
+ all: true
374
+ });
375
+ }
376
+ console.log("");
377
+ p5.outro(
378
+ chalk7.green("Your Globio project is ready.") + "\n\n" + chalk7.white(" Next steps:\n") + chalk7.gray(" npm install @globio/sdk\n") + chalk7.gray(" npx @globio/cli functions create my-first-function\n")
379
+ );
380
+ }
381
+
382
+ // src/commands/projects.ts
383
+ import chalk8 from "chalk";
384
+ async function projectsList() {
385
+ const cfg = config.get();
386
+ console.log("");
387
+ console.log(
388
+ chalk8.cyan("Active project: ") + (cfg.projectId ?? chalk8.gray("none"))
389
+ );
390
+ console.log("");
391
+ }
392
+ async function projectsUse(projectId) {
393
+ config.set({ projectId });
394
+ console.log(chalk8.green("Active project set to: ") + chalk8.cyan(projectId));
395
+ }
396
+
397
+ // src/commands/services.ts
398
+ import chalk9 from "chalk";
399
+ var ALL_SERVICES = [
400
+ "id",
401
+ "doc",
402
+ "vault",
403
+ "pulse",
404
+ "scope",
405
+ "sync",
406
+ "signal",
407
+ "mart",
408
+ "brain",
409
+ "code"
410
+ ];
411
+ async function servicesList() {
412
+ console.log("");
413
+ console.log(chalk9.cyan("Available Globio services:"));
414
+ ALL_SERVICES.forEach((service) => {
415
+ console.log(" " + chalk9.white(service));
416
+ });
417
+ console.log("");
418
+ console.log(
419
+ chalk9.gray("Manage service access via console.globio.stanlink.online")
420
+ );
421
+ console.log("");
422
+ }
423
+
424
+ // src/commands/functions.ts
425
+ import chalk10 from "chalk";
426
+ import ora from "ora";
427
+ import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
428
+ async function functionsList() {
429
+ const client = getClient();
430
+ const spinner2 = ora("Fetching functions...").start();
431
+ const result = await client.code.listFunctions();
432
+ spinner2.stop();
433
+ if (!result.success || !result.data.length) {
434
+ console.log(chalk10.gray("No functions found."));
435
+ return;
436
+ }
437
+ console.log("");
438
+ result.data.forEach((fn) => {
439
+ const status = fn.active ? chalk10.green("\u25CF active") : chalk10.gray("\u25CB inactive");
440
+ const type = fn.type === "hook" ? chalk10.yellow("[hook]") : chalk10.cyan("[function]");
441
+ console.log(` ${status} ${type} ${chalk10.white(fn.slug)}`);
442
+ if (fn.type === "hook") {
443
+ console.log(chalk10.gray(` trigger: ${fn.trigger_event}`));
444
+ }
445
+ });
446
+ console.log("");
447
+ }
448
+ async function functionsCreate(slug) {
449
+ const filename = `${slug}.js`;
450
+ if (existsSync2(filename)) {
451
+ console.log(chalk10.yellow(`${filename} already exists.`));
452
+ return;
453
+ }
454
+ const template = `/**
455
+ * Globio Edge Function: ${slug}
456
+ * Invoke: npx @globio/cli functions invoke ${slug} --input '{"key":"value"}'
457
+ */
458
+ async function handler(input, globio) {
459
+ // input: the payload from the caller
460
+ // globio: injected SDK \u2014 access all Globio services
461
+ // Example: const player = await globio.doc.get('players', input.userId);
462
+
463
+ return {
464
+ ok: true,
465
+ received: input,
466
+ };
467
+ }
468
+ `;
469
+ writeFileSync2(filename, template);
470
+ console.log(chalk10.green(`Created ${filename}`));
471
+ console.log(
472
+ chalk10.gray(`Deploy with: npx @globio/cli functions deploy ${slug}`)
473
+ );
474
+ }
475
+ async function functionsDeploy(slug, options) {
476
+ const filename = options.file ?? `${slug}.js`;
477
+ if (!existsSync2(filename)) {
478
+ console.log(
479
+ chalk10.red(
480
+ `File not found: ${filename}. Create it with: npx @globio/cli functions create ${slug}`
481
+ )
482
+ );
483
+ process.exit(1);
484
+ }
485
+ const code = readFileSync2(filename, "utf-8");
486
+ const client = getClient();
487
+ const spinner2 = ora(`Deploying ${slug}...`).start();
488
+ const existing = await client.code.getFunction(slug);
489
+ let result;
490
+ if (existing.success) {
491
+ result = await client.code.updateFunction(slug, {
492
+ code,
493
+ name: options.name ?? slug
494
+ });
495
+ } else {
496
+ result = await client.code.createFunction({
497
+ name: options.name ?? slug,
498
+ slug,
499
+ type: "function",
500
+ code
501
+ });
502
+ }
503
+ if (!result.success) {
504
+ spinner2.fail("Deploy failed");
505
+ console.error(result.error.message);
506
+ process.exit(1);
507
+ }
508
+ spinner2.succeed(existing.success ? `Updated ${slug}` : `Deployed ${slug}`);
509
+ }
510
+ async function functionsInvoke(slug, options) {
511
+ let input = {};
512
+ if (options.input) {
513
+ try {
514
+ input = JSON.parse(options.input);
515
+ } catch {
516
+ console.error(chalk10.red("--input must be valid JSON"));
517
+ process.exit(1);
518
+ }
519
+ }
520
+ const client = getClient();
521
+ const spinner2 = ora(`Invoking ${slug}...`).start();
522
+ const result = await client.code.invoke(slug, input);
523
+ spinner2.stop();
524
+ if (!result.success) {
525
+ console.log(chalk10.red("Invocation failed"));
526
+ console.error(result.error.message);
527
+ return;
528
+ }
529
+ console.log("");
530
+ console.log(chalk10.cyan("Result:"));
531
+ console.log(JSON.stringify(result.data.result, null, 2));
532
+ console.log(chalk10.gray(`
533
+ Duration: ${result.data.duration_ms}ms`));
534
+ }
535
+ async function functionsLogs(slug, options) {
536
+ const limit = options.limit ? parseInt(options.limit, 10) : 20;
537
+ const client = getClient();
538
+ const spinner2 = ora("Fetching invocations...").start();
539
+ const result = await client.code.getInvocations(slug, limit);
540
+ spinner2.stop();
541
+ if (!result.success || !result.data.length) {
542
+ console.log(chalk10.gray("No invocations yet."));
543
+ return;
544
+ }
545
+ console.log("");
546
+ result.data.forEach((inv) => {
547
+ const status = inv.success ? chalk10.green("\u2713") : chalk10.red("\u2717");
548
+ const date = new Date(inv.invoked_at * 1e3).toISOString().replace("T", " ").slice(0, 19);
549
+ console.log(
550
+ ` ${status} ${chalk10.gray(date)} ${inv.duration_ms}ms ${chalk10.gray(`[${inv.trigger_type}]`)}`
551
+ );
552
+ });
553
+ console.log("");
554
+ }
555
+ async function functionsDelete(slug) {
556
+ const client = getClient();
557
+ const spinner2 = ora(`Deleting ${slug}...`).start();
558
+ const result = await client.code.deleteFunction(slug);
559
+ if (!result.success) {
560
+ spinner2.fail(`Delete failed for ${slug}`);
561
+ console.error(result.error.message);
562
+ process.exit(1);
563
+ }
564
+ spinner2.succeed(`Deleted ${slug}`);
565
+ }
566
+ async function functionsToggle(slug, active) {
567
+ const client = getClient();
568
+ const spinner2 = ora(
569
+ `${active ? "Enabling" : "Disabling"} ${slug}...`
570
+ ).start();
571
+ const result = await client.code.toggleFunction(slug, active);
572
+ if (!result.success) {
573
+ spinner2.fail(`Toggle failed for ${slug}`);
574
+ console.error(result.error.message);
575
+ process.exit(1);
576
+ }
577
+ spinner2.succeed(`${slug} is now ${active ? "active" : "inactive"}`);
578
+ }
579
+
580
+ // src/index.ts
581
+ var program = new Command();
582
+ program.name("globio").description("The official Globio CLI").version("0.1.0");
583
+ program.command("login").description("Log in to your Globio account").action(login);
584
+ program.command("logout").description("Log out").action(logout);
585
+ program.command("whoami").description("Show current account and project").action(whoami);
586
+ program.command("init").description("Initialize a Globio project").action(init);
587
+ var projects = program.command("projects").description("Manage projects");
588
+ projects.command("list").description("List projects").action(projectsList);
589
+ projects.command("use <projectId>").description("Set active project").action(projectsUse);
590
+ program.command("services").description("List available Globio services").action(servicesList);
591
+ var functions = program.command("functions").alias("fn").description("Manage GlobalCode edge functions");
592
+ functions.command("list").description("List all functions").action(functionsList);
593
+ functions.command("create <slug>").description("Scaffold a new function file locally").action(functionsCreate);
594
+ functions.command("deploy <slug>").description("Deploy a function to GlobalCode").option("-f, --file <path>", "Path to function file").option("-n, --name <name>", "Display name").action(functionsDeploy);
595
+ functions.command("invoke <slug>").description("Invoke a function").option("-i, --input <json>", "JSON input payload").action(functionsInvoke);
596
+ functions.command("logs <slug>").description("Show invocation history").option("-l, --limit <n>", "Number of entries", "20").action(functionsLogs);
597
+ functions.command("delete <slug>").description("Delete a function").action(functionsDelete);
598
+ functions.command("enable <slug>").description("Enable a function").action((slug) => functionsToggle(slug, true));
599
+ functions.command("disable <slug>").description("Disable a function").action((slug) => functionsToggle(slug, false));
600
+ var migrate = program.command("migrate").description("Migrate from Firebase to Globio");
601
+ migrate.command("firestore").description("Migrate Firestore collections to GlobalDoc").requiredOption("--from <path>", "Path to Firebase service account JSON").option("--collection <name>", "Migrate a specific collection").option("--all", "Migrate all collections").action(migrateFirestore);
602
+ migrate.command("firebase-storage").description("Migrate Firebase Storage to GlobalVault").requiredOption("--from <path>", "Path to Firebase service account JSON").requiredOption("--bucket <name>", "Firebase Storage bucket").option("--folder <path>", "Migrate a specific folder").option("--all", "Migrate all files").action(migrateFirebaseStorage);
603
+ await program.parseAsync();
package/jsr.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "@globio/cli",
3
+ "version": "0.1.0",
4
+ "license": "MIT",
5
+ "exports": "./src/index.ts"
6
+ }
package/package.json CHANGED
@@ -1,10 +1,36 @@
1
1
  {
2
2
  "name": "@globio/cli",
3
- "version": "0.0.1",
4
- "description": "The official Globio CLI",
3
+ "version": "0.1.0",
4
+ "description": "The official CLI for Globio — game backend as a service",
5
+ "type": "module",
6
+ "license": "MIT",
5
7
  "bin": {
6
8
  "globio": "./dist/index.js"
7
9
  },
10
+ "scripts": {
11
+ "build": "tsup src/index.ts --format esm --out-dir dist --clean",
12
+ "dev": "tsup src/index.ts --format esm --out-dir dist --watch",
13
+ "typecheck": "tsc --noEmit"
14
+ },
15
+ "dependencies": {
16
+ "@clack/prompts": "^0.9.0",
17
+ "@globio/sdk": "^1.0.0",
18
+ "chalk": "^5.3.0",
19
+ "cli-progress": "^3.12.0",
20
+ "commander": "^12.0.0",
21
+ "conf": "^13.0.0",
22
+ "firebase-admin": "^12.0.0",
23
+ "ora": "^8.0.0"
24
+ },
25
+ "devDependencies": {
26
+ "@types/cli-progress": "^3.11.0",
27
+ "@types/node": "^20.0.0",
28
+ "tsup": "^8.0.0",
29
+ "typescript": "^5.4.0"
30
+ },
31
+ "engines": {
32
+ "node": ">=18"
33
+ },
8
34
  "publishConfig": {
9
35
  "access": "public"
10
36
  }