@x12i/catalox 2.2.2 → 2.4.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.
Files changed (75) hide show
  1. package/README.md +42 -7
  2. package/dist/src/catalox/backup-data.d.ts +40 -0
  3. package/dist/src/catalox/backup-data.d.ts.map +1 -0
  4. package/dist/src/catalox/backup-data.js +522 -0
  5. package/dist/src/catalox/backup-data.js.map +1 -0
  6. package/dist/src/catalox/catalox.d.ts +25 -0
  7. package/dist/src/catalox/catalox.d.ts.map +1 -1
  8. package/dist/src/catalox/catalox.js +63 -1
  9. package/dist/src/catalox/catalox.js.map +1 -1
  10. package/dist/src/catalox/index.d.ts +3 -0
  11. package/dist/src/catalox/index.d.ts.map +1 -1
  12. package/dist/src/catalox/index.js +3 -0
  13. package/dist/src/catalox/index.js.map +1 -1
  14. package/dist/src/catalox/native-catalog-layout-diagnostics.d.ts +29 -0
  15. package/dist/src/catalox/native-catalog-layout-diagnostics.d.ts.map +1 -0
  16. package/dist/src/catalox/native-catalog-layout-diagnostics.js +55 -0
  17. package/dist/src/catalox/native-catalog-layout-diagnostics.js.map +1 -0
  18. package/dist/src/catalox/restore-firestore-backup.d.ts +13 -0
  19. package/dist/src/catalox/restore-firestore-backup.d.ts.map +1 -0
  20. package/dist/src/catalox/restore-firestore-backup.js +326 -0
  21. package/dist/src/catalox/restore-firestore-backup.js.map +1 -0
  22. package/dist/src/cli/index.js +156 -5
  23. package/dist/src/cli/index.js.map +1 -1
  24. package/dist/src/contracts/backup.d.ts +36 -0
  25. package/dist/src/contracts/backup.d.ts.map +1 -0
  26. package/dist/src/contracts/backup.js +2 -0
  27. package/dist/src/contracts/backup.js.map +1 -0
  28. package/dist/src/contracts/catalog-data-index.d.ts +13 -0
  29. package/dist/src/contracts/catalog-data-index.d.ts.map +1 -0
  30. package/dist/src/contracts/catalog-data-index.js +2 -0
  31. package/dist/src/contracts/catalog-data-index.js.map +1 -0
  32. package/dist/src/contracts/catalogs.d.ts +2 -1
  33. package/dist/src/contracts/catalogs.d.ts.map +1 -1
  34. package/dist/src/contracts/index.d.ts +3 -0
  35. package/dist/src/contracts/index.d.ts.map +1 -1
  36. package/dist/src/contracts/index.js.map +1 -1
  37. package/dist/src/contracts/restore.d.ts +44 -0
  38. package/dist/src/contracts/restore.d.ts.map +1 -0
  39. package/dist/src/contracts/restore.js +2 -0
  40. package/dist/src/contracts/restore.js.map +1 -0
  41. package/dist/src/firebase/catalog-data-index-store.d.ts +14 -0
  42. package/dist/src/firebase/catalog-data-index-store.d.ts.map +1 -0
  43. package/dist/src/firebase/catalog-data-index-store.js +33 -0
  44. package/dist/src/firebase/catalog-data-index-store.js.map +1 -0
  45. package/dist/src/firebase/catalog-data-paths.d.ts +14 -0
  46. package/dist/src/firebase/catalog-data-paths.d.ts.map +1 -0
  47. package/dist/src/firebase/catalog-data-paths.js +31 -0
  48. package/dist/src/firebase/catalog-data-paths.js.map +1 -0
  49. package/dist/src/firebase/index.d.ts +2 -0
  50. package/dist/src/firebase/index.d.ts.map +1 -1
  51. package/dist/src/firebase/index.js +2 -0
  52. package/dist/src/firebase/index.js.map +1 -1
  53. package/dist/src/firebase/native-item-store.d.ts +5 -1
  54. package/dist/src/firebase/native-item-store.d.ts.map +1 -1
  55. package/dist/src/firebase/native-item-store.js +33 -15
  56. package/dist/src/firebase/native-item-store.js.map +1 -1
  57. package/dist/src/migrations/index.d.ts +1 -0
  58. package/dist/src/migrations/index.d.ts.map +1 -1
  59. package/dist/src/migrations/index.js +1 -0
  60. package/dist/src/migrations/index.js.map +1 -1
  61. package/dist/src/migrations/migrate-native-catalog-layout.d.ts +51 -0
  62. package/dist/src/migrations/migrate-native-catalog-layout.d.ts.map +1 -0
  63. package/dist/src/migrations/migrate-native-catalog-layout.js +224 -0
  64. package/dist/src/migrations/migrate-native-catalog-layout.js.map +1 -0
  65. package/dist/test/integration/firestore.emulator.test.js +10 -2
  66. package/dist/test/integration/firestore.emulator.test.js.map +1 -1
  67. package/dist/test/unit/backup-timestamp.test.d.ts +2 -0
  68. package/dist/test/unit/backup-timestamp.test.d.ts.map +1 -0
  69. package/dist/test/unit/backup-timestamp.test.js +11 -0
  70. package/dist/test/unit/backup-timestamp.test.js.map +1 -0
  71. package/dist/test/unit/resolve-native-items-layout.test.d.ts +2 -0
  72. package/dist/test/unit/resolve-native-items-layout.test.d.ts.map +1 -0
  73. package/dist/test/unit/resolve-native-items-layout.test.js +50 -0
  74. package/dist/test/unit/resolve-native-items-layout.test.js.map +1 -0
  75. package/package.json +2 -1
package/README.md CHANGED
@@ -22,7 +22,7 @@ This repo is currently set up as a workspace package.
22
22
 
23
23
  ## Configuration (real connections)
24
24
 
25
- Catalox is a library: you provide initialized clients + runtime env.
25
+ Catalox is a library: you provide initialized clients + runtime env. For a **full list of environment variables**, CLI vs library behavior, and integration-test requirements, see [`docs/environment.md`](docs/environment.md).
26
26
 
27
27
  ### Firestore (Firebase Admin SDK)
28
28
 
@@ -66,15 +66,39 @@ GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
66
66
  FIREBASE_SERVICE_ACCOUNT_PATH=/path/to/service-account.json
67
67
  FIREBASE_PROJECT_ID=your-project-id
68
68
  FIRESTORE_LIVE_TESTS=1
69
+ # Optional defaults for the packaged `catalox` CLI (Catalox app/store context, not GCP):
70
+ # CATALOX_APP_ID=myAppId
71
+ # CATALOX_STORE_ID=myStoreId
72
+ # CATALOX_USER_ID=user-123
73
+ # CATALOX_MONGO_URI=mongodb://127.0.0.1:27017
74
+ ```
75
+
76
+ ### `catalox` CLI environment
77
+
78
+ The `catalox` binary loads `.env` via `dotenv`. Use **`CATALOX_*`** for **Catalox runtime context** (catalog `appId`, optional `storeId`, actor, Mongo URI for the bundled adapter). Use **`FIREBASE_*` / `FIRESTORE_*`** for **Firebase Admin / Firestore connection** (service account path, GCP `projectId`, database id, live-test flags).
79
+
80
+ - **`CATALOX_APP_ID`** — Default `appId` in CLI context when a command does not pass `--app` (when present, `--app` overrides).
81
+ - **`CATALOX_STORE_ID`** — Default `storeId` for **`report`** and **`export`** when `--store` is omitted (`--store` overrides).
82
+ - **`CATALOX_USER_ID`** — Optional user id / actor for authz-sensitive CLI paths.
83
+ - **`CATALOX_MONGO_URI`** — If set, enables the Mongo catalog adapter in the CLI (see `createCatalox()` in `src/cli/index.ts`).
84
+
85
+ **Running commands from this repository:** the shell command `catalox` is only on your `PATH` if the package is installed globally (`npm i -g @x12i/catalox`) or linked (`npm link` from this repo). Otherwise, after `npm run build`, use:
86
+
87
+ ```bash
88
+ npm run cli -- firestore report-native-layout --app "narrix"
89
+ # same as: node dist/src/cli/index.js firestore report-native-layout --app "narrix"
69
90
  ```
70
91
 
71
92
  ## Firestore data model (logical collections)
72
93
 
94
+ For a **full layout** (subcollections, document id conventions, snapshot runs, and query notes), see [`docs/firestore-data-model.md`](docs/firestore-data-model.md).
95
+
73
96
  Metadata:
74
97
 
75
98
  - `apps/{appId}`
76
99
  - `catalogs/{catalogId}`
77
100
  - `catalogBindings/{bindingId}` (many-to-many app↔catalog)
101
+ - `storeAppBindings/{bindingId}` (store↔app, multi-app export/report)
78
102
  - `catalogDefinitions/{catalogId}` (native vs mapped specifics)
79
103
  - `catalogAdapters/{adapterId}` (mongo/api adapter definitions)
80
104
  - `catalogMappings/{mappingId}` (field mapping specs)
@@ -84,16 +108,24 @@ Metadata:
84
108
 
85
109
  Data:
86
110
 
87
- - `catalogData/{catalogId}/items/{itemId}` (native items)
111
+ - `catalogData-{catalogId}-items/{itemId}` (native item rows; top-level collection per catalog)
112
+ - `catalogData/{catalogId}` (index and metadata for that catalog’s native storage; not item payloads)
88
113
  - `catalogSnapshots/{catalogId}/items/{itemId}` (mapped snapshot mode)
89
114
 
115
+ Backups (optional operator feature):
116
+
117
+ - `backup-*` and `{timestamp}__backup-*` (Firebase mode, same database)
118
+ - Mongo database `catalox-backups` (Mongo mode)
119
+
120
+ See [`docs/backup.md`](docs/backup.md) for `backupData` / CLI backup, [`docs/restore-firestore-backup.md`](docs/restore-firestore-backup.md) for restoring Firebase mirrors to live data with undo, [`docs/migration-native-catalog-data.md`](docs/migration-native-catalog-data.md) for moving legacy native rows into `catalogData-{catalogId}-items`, and [`docs/firestore-native-layout-vs-backup.md`](docs/firestore-native-layout-vs-backup.md) for how live paths differ from `backup-*` mirrors and what `backupData` reports in `nativeItemSourceLayoutByCatalogId`. If the console still shows **`catalogData/{catalogId}/items`**, run **`catalox firestore report-native-layout`** then **`catalox firestore migrate-native-catalog-data`** (backup + copy to flat; optional `--delete-legacy` after you trust backups).
121
+
90
122
  ## Core usage (generic from `appId`)
91
123
 
92
124
  ### Create stores and `Catalox`
93
125
 
94
126
  ```ts
95
127
  import { FirestoreStore } from "@x12i/catalox";
96
- import { AppStore, CatalogStore, BindingStore, DefinitionStore, MappingStore, DescriptorStore, ReferenceStore, NativeItemStore, SnapshotStore, AdapterStore } from "@x12i/catalox";
128
+ import { AppStore, CatalogStore, BindingStore, DefinitionStore, MappingStore, DescriptorStore, ReferenceStore, NativeItemStore, CatalogDataIndexStore, SnapshotStore, AdapterStore } from "@x12i/catalox";
97
129
  import { AuthorizationService, Catalox } from "@x12i/catalox";
98
130
 
99
131
  // firebase-admin initialization is up to the consumer
@@ -102,18 +134,21 @@ import { getFirestore } from "firebase-admin/firestore";
102
134
  const firestore = getFirestore();
103
135
  const store = new FirestoreStore({ firestore });
104
136
 
137
+ const bindings = new BindingStore(store);
105
138
  const deps = {
106
139
  apps: new AppStore(store),
107
140
  catalogs: new CatalogStore(store),
108
- bindings: new BindingStore(store),
141
+ bindings,
109
142
  definitions: new DefinitionStore(store),
110
143
  mappings: new MappingStore(store),
111
144
  descriptors: new DescriptorStore(store),
112
145
  references: new ReferenceStore(store),
113
146
  nativeItems: new NativeItemStore(store),
147
+ catalogDataIndex: new CatalogDataIndexStore(store),
114
148
  snapshots: new SnapshotStore(store),
115
149
  adapters: new AdapterStore(store),
116
- authz: new AuthorizationService(new BindingStore(store)),
150
+ firestoreStore: store,
151
+ authz: new AuthorizationService(bindings),
117
152
  };
118
153
 
119
154
  const catalox = new Catalox(deps);
@@ -306,7 +341,7 @@ await catalox.createCatalog(ctx, {
306
341
  catalogId: "signals",
307
342
  name: "Signals",
308
343
  sourceMode: "native",
309
- native: { type: "native", firestoreCollectionPath: "catalogData/signals/items" },
344
+ native: { type: "native" },
310
345
  });
311
346
  ```
312
347
 
@@ -450,7 +485,7 @@ Integration tests are **live-only** (no mocks, no emulators). They require:
450
485
  ### Live test safety (read before running)
451
486
 
452
487
  - **Never run against production credentials/projects.** Use a dedicated Firebase project for tests.
453
- - **Touched collections**: `apps`, `catalogs`, `catalogBindings`, `catalogDefinitions`, `catalogDescriptors`, and `catalogData/{catalogId}/items/...`.
488
+ - **Touched collections**: `apps`, `catalogs`, `catalogBindings`, `catalogDefinitions`, `catalogDescriptors`, `catalogData/{catalogId}`, and `catalogData-{catalogId}-items/...`. The **`catalox firestore restore-backup`** / **`undo-restore-backup`** commands additionally write `backup-restoreSessions` and `{restoreSessionId}__preRestore-*` sidecar collections (see [`docs/restore-firestore-backup.md`](docs/restore-firestore-backup.md)).
454
489
  - **Cleanup**: tests do best-effort deletes of the docs they created, but do not guarantee full teardown.
455
490
 
456
491
  ## Boundaries (important)
@@ -0,0 +1,40 @@
1
+ import { type Firestore } from "firebase-admin/firestore";
2
+ import { type Db } from "mongodb";
3
+ import type { CatalogId } from "../contracts/ids.js";
4
+ import type { BackupDataInput, BackupDataResult } from "../contracts/backup.js";
5
+ import type { CatalogRecord } from "../contracts/catalogs.js";
6
+ import { CatalogStore } from "../firebase/catalog-store.js";
7
+ import { BindingStore } from "../firebase/binding-store.js";
8
+ import { FirestoreStore } from "../firebase/firestore-store.js";
9
+ export declare const BACKUP_METADATA_SOURCE_NAMES: readonly ["apps", "catalogs", "catalogBindings", "storeAppBindings", "catalogDefinitions", "catalogDescriptors", "catalogMappings", "catalogAdapters", "catalogReferences", "catalogData"];
10
+ export type BackupDataDeps = {
11
+ firestoreStore: FirestoreStore;
12
+ catalogs: CatalogStore;
13
+ bindings: BindingStore;
14
+ };
15
+ export declare function formatBackupTimestamp(versionOverride?: string, d?: Date): string;
16
+ /** Latest Firebase backup mirror collection id for a logical source (e.g. `apps`, `catalogData--{id}`). */
17
+ export declare function firebaseLatestName(logical: string): string;
18
+ /** Versioned Firebase backup collection id. */
19
+ export declare function firebaseVersionedName(ts: string, logical: string): string;
20
+ export declare function firebaseNativeLogical(catalogId: string): string;
21
+ export declare function firebaseSnapshotLogical(catalogId: string): string;
22
+ export declare function firebaseSnapshotRunLogical(catalogId: string, runId: string): string;
23
+ export declare function paginatedCopyFirestoreToFirestore(fs: Firestore, sourceCollectionPath: string, destCollectionPath: string, counts: Record<string, number>, countKey: string): Promise<void>;
24
+ export declare function deleteAllDocsInFirestoreCollection(fs: Firestore, collectionPath: string): Promise<void>;
25
+ export declare function discoverNativeCatalogIds(fs: Firestore, catalogs: CatalogRecord[], opts: {
26
+ bindings: BindingStore;
27
+ catalogIds?: CatalogId[];
28
+ appId?: string;
29
+ }): Promise<CatalogId[]>;
30
+ /** Delete Mongo `backupRuns` documents with createdAt older than cutoff ISO string. */
31
+ export declare function pruneMongoBackupRuns(db: Db, createdBeforeIso: string): Promise<number>;
32
+ /**
33
+ * Delete documents in oldest Firestore versioned backup collections matching `{ts}__backup-*`
34
+ * until at most `keepLast` such collections remain.
35
+ */
36
+ export declare function pruneFirebaseVersionedBackups(firestore: Firestore, keepLast: number): Promise<{
37
+ deleted: string[];
38
+ }>;
39
+ export declare function runBackupData(deps: BackupDataDeps, input: BackupDataInput): Promise<BackupDataResult>;
40
+ //# sourceMappingURL=backup-data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backup-data.d.ts","sourceRoot":"","sources":["../../../src/catalox/backup-data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAe,KAAK,EAAE,EAAE,MAAM,SAAS,CAAC;AAE/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,eAAe,EAAmB,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AACjG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAWhE,eAAO,MAAM,4BAA4B,4LAY/B,CAAC;AAEX,MAAM,MAAM,cAAc,GAAG;IAC3B,cAAc,EAAE,cAAc,CAAC;IAC/B,QAAQ,EAAE,YAAY,CAAC;IACvB,QAAQ,EAAE,YAAY,CAAC;CACxB,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC,OAAa,GAAG,MAAM,CAMtF;AAMD,2GAA2G;AAC3G,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,+CAA+C;AAC/C,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEzE;AA0BD,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEjE;AAED,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnF;AAED,wBAAsB,iCAAiC,CACrD,EAAE,EAAE,SAAS,EACb,oBAAoB,EAAE,MAAM,EAC5B,kBAAkB,EAAE,MAAM,EAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAmBf;AAED,wBAAsB,kCAAkC,CAAC,EAAE,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAS7G;AAED,wBAAsB,wBAAwB,CAC5C,EAAE,EAAE,SAAS,EACb,QAAQ,EAAE,aAAa,EAAE,EACzB,IAAI,EAAE;IAAE,QAAQ,EAAE,YAAY,CAAC;IAAC,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GACzE,OAAO,CAAC,SAAS,EAAE,CAAC,CAwBtB;AA0PD,uFAAuF;AACvF,wBAAsB,oBAAoB,CAAC,EAAE,EAAE,EAAE,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAK5F;AAED;;;GAGG;AACH,wBAAsB,6BAA6B,CACjD,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAchC;AAED,wBAAsB,aAAa,CACjC,IAAI,EAAE,cAAc,EACpB,KAAK,EAAE,eAAe,GACrB,OAAO,CAAC,gBAAgB,CAAC,CA+K3B"}