@globio/cli 0.1.7 → 0.1.8

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/README.md CHANGED
@@ -35,6 +35,12 @@ npx @globio/cli migrate firebase-storage \
35
35
  --all
36
36
  ```
37
37
 
38
+ After migration, GlobalDoc indexes are created automatically for every field in your collections.
39
+ Queries using `where()` clauses will work immediately.
40
+
41
+ Note: GlobalDoc requires explicit indexes unlike Firestore's automatic indexing.
42
+ The migrate command handles this for you automatically.
43
+
38
44
  ## Commands
39
45
 
40
46
  ### Auth
package/dist/index.js CHANGED
@@ -475,6 +475,20 @@ async function docSet(collection, docId, data, profile) {
475
475
  profile
476
476
  });
477
477
  }
478
+ async function createIndex(collection, field, fieldType = "string", profile) {
479
+ void fieldType;
480
+ try {
481
+ await apiCall(`/doc/${collection}/indexes`, {
482
+ method: "POST",
483
+ body: {
484
+ field_path: field,
485
+ index_type: "asc"
486
+ },
487
+ profile
488
+ });
489
+ } catch {
490
+ }
491
+ }
478
492
 
479
493
  // src/lib/firebase.ts
480
494
  async function initFirebase(serviceAccountPath) {
@@ -550,6 +564,8 @@ async function migrateFirestore(options) {
550
564
  };
551
565
  let lastDoc = null;
552
566
  let processed = 0;
567
+ let firstDocData = null;
568
+ let indexFieldCount = 0;
553
569
  while (processed < total) {
554
570
  let query = firestore.collection(collectionId).limit(100);
555
571
  if (lastDoc) {
@@ -561,6 +577,14 @@ async function migrateFirestore(options) {
561
577
  }
562
578
  for (const doc of snapshot.docs) {
563
579
  try {
580
+ if (!firstDocData) {
581
+ firstDocData = doc.data();
582
+ for (const [field, value] of Object.entries(firstDocData)) {
583
+ const fieldType = typeof value === "number" ? "number" : typeof value === "boolean" ? "boolean" : "string";
584
+ await createIndex(collectionId, field, fieldType, profileName);
585
+ }
586
+ indexFieldCount = Object.keys(firstDocData).length;
587
+ }
564
588
  await docSet(collectionId, doc.id, doc.data(), profileName);
565
589
  results[collectionId].success++;
566
590
  } catch {
@@ -576,6 +600,11 @@ async function migrateFirestore(options) {
576
600
  console.log(
577
601
  chalk7.green(` \u2713 ${results[collectionId].success} documents migrated`)
578
602
  );
603
+ if (indexFieldCount > 0) {
604
+ console.log(
605
+ chalk7.gray(` Indexes created for ${indexFieldCount} fields`)
606
+ );
607
+ }
579
608
  if (results[collectionId].failed > 0) {
580
609
  console.log(chalk7.red(` \u2717 ${results[collectionId].failed} failed`));
581
610
  console.log(
package/jsr.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@globio/cli",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
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.7",
3
+ "version": "0.1.8",
4
4
  "description": "The official CLI for Globio — game backend as a service",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -8,7 +8,7 @@ import {
8
8
  orange,
9
9
  printBanner,
10
10
  } from '../lib/banner.js';
11
- import { docSet } from '../lib/api.js';
11
+ import { createIndex, docSet } from '../lib/api.js';
12
12
  import { initFirebase } from '../lib/firebase.js';
13
13
  import { createProgressBar } from '../lib/progress.js';
14
14
  import { config } from '../lib/config.js';
@@ -81,6 +81,8 @@ export async function migrateFirestore(options: MigrateFirestoreOptions) {
81
81
 
82
82
  let lastDoc: unknown = null;
83
83
  let processed = 0;
84
+ let firstDocData: Record<string, unknown> | null = null;
85
+ let indexFieldCount = 0;
84
86
 
85
87
  while (processed < total) {
86
88
  let query = firestore.collection(collectionId).limit(100);
@@ -96,6 +98,20 @@ export async function migrateFirestore(options: MigrateFirestoreOptions) {
96
98
 
97
99
  for (const doc of snapshot.docs) {
98
100
  try {
101
+ if (!firstDocData) {
102
+ firstDocData = doc.data();
103
+ for (const [field, value] of Object.entries(firstDocData)) {
104
+ const fieldType =
105
+ typeof value === 'number'
106
+ ? 'number'
107
+ : typeof value === 'boolean'
108
+ ? 'boolean'
109
+ : 'string';
110
+ await createIndex(collectionId, field, fieldType, profileName);
111
+ }
112
+ indexFieldCount = Object.keys(firstDocData).length;
113
+ }
114
+
99
115
  await docSet(collectionId, doc.id, doc.data(), profileName);
100
116
  results[collectionId].success++;
101
117
  } catch {
@@ -114,6 +130,11 @@ export async function migrateFirestore(options: MigrateFirestoreOptions) {
114
130
  console.log(
115
131
  chalk.green(` ✓ ${results[collectionId].success} documents migrated`)
116
132
  );
133
+ if (indexFieldCount > 0) {
134
+ console.log(
135
+ chalk.gray(` Indexes created for ${indexFieldCount} fields`)
136
+ );
137
+ }
117
138
  if (results[collectionId].failed > 0) {
118
139
  console.log(chalk.red(` ✗ ${results[collectionId].failed} failed`));
119
140
  console.log(
package/src/lib/api.ts CHANGED
@@ -50,3 +50,24 @@ export async function docSet(
50
50
  profile,
51
51
  });
52
52
  }
53
+
54
+ export async function createIndex(
55
+ collection: string,
56
+ field: string,
57
+ fieldType: 'string' | 'number' | 'boolean' = 'string',
58
+ profile?: string
59
+ ): Promise<void> {
60
+ void fieldType;
61
+ try {
62
+ await apiCall(`/doc/${collection}/indexes`, {
63
+ method: 'POST',
64
+ body: {
65
+ field_path: field,
66
+ index_type: 'asc',
67
+ },
68
+ profile,
69
+ });
70
+ } catch {
71
+ // Index may already exist. Ignore duplicate-style failures.
72
+ }
73
+ }